fix: eslint for vue components

This commit is contained in:
NGPixel 2017-10-29 21:36:05 -04:00
parent 72e3bacc2e
commit 98d311145b
45 changed files with 953 additions and 1253 deletions

View File

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

12
.eslintrc.yml Normal file
View File

@ -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

View File

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

View File

@ -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>

View File

@ -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')
},
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()
}
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()
}
}
}
</script>

View File

@ -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>

View File

@ -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: '',
gitAuthPass: '',
gitAuthSSL: true,
gitShowUserEmail: true,
gitServerEmail: '',
mongo: 'mongodb://',
adminEmail: '',
adminPassword: '',
adminPasswordConfirm: ''
adminPasswordConfirm: '',
gitAuthPass: '',
gitAuthSSHKey: '',
gitAuthSSL: true,
gitAuthType: 'ssh',
gitAuthUser: '',
gitBranch: 'master',
gitServerEmail: '',
gitShowUserEmail: true,
gitUrl: '',
gitUseRemote: (siteConfig.git !== false),
lang: siteConfig.lang || 'en',
mongo: 'mongodb://',
path: siteConfig.path || '/',
pathRepo: './repo',
port: siteConfig.port || 80,
public: (siteConfig.public === true),
telemetry: true,
title: siteConfig.title || 'Wiki',
upgrade: false
},
considerations: {
https: false,

View File

@ -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)

View File

@ -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
// -------------------------------------------
// -------------------------------------------
// 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)
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 = ''
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 + '")'
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.$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
}
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 })
})
})
this.cancel()
},
})
},
// -------------------------------------------
// NEW FOLDER
// -------------------------------------------
// -------------------------------------------
// FETCH FROM URL
// -------------------------------------------
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))
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
if (this._.isEmpty(this.newFolderName) || !regFolderName.test(this.newFolderName)) {
this.newFolderError = true
return
}
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 = []
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: '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
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
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 })
})
}
})
})
},
// -------------------------------------------
// 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: '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 })
})
}
})
})
},
// -------------------------------------------
// DELETE FILE
// -------------------------------------------
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')
})
})
})
},
// -------------------------------------------
// LOAD FROM REMOTE
// -------------------------------------------
selectFolder(fldName) {
this.currentFolder = fldName
this.loadFiles()
},
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()
})
})
},
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)
})
})
})
},
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)
}
})
})
},
// -------------------------------------------
// 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()
}
},
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
self.$store.dispatch('alert', {
style: 'blue',
icon: 'arrows-1_cloud-upload-96',
msg: self.$t('editor.fileuploadsuccess')
})
}
} else {
self.$store.dispatch('alert', {
style: 'red',
icon: 'ui-2_square-remove-09',
msg: self.$t('editor.fileuploaderror', { err: data.msg })
})
}
},
error: (error) => {
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 {
// -------------------------------------------
// 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 })
})
}
})
})
},
// -------------------------------------------
// 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: '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 })
})
}
})
})
},
// -------------------------------------------
// DELETE FILE
// -------------------------------------------
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')
})
})
})
},
// -------------------------------------------
// LOAD FROM REMOTE
// -------------------------------------------
selectFolder(fldName) {
this.currentFolder = fldName
this.loadFiles()
},
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()
})
})
},
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)
})
})
}
})
},
mounted() {
this.$root.$on('editorFile/init', this.init)
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)
}
})
})
},
// -------------------------------------------
// 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()
}
},
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
self.$store.dispatch('alert', {
style: 'blue',
icon: 'arrows-1_cloud-upload-96',
msg: self.$t('editor.fileuploadsuccess')
})
}
} else {
self.$store.dispatch('alert', {
style: 'red',
icon: 'ui-2_square-remove-09',
msg: self.$t('editor.fileuploaderror', { err: data.msg })
})
}
},
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)
}
}
</script>

View File

@ -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
}
},
computed: {
isShown () {
return this.$store.state.editorVideo.shown
}
},
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
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()
}
},
mounted () {
this.$root.$on('editorVideo/init', this.init)
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)
},
cancel () {
this.$store.dispatch('editorVideo/close')
},
insertVideo () {
let self = this
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()
}
},
mounted () {
this.$root.$on('editorVideo/init', this.init)
}
}
</script>

View File

@ -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 => {

View File

@ -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>

View File

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

View File

@ -18,50 +18,50 @@
</template>
<script>
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)
},
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)
}
}
},
mounted () {
this.currentPath = (this.basepath === 'home') ? '' : this.basepath
this.userPath = (this._.isEmpty(this.currentPath)) ? 'new-page' : this.currentPath + '/new-page'
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)
},
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)
}
}
},
mounted () {
this.currentPath = (this.basepath === 'home') ? '' : this.basepath
this.userPath = (this._.isEmpty(this.currentPath)) ? 'new-page' : this.currentPath + '/new-page'
}
}
</script>

View File

@ -18,49 +18,49 @@
</template>
<script>
export default {
name: 'modal-delete-page',
props: ['currentPath'],
data () {
return {
isLoading: false
}
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')
},
computed: {
isShown () {
return this.$store.state.modalDeletePage.shown
}
},
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>

View File

@ -16,28 +16,28 @@
</template>
<script>
export default {
name: 'modal-discard-page',
props: ['mode', 'currentPath'],
data () {
return {}
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')
},
computed: {
isShown () {
return this.$store.state.modalDiscardPage.shown
}
},
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>

View File

@ -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>

View File

@ -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 = ''
}

View File

@ -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>

View File

@ -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
}
})
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)
}
}
},
mounted () {
let basePath = window.location.pathname.slice(0, -4)
if (basePath.length > 1) {
basePath = basePath.slice(1)
}
this.fetch(basePath)
/* 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')
})
})
},
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
})
},
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)
}
}
},
mounted () {
let basePath = window.location.pathname.slice(0, -4)
if (basePath.length > 1) {
basePath = basePath.slice(1)
}
this.fetch(basePath)
}
}
</script>

View File

@ -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)
}
}
})
})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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",

View File

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

View File

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

View File

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

View File

@ -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

View File

@ -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)
}

View File

@ -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',

View File

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

View File

@ -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}

View File

@ -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')

View File

@ -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'))

View File

@ -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"