2
0
Эх сурвалжийг харах

fix: eslint for vue components

NGPixel 7 жил өмнө
parent
commit
98d311145b
45 өөрчлөгдсөн 906 нэмэгдсэн , 1206 устгасан
  1. 0 14
      .eslintrc.json
  2. 12 0
      .eslintrc.yml
  3. 5 1
      .vscode/settings.json
  4. 11 11
      client/js/components/alert.vue
  5. 31 31
      client/js/components/anchor.vue
  6. 32 32
      client/js/components/color-picker.vue
  7. 18 19
      client/js/components/config-manager.component.js
  8. 1 1
      client/js/components/editor-codeblock.vue
  9. 419 417
      client/js/components/editor-file.vue
  10. 50 50
      client/js/components/editor-video.vue
  11. 3 1
      client/js/components/history.vue
  12. 5 5
      client/js/components/loading-spinner.vue
  13. 2 1
      client/js/components/login.vue
  14. 40 40
      client/js/components/modal-create-page.vue
  15. 36 36
      client/js/components/modal-delete-page.vue
  16. 20 20
      client/js/components/modal-discard-page.vue
  17. 52 52
      client/js/components/modal-move-page.vue
  18. 5 3
      client/js/components/search.vue
  19. 10 10
      client/js/components/toggle.vue
  20. 59 57
      client/js/components/tree.vue
  21. 0 310
      client/js/configure.js
  22. 1 1
      client/js/store/modules/editor-codeblock.js
  23. 1 1
      client/js/store/modules/editor-file.js
  24. 1 1
      client/js/store/modules/editor-video.js
  25. 1 1
      client/js/store/modules/editor.js
  26. 0 2
      client/js/store/modules/modal-create-page.js
  27. 1 1
      client/js/store/modules/modal-create-user.js
  28. 0 2
      client/js/store/modules/modal-delete-user.js
  29. 0 2
      client/js/store/modules/modal-discard-page.js
  30. 0 2
      client/js/store/modules/modal-move-page.js
  31. 0 2
      client/js/store/modules/modal-profile-2fa.js
  32. 0 2
      client/js/store/modules/modal-upgrade-system.js
  33. 0 2
      client/js/store/modules/page-loader.js
  34. 2 1
      package.json
  35. 1 1
      server/helpers/entry.js
  36. 1 1
      server/middlewares/auth.js
  37. 1 1
      server/models/user.js
  38. 41 43
      server/modules/documents.js
  39. 1 4
      server/modules/markdown.js
  40. 2 2
      server/modules/search.js
  41. 1 1
      server/modules/system.js
  42. 12 12
      server/views/configure/index.pug
  43. 6 6
      test/lint.js
  44. 0 3
      tools/fuse_tasks.js
  45. 22 1
      yarn.lock

+ 0 - 14
.eslintrc.json

@@ -1,14 +0,0 @@
-{
-  "extends": "requarks",
-  "env": {
-    "node": true,
-    "es6": true,
-    "jest": true
-  },
-  "globals": {
-    "document": false,
-    "navigator": false,
-    "window": false,
-    "FuseBox": false
-  }
-}

+ 12 - 0
.eslintrc.yml

@@ -0,0 +1,12 @@
+extends:
+  - requarks
+  - plugin:vue/recommended
+env:
+  node: true
+  es6: true
+  jest: true
+globals:
+  document: false
+  navigator: false
+  window: false
+  FuseBox: false

+ 5 - 1
.vscode/settings.json

@@ -4,5 +4,9 @@
   "puglint.enable": true,
   "standard.enable": false,
   "editor.formatOnSave": false,
-  "editor.tabSize": 2
+  "editor.tabSize": 2,
+  "eslint.validate": [
+    "javascript",
+    "vue"
+  ]
 }

+ 11 - 11
client/js/components/alert.vue

@@ -6,16 +6,16 @@
 </template>
 
 <script>
-  export default {
-    name: 'alert',
-    data () {
-      return {}
-    },
-    computed: {
-      shown() { return this.$store.state.alert.shown },
-      style() { return 'is-' + this.$store.state.alert.style },
-      icon() { return 'nc-icon-outline ' + this.$store.state.alert.icon },
-      msg() { return this.$store.state.alert.msg },
-    }
+export default {
+  name: 'alert',
+  data () {
+    return {}
+  },
+  computed: {
+    shown() { return this.$store.state.alert.shown },
+    style() { return 'is-' + this.$store.state.alert.style },
+    icon() { return 'nc-icon-outline ' + this.$store.state.alert.icon },
+    msg() { return this.$store.state.alert.msg }
   }
+}
 </script>

+ 31 - 31
client/js/components/anchor.vue

@@ -17,39 +17,39 @@
 </template>
 
 <script>
-  export default {
-    name: 'anchor',
-    data () {
-      return {}
+export default {
+  name: 'anchor',
+  data () {
+    return {}
+  },
+  computed: {
+    anchorURL () {
+      return window.location.href.split('#')[0] + '#' + this.$store.state.anchor.hash
     },
-    computed: {
-      anchorURL () {
-        return window.location.href.split('#')[0] + '#' + this.$store.state.anchor.hash
-      },
-      isShown () {
-        return this.$store.state.anchor.shown
-      }
+    isShown () {
+      return this.$store.state.anchor.shown
+    }
+  },
+  methods: {
+    cancel () {
+      this.$store.dispatch('anchor/close')
+    },
+    clipboardSuccess () {
+      this.$store.dispatch('alert', {
+        style: 'blue',
+        icon: 'business_notes',
+        msg: this.$t('modal.anchorsuccess')
+      })
+      this.$store.dispatch('anchor/close')
     },
-    methods: {
-      cancel () {
-        this.$store.dispatch('anchor/close')
-      },
-      clipboardSuccess () {
-        this.$store.dispatch('alert', {
-          style: 'blue',
-          icon: 'business_notes',
-          msg: this.$t('modal.anchorsuccess')
-        })
-        this.$store.dispatch('anchor/close')
-      },
-      clipboardError () {
-        this.$store.dispatch('alert', {
-          style: 'red',
-          icon: 'business_notes',
-          msg: this.$t('modal.anchorerror')
-        })
-        this.$refs.anchorURLinput.select()
-      }
+    clipboardError () {
+      this.$store.dispatch('alert', {
+        style: 'red',
+        icon: 'business_notes',
+        msg: this.$t('modal.anchorerror')
+      })
+      this.$refs.anchorURLinput.select()
     }
   }
+}
 </script>

+ 32 - 32
client/js/components/color-picker.vue

@@ -4,38 +4,38 @@
 </template>
 
 <script>
-  export default {
-    name: 'color-picker',
-    props: ['value'],
-    data () {
-      return {
-        colors: [
-          'red',
-          'pink',
-          'purple',
-          'deep-purple',
-          'indigo',
-          'blue',
-          'light-blue',
-          'cyan',
-          'teal',
-          'green',
-          'light-green',
-          'lime',
-          'yellow',
-          'amber',
-          'orange',
-          'deep-orange',
-          'brown',
-          'grey',
-          'blue-grey'
-        ]
-      }
-    },
-    methods: {
-      setColor(color) {
-        this.$emit('input', color)
-      }
+export default {
+  name: 'color-picker',
+  props: ['value'],
+  data () {
+    return {
+      colors: [
+        'red',
+        'pink',
+        'purple',
+        'deep-purple',
+        'indigo',
+        'blue',
+        'light-blue',
+        'cyan',
+        'teal',
+        'green',
+        'light-green',
+        'lime',
+        'yellow',
+        'amber',
+        'orange',
+        'deep-orange',
+        'brown',
+        'grey',
+        'blue-grey'
+      ]
+    }
+  },
+  methods: {
+    setColor(color) {
+      this.$emit('input', color)
     }
   }
+}
 </script>

+ 18 - 19
client/js/components/config-manager.component.js

@@ -27,29 +27,28 @@ export default {
         results: []
       },
       conf: {
-        telemetry: true,
-        upgrade: false,
-        title: siteConfig.title || 'Wiki',
-        path: siteConfig.path || '/',
-        port: siteConfig.port || 80,
-        lang: siteConfig.lang || 'en',
-        public: (siteConfig.public === true),
-        pathData: './data',
-        pathRepo: './repo',
-        gitUseRemote: (siteConfig.git !== false),
-        gitUrl: '',
-        gitBranch: 'master',
-        gitAuthType: 'ssh',
-        gitAuthSSHKey: '',
-        gitAuthUser: '',
+        adminEmail: '',
+        adminPassword: '',
+        adminPasswordConfirm: '',
         gitAuthPass: '',
+        gitAuthSSHKey: '',
         gitAuthSSL: true,
-        gitShowUserEmail: true,
+        gitAuthType: 'ssh',
+        gitAuthUser: '',
+        gitBranch: 'master',
         gitServerEmail: '',
+        gitShowUserEmail: true,
+        gitUrl: '',
+        gitUseRemote: (siteConfig.git !== false),
+        lang: siteConfig.lang || 'en',
         mongo: 'mongodb://',
-        adminEmail: '',
-        adminPassword: '',
-        adminPasswordConfirm: ''
+        path: siteConfig.path || '/',
+        pathRepo: './repo',
+        port: siteConfig.port || 80,
+        public: (siteConfig.public === true),
+        telemetry: true,
+        title: siteConfig.title || 'Wiki',
+        upgrade: false
       },
       considerations: {
         https: false,

+ 1 - 1
client/js/components/editor-codeblock.vue

@@ -81,7 +81,7 @@ export default {
         self.isLoading = true
         self.$http.get('/js/ace/mode-' + m + '.js').then(resp => {
           if (resp.ok) {
-            eval(resp.bodyText)
+            eval(resp.bodyText) // eslint-disable-line no-eval
             self.modelistLoaded.push(m)
             ace.acequire('ace/mode/' + m)
             codeEditor.getSession().setMode('ace/mode/' + m)

+ 419 - 417
client/js/components/editor-file.vue

@@ -128,476 +128,478 @@
 </template>
 
 <script>
-  export default {
-    name: 'editor-file',
-    data () {
-      return {
-        isLoading: false,
-        isLoadingText: '',
-        newFolderName: '',
-        newFolderShow: false,
-        newFolderError: false,
-        fetchFromUrlURL: '',
-        fetchFromUrlShow: false,
-        folders: [],
-        currentFolder: '',
-        currentFile: '',
-        currentAlign: 'left',
-        files: [],
-        uploadSucceeded: false,
-        postUploadChecks: 0,
-        renameFileShow: false,
-        renameFileId: '',
-        renameFileFilename: '',
-        deleteFileShow: false,
-        deleteFileId: '',
-        deleteFileFilename: ''
-      }
+/* global $, socket */
+
+export default {
+  name: 'editor-file',
+  data () {
+    return {
+      isLoading: false,
+      isLoadingText: '',
+      newFolderName: '',
+      newFolderShow: false,
+      newFolderError: false,
+      fetchFromUrlURL: '',
+      fetchFromUrlShow: false,
+      folders: [],
+      currentFolder: '',
+      currentFile: '',
+      currentAlign: 'left',
+      files: [],
+      uploadSucceeded: false,
+      postUploadChecks: 0,
+      renameFileShow: false,
+      renameFileId: '',
+      renameFileFilename: '',
+      deleteFileShow: false,
+      deleteFileId: '',
+      deleteFileFilename: ''
+    }
+  },
+  computed: {
+    isShown () {
+      return this.$store.state.editorFile.shown
     },
-    computed: {
-      isShown () {
-        return this.$store.state.editorFile.shown
-      },
-      mode () {
-        return this.$store.state.editorFile.mode
-      }
+    mode () {
+      return this.$store.state.editorFile.mode
+    }
+  },
+  methods: {
+    init () {
+      $(this.$refs.editorFileUploadInput).on('change', this.upload)
+      this.refreshFolders()
+    },
+    cancel () {
+      $(this.$refs.editorFileUploadInput).off('change', this.upload)
+      this.$store.dispatch('editorFile/close')
+    },
+    filesize (rawSize) {
+      return this.$helpers.common.filesize(rawSize)
     },
-    methods: {
-      init () {
-        $(this.$refs.editorFileUploadInput).on('change', this.upload)
-        this.refreshFolders()
-      },
-      cancel () {
-        $(this.$refs.editorFileUploadInput).off('change', this.upload)
-        this.$store.dispatch('editorFile/close')
-      },
-      filesize (rawSize) {
-        return this.$helpers.common.filesize(rawSize)
-      },
-
-      // -------------------------------------------
-      // INSERT LINK TO FILE
-      // -------------------------------------------
-
-      selectFile(fileId) {
-        this.currentFile = fileId
-      },
-      insertFileLink() {
-        let selFile = this._.find(this.files, ['_id', this.currentFile])
-        selFile.normalizedPath = (selFile.folder === 'f:') ? selFile.filename : selFile.folder.slice(2) + '/' + selFile.filename
-        selFile.titleGuess = this._.startCase(selFile.basename)
-
-        let textToInsert = ''
-
-        if (this.mode === 'image') {
-          textToInsert = '![' + selFile.titleGuess + '](/uploads/' + selFile.normalizedPath + ' "' + selFile.titleGuess + '")'
-          switch (this.currentAlign) {
-            case 'center':
-              textToInsert += '{.align-center}'
-              break
-            case 'right':
-              textToInsert += '{.align-right}'
-              break
-            case 'logo':
-              textToInsert += '{.pagelogo}'
-              break
-          }
-        } else {
-          textToInsert = '[' + selFile.titleGuess + '](/uploads/' + selFile.normalizedPath + ' "' + selFile.titleGuess + '")'
-        }
 
-        this.$store.dispatch('editor/insert', textToInsert)
-        this.$store.dispatch('alert', {
-          style: 'blue',
-          icon: 'ui-1_check-square-09',
-          msg: (this.mode === 'file') ? this.$t('editor.filesuccess') : this.$t('editor.imagesuccess')
-        })
-        this.cancel()
-      },
-
-      // -------------------------------------------
-      // NEW FOLDER
-      // -------------------------------------------
-
-      newFolder() {
-        let self = this
-        this.newFolderName = ''
-        this.newFolderError = false
-        this.newFolderShow = true
-        this._.delay(() => { self.$refs.editorFileNewFolderInput.focus() }, 400)
-      },
-      newFolderDiscard() {
-        this.newFolderShow = false
-      },
-      newFolderCreate() {
-        let self = this
-        let regFolderName = new RegExp('^[a-z0-9][a-z0-9-]*[a-z0-9]$')
-        this.newFolderName = this._.kebabCase(this._.trim(this.newFolderName))
-
-        if (this._.isEmpty(this.newFolderName) || !regFolderName.test(this.newFolderName)) {
-          this.newFolderError = true
-          return
+    // -------------------------------------------
+    // INSERT LINK TO FILE
+    // -------------------------------------------
+
+    selectFile(fileId) {
+      this.currentFile = fileId
+    },
+    insertFileLink() {
+      let selFile = this._.find(this.files, ['_id', this.currentFile])
+      selFile.normalizedPath = (selFile.folder === 'f:') ? selFile.filename : selFile.folder.slice(2) + '/' + selFile.filename
+      selFile.titleGuess = this._.startCase(selFile.basename)
+
+      let textToInsert = ''
+
+      if (this.mode === 'image') {
+        textToInsert = '![' + selFile.titleGuess + '](/uploads/' + selFile.normalizedPath + ' "' + selFile.titleGuess + '")'
+        switch (this.currentAlign) {
+          case 'center':
+            textToInsert += '{.align-center}'
+            break
+          case 'right':
+            textToInsert += '{.align-right}'
+            break
+          case 'logo':
+            textToInsert += '{.pagelogo}'
+            break
         }
+      } else {
+        textToInsert = '[' + selFile.titleGuess + '](/uploads/' + selFile.normalizedPath + ' "' + selFile.titleGuess + '")'
+      }
 
-        this.newFolderDiscard()
-        this.isLoadingText = this.$t('modal.newfolderloading')
-        this.isLoading = true
+      this.$store.dispatch('editor/insert', textToInsert)
+      this.$store.dispatch('alert', {
+        style: 'blue',
+        icon: 'ui-1_check-square-09',
+        msg: (this.mode === 'file') ? this.$t('editor.filesuccess') : this.$t('editor.imagesuccess')
+      })
+      this.cancel()
+    },
 
-        this.$nextTick(() => {
-          socket.emit('uploadsCreateFolder', { foldername: self.newFolderName }, (data) => {
-            self.folders = data
-            self.currentFolder = self.newFolderName
-            self.files = []
-            self.isLoading = false
-            self.$store.dispatch('alert', {
-              style: 'blue',
-              icon: 'files_folder-check',
-              msg: self.$t('modal.newfoldersuccess', { name: self.newFolderName })
-            })
-          })
-        })
-      },
-
-      // -------------------------------------------
-      // FETCH FROM URL
-      // -------------------------------------------
-
-      fetchFromUrl() {
-        let self = this
-        this.fetchFromUrlURL = ''
-        this.fetchFromUrlShow = true
-        this._.delay(() => { self.$refs.editorFileFetchInput.focus() }, 400)
-      },
-      fetchFromUrlDiscard() {
-        this.fetchFromUrlShow = false
-      },
-      fetchFromUrlGo() {
-        let self = this
-        this.fetchFromUrlDiscard()
-        this.isLoadingText = 'Fetching image...'
-        this.isLoading = true
+    // -------------------------------------------
+    // NEW FOLDER
+    // -------------------------------------------
 
-        this.$nextTick(() => {
-          socket.emit('uploadsFetchFileFromURL', { folder: self.currentFolder, fetchUrl: self.fetchFromUrlURL }, (data) => {
-            if (data.ok) {
-              self.waitChangeComplete(self.files.length, true)
-            } else {
-              self.isLoading = false
-              self.$store.dispatch('alert', {
-                style: 'red',
-                icon: 'ui-2_square-remove-09',
-                msg: self.$t('editor.fileuploaderror', { err: data.msg })
-              })
-            }
-          })
-        })
-      },
-
-      // -------------------------------------------
-      // RENAME FILE
-      // -------------------------------------------
-
-      renameFile() {
-        let self = this
-        let c = this._.find(this.files, [ '_id', this.renameFileId ])
-        this.renameFileFilename = c.basename || ''
-        this.renameFileShow = true
-        this._.delay(() => {
-          self.$refs.editorFileRenameInput.select()
-        }, 100)
-      },
-      renameFileDiscard() {
-        this.renameFileShow = false
-      },
-      renameFileGo() {
-        let self = this
-        this.renameFileDiscard()
-        this.isLoadingText = this.$t('modal.renamefileloading')
-        this.isLoading = true
+    newFolder() {
+      let self = this
+      this.newFolderName = ''
+      this.newFolderError = false
+      this.newFolderShow = true
+      this._.delay(() => { self.$refs.editorFileNewFolderInput.focus() }, 400)
+    },
+    newFolderDiscard() {
+      this.newFolderShow = false
+    },
+    newFolderCreate() {
+      let self = this
+      let regFolderName = new RegExp('^[a-z0-9][a-z0-9-]*[a-z0-9]$')
+      this.newFolderName = this._.kebabCase(this._.trim(this.newFolderName))
+
+      if (this._.isEmpty(this.newFolderName) || !regFolderName.test(this.newFolderName)) {
+        this.newFolderError = true
+        return
+      }
 
-        this.$nextTick(() => {
-          socket.emit('uploadsRenameFile', { uid: self.renameFileId, folder: self.currentFolder, filename: self.renameFileFilename }, (data) => {
-            if (data.ok) {
-              self.waitChangeComplete(self.files.length, false)
-            } else {
-              self.isLoading = false
-              self.$store.dispatch('alert', {
-                style: 'red',
-                icon: 'ui-2_square-remove-09',
-                msg: self.$t('modal.renamefileerror', { err: data.msg })
-              })
-            }
+      this.newFolderDiscard()
+      this.isLoadingText = this.$t('modal.newfolderloading')
+      this.isLoading = true
+
+      this.$nextTick(() => {
+        socket.emit('uploadsCreateFolder', { foldername: self.newFolderName }, (data) => {
+          self.folders = data
+          self.currentFolder = self.newFolderName
+          self.files = []
+          self.isLoading = false
+          self.$store.dispatch('alert', {
+            style: 'blue',
+            icon: 'files_folder-check',
+            msg: self.$t('modal.newfoldersuccess', { name: self.newFolderName })
           })
         })
-      },
+      })
+    },
 
-      // -------------------------------------------
-      // MOVE FILE
-      // -------------------------------------------
+    // -------------------------------------------
+    // FETCH FROM URL
+    // -------------------------------------------
 
-      moveFile(uid, fld) {
-        let self = this
-        this.isLoadingText = this.$t('editor.filemoveloading')
-        this.isLoading = true
-        this.$nextTick(() => {
-          socket.emit('uploadsMoveFile', { uid, folder: fld }, (data) => {
-            if (data.ok) {
-              self.loadFiles()
-              self.$store.dispatch('alert', {
-                style: 'blue',
-                icon: 'files_check',
-                msg: self.$t('editor.filemovesuccess')
-              })
-            } else {
-              self.isLoading = false
-              self.$store.dispatch('alert', {
-                style: 'red',
-                icon: 'ui-2_square-remove-09',
-                msg: self.$t('editor.filemoveerror', { err: data.msg })
-              })
-            }
-          })
+    fetchFromUrl() {
+      let self = this
+      this.fetchFromUrlURL = ''
+      this.fetchFromUrlShow = true
+      this._.delay(() => { self.$refs.editorFileFetchInput.focus() }, 400)
+    },
+    fetchFromUrlDiscard() {
+      this.fetchFromUrlShow = false
+    },
+    fetchFromUrlGo() {
+      let self = this
+      this.fetchFromUrlDiscard()
+      this.isLoadingText = 'Fetching image...'
+      this.isLoading = true
+
+      this.$nextTick(() => {
+        socket.emit('uploadsFetchFileFromURL', { folder: self.currentFolder, fetchUrl: self.fetchFromUrlURL }, (data) => {
+          if (data.ok) {
+            self.waitChangeComplete(self.files.length, true)
+          } else {
+            self.isLoading = false
+            self.$store.dispatch('alert', {
+              style: 'red',
+              icon: 'ui-2_square-remove-09',
+              msg: self.$t('editor.fileuploaderror', { err: data.msg })
+            })
+          }
         })
-      },
+      })
+    },
 
-      // -------------------------------------------
-      // DELETE FILE
-      // -------------------------------------------
+    // -------------------------------------------
+    // RENAME FILE
+    // -------------------------------------------
+
+    renameFile() {
+      let self = this
+      let c = this._.find(this.files, [ '_id', this.renameFileId ])
+      this.renameFileFilename = c.basename || ''
+      this.renameFileShow = true
+      this._.delay(() => {
+        self.$refs.editorFileRenameInput.select()
+      }, 100)
+    },
+    renameFileDiscard() {
+      this.renameFileShow = false
+    },
+    renameFileGo() {
+      let self = this
+      this.renameFileDiscard()
+      this.isLoadingText = this.$t('modal.renamefileloading')
+      this.isLoading = true
+
+      this.$nextTick(() => {
+        socket.emit('uploadsRenameFile', { uid: self.renameFileId, folder: self.currentFolder, filename: self.renameFileFilename }, (data) => {
+          if (data.ok) {
+            self.waitChangeComplete(self.files.length, false)
+          } else {
+            self.isLoading = false
+            self.$store.dispatch('alert', {
+              style: 'red',
+              icon: 'ui-2_square-remove-09',
+              msg: self.$t('modal.renamefileerror', { err: data.msg })
+            })
+          }
+        })
+      })
+    },
 
-      deleteFileWarn(show) {
-        if (show) {
-          let c = this._.find(this.files, [ '_id', this.deleteFileId ])
-          this.deleteFileFilename = c.filename || this.$t('editor.filedeletedefault')
-        }
-        this.deleteFileShow = show
-      },
-      deleteFileGo() {
-        let self = this
-        this.deleteFileWarn(false)
-        this.isLoadingText = this.$t('editor.filedeleteloading')
-        this.isLoading = true
-        this.$nextTick(() => {
-          socket.emit('uploadsDeleteFile', { uid: this.deleteFileId }, (data) => {
+    // -------------------------------------------
+    // MOVE FILE
+    // -------------------------------------------
+
+    moveFile(uid, fld) {
+      let self = this
+      this.isLoadingText = this.$t('editor.filemoveloading')
+      this.isLoading = true
+      this.$nextTick(() => {
+        socket.emit('uploadsMoveFile', { uid, folder: fld }, (data) => {
+          if (data.ok) {
             self.loadFiles()
             self.$store.dispatch('alert', {
               style: 'blue',
-              icon: 'ui-1_trash',
-              msg: self.$t('editor.filedeletesuccess')
+              icon: 'files_check',
+              msg: self.$t('editor.filemovesuccess')
             })
-          })
+          } else {
+            self.isLoading = false
+            self.$store.dispatch('alert', {
+              style: 'red',
+              icon: 'ui-2_square-remove-09',
+              msg: self.$t('editor.filemoveerror', { err: data.msg })
+            })
+          }
         })
-      },
-
-      // -------------------------------------------
-      // LOAD FROM REMOTE
-      // -------------------------------------------
+      })
+    },
 
-      selectFolder(fldName) {
-        this.currentFolder = fldName
-        this.loadFiles()
-      },
+    // -------------------------------------------
+    // DELETE FILE
+    // -------------------------------------------
 
-      refreshFolders() {
-        let self = this
-        this.isLoadingText = this.$t('editor.foldersloading')
-        this.isLoading = true
-        this.currentFolder = ''
-        this.currentImage = ''
-        this.$nextTick(() => {
-          socket.emit('uploadsGetFolders', { }, (data) => {
-            self.folders = data
-            self.loadFiles()
+    deleteFileWarn(show) {
+      if (show) {
+        let c = this._.find(this.files, [ '_id', this.deleteFileId ])
+        this.deleteFileFilename = c.filename || this.$t('editor.filedeletedefault')
+      }
+      this.deleteFileShow = show
+    },
+    deleteFileGo() {
+      let self = this
+      this.deleteFileWarn(false)
+      this.isLoadingText = this.$t('editor.filedeleteloading')
+      this.isLoading = true
+      this.$nextTick(() => {
+        socket.emit('uploadsDeleteFile', { uid: this.deleteFileId }, (data) => {
+          self.loadFiles()
+          self.$store.dispatch('alert', {
+            style: 'blue',
+            icon: 'ui-1_trash',
+            msg: self.$t('editor.filedeletesuccess')
           })
         })
-      },
+      })
+    },
 
-      loadFiles(silent) {
-        let self = this
-        if (!silent) {
-          this.isLoadingText = this.$t('editor.fileloading')
-          this.isLoading = true
-        }
-        return new Promise((resolve, reject) => {
-          self.$nextTick(() => {
-            let loadAction = (self.mode === 'image') ? 'uploadsGetImages' : 'uploadsGetFiles'
-            socket.emit(loadAction, { folder: self.currentFolder }, (data) => {
-              self.files = data
-              if (!silent) {
-                self.isLoading = false
-              }
-              self.attachContextMenus()
-              resolve(true)
-            })
-          })
-        })
-      },
+    // -------------------------------------------
+    // LOAD FROM REMOTE
+    // -------------------------------------------
 
-      waitChangeComplete(oldAmount, expectChange) {
-        let self = this
-        expectChange = (this._.isBoolean(expectChange)) ? expectChange : true
+    selectFolder(fldName) {
+      this.currentFolder = fldName
+      this.loadFiles()
+    },
 
-        this.postUploadChecks++
-        this.isLoadingText = this.$t('editor.fileprocessing')
+    refreshFolders() {
+      let self = this
+      this.isLoadingText = this.$t('editor.foldersloading')
+      this.isLoading = true
+      this.currentFolder = ''
+      this.currentImage = ''
+      this.$nextTick(() => {
+        socket.emit('uploadsGetFolders', { }, (data) => {
+          self.folders = data
+          self.loadFiles()
+        })
+      })
+    },
 
-        this.$nextTick(() => {
-          self.loadFiles(true).then(() => {
-            if ((self.files.length !== oldAmount) === expectChange) {
-              self.postUploadChecks = 0
-              self.isLoading = false
-            } else if (self.postUploadChecks > 5) {
-              self.postUploadChecks = 0
+    loadFiles(silent) {
+      let self = this
+      if (!silent) {
+        this.isLoadingText = this.$t('editor.fileloading')
+        this.isLoading = true
+      }
+      return new Promise((resolve, reject) => {
+        self.$nextTick(() => {
+          let loadAction = (self.mode === 'image') ? 'uploadsGetImages' : 'uploadsGetFiles'
+          socket.emit(loadAction, { folder: self.currentFolder }, (data) => {
+            self.files = data
+            if (!silent) {
               self.isLoading = false
-              self.$store.dispatch('alert', {
-                style: 'red',
-                icon: 'ui-2_square-remove-09',
-                msg: self.$t('editor.fileerror')
-              })
-            } else {
-              self._.delay(() => {
-                self.waitChangeComplete(oldAmount, expectChange)
-              }, 1500)
             }
+            self.attachContextMenus()
+            resolve(true)
           })
         })
-      },
-
-      // -------------------------------------------
-      // IMAGE CONTEXT MENU
-      // -------------------------------------------
-
-      attachContextMenus() {
-        let self = this
-        let moveFolders = this._.map(this.folders, (f) => {
-          return {
-            name: (f !== '') ? f : '/ (root)',
-            icon: 'nc-icon-outline files_folder-15',
-            callback: (key, opt) => {
-              let moveFileId = self._.toString($(opt.$trigger).data('uid'))
-              let moveFileDestFolder = self._.nth(self.folders, key)
-              self.moveFile(moveFileId, moveFileDestFolder)
-            }
+      })
+    },
+
+    waitChangeComplete(oldAmount, expectChange) {
+      let self = this
+      expectChange = (this._.isBoolean(expectChange)) ? expectChange : true
+
+      this.postUploadChecks++
+      this.isLoadingText = this.$t('editor.fileprocessing')
+
+      this.$nextTick(() => {
+        self.loadFiles(true).then(() => {
+          if ((self.files.length !== oldAmount) === expectChange) {
+            self.postUploadChecks = 0
+            self.isLoading = false
+          } else if (self.postUploadChecks > 5) {
+            self.postUploadChecks = 0
+            self.isLoading = false
+            self.$store.dispatch('alert', {
+              style: 'red',
+              icon: 'ui-2_square-remove-09',
+              msg: self.$t('editor.fileerror')
+            })
+          } else {
+            self._.delay(() => {
+              self.waitChangeComplete(oldAmount, expectChange)
+            }, 1500)
           }
         })
+      })
+    },
 
-        $.contextMenu('destroy', '.editor-modal-choices > figure')
-        $.contextMenu({
-          selector: '.editor-modal-choices > figure',
-          appendTo: '.editor-modal-choices',
-          position: (opt, x, y) => {
-            $(opt.$trigger).addClass('is-contextopen')
-            let trigPos = $(opt.$trigger).position()
-            let trigDim = { w: $(opt.$trigger).width() / 5, h: $(opt.$trigger).height() / 2 }
-            opt.$menu.css({ top: trigPos.top + trigDim.h, left: trigPos.left + trigDim.w })
-          },
-          events: {
-            hide: (opt) => {
-              $(opt.$trigger).removeClass('is-contextopen')
+    // -------------------------------------------
+    // IMAGE CONTEXT MENU
+    // -------------------------------------------
+
+    attachContextMenus() {
+      let self = this
+      let moveFolders = this._.map(this.folders, (f) => {
+        return {
+          name: (f !== '') ? f : '/ (root)',
+          icon: 'nc-icon-outline files_folder-15',
+          callback: (key, opt) => {
+            let moveFileId = self._.toString($(opt.$trigger).data('uid'))
+            let moveFileDestFolder = self._.nth(self.folders, key)
+            self.moveFile(moveFileId, moveFileDestFolder)
+          }
+        }
+      })
+
+      $.contextMenu('destroy', '.editor-modal-choices > figure')
+      $.contextMenu({
+        selector: '.editor-modal-choices > figure',
+        appendTo: '.editor-modal-choices',
+        position: (opt, x, y) => {
+          $(opt.$trigger).addClass('is-contextopen')
+          let trigPos = $(opt.$trigger).position()
+          let trigDim = { w: $(opt.$trigger).width() / 5, h: $(opt.$trigger).height() / 2 }
+          opt.$menu.css({ top: trigPos.top + trigDim.h, left: trigPos.left + trigDim.w })
+        },
+        events: {
+          hide: (opt) => {
+            $(opt.$trigger).removeClass('is-contextopen')
+          }
+        },
+        items: {
+          rename: {
+            name: self.$t('editor.filerenameaction'),
+            icon: 'nc-icon-outline files_vector',
+            callback: (key, opt) => {
+              self.renameFileId = self._.toString(opt.$trigger[0].dataset.uid)
+              self.renameFile()
             }
           },
-          items: {
-            rename: {
-              name: self.$t('editor.filerenameaction'),
-              icon: 'nc-icon-outline files_vector',
-              callback: (key, opt) => {
-                self.renameFileId = self._.toString(opt.$trigger[0].dataset.uid)
-                self.renameFile()
-              }
-            },
-            move: {
-              name: self.$t('editor.filemoveaction'),
-              icon: 'fa-folder-open-o',
-              items: moveFolders
-            },
-            delete: {
-              name: self.$t('editor.filedeleteaction'),
-              icon: 'icon-trash2',
-              callback: (key, opt) => {
-                self.deleteFileId = self._.toString(opt.$trigger[0].dataset.uid)
-                self.deleteFileWarn(true)
-              }
+          move: {
+            name: self.$t('editor.filemoveaction'),
+            icon: 'fa-folder-open-o',
+            items: moveFolders
+          },
+          delete: {
+            name: self.$t('editor.filedeleteaction'),
+            icon: 'icon-trash2',
+            callback: (key, opt) => {
+              self.deleteFileId = self._.toString(opt.$trigger[0].dataset.uid)
+              self.deleteFileWarn(true)
             }
           }
-        })
-      },
-      upload() {
-        let self = this
-        let curFileAmount = this.files.length
-        let uplUrl = (self.mode === 'image') ? '/uploads/img' : '/uploads/file'
-
-        $(this.$refs.editorFileUploadInput).simpleUpload(uplUrl, {
-
-          name: (self.mode === 'image') ? 'imgfile' : 'binfile',
-          data: {
-            folder: self.currentFolder
-          },
-          limit: 20,
-          expect: 'json',
-          allowedExts: (self.mode === 'image') ? ['jpg', 'jpeg', 'gif', 'png', 'webp'] : undefined,
-          allowedTypes: (self.mode === 'image') ? ['image/png', 'image/jpeg', 'image/gif', 'image/webp'] : undefined,
-          maxFileSize: (self.mode === 'image') ? 3145728 : 0, // max 3 MB
-
-          init: (totalUploads) => {
-            self.uploadSucceeded = false
-            self.isLoadingText = 'Preparing to upload...'
-            self.isLoading = true
-          },
-
-          progress: (progress) => {
-            self.isLoadingText = 'Uploading...' + Math.round(progress) + '%'
-          },
-
-          success: (data) => {
-            if (data.ok) {
-              let failedUpls = self._.filter(data.results, ['ok', false])
-              if (failedUpls.length) {
-                self._.forEach(failedUpls, (u) => {
-                  self.$store.dispatch('alert', {
-                    style: 'red',
-                    icon: 'ui-2_square-remove-09',
-                    msg: self.$t('editor.fileuploaderror', { err: u.msg })
-                  })
-                })
-                if (failedUpls.length < data.results.length) {
-                  self.uploadSucceeded = true
-                }
-              } else {
-                self.uploadSucceeded = true
+        }
+      })
+    },
+    upload() {
+      let self = this
+      let curFileAmount = this.files.length
+      let uplUrl = (self.mode === 'image') ? '/uploads/img' : '/uploads/file'
+
+      $(this.$refs.editorFileUploadInput).simpleUpload(uplUrl, {
+
+        name: (self.mode === 'image') ? 'imgfile' : 'binfile',
+        data: {
+          folder: self.currentFolder
+        },
+        limit: 20,
+        expect: 'json',
+        allowedExts: (self.mode === 'image') ? ['jpg', 'jpeg', 'gif', 'png', 'webp'] : undefined,
+        allowedTypes: (self.mode === 'image') ? ['image/png', 'image/jpeg', 'image/gif', 'image/webp'] : undefined,
+        maxFileSize: (self.mode === 'image') ? 3145728 : 0, // max 3 MB
+
+        init: (totalUploads) => {
+          self.uploadSucceeded = false
+          self.isLoadingText = 'Preparing to upload...'
+          self.isLoading = true
+        },
+
+        progress: (progress) => {
+          self.isLoadingText = 'Uploading...' + Math.round(progress) + '%'
+        },
+
+        success: (data) => {
+          if (data.ok) {
+            let failedUpls = self._.filter(data.results, ['ok', false])
+            if (failedUpls.length) {
+              self._.forEach(failedUpls, (u) => {
                 self.$store.dispatch('alert', {
-                  style: 'blue',
-                  icon: 'arrows-1_cloud-upload-96',
-                  msg: self.$t('editor.fileuploadsuccess')
+                  style: 'red',
+                  icon: 'ui-2_square-remove-09',
+                  msg: self.$t('editor.fileuploaderror', { err: u.msg })
                 })
+              })
+              if (failedUpls.length < data.results.length) {
+                self.uploadSucceeded = true
               }
             } else {
+              self.uploadSucceeded = true
               self.$store.dispatch('alert', {
-                style: 'red',
-                icon: 'ui-2_square-remove-09',
-                msg: self.$t('editor.fileuploaderror', { err: data.msg })
+                style: 'blue',
+                icon: 'arrows-1_cloud-upload-96',
+                msg: self.$t('editor.fileuploadsuccess')
               })
             }
-          },
-
-          error: (error) => {
+          } else {
             self.$store.dispatch('alert', {
               style: 'red',
               icon: 'ui-2_square-remove-09',
-              msg: self.$t('editor.fileuploaderror', { err: error.message })
+              msg: self.$t('editor.fileuploaderror', { err: data.msg })
             })
-          },
+          }
+        },
 
-          finish: () => {
-            if (self.uploadSucceeded) {
-              self.waitChangeComplete(curFileAmount, true)
-            } else {
-              self.isLoading = false
-            }
+        error: (error) => {
+          self.$store.dispatch('alert', {
+            style: 'red',
+            icon: 'ui-2_square-remove-09',
+            msg: self.$t('editor.fileuploaderror', { err: error.message })
+          })
+        },
+
+        finish: () => {
+          if (self.uploadSucceeded) {
+            self.waitChangeComplete(curFileAmount, true)
+          } else {
+            self.isLoading = false
           }
+        }
 
-        })
-      }
-    },
-    mounted() {
-      this.$root.$on('editorFile/init', this.init)
+      })
     }
+  },
+  mounted() {
+    this.$root.$on('editorFile/init', this.init)
   }
+}
 </script>

+ 50 - 50
client/js/components/editor-video.vue

@@ -33,62 +33,62 @@
 </template>
 
 <script>
-  const videoRules = {
-    'youtube': new RegExp('/(?:(?:youtu\\.be\\/|v\\/|vi\\/|u\\/\\w\\/|embed\\/)|(?:(?:watch)?\\?v(?:i)?=|&v(?:i)?=))([^#&?]*).*/', 'i'),
-    'vimeo': new RegExp('/vimeo.com\\/(?:channels\\/(?:\\w+\\/)?|groups\\/(?:[^/]*)\\/videos\\/|album\\/(?:\\d+)\\/video\\/|)(\\d+)(?:$|\\/|\\?)/', 'i'),
-    'dailymotion': new RegExp('/(?:dailymotion\\.com(?:\\/embed)?(?:\\/video|\\/hub)|dai\\.ly)\\/([0-9a-z]+)(?:[-_0-9a-zA-Z]+(?:#video=)?([a-z0-9]+)?)?/', 'i')
-  }
+const videoRules = {
+  'youtube': new RegExp('/(?:(?:youtu\\.be\\/|v\\/|vi\\/|u\\/\\w\\/|embed\\/)|(?:(?:watch)?\\?v(?:i)?=|&v(?:i)?=))([^#&?]*).*/', 'i'),
+  'vimeo': new RegExp('/vimeo.com\\/(?:channels\\/(?:\\w+\\/)?|groups\\/(?:[^/]*)\\/videos\\/|album\\/(?:\\d+)\\/video\\/|)(\\d+)(?:$|\\/|\\?)/', 'i'),
+  'dailymotion': new RegExp('/(?:dailymotion\\.com(?:\\/embed)?(?:\\/video|\\/hub)|dai\\.ly)\\/([0-9a-z]+)(?:[-_0-9a-zA-Z]+(?:#video=)?([a-z0-9]+)?)?/', 'i')
+}
 
-  export default {
-    name: 'editor-video',
-    data () {
-      return {
-        link: '',
-        isInvalid: false
-      }
+export default {
+  name: 'editor-video',
+  data () {
+    return {
+      link: '',
+      isInvalid: false
+    }
+  },
+  computed: {
+    isShown () {
+      return this.$store.state.editorVideo.shown
+    }
+  },
+  methods: {
+    init () {
+      let self = this
+      self.isInvalid = false
+      self._.delay(() => {
+        self.$refs.editorVideoInput.focus()
+      }, 100)
     },
-    computed: {
-      isShown () {
-        return this.$store.state.editorVideo.shown
-      }
+    cancel () {
+      this.$store.dispatch('editorVideo/close')
     },
-    methods: {
-      init () {
-        let self = this
-        self.isInvalid = false
-        self._.delay(() => {
-          self.$refs.editorVideoInput.focus()
-        }, 100)
-      },
-      cancel () {
-        this.$store.dispatch('editorVideo/close')
-      },
-      insertVideo () {
-        let self = this
+    insertVideo () {
+      let self = this
 
-        if (this._.isEmpty(self.link) || self.link.length < 5) {
-          this.isInvalid = true
-          return
-        }
+      if (this._.isEmpty(self.link) || self.link.length < 5) {
+        this.isInvalid = true
+        return
+      }
 
-        let videoType = this._.findKey(videoRules, (vr) => {
-          return vr.test(self.link)
-        })
-        if (this._.isNil(videoType)) {
-          videoType = 'video'
-        }
-        let videoText = '[video](' + this.link + '){.' + videoType + '}\n'
-        this.$store.dispatch('editor/insert', videoText)
-        this.$store.dispatch('alert', {
-          style: 'blue',
-          icon: 'media-1_action-74',
-          msg: self.$t('editor.videosuccess')
-        })
-        this.cancel()
+      let videoType = this._.findKey(videoRules, (vr) => {
+        return vr.test(self.link)
+      })
+      if (this._.isNil(videoType)) {
+        videoType = 'video'
       }
-    },
-    mounted () {
-      this.$root.$on('editorVideo/init', this.init)
+      let videoText = '[video](' + this.link + '){.' + videoType + '}\n'
+      this.$store.dispatch('editor/insert', videoText)
+      this.$store.dispatch('alert', {
+        style: 'blue',
+        icon: 'media-1_action-74',
+        msg: self.$t('editor.videosuccess')
+      })
+      this.cancel()
     }
+  },
+  mounted () {
+    this.$root.$on('editorVideo/init', this.init)
   }
+}
 </script>

+ 3 - 1
client/js/components/history.vue

@@ -44,6 +44,8 @@
 </template>
 
 <script>
+/* global wiki, Diff2HtmlUI */
+
 let diffui
 let diffuiIsReady = false
 export default {
@@ -98,7 +100,7 @@ export default {
       let self = this
       diffuiIsReady = false
       self.current = cm
-      self.$http.post(siteRoot + '/hist', {
+      self.$http.post(wiki.siteRoot + '/hist', {
         path: self.currentPath,
         commit: cm.commit
       }).then(resp => {

+ 5 - 5
client/js/components/loading-spinner.vue

@@ -3,10 +3,10 @@
 </template>
 
 <script>
-  import { mapState } from 'vuex'
+import { mapState } from 'vuex'
 
-  export default {
-    name: 'loading-spinner',
-    computed: mapState(['loading'])
-  }
+export default {
+  name: 'loading-spinner',
+  computed: mapState(['loading'])
+}
 </script>

+ 2 - 1
client/js/components/login.vue

@@ -24,6 +24,8 @@
 </template>
 
 <script>
+/* global CONSTANTS, graphQL, siteConfig */
+
 export default {
   name: 'login',
   data() {
@@ -67,4 +69,3 @@ export default {
   }
 }
 </script>
-

+ 40 - 40
client/js/components/modal-create-page.vue

@@ -18,50 +18,50 @@
 </template>
 
 <script>
-  export default {
-    name: 'modal-create-page',
-    props: ['basepath'],
-    data () {
-      return {
-        currentPath: '',
-        userPath: '',
-        isLoading: false,
-        isInvalid: false
+export default {
+  name: 'modal-create-page',
+  props: ['basepath'],
+  data () {
+    return {
+      currentPath: '',
+      userPath: '',
+      isLoading: false,
+      isInvalid: false
+    }
+  },
+  computed: {
+    isShown () {
+      if (this.$store.state.modalCreatePage.shown) {
+        this.makeSelection()
       }
+      return this.$store.state.modalCreatePage.shown
+    }
+  },
+  methods: {
+    makeSelection: function () {
+      let self = this
+      self._.delay(() => {
+        let startPos = (self.currentPath.length > 0) ? self.currentPath.length + 1 : 0
+        self.$helpers.form.setInputSelection(self.$refs.createPageInput, startPos, self.userPath.length)
+      }, 100)
     },
-    computed: {
-      isShown () {
-        if(this.$store.state.modalCreatePage.shown) {
-          this.makeSelection()
-        }
-        return this.$store.state.modalCreatePage.shown
-      }
+    cancel: function () {
+      this.$store.dispatch('modalCreatePage/close')
     },
-    methods: {
-      makeSelection: function () {
-        let self = this;
-        self._.delay(() => {
-          let startPos = (self.currentPath.length > 0) ? self.currentPath.length + 1 : 0
-          self.$helpers.form.setInputSelection(self.$refs.createPageInput, startPos, self.userPath.length)
-        }, 100)
-      },
-      cancel: function () {
-        this.$store.dispatch('modalCreatePage/close')
-      },
-      create: function () {
-        this.isInvalid = false
-        let newDocPath = this.$helpers.pages.makeSafePath(this.userPath)
-        if (this._.isEmpty(newDocPath)) {
-          this.isInvalid = true
-        } else {
-          this.isLoading = true
-          window.location.assign('/create/' + newDocPath)
-        }
+    create: function () {
+      this.isInvalid = false
+      let newDocPath = this.$helpers.pages.makeSafePath(this.userPath)
+      if (this._.isEmpty(newDocPath)) {
+        this.isInvalid = true
+      } else {
+        this.isLoading = true
+        window.location.assign('/create/' + newDocPath)
       }
-    },
-    mounted () {
-      this.currentPath = (this.basepath === 'home') ? '' : this.basepath
-      this.userPath = (this._.isEmpty(this.currentPath)) ? 'new-page' : this.currentPath + '/new-page'
     }
+  },
+  mounted () {
+    this.currentPath = (this.basepath === 'home') ? '' : this.basepath
+    this.userPath = (this._.isEmpty(this.currentPath)) ? 'new-page' : this.currentPath + '/new-page'
   }
+}
 </script>

+ 36 - 36
client/js/components/modal-delete-page.vue

@@ -18,49 +18,49 @@
 </template>
 
 <script>
-  export default {
-    name: 'modal-delete-page',
-    props: ['currentPath'],
-    data () {
-      return {
-        isLoading: false
-      }
-    },
-    computed: {
-      isShown () {
-        return this.$store.state.modalDeletePage.shown
-      }
+export default {
+  name: 'modal-delete-page',
+  props: ['currentPath'],
+  data () {
+    return {
+      isLoading: false
+    }
+  },
+  computed: {
+    isShown () {
+      return this.$store.state.modalDeletePage.shown
+    }
+  },
+  methods: {
+    discard () {
+      this.isLoading = false
+      this.$store.dispatch('modalDeletePage/close')
     },
-    methods: {
-      discard () {
-        this.isLoading = false
-        this.$store.dispatch('modalDeletePage/close')
-      },
-      deletePage () {
-        let self = this
-        this.isLoading = true
-        this.$http.delete(window.location.href).then(resp => {
-          return resp.json()
-        }).then(resp => {
-          if (resp.ok) {
-            window.location.assign('/')
-          } else {
-            self.isLoading = false
-            self.$store.dispatch('alert', {
-              style: 'red',
-              icon: 'ui-2_square-remove-09',
-              msg: resp.msg
-            })
-          }
-        }).catch(err => {
+    deletePage () {
+      let self = this
+      this.isLoading = true
+      this.$http.delete(window.location.href).then(resp => {
+        return resp.json()
+      }).then(resp => {
+        if (resp.ok) {
+          window.location.assign('/')
+        } else {
           self.isLoading = false
           self.$store.dispatch('alert', {
             style: 'red',
             icon: 'ui-2_square-remove-09',
-            msg: 'Error: ' + err.body.msg
+            msg: resp.msg
           })
+        }
+      }).catch(err => {
+        self.isLoading = false
+        self.$store.dispatch('alert', {
+          style: 'red',
+          icon: 'ui-2_square-remove-09',
+          msg: 'Error: ' + err.body.msg
         })
-      }
+      })
     }
   }
+}
 </script>

+ 20 - 20
client/js/components/modal-discard-page.vue

@@ -16,28 +16,28 @@
 </template>
 
 <script>
-  export default {
-    name: 'modal-discard-page',
-    props: ['mode', 'currentPath'],
-    data () {
-      return {}
-    },
-    computed: {
-      isShown () {
-        return this.$store.state.modalDiscardPage.shown
-      }
+export default {
+  name: 'modal-discard-page',
+  props: ['mode', 'currentPath'],
+  data () {
+    return {}
+  },
+  computed: {
+    isShown () {
+      return this.$store.state.modalDiscardPage.shown
+    }
+  },
+  methods: {
+    stay: function () {
+      this.$store.dispatch('modalDiscardPage/close')
     },
-    methods: {
-      stay: function () {
-        this.$store.dispatch('modalDiscardPage/close')
-      },
-      discard: function () {
-        if(this.mode === 'create') {
-          window.location.assign('/')
-        } else {
-          window.location.assign('/' + this.currentPath)
-        }
+    discard: function () {
+      if (this.mode === 'create') {
+        window.location.assign('/')
+      } else {
+        window.location.assign('/' + this.currentPath)
       }
     }
   }
+}
 </script>

+ 52 - 52
client/js/components/modal-move-page.vue

@@ -19,68 +19,68 @@
 </template>
 
 <script>
-  export default {
-    name: 'modal-move-page',
-    props: ['currentPath'],
-    data () {
-      return {
-        movePath: '',
-        isLoading: false,
-        isInvalid: false
+export default {
+  name: 'modal-move-page',
+  props: ['currentPath'],
+  data () {
+    return {
+      movePath: '',
+      isLoading: false,
+      isInvalid: false
+    }
+  },
+  computed: {
+    isShown () {
+      if (this.$store.state.modalMovePage.shown) {
+        this.movePath = this.currentPath
+        this.makeSelection()
       }
+      return this.$store.state.modalMovePage.shown
+    }
+  },
+  methods: {
+    makeSelection() {
+      let self = this
+      self._.delay(() => {
+        let startPos = (self._.includes(self.currentPath, '/')) ? self._.lastIndexOf(self.movePath, '/') + 1 : 0
+        self.$helpers.form.setInputSelection(self.$refs.movePageInput, startPos, self.movePath.length)
+      }, 100)
     },
-    computed: {
-      isShown () {
-        if(this.$store.state.modalMovePage.shown) {
-          this.movePath = this.currentPath
-          this.makeSelection()
-        }
-        return this.$store.state.modalMovePage.shown
-      }
+    cancel() {
+      this.$store.dispatch('modalMovePage/close')
     },
-    methods: {
-      makeSelection() {
-        let self = this;
-        self._.delay(() => {
-          let startPos = (self._.includes(self.currentPath, '/')) ? self._.lastIndexOf(self.movePath, '/') + 1 : 0
-          self.$helpers.form.setInputSelection(self.$refs.movePageInput, startPos, self.movePath.length)
-        }, 100)
-      },
-      cancel() {
-        this.$store.dispatch('modalMovePage/close')
-      },
-      move () {
-        this.isInvalid = false
-        let newDocPath = this.$helpers.pages.makeSafePath(this.movePath)
-        if (this._.isEmpty(newDocPath) || newDocPath === this.currentPath || newDocPath === 'home') {
-          this.isInvalid = true
-        } else {
-          this.isLoading = true
-          this.$http.put(window.location.href, {
-            move: newDocPath
-          }).then(resp => {
-            return resp.json()
-          }).then(resp => {
-            if (resp.ok) {
-              window.location.assign('/' + newDocPath)
-            } else {
-              this.loading = false
-              self.$store.dispatch('alert', {
-                style: 'red',
-                icon: 'ui-2_square-remove-09',
-                msg: resp.msg
-              })
-            }
-          }).catch(err => {
+    move () {
+      this.isInvalid = false
+      let newDocPath = this.$helpers.pages.makeSafePath(this.movePath)
+      if (this._.isEmpty(newDocPath) || newDocPath === this.currentPath || newDocPath === 'home') {
+        this.isInvalid = true
+      } else {
+        this.isLoading = true
+        this.$http.put(window.location.href, {
+          move: newDocPath
+        }).then(resp => {
+          return resp.json()
+        }).then(resp => {
+          if (resp.ok) {
+            window.location.assign('/' + newDocPath)
+          } else {
             this.loading = false
             self.$store.dispatch('alert', {
               style: 'red',
               icon: 'ui-2_square-remove-09',
-              msg: 'Error: ' + err.body.msg
+              msg: resp.msg
             })
+          }
+        }).catch(err => {
+          this.loading = false
+          self.$store.dispatch('alert', {
+            style: 'red',
+            icon: 'ui-2_square-remove-09',
+            msg: 'Error: ' + err.body.msg
           })
-        }
+        })
       }
     }
   }
+}
 </script>

+ 5 - 3
client/js/components/search.vue

@@ -18,6 +18,8 @@
 </template>
 
 <script>
+/* global siteRoot, socket, $ */
+
 export default {
   data() {
     return {
@@ -57,9 +59,9 @@ export default {
     },
     searchmoveidx: function (val, oldVal) {
       if (val > 0) {
-        this.searchmovekey = (this.searchmovearr[val - 1])
-          ? 'res.' + this.searchmovearr[val - 1].entryPath
-          : 'sug.' + this.searchmovearr[val - 1]
+        this.searchmovekey = (this.searchmovearr[val - 1]) ?
+          'res.' + this.searchmovearr[val - 1].entryPath :
+          'sug.' + this.searchmovearr[val - 1]
       } else {
         this.searchmovekey = ''
       }

+ 10 - 10
client/js/components/toggle.vue

@@ -6,16 +6,16 @@
 </template>
 
 <script>
-  export default {
-    name: 'toggle',
-    props: ['value', 'desc'],
-    data () {
-      return { }
-    },
-    methods: {
-      changeToggle() {
-        this.$emit('input', !this.value)
-      }
+export default {
+  name: 'toggle',
+  props: ['value', 'desc'],
+  data () {
+    return { }
+  },
+  methods: {
+    changeToggle() {
+      this.$emit('input', !this.value)
     }
   }
+}
 </script>

+ 59 - 57
client/js/components/tree.vue

@@ -15,68 +15,70 @@
 </template>
 
 <script>
-  export default {
-    name: 'tree',
-    data () {
-      return {
-        tree: []
-      }
-    },
-    methods: {
-      fetch (basePath) {
-        let self = this
-        self.$store.dispatch('startLoading')
-        self.$nextTick(() => {
-          socket.emit('treeFetch', { basePath }, (data) => {
-            if (self.tree.length > 0) {
-              let branch = self._.last(self.tree)
-              branch.hasChildren = true
-              self._.find(branch.pages, { _id: basePath }).isActive = true
-            }
-            self.tree.push({
-              hasChildren: false,
-              pages: data
-            })
-            self.$store.dispatch('stopLoading')
-          })
-        })
-      },
-      goto (entryPath) {
-        window.location.assign(siteRoot + '/' + entryPath)
-      },
-      unfold (entryPath) {
-        let self = this
-        let lastIndex = 0
-        self._.forEach(self.tree, branch => {
-          lastIndex++
-          if (self._.find(branch.pages, { _id: entryPath }) !== undefined) {
-            return false
+/* global socket, siteRoot */
+
+export default {
+  name: 'tree',
+  data () {
+    return {
+      tree: []
+    }
+  },
+  methods: {
+    fetch (basePath) {
+      let self = this
+      self.$store.dispatch('startLoading')
+      self.$nextTick(() => {
+        socket.emit('treeFetch', { basePath }, (data) => {
+          if (self.tree.length > 0) {
+            let branch = self._.last(self.tree)
+            branch.hasChildren = true
+            self._.find(branch.pages, { _id: basePath }).isActive = true
           }
+          self.tree.push({
+            hasChildren: false,
+            pages: data
+          })
+          self.$store.dispatch('stopLoading')
         })
-        self.tree = self._.slice(self.tree, 0, lastIndex)
-        let branch = self._.last(self.tree)
-        branch.hasChildren = false
-        branch.pages.forEach(page => {
-          page.isActive = false
-        })
-      },
-      mainAction (page) {
-        let self = this
-        if (page.isActive) {
-          self.unfold(page._id)
-        } else if (page.isDirectory) {
-          self.fetch(page._id)
-        } else {
-          self.goto(page._id)
+      })
+    },
+    goto (entryPath) {
+      window.location.assign(siteRoot + '/' + entryPath)
+    },
+    unfold (entryPath) {
+      let self = this
+      let lastIndex = 0
+      self._.forEach(self.tree, branch => {
+        lastIndex++
+        if (self._.find(branch.pages, { _id: entryPath }) !== undefined) {
+          return false
         }
-      }
+      })
+      self.tree = self._.slice(self.tree, 0, lastIndex)
+      let branch = self._.last(self.tree)
+      branch.hasChildren = false
+      branch.pages.forEach(page => {
+        page.isActive = false
+      })
     },
-    mounted () {
-      let basePath = window.location.pathname.slice(0, -4)
-      if (basePath.length > 1) {
-        basePath = basePath.slice(1)
+    mainAction (page) {
+      let self = this
+      if (page.isActive) {
+        self.unfold(page._id)
+      } else if (page.isDirectory) {
+        self.fetch(page._id)
+      } else {
+        self.goto(page._id)
       }
-      this.fetch(basePath)
     }
+  },
+  mounted () {
+    let basePath = window.location.pathname.slice(0, -4)
+    if (basePath.length > 1) {
+      basePath = basePath.slice(1)
+    }
+    this.fetch(basePath)
   }
+}
 </script>

+ 0 - 310
client/js/configure.js

@@ -1,310 +0,0 @@
-'use strict'
-
-/* global appconfig, runmode */
-
-import jQuery from 'jquery'
-import _ from 'lodash'
-import Vue from 'vue'
-import VeeValidate from 'vee-validate'
-import axios from 'axios'
-
-Vue.use(VeeValidate, {
-  enableAutoClasses: true,
-  classNames: {
-    touched: 'is-touched', // the control has been blurred
-    untouched: 'is-untouched', // the control hasn't been blurred
-    valid: 'is-valid', // model is valid
-    invalid: 'is-invalid', // model is invalid
-    pristine: 'is-pristine', // control has not been interacted with
-    dirty: 'is-dirty' // control has been interacted with
-  }
-})
-
-jQuery(document).ready(function ($) {
-  new Vue({ // eslint-disable-line no-new
-    el: 'main',
-    data: {
-      loading: false,
-      state: 'welcome',
-      syscheck: {
-        ok: false,
-        error: '',
-        results: []
-      },
-      dbcheck: {
-        ok: false,
-        error: ''
-      },
-      gitcheck: {
-        ok: false,
-        error: ''
-      },
-      final: {
-        ok: false,
-        error: '',
-        results: []
-      },
-      conf: {
-        title: appconfig.title || 'Wiki',
-        host: appconfig.host || 'http://',
-        port: appconfig.port || 80,
-        lang: appconfig.lang || 'en',
-        public: (appconfig.public === true),
-        db: appconfig.db || 'mongodb://localhost:27017/wiki',
-        pathData: './data',
-        pathRepo: './repo',
-        gitUseRemote: (appconfig.git !== false),
-        gitUrl: '',
-        gitBranch: 'master',
-        gitAuthType: 'ssh',
-        gitAuthSSHKey: '',
-        gitAuthUser: '',
-        gitAuthPass: '',
-        gitAuthSSL: true,
-        gitShowUserEmail: true,
-        gitServerEmail: '',
-        adminEmail: '',
-        adminPassword: '',
-        adminPasswordConfirm: ''
-      },
-      considerations: {
-        https: false,
-        port: false,
-        localhost: false
-      }
-    },
-    computed: {
-      currentProgress: function () {
-        let perc = '0%'
-        switch (this.state) {
-          case 'welcome':
-            perc = '0%'
-            break
-          case 'syscheck':
-            perc = (this.syscheck.ok) ? '15%' : '5%'
-            break
-          case 'general':
-            perc = '20%'
-            break
-          case 'considerations':
-            perc = '30%'
-            break
-          case 'db':
-            perc = '35%'
-            break
-          case 'dbcheck':
-            perc = (this.dbcheck.ok) ? '50%' : '40%'
-            break
-          case 'paths':
-            perc = '55%'
-            break
-          case 'git':
-            perc = '60%'
-            break
-          case 'gitcheck':
-            perc = (this.gitcheck.ok) ? '75%' : '65%'
-            break
-          case 'admin':
-            perc = '80%'
-            break
-        }
-        return perc
-      }
-    },
-    mounted: function () {
-      if (appconfig.paths) {
-        this.conf.pathData = appconfig.paths.data || './data'
-        this.conf.pathRepo = appconfig.paths.repo || './repo'
-      }
-      if (appconfig.git !== false && _.isPlainObject(appconfig.git)) {
-        this.conf.gitUrl = appconfig.git.url || ''
-        this.conf.gitBranch = appconfig.git.branch || 'master'
-        this.conf.gitShowUserEmail = (appconfig.git.showUserEmail !== false)
-        this.conf.gitServerEmail = appconfig.git.serverEmail || ''
-        if (_.isPlainObject(appconfig.git.auth)) {
-          this.conf.gitAuthType = appconfig.git.auth.type || 'ssh'
-          this.conf.gitAuthSSHKey = appconfig.git.auth.privateKey || ''
-          this.conf.gitAuthUser = appconfig.git.auth.username || ''
-          this.conf.gitAuthPass = appconfig.git.auth.password || ''
-          this.conf.gitAuthSSL = (appconfig.git.auth.sslVerify !== false)
-        }
-      }
-    },
-    methods: {
-      proceedToWelcome: function (ev) {
-        this.state = 'welcome'
-        this.loading = false
-      },
-      proceedToSyscheck: function (ev) {
-        let self = this
-        this.state = 'syscheck'
-        this.loading = true
-        self.syscheck = {
-          ok: false,
-          error: '',
-          results: []
-        }
-
-        _.delay(() => {
-          axios.post('/syscheck').then(resp => {
-            if (resp.data.ok === true) {
-              self.syscheck.ok = true
-              self.syscheck.results = resp.data.results
-            } else {
-              self.syscheck.ok = false
-              self.syscheck.error = resp.data.error
-            }
-            self.loading = false
-            self.$nextTick()
-          }).catch(err => {
-            window.alert(err.message)
-          })
-        }, 1000)
-      },
-      proceedToGeneral: function (ev) {
-        let self = this
-        self.state = 'general'
-        self.loading = false
-        self.$nextTick(() => {
-          self.$validator.validateAll('general')
-        })
-      },
-      proceedToConsiderations: function (ev) {
-        this.considerations = {
-          https: !_.startsWith(this.conf.host, 'https'),
-          port: false, // TODO
-          localhost: _.includes(this.conf.host, 'localhost')
-        }
-        this.state = 'considerations'
-        this.loading = false
-      },
-      proceedToDb: function (ev) {
-        let self = this
-        if (runmode.staticMongo) {
-          return self.proceedToDbcheck()
-        }
-        self.state = 'db'
-        self.loading = false
-        self.$nextTick(() => {
-          self.$validator.validateAll('db')
-        })
-      },
-      proceedToDbcheck: function (ev) {
-        let self = this
-        this.state = 'dbcheck'
-        this.loading = true
-        self.dbcheck = {
-          ok: false,
-          error: ''
-        }
-
-        _.delay(() => {
-          axios.post('/dbcheck', {
-            db: self.conf.db
-          }).then(resp => {
-            if (resp.data.ok === true) {
-              self.dbcheck.ok = true
-            } else {
-              self.dbcheck.ok = false
-              self.dbcheck.error = resp.data.error
-            }
-            self.loading = false
-            self.$nextTick()
-          }).catch(err => {
-            window.alert(err.message)
-          })
-        }, 1000)
-      },
-      proceedToPaths: function (ev) {
-        let self = this
-        self.state = 'paths'
-        self.loading = false
-        self.$nextTick(() => {
-          self.$validator.validateAll('paths')
-        })
-      },
-      proceedToGit: function (ev) {
-        let self = this
-        self.state = 'git'
-        self.loading = false
-        self.$nextTick(() => {
-          self.$validator.validateAll('git')
-        })
-      },
-      proceedToGitCheck: function (ev) {
-        let self = this
-        this.state = 'gitcheck'
-        this.loading = true
-        self.gitcheck = {
-          ok: false,
-          results: [],
-          error: ''
-        }
-
-        _.delay(() => {
-          axios.post('/gitcheck', self.conf).then(resp => {
-            if (resp.data.ok === true) {
-              self.gitcheck.ok = true
-              self.gitcheck.results = resp.data.results
-            } else {
-              self.gitcheck.ok = false
-              self.gitcheck.error = resp.data.error
-            }
-            self.loading = false
-            self.$nextTick()
-          }).catch(err => {
-            window.alert(err.message)
-          })
-        }, 1000)
-      },
-      proceedToAdmin: function (ev) {
-        let self = this
-        self.state = 'admin'
-        self.loading = false
-        self.$nextTick(() => {
-          self.$validator.validateAll('admin')
-        })
-      },
-      proceedToFinal: function (ev) {
-        let self = this
-        self.state = 'final'
-        self.loading = true
-        self.final = {
-          ok: false,
-          error: '',
-          results: []
-        }
-
-        _.delay(() => {
-          axios.post('/finalize', self.conf).then(resp => {
-            if (resp.data.ok === true) {
-              self.final.ok = true
-              self.final.results = resp.data.results
-            } else {
-              self.final.ok = false
-              self.final.error = resp.data.error
-            }
-            self.loading = false
-            self.$nextTick()
-          }).catch(err => {
-            window.alert(err.message)
-          })
-        }, 1000)
-      },
-      finish: function (ev) {
-        let self = this
-        self.state = 'restart'
-
-        _.delay(() => {
-          axios.post('/restart', {}).then(resp => {
-            _.delay(() => {
-              window.location.assign(self.conf.host)
-            }, 30000)
-          }).catch(err => {
-            window.alert(err.message)
-          })
-        }, 1000)
-      }
-    }
-  })
-})

+ 1 - 1
client/js/store/modules/editor-codeblock.js

@@ -1,4 +1,4 @@
-'use strict'
+/* global wikijs */
 
 export default {
   namespaced: true,

+ 1 - 1
client/js/store/modules/editor-file.js

@@ -1,4 +1,4 @@
-'use strict'
+/* global wikijs */
 
 export default {
   namespaced: true,

+ 1 - 1
client/js/store/modules/editor-video.js

@@ -1,4 +1,4 @@
-'use strict'
+/* global wikijs */
 
 export default {
   namespaced: true,

+ 1 - 1
client/js/store/modules/editor.js

@@ -1,4 +1,4 @@
-'use strict'
+/* global wikijs */
 
 export default {
   namespaced: true,

+ 0 - 2
client/js/store/modules/modal-create-page.js

@@ -1,5 +1,3 @@
-'use strict'
-
 export default {
   namespaced: true,
   state: {

+ 1 - 1
client/js/store/modules/modal-create-user.js

@@ -1,4 +1,4 @@
-'use strict'
+/* global wikijs */
 
 export default {
   namespaced: true,

+ 0 - 2
client/js/store/modules/modal-delete-user.js

@@ -1,5 +1,3 @@
-'use strict'
-
 export default {
   namespaced: true,
   state: {

+ 0 - 2
client/js/store/modules/modal-discard-page.js

@@ -1,5 +1,3 @@
-'use strict'
-
 export default {
   namespaced: true,
   state: {

+ 0 - 2
client/js/store/modules/modal-move-page.js

@@ -1,5 +1,3 @@
-'use strict'
-
 export default {
   namespaced: true,
   state: {

+ 0 - 2
client/js/store/modules/modal-profile-2fa.js

@@ -1,5 +1,3 @@
-'use strict'
-
 export default {
   namespaced: true,
   state: {

+ 0 - 2
client/js/store/modules/modal-upgrade-system.js

@@ -1,5 +1,3 @@
-'use strict'
-
 export default {
   namespaced: true,
   state: {

+ 0 - 2
client/js/store/modules/page-loader.js

@@ -1,5 +1,3 @@
-'use strict'
-
 export default {
   namespaced: true,
   state: {

+ 2 - 1
package.json

@@ -9,7 +9,7 @@
     "restart": "node wiki restart",
     "build": "node tools/fuse",
     "dev": "node tools/fuse -d",
-    "test": "jest"
+    "test": "eslint --ext .js,.vue . && jest"
   },
   "bin": {
     "wiki": "wiki.js"
@@ -149,6 +149,7 @@
     "eslint-plugin-node": "5.2.1",
     "eslint-plugin-promise": "3.6.0",
     "eslint-plugin-standard": "3.0.1",
+    "eslint-plugin-vue": "3.13.1",
     "fuse-box": "2.4.0",
     "graphql-tag": "^2.5.0",
     "i18next-xhr-backend": "1.4.3",

+ 1 - 1
server/helpers/entry.js

@@ -1,4 +1,4 @@
-'use strict'
+/* global appdata, ROOTPATH */
 
 const crypto = require('crypto')
 const path = require('path')

+ 1 - 1
server/middlewares/auth.js

@@ -1,6 +1,6 @@
 'use strict'
 
-/* global appdata, rights */
+/* global rights */
 
 /**
  * Authentication middleware

+ 1 - 1
server/models/user.js

@@ -1,4 +1,4 @@
-/* global wiki */
+/* global wiki, appconfig */
 
 const Promise = require('bluebird')
 const bcrypt = require('bcryptjs-then')

+ 41 - 43
server/modules/documents.js

@@ -1,5 +1,3 @@
-'use strict'
-
 /* global wiki */
 
 const Promise = require('bluebird')
@@ -78,7 +76,7 @@ module.exports = {
         return fs.readFileAsync(cpath).then((contents) => {
           return JSON.parse(contents)
         }).catch((err) => { // eslint-disable-line handle-callback-err
-          winston.error('Corrupted cache file. Deleting it...')
+          wiki.logger.error('Corrupted cache file. Deleting it...')
           fs.unlinkSync(cpath)
           return false
         })
@@ -115,7 +113,7 @@ module.exports = {
     return fs.statAsync(fpath).then((st) => {
       if (st.isFile()) {
         return fs.readFileAsync(fpath, 'utf8').then((contents) => {
-          let htmlProcessor = (options.parseMarkdown) ? mark.parseContent(contents) : Promise.resolve('')
+          let htmlProcessor = (options.parseMarkdown) ? wiki.mark.parseContent(contents) : Promise.resolve('')
 
           // Parse contents
 
@@ -123,8 +121,8 @@ module.exports = {
             let pageData = {
               markdown: (options.includeMarkdown) ? contents : '',
               html,
-              meta: (options.parseMeta) ? mark.parseMeta(contents) : {},
-              tree: (options.parseTree) ? mark.parseTree(contents) : []
+              meta: (options.parseMeta) ? wiki.mark.parseMeta(contents) : {},
+              tree: (options.parseTree) ? wiki.mark.parseTree(contents) : []
             }
 
             if (!pageData.meta.title) {
@@ -147,8 +145,8 @@ module.exports = {
               if (options.cache) {
                 let cacheData = JSON.stringify(_.pick(pageData, ['html', 'meta', 'tree', 'parent']), false, false, false)
                 return fs.writeFileAsync(cpath, cacheData).catch((err) => {
-                  winston.error('Unable to write to cache! Performance may be affected.')
-                  winston.error(err)
+                  wiki.logger.error('Unable to write to cache! Performance may be affected.')
+                  wiki.logger.error(err)
                   return true
                 })
               } else {
@@ -161,7 +159,7 @@ module.exports = {
         return false
       }
     }).catch((err) => { // eslint-disable-line handle-callback-err
-      throw new Promise.OperationalError(lang.t('errors:notexist', { path: entryPath }))
+      throw new Promise.OperationalError(wiki.lang.t('errors:notexist', { path: entryPath }))
     })
   },
 
@@ -181,7 +179,7 @@ module.exports = {
       return fs.statAsync(fpath).then((st) => {
         if (st.isFile()) {
           return fs.readFileAsync(fpath, 'utf8').then((contents) => {
-            let pageMeta = mark.parseMeta(contents)
+            let pageMeta = wiki.mark.parseMeta(contents)
 
             return {
               path: parentPath,
@@ -190,11 +188,11 @@ module.exports = {
             }
           })
         } else {
-          return Promise.reject(new Error(lang.t('errors:parentinvalid')))
+          return Promise.reject(new Error(wiki.lang.t('errors:parentinvalid')))
         }
       })
     } else {
-      return Promise.reject(new Error(lang.t('errors:parentisroot')))
+      return Promise.reject(new Error(wiki.lang.t('errors:parentisroot')))
     }
   },
 
@@ -214,15 +212,15 @@ module.exports = {
       if (st.isFile()) {
         return self.makePersistent(entryPath, contents, author).then(() => {
           return self.updateCache(entryPath).then(entry => {
-            return search.add(entry)
+            return wiki.search.add(entry)
           })
         })
       } else {
-        return Promise.reject(new Error(lang.t('errors:notexist', { path: entryPath })))
+        return Promise.reject(new Error(wiki.lang.t('errors:notexist', { path: entryPath })))
       }
     }).catch((err) => {
-      winston.error(err)
-      return Promise.reject(new Error(lang.t('errors:savefailed')))
+      wiki.logger.error(err)
+      return Promise.reject(new Error(wiki.lang.t('errors:savefailed')))
     })
   },
 
@@ -243,21 +241,21 @@ module.exports = {
       includeParentInfo: true,
       cache: true
     }).catch(err => {
-      winston.error(err)
+      wiki.logger.error(err)
       return err
     }).then((pageData) => {
       return {
         entryPath,
         meta: pageData.meta,
         parent: pageData.parent || {},
-        text: mark.removeMarkdown(pageData.markdown)
+        text: wiki.mark.removeMarkdown(pageData.markdown)
       }
     }).catch(err => {
-      winston.error(err)
+      wiki.logger.error(err)
       return err
     }).then((content) => {
       let parentPath = _.chain(content.entryPath).split('/').initial().join('/').value()
-      return db.Entry.findOneAndUpdate({
+      return wiki.db.Entry.findOneAndUpdate({
         _id: content.entryPath
       }, {
         _id: content.entryPath,
@@ -280,7 +278,7 @@ module.exports = {
         return result
       })
     }).catch(err => {
-      winston.error(err)
+      wiki.logger.error(err)
       return err
     })
   },
@@ -291,12 +289,12 @@ module.exports = {
    * @returns {Promise<Boolean>} Promise of the operation
    */
   updateTreeInfo() {
-    return db.Entry.distinct('parentPath', { parentPath: { $ne: '' } }).then(allPaths => {
+    return wiki.db.Entry.distinct('parentPath', { parentPath: { $ne: '' } }).then(allPaths => {
       if (allPaths.length > 0) {
         return Promise.map(allPaths, pathItem => {
           let parentPath = _.chain(pathItem).split('/').initial().join('/').value()
           let guessedTitle = _.chain(pathItem).split('/').last().startCase().value()
-          return db.Entry.update({ _id: pathItem }, {
+          return wiki.db.Entry.update({ _id: pathItem }, {
             $set: { isDirectory: true },
             $setOnInsert: { isEntry: false, title: guessedTitle, parentPath }
           }, { upsert: true })
@@ -322,15 +320,15 @@ module.exports = {
       if (!docExists) {
         return self.makePersistent(entryPath, contents, author).then(() => {
           return self.updateCache(entryPath).then(entry => {
-            return search.add(entry)
+            return wiki.search.add(entry)
           })
         })
       } else {
-        return Promise.reject(new Error(lang.t('errors:alreadyexists')))
+        return Promise.reject(new Error(wiki.lang.t('errors:alreadyexists')))
       }
     }).catch((err) => {
-      winston.error(err)
-      return Promise.reject(new Error(lang.t('errors:generic')))
+      wiki.logger.error(err)
+      return Promise.reject(new Error(wiki.lang.t('errors:generic')))
     })
   },
 
@@ -346,7 +344,7 @@ module.exports = {
     let fpath = entryHelper.getFullPath(entryPath)
 
     return fs.outputFileAsync(fpath, contents).then(() => {
-      return git.commitDocument(entryPath, author)
+      return wiki.git.commitDocument(entryPath, author)
     })
   },
 
@@ -362,11 +360,11 @@ module.exports = {
     let self = this
 
     if (_.isEmpty(entryPath) || entryPath === 'home') {
-      return Promise.reject(new Error(lang.t('errors:invalidpath')))
+      return Promise.reject(new Error(wiki.lang.t('errors:invalidpath')))
     }
 
-    return git.moveDocument(entryPath, newEntryPath).then(() => {
-      return git.commitDocument(newEntryPath, author).then(() => {
+    return wiki.git.moveDocument(entryPath, newEntryPath).then(() => {
+      return wiki.git.commitDocument(newEntryPath, author).then(() => {
         // Delete old cache version
 
         let oldEntryCachePath = entryHelper.getCachePath(entryPath)
@@ -374,14 +372,14 @@ module.exports = {
 
         // Delete old index entry
 
-        search.delete(entryPath)
+        wiki.search.delete(entryPath)
 
         // Create cache for new entry
 
         return Promise.join(
-          db.Entry.deleteOne({ _id: entryPath }),
+          wiki.db.Entry.deleteOne({ _id: entryPath }),
           self.updateCache(newEntryPath).then(entry => {
-            return search.add(entry)
+            return wiki.search.add(entry)
           })
         )
       })
@@ -397,20 +395,20 @@ module.exports = {
    */
   remove(entryPath, author) {
     if (_.isEmpty(entryPath) || entryPath === 'home') {
-      return Promise.reject(new Error(lang.t('errors:invalidpath')))
+      return Promise.reject(new Error(wiki.lang.t('errors:invalidpath')))
     }
 
-    return git.deleteDocument(entryPath, author).then(() => {
+    return wiki.git.deleteDocument(entryPath, author).then(() => {
       // Delete old cache version
 
       let oldEntryCachePath = entryHelper.getCachePath(entryPath)
       fs.unlinkAsync(oldEntryCachePath).catch((err) => { return true }) // eslint-disable-line handle-callback-err
 
       // Delete old index entry
-      search.delete(entryPath)
+      wiki.search.delete(entryPath)
 
       // Delete entry
-      return db.Entry.deleteOne({ _id: entryPath })
+      return wiki.db.Entry.deleteOne({ _id: entryPath })
     })
   },
 
@@ -423,7 +421,7 @@ module.exports = {
   getStarter(entryPath) {
     let formattedTitle = _.startCase(_.last(_.split(entryPath, '/')))
 
-    return fs.readFileAsync(path.join(SERVERPATH, 'app/content/create.md'), 'utf8').then((contents) => {
+    return fs.readFileAsync(path.join(wiki.SERVERPATH, 'app/content/create.md'), 'utf8').then((contents) => {
       return _.replace(contents, new RegExp('{TITLE}', 'g'), formattedTitle)
     })
   },
@@ -436,17 +434,17 @@ module.exports = {
    * @return {Promise<Array>} List of entries
    */
   getFromTree(basePath, usr) {
-    return db.Entry.find({ parentPath: basePath }, 'title parentPath isDirectory isEntry').sort({ title: 'asc' }).then(results => {
+    return wiki.db.Entry.find({ parentPath: basePath }, 'title parentPath isDirectory isEntry').sort({ title: 'asc' }).then(results => {
       return _.filter(results, r => {
-        return rights.checkRole('/' + r._id, usr.rights, 'read')
+        return wiki.rights.checkRole('/' + r._id, usr.rights, 'read')
       })
     })
   },
 
   getHistory(entryPath) {
-    return db.Entry.findOne({ _id: entryPath, isEntry: true }).then(entry => {
+    return wiki.db.Entry.findOne({ _id: entryPath, isEntry: true }).then(entry => {
       if (!entry) { return false }
-      return git.getHistory(entryPath).then(history => {
+      return wiki.git.getHistory(entryPath).then(history => {
         return {
           meta: entry,
           history

+ 1 - 4
server/modules/markdown.js

@@ -1,5 +1,3 @@
-'use strict'
-
 /* global wiki */
 
 const Promise = require('bluebird')
@@ -58,8 +56,7 @@ var mkdown = md({
   })
   .use(mdAttrs)
 
-// if (wiki.config.features.mathjax) {
-if (true) {
+if (wiki.config.features.mathjax) {
   mkdown.use(mdMathjax)
 }
 

+ 2 - 2
server/modules/search.js

@@ -5,7 +5,7 @@
 const Promise = require('bluebird')
 const _ = require('lodash')
 // const searchIndex = require('./search-index')
-const stopWord = require('stopword')
+// const stopWord = require('stopword')
 const streamToPromise = require('stream-to-promise')
 const searchAllowedChars = new RegExp('[^a-z0-9' + wiki.data.regex.cjk + wiki.data.regex.arabic + ' ]', 'g')
 
@@ -22,7 +22,7 @@ module.exports = {
   init () {
     let self = this
     self._isReady = new Promise((resolve, reject) => {
-      /*searchIndex({
+      /* searchIndex({
         deletable: true,
         fieldedSearch: true,
         indexPath: 'wiki',

+ 1 - 1
server/modules/system.js

@@ -1,6 +1,6 @@
 'use strict'
 
-/* global winston */
+/* global winston, ROOTPATH, appconfig */
 
 const Promise = require('bluebird')
 const crypto = require('crypto')

+ 12 - 12
server/views/configure/index.pug

@@ -26,7 +26,7 @@ block body
                   .panel-content.form-sections
                     section
                       p
-                        svg.icons.is-18.is-outlined.has-right-pad.is-text: use(xlink:href="#nc-cd-reader")
+                        svg.icons.is-18.is-outlined.has-right-pad.is-text: use(xlink:href='#nc-cd-reader')
                         span You are about to install Wiki.js #[strong= packageObj.version].
                     section
                       p.control.is-fullwidth
@@ -51,14 +51,14 @@ block body
                     span System Check
                     i(v-if='loading')
                   .panel-content.is-text
-                    p(v-if='loading') #[svg.icons.is-24.is-text: use(xlink:href="#nc-ms-dots")] Checking your system for compatibility...
+                    p(v-if='loading') #[svg.icons.is-24.is-text: use(xlink:href='#nc-ms-dots')] Checking your system for compatibility...
                     p(v-if='!loading && syscheck.ok')
                       ul
-                        li(v-for='rs in syscheck.results') #[svg.icons.is-18.is-text: use(xlink:href="#nc-check-bold")] {{rs}}
+                        li(v-for='rs in syscheck.results') #[svg.icons.is-18.is-text: use(xlink:href='#nc-check-bold')] {{rs}}
                     p(v-if='!loading && syscheck.ok')
-                      svg.icons.is-18.is-text: use(xlink:href="#nc-check-bold")
+                      svg.icons.is-18.is-text: use(xlink:href='#nc-check-bold')
                       strong  Looks good! No issues so far.
-                    p(v-if='!loading && !syscheck.ok') #[svg.icons.is-18.is-text: use(xlink:href="#nc-square-remove-12")] Error: {{ syscheck.error }}
+                    p(v-if='!loading && !syscheck.ok') #[svg.icons.is-18.is-text: use(xlink:href='#nc-square-remove-12')] Error: {{ syscheck.error }}
                   .panel-footer
                     .progress-bar: div(v-bind:style='{width: currentProgress}')
                     button.button.is-small.is-light-blue.is-outlined(v-on:click='proceedToWelcome', v-bind:disabled='loading') Back
@@ -218,14 +218,14 @@ block body
                     span Git Repository Check
                     i(v-if='loading')
                   .panel-content.is-text
-                    p(v-if='loading') #[svg.icons.is-24.is-text: use(xlink:href="#nc-ms-dots")] Verifying Git repository settings...
+                    p(v-if='loading') #[svg.icons.is-24.is-text: use(xlink:href='#nc-ms-dots')] Verifying Git repository settings...
                     p(v-if='!loading && gitcheck.ok')
                       ul
-                        li(v-for='rs in gitcheck.results') #[svg.icons.is-18.is-text: use(xlink:href="#nc-check-bold")] {{rs}}
+                        li(v-for='rs in gitcheck.results') #[svg.icons.is-18.is-text: use(xlink:href='#nc-check-bold')] {{rs}}
                     p(v-if='!loading && gitcheck.ok')
-                      svg.icons.is-18.is-text: use(xlink:href="#nc-check-bold")
+                      svg.icons.is-18.is-text: use(xlink:href='#nc-check-bold')
                       strong  Git settings are correct!
-                    p(v-if='!loading && !gitcheck.ok') #[svg.icons.is-18.is-text: use(xlink:href="#nc-square-remove-12")] Error: {{ gitcheck.error }}
+                    p(v-if='!loading && !gitcheck.ok') #[svg.icons.is-18.is-text: use(xlink:href='#nc-square-remove-12')] Error: {{ gitcheck.error }}
                   .panel-footer
                     .progress-bar: div(v-bind:style='{width: currentProgress}')
                     button.button.is-small.is-light-blue.is-outlined(v-on:click='proceedToGit', v-bind:disabled='loading') Back
@@ -280,11 +280,11 @@ block body
                     section
                       p.control.is-fullwidth
                         label.label Connection String to Wiki.js 1.x MongoDB database
-                        input(type='text', placeholder='mongodb://', v-model='conf.mongo', data-vv-scope='mongo', name='ipt-mongo', v-validate='{ required: true, min: 2 }')
+                        input(type='text', placeholder='mongodb://', v-model='conf.mongo', data-vv-scope='upgrade', name='ipt-mongo', v-validate='{ required: true, min: 2 }')
                         span.desc A MongoDB database connection string where a Wiki.js 1.x installation is located. #[strong No alterations will be made to this database. ]
                     section
                       p.control.is-fullwidth
-                        input#ipt-public(type='checkbox', v-model='conf.public', data-vv-scope='general', name='ipt-public')
+                        input#ipt-public(type='checkbox', v-model='conf.public', data-vv-scope='upgrade', name='ipt-public')
                         label.label(for='ipt-public') Create groups based on individual permissions
                         span.desc User groups will be created based on existing users permissions. If multiple users have the exact same permission rules, they will be put in the same user group.
                   .panel-footer
@@ -332,4 +332,4 @@ block body
           
           .footer
             small Wiki.js Installation Wizard
-            small(v-if='conf.telemetry') Telemetry Client ID: !{telemetryClientID}
+            small(v-if='conf.telemetry') Telemetry Client ID: !{telemetryClientID}

+ 6 - 6
test/lint.js

@@ -59,12 +59,12 @@ expect.extend({
 })
 
 describe('Code Linting', () => {
-  it('should pass ESLint validation', () => {
-    const CLIEngine = require('eslint').CLIEngine
-    const cli = new CLIEngine()
-    let report = cli.executeOnFiles(['**/*.js'])
-    expect(report).toESLint()
-  })
+  // it('should pass ESLint validation', () => {
+  //   const CLIEngine = require('eslint').CLIEngine
+  //   const cli = new CLIEngine()
+  //   let report = cli.executeOnFiles(['**/*.js', '**/*.vue'])
+  //   expect(report).toESLint()
+  // })
 
   it('should pass PugLint validation', () => {
     const PugLint = require('pug-lint')

+ 0 - 3
tools/fuse_tasks.js

@@ -1,6 +1,3 @@
-'use strict'
-
-const _ = require('lodash')
 const Promise = require('bluebird')
 const colors = require('colors/safe')
 const fs = Promise.promisifyAll(require('fs-extra'))

+ 22 - 1
yarn.lock

@@ -2575,6 +2575,13 @@ eslint-plugin-standard@3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2"
 
+eslint-plugin-vue@3.13.1:
+  version "3.13.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-3.13.1.tgz#875dc47a90c2e4034013b6ce1b915e5a5c6e9bf9"
+  dependencies:
+    requireindex "^1.1.0"
+    vue-eslint-parser "^2.0.1-beta.1"
+
 eslint-scope@^3.7.1:
   version "3.7.1"
   resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
@@ -2624,7 +2631,7 @@ eslint@4.10.0:
     table "^4.0.1"
     text-table "~0.2.0"
 
-espree@^3.5.1:
+espree@^3.3.2, espree@^3.5.1:
   version "3.5.1"
   resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.1.tgz#0c988b8ab46db53100a1954ae4ba995ddd27d87e"
   dependencies:
@@ -6727,6 +6734,10 @@ require_optional@~1.0.0:
     resolve-from "^2.0.0"
     semver "^5.1.0"
 
+requireindex@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162"
+
 resolve-from@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
@@ -7799,6 +7810,16 @@ vue-clipboards@1.1.0:
   dependencies:
     clipboard "^1.7.1"
 
+vue-eslint-parser@^2.0.1-beta.1:
+  version "2.0.1-beta.1"
+  resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-2.0.1-beta.1.tgz#7e1b3c0865905264605169497fe9e42d27c1ae60"
+  dependencies:
+    debug "^3.0.0"
+    eslint-scope "^3.7.1"
+    espree "^3.3.2"
+    esquery "^1.0.0"
+    lodash "^4.17.4"
+
 vue-hot-reload-api@2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.2.0.tgz#9a21b35ced3634434a43ee80efb7350ea8fb206d"