refactor: editor codeblock -> Vue component
This commit is contained in:
parent
ebe288a5b2
commit
f577a8134e
161
.build/_tasks.js
Normal file
161
.build/_tasks.js
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const _ = require('lodash')
|
||||||
|
const Promise = require('bluebird')
|
||||||
|
const colors = require('colors/safe')
|
||||||
|
const fs = Promise.promisifyAll(require('fs-extra'))
|
||||||
|
const path = require('path')
|
||||||
|
const uglify = require('uglify-es')
|
||||||
|
|
||||||
|
module.exports = Promise.mapSeries([
|
||||||
|
/**
|
||||||
|
* SimpleMDE
|
||||||
|
*/
|
||||||
|
() => {
|
||||||
|
return fs.accessAsync('./assets/js/simplemde').then(() => {
|
||||||
|
console.info(colors.white(' └── ') + colors.magenta('SimpleMDE directory already exists. Task aborted.'))
|
||||||
|
return true
|
||||||
|
}).catch(err => {
|
||||||
|
if (err.code === 'ENOENT') {
|
||||||
|
console.info(colors.white(' └── ') + colors.green('Copy + Minify SimpleMDE to assets...'))
|
||||||
|
return fs.copy('./node_modules/simplemde/dist/simplemde.min.js', './assets/js/simplemde/simplemde.min.js')
|
||||||
|
} else {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* ACE Modes
|
||||||
|
*/
|
||||||
|
() => {
|
||||||
|
return fs.accessAsync('./assets/js/ace').then(() => {
|
||||||
|
console.info(colors.white(' └── ') + colors.magenta('ACE modes directory already exists. Task aborted.'))
|
||||||
|
return true
|
||||||
|
}).catch(err => {
|
||||||
|
if (err.code === 'ENOENT') {
|
||||||
|
console.info(colors.white(' └── ') + colors.green('Copy + Minify ACE modes to assets...'))
|
||||||
|
return fs.ensureDirAsync('./assets/js/ace').then(() => {
|
||||||
|
return Promise.join(
|
||||||
|
// Core
|
||||||
|
Promise.all([
|
||||||
|
fs.readFileAsync('./node_modules/brace/index.js', 'utf8'),
|
||||||
|
fs.readFileAsync('./node_modules/brace/ext/modelist.js', 'utf8'),
|
||||||
|
fs.readFileAsync('./node_modules/brace/theme/dawn.js', 'utf8'),
|
||||||
|
fs.readFileAsync('./node_modules/brace/theme/tomorrow_night.js', 'utf8'),
|
||||||
|
fs.readFileAsync('./node_modules/brace/mode/markdown.js', 'utf8')
|
||||||
|
]).then(items => {
|
||||||
|
console.info(colors.white(' ace.js'))
|
||||||
|
let result = uglify.minify(items.join(';\n'), { output: { 'max_line_len': 1000000 } })
|
||||||
|
return fs.writeFileAsync('./assets/js/ace/ace.js', result.code)
|
||||||
|
}),
|
||||||
|
// Modes
|
||||||
|
fs.readdirAsync('./node_modules/brace/mode').then(modeList => {
|
||||||
|
return Promise.map(modeList, mdFile => {
|
||||||
|
return fs.readFileAsync(path.join('./node_modules/brace/mode', mdFile), 'utf8').then(modeCode => {
|
||||||
|
console.info(colors.white(' mode-' + mdFile))
|
||||||
|
let result = uglify.minify(modeCode, { output: { 'max_line_len': 1000000 } })
|
||||||
|
return fs.writeFileAsync(path.join('./assets/js/ace', 'mode-' + mdFile), result.code)
|
||||||
|
})
|
||||||
|
}, { concurrency: 3 })
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* MathJax
|
||||||
|
*/
|
||||||
|
() => {
|
||||||
|
return fs.accessAsync('./assets/js/mathjax').then(() => {
|
||||||
|
console.info(colors.white(' └── ') + colors.magenta('MathJax directory already exists. Task aborted.'))
|
||||||
|
return true
|
||||||
|
}).catch(err => {
|
||||||
|
if (err.code === 'ENOENT') {
|
||||||
|
console.info(colors.white(' └── ') + colors.green('Copy MathJax dependencies to assets...'))
|
||||||
|
return fs.ensureDirAsync('./assets/js/mathjax').then(() => {
|
||||||
|
return fs.copyAsync('./node_modules/mathjax', './assets/js/mathjax', {
|
||||||
|
filter: (src, dest) => {
|
||||||
|
let srcNormalized = src.replace(/\\/g, '/')
|
||||||
|
let shouldCopy = false
|
||||||
|
console.info(colors.white(' ' + srcNormalized))
|
||||||
|
_.forEach([
|
||||||
|
'/node_modules/mathjax',
|
||||||
|
'/node_modules/mathjax/jax',
|
||||||
|
'/node_modules/mathjax/jax/input',
|
||||||
|
'/node_modules/mathjax/jax/output'
|
||||||
|
], chk => {
|
||||||
|
if (srcNormalized.endsWith(chk)) {
|
||||||
|
shouldCopy = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
_.forEach([
|
||||||
|
'/node_modules/mathjax/extensions',
|
||||||
|
'/node_modules/mathjax/MathJax.js',
|
||||||
|
'/node_modules/mathjax/jax/element',
|
||||||
|
'/node_modules/mathjax/jax/input/MathML',
|
||||||
|
'/node_modules/mathjax/jax/input/TeX',
|
||||||
|
'/node_modules/mathjax/jax/output/SVG'
|
||||||
|
], chk => {
|
||||||
|
if (srcNormalized.indexOf(chk) > 0) {
|
||||||
|
shouldCopy = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (shouldCopy && srcNormalized.indexOf('/fonts/') > 0 && srcNormalized.indexOf('/STIX-Web') <= 1) {
|
||||||
|
shouldCopy = false
|
||||||
|
}
|
||||||
|
return shouldCopy
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* i18n
|
||||||
|
*/
|
||||||
|
() => {
|
||||||
|
console.info(colors.white(' └── ') + colors.green('Copying i18n client files...'))
|
||||||
|
return fs.ensureDirAsync('./assets/js/i18n').then(() => {
|
||||||
|
return fs.readJsonAsync('./server/locales/en/browser.json').then(enContent => {
|
||||||
|
return fs.readdirAsync('./server/locales').then(langs => {
|
||||||
|
return Promise.map(langs, lang => {
|
||||||
|
console.info(colors.white(' ' + lang + '.json'))
|
||||||
|
let outputPath = path.join('./assets/js/i18n', lang + '.json')
|
||||||
|
return fs.readJsonAsync(path.join('./server/locales', lang + '.json'), 'utf8').then((content) => {
|
||||||
|
return fs.outputJsonAsync(outputPath, _.defaultsDeep(content, enContent))
|
||||||
|
}).catch(err => { // eslint-disable-line handle-callback-err
|
||||||
|
return fs.outputJsonAsync(outputPath, enContent)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Bundle pre-init scripts
|
||||||
|
*/
|
||||||
|
() => {
|
||||||
|
console.info(colors.white(' └── ') + colors.green('Bundling pre-init scripts...'))
|
||||||
|
let preInitContent = ''
|
||||||
|
return fs.readdirAsync('./client/js/pre-init').map(f => {
|
||||||
|
let fPath = path.join('./client/js/pre-init/', f)
|
||||||
|
return fs.readFileAsync(fPath, 'utf8').then(fContent => {
|
||||||
|
preInitContent += fContent + ';\n'
|
||||||
|
})
|
||||||
|
}).then(() => {
|
||||||
|
return fs.outputFileAsync('./.build/_preinit.js', preInitContent, 'utf8')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Delete Fusebox cache
|
||||||
|
*/
|
||||||
|
() => {
|
||||||
|
console.info(colors.white(' └── ') + colors.green('Clearing fuse-box cache...'))
|
||||||
|
return fs.emptyDirAsync('./.fusebox')
|
||||||
|
}
|
||||||
|
], f => { return f() })
|
@ -6,9 +6,15 @@
|
|||||||
"jest": true
|
"jest": true
|
||||||
},
|
},
|
||||||
"globals": {
|
"globals": {
|
||||||
|
// Client
|
||||||
"document": false,
|
"document": false,
|
||||||
"navigator": false,
|
"navigator": false,
|
||||||
"window": false,
|
"window": false,
|
||||||
|
"siteLang": false,
|
||||||
|
"socket": true,
|
||||||
|
"wikijs": true,
|
||||||
|
"FuseBox": false,
|
||||||
|
// Server
|
||||||
"appconfig": true,
|
"appconfig": true,
|
||||||
"appdata": true,
|
"appdata": true,
|
||||||
"ROOTPATH": true,
|
"ROOTPATH": true,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
/* global siteLang */
|
|
||||||
/* eslint-disable no-new */
|
/* eslint-disable no-new */
|
||||||
|
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
@ -147,7 +146,7 @@ $(() => {
|
|||||||
// ====================================
|
// ====================================
|
||||||
|
|
||||||
const i18n = new VueI18Next(i18next)
|
const i18n = new VueI18Next(i18next)
|
||||||
new Vue({
|
window.wikijs = new Vue({
|
||||||
mixins: [helpers],
|
mixins: [helpers],
|
||||||
components: {
|
components: {
|
||||||
alert: alertComponent,
|
alert: alertComponent,
|
||||||
|
@ -1,87 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
import $ from 'jquery'
|
|
||||||
import Vue from 'vue'
|
|
||||||
import _ from 'lodash'
|
|
||||||
import * as ace from 'brace'
|
|
||||||
import 'brace/theme/tomorrow_night'
|
|
||||||
import 'brace/mode/markdown'
|
|
||||||
import 'brace-ext-modelist'
|
|
||||||
|
|
||||||
let codeEditor = null
|
|
||||||
|
|
||||||
// ACE - Mode Loader
|
|
||||||
|
|
||||||
let modelistLoaded = []
|
|
||||||
let loadAceMode = (m) => {
|
|
||||||
return $.ajax({
|
|
||||||
url: '/js/ace/mode-' + m + '.js',
|
|
||||||
dataType: 'script',
|
|
||||||
cache: true,
|
|
||||||
beforeSend: () => {
|
|
||||||
if (_.includes(modelistLoaded, m)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
success: () => {
|
|
||||||
modelistLoaded.push(m)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vue Code Block instance
|
|
||||||
|
|
||||||
module.exports = (mde, mdeModalOpenState) => {
|
|
||||||
let modelist = ace.acequire('ace/ext/modelist')
|
|
||||||
let vueCodeBlock = new Vue({
|
|
||||||
el: '#modal-editor-codeblock',
|
|
||||||
data: {
|
|
||||||
modes: modelist.modesByName,
|
|
||||||
modeSelected: 'text',
|
|
||||||
initContent: ''
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
modeSelected: (val, oldVal) => {
|
|
||||||
loadAceMode(val).done(() => {
|
|
||||||
ace.acequire('ace/mode/' + val)
|
|
||||||
codeEditor.getSession().setMode('ace/mode/' + val)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
open: (ev) => {
|
|
||||||
mdeModalOpenState = true
|
|
||||||
$('#modal-editor-codeblock').addClass('is-active')
|
|
||||||
|
|
||||||
_.delay(() => {
|
|
||||||
codeEditor = ace.edit('codeblock-editor')
|
|
||||||
codeEditor.setTheme('ace/theme/tomorrow_night')
|
|
||||||
codeEditor.getSession().setMode('ace/mode/' + vueCodeBlock.modeSelected)
|
|
||||||
codeEditor.setOption('fontSize', '14px')
|
|
||||||
codeEditor.setOption('hScrollBarAlwaysVisible', false)
|
|
||||||
codeEditor.setOption('wrap', true)
|
|
||||||
|
|
||||||
codeEditor.setValue(vueCodeBlock.initContent)
|
|
||||||
|
|
||||||
codeEditor.focus()
|
|
||||||
codeEditor.renderer.updateFull()
|
|
||||||
}, 300)
|
|
||||||
},
|
|
||||||
cancel: (ev) => {
|
|
||||||
mdeModalOpenState = false // eslint-disable-line no-undef
|
|
||||||
$('#modal-editor-codeblock').removeClass('is-active')
|
|
||||||
vueCodeBlock.initContent = ''
|
|
||||||
},
|
|
||||||
insertCode: (ev) => {
|
|
||||||
if (mde.codemirror.doc.somethingSelected()) {
|
|
||||||
mde.codemirror.execCommand('singleSelection')
|
|
||||||
}
|
|
||||||
let codeBlockText = '\n```' + vueCodeBlock.modeSelected + '\n' + codeEditor.getValue() + '\n```\n'
|
|
||||||
|
|
||||||
mde.codemirror.doc.replaceSelection(codeBlockText)
|
|
||||||
vueCodeBlock.cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return vueCodeBlock
|
|
||||||
}
|
|
@ -24,28 +24,85 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
let codeEditor
|
||||||
|
let ace
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'editor-codeblock',
|
name: 'editor-codeblock',
|
||||||
data () {
|
data () {
|
||||||
return {}
|
return {
|
||||||
|
modes: [],
|
||||||
|
modeSelected: 'text',
|
||||||
|
modelistLoaded: []
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
content () {
|
||||||
|
return this.$store.state.editorCodeblock.content
|
||||||
|
},
|
||||||
isShown () {
|
isShown () {
|
||||||
return this.$store.state.editorCodeblock.shown
|
return this.$store.state.editorCodeblock.shown
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
modeSelected(val, oldVal) {
|
||||||
|
this.loadMode(val)
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
init () {
|
||||||
|
let self = this
|
||||||
|
self._.delay(() => {
|
||||||
|
codeEditor = ace.edit('codeblock-editor')
|
||||||
|
codeEditor.setTheme('ace/theme/tomorrow_night')
|
||||||
|
codeEditor.getSession().setMode('ace/mode/' + self.modeSelected)
|
||||||
|
codeEditor.setOption('fontSize', '14px')
|
||||||
|
codeEditor.setOption('hScrollBarAlwaysVisible', false)
|
||||||
|
codeEditor.setOption('wrap', true)
|
||||||
|
codeEditor.setOption('showPrintMargin', false)
|
||||||
|
|
||||||
|
codeEditor.setValue(self.content)
|
||||||
|
|
||||||
|
codeEditor.focus()
|
||||||
|
codeEditor.renderer.updateFull()
|
||||||
|
}, 100)
|
||||||
|
},
|
||||||
|
loadMode (m) {
|
||||||
|
let self = this
|
||||||
|
if (self._.includes(self.modelistLoaded, m)) {
|
||||||
|
codeEditor.getSession().setMode('ace/mode/' + m)
|
||||||
|
} else {
|
||||||
|
self.$http.get('/js/ace/mode-' + m + '.js').then(resp => {
|
||||||
|
if(resp.ok) {
|
||||||
|
eval(resp.bodyText)
|
||||||
|
self.modelistLoaded.push(m)
|
||||||
|
ace.acequire('ace/mode/' + m)
|
||||||
|
codeEditor.getSession().setMode('ace/mode/' + m)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
cancel () {
|
cancel () {
|
||||||
this.$store.dispatch('editorCodeBlock/close')
|
codeEditor.destroy()
|
||||||
|
this.$store.dispatch('editorCodeblock/close')
|
||||||
},
|
},
|
||||||
insertCode () {
|
insertCode () {
|
||||||
|
let codeBlockText = '\n```' + this.modeSelected + '\n' + codeEditor.getValue() + '\n```\n'
|
||||||
|
this.$store.dispatch('editor/insert', codeBlockText)
|
||||||
this.$store.dispatch('alert', {
|
this.$store.dispatch('alert', {
|
||||||
style: 'pink',
|
style: 'blue',
|
||||||
icon: 'inbox',
|
icon: 'inbox',
|
||||||
msg: 'Your code block has been inserted.'
|
msg: 'Your code block has been inserted.'
|
||||||
})
|
})
|
||||||
this.cancel()
|
this.cancel()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
FuseBox.import('/js/ace/ace.js', (acePkg) => {
|
||||||
|
ace = acePkg
|
||||||
|
this.modes = ace.acequire('ace/ext/modelist').modesByName
|
||||||
|
})
|
||||||
|
this.$root.$on('editorCodeblock/init', this.init)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
/* global FuseBox */
|
|
||||||
|
|
||||||
import filesize from 'filesize.js'
|
import filesize from 'filesize.js'
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
|
|
||||||
@ -18,7 +16,18 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
insertContent() {
|
||||||
|
return this.$store.state.editor.insertContent
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
insert(content) {
|
||||||
|
if (mde.codemirror.doc.somethingSelected()) {
|
||||||
|
mde.codemirror.execCommand('singleSelection')
|
||||||
|
}
|
||||||
|
mde.codemirror.doc.replaceSelection(this.insertContent)
|
||||||
|
},
|
||||||
save() {
|
save() {
|
||||||
let self = this
|
let self = this
|
||||||
this.$http.put(window.location.href, {
|
this.$http.put(window.location.href, {
|
||||||
@ -177,13 +186,9 @@ export default {
|
|||||||
{
|
{
|
||||||
name: 'code-block',
|
name: 'code-block',
|
||||||
action: (editor) => {
|
action: (editor) => {
|
||||||
// if (!mdeModalOpenState) {
|
self.$store.dispatch('editorCodeblock/open', {
|
||||||
// if (mde.codemirror.doc.somethingSelected()) {
|
initialContent: (mde.codemirror.doc.somethingSelected()) ? mde.codemirror.doc.getSelection() : ''
|
||||||
// vueCodeBlock.initContent = mde.codemirror.doc.getSelection()
|
})
|
||||||
// }
|
|
||||||
|
|
||||||
// vueCodeBlock.open()
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
className: 'icon-code',
|
className: 'icon-code',
|
||||||
title: 'Code Block'
|
title: 'Code Block'
|
||||||
@ -212,8 +217,6 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
|
|
||||||
this.$root.$on('editor-save', this.save)
|
|
||||||
$(window).bind('keydown', (ev) => {
|
$(window).bind('keydown', (ev) => {
|
||||||
if (ev.ctrlKey || ev.metaKey) {
|
if (ev.ctrlKey || ev.metaKey) {
|
||||||
switch (String.fromCharCode(ev.which).toLowerCase()) {
|
switch (String.fromCharCode(ev.which).toLowerCase()) {
|
||||||
@ -225,6 +228,10 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Listeners
|
||||||
|
this.$root.$on('editor/save', this.save)
|
||||||
|
this.$root.$on('editor/insert', this.insert)
|
||||||
|
|
||||||
this.$store.dispatch('pageLoader/complete')
|
this.$store.dispatch('pageLoader/complete')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
/* global FuseBox */
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'source-view',
|
name: 'source-view',
|
||||||
data() {
|
data() {
|
||||||
@ -9,13 +7,14 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
let self = this
|
let self = this
|
||||||
FuseBox.import('/js/ace/source-view.js', (ace) => {
|
FuseBox.import('/js/ace/ace.js', (ace) => {
|
||||||
let scEditor = ace.edit('source-display')
|
let scEditor = ace.edit('source-display')
|
||||||
scEditor.setTheme('ace/theme/dawn')
|
scEditor.setTheme('ace/theme/dawn')
|
||||||
scEditor.getSession().setMode('ace/mode/markdown')
|
scEditor.getSession().setMode('ace/mode/markdown')
|
||||||
scEditor.setOption('fontSize', '14px')
|
scEditor.setOption('fontSize', '14px')
|
||||||
scEditor.setOption('hScrollBarAlwaysVisible', false)
|
scEditor.setOption('hScrollBarAlwaysVisible', false)
|
||||||
scEditor.setOption('wrap', true)
|
scEditor.setOption('wrap', true)
|
||||||
|
scEditor.setOption('showPrintMargin', false)
|
||||||
scEditor.setReadOnly(true)
|
scEditor.setReadOnly(true)
|
||||||
scEditor.renderer.updateFull()
|
scEditor.renderer.updateFull()
|
||||||
scEditor.renderer.on('afterRender', () => {
|
scEditor.renderer.on('afterRender', () => {
|
||||||
|
@ -3,14 +3,20 @@
|
|||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
state: {
|
state: {
|
||||||
shown: false
|
shown: false,
|
||||||
|
content: ''
|
||||||
},
|
},
|
||||||
getters: {},
|
getters: {},
|
||||||
mutations: {
|
mutations: {
|
||||||
shownChange: (state, shownState) => { state.shown = shownState }
|
shownChange: (state, shownState) => { state.shown = shownState },
|
||||||
|
contentChange: (state, newContent) => { state.content = newContent }
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
open({ commit }) { commit('shownChange', true) },
|
open({ commit }, opts) {
|
||||||
|
commit('shownChange', true)
|
||||||
|
commit('contentChange', opts.initialContent || '')
|
||||||
|
wikijs.$emit('editorCodeblock/init')
|
||||||
|
},
|
||||||
close({ commit }) { commit('shownChange', false) }
|
close({ commit }) { commit('shownChange', false) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,21 @@
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
state: {},
|
state: {
|
||||||
|
busy: false,
|
||||||
|
insertContent: ''
|
||||||
|
},
|
||||||
getters: {},
|
getters: {},
|
||||||
mutations: {},
|
mutations: {
|
||||||
actions: {}
|
busyChange: (state, busyState) => { state.shown = busyState },
|
||||||
|
insertContentChange: (state, newContent) => { state.insertContent = newContent }
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
busyStart({ commit }) { commit('busyChange', true) },
|
||||||
|
busyStop({ commit }) { commit('busyChange', false) },
|
||||||
|
insert({ commit }, content) {
|
||||||
|
commit('insertContentChange', content)
|
||||||
|
wikijs.$emit('editor/insert')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
162
fuse.js
162
fuse.js
@ -6,14 +6,9 @@
|
|||||||
* Client & Server compiler / bundler / watcher
|
* Client & Server compiler / bundler / watcher
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const _ = require('lodash')
|
|
||||||
const Promise = require('bluebird')
|
|
||||||
const colors = require('colors/safe')
|
const colors = require('colors/safe')
|
||||||
const fs = Promise.promisifyAll(require('fs-extra'))
|
|
||||||
const fsbx = require('fuse-box')
|
const fsbx = require('fuse-box')
|
||||||
const nodemon = require('nodemon')
|
const nodemon = require('nodemon')
|
||||||
const path = require('path')
|
|
||||||
const uglify = require('uglify-es')
|
|
||||||
|
|
||||||
// ======================================================
|
// ======================================================
|
||||||
// Parse cmd arguments
|
// Parse cmd arguments
|
||||||
@ -77,157 +72,7 @@ const SHIMS = {
|
|||||||
// ======================================================
|
// ======================================================
|
||||||
|
|
||||||
console.info(colors.white('└── ') + colors.green('Running global tasks...'))
|
console.info(colors.white('└── ') + colors.green('Running global tasks...'))
|
||||||
|
let globalTasks = require('./.build/_tasks')
|
||||||
let globalTasks = Promise.mapSeries([
|
|
||||||
/**
|
|
||||||
* SimpleMDE
|
|
||||||
*/
|
|
||||||
() => {
|
|
||||||
return fs.accessAsync('./assets/js/simplemde').then(() => {
|
|
||||||
console.info(colors.white(' └── ') + colors.magenta('SimpleMDE directory already exists. Task aborted.'))
|
|
||||||
return true
|
|
||||||
}).catch(err => {
|
|
||||||
if (err.code === 'ENOENT') {
|
|
||||||
console.info(colors.white(' └── ') + colors.green('Copy + Minify SimpleMDE to assets...'))
|
|
||||||
return fs.copy('./node_modules/simplemde/dist/simplemde.min.js', './assets/js/simplemde/simplemde.min.js')
|
|
||||||
} else {
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* ACE Modes
|
|
||||||
*/
|
|
||||||
() => {
|
|
||||||
return fs.accessAsync('./assets/js/ace').then(() => {
|
|
||||||
console.info(colors.white(' └── ') + colors.magenta('ACE modes directory already exists. Task aborted.'))
|
|
||||||
return true
|
|
||||||
}).catch(err => {
|
|
||||||
if (err.code === 'ENOENT') {
|
|
||||||
console.info(colors.white(' └── ') + colors.green('Copy + Minify ACE modes to assets...'))
|
|
||||||
return fs.ensureDirAsync('./assets/js/ace').then(() => {
|
|
||||||
return Promise.join(
|
|
||||||
// Core
|
|
||||||
Promise.all([
|
|
||||||
fs.readFileAsync('./node_modules/brace/index.js', 'utf8'),
|
|
||||||
fs.readFileAsync('./node_modules/brace/theme/dawn.js', 'utf8'),
|
|
||||||
fs.readFileAsync('./node_modules/brace/mode/markdown.js', 'utf8')
|
|
||||||
]).then(items => {
|
|
||||||
console.info(colors.white(' source-view.js'))
|
|
||||||
let result = uglify.minify(items.join(';\n'), { output: { 'max_line_len': 1000000 } })
|
|
||||||
return fs.writeFileAsync('./assets/js/ace/source-view.js', result.code)
|
|
||||||
}),
|
|
||||||
// Modes
|
|
||||||
fs.readdirAsync('./node_modules/brace/mode').then(modeList => {
|
|
||||||
return Promise.map(modeList, mdFile => {
|
|
||||||
return fs.readFileAsync(path.join('./node_modules/brace/mode', mdFile), 'utf8').then(modeCode => {
|
|
||||||
console.info(colors.white(' mode-' + mdFile))
|
|
||||||
let result = uglify.minify(modeCode, { output: { 'max_line_len': 1000000 } })
|
|
||||||
return fs.writeFileAsync(path.join('./assets/js/ace', 'mode-' + mdFile), result.code)
|
|
||||||
})
|
|
||||||
}, { concurrency: 3 })
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* MathJax
|
|
||||||
*/
|
|
||||||
() => {
|
|
||||||
return fs.accessAsync('./assets/js/mathjax').then(() => {
|
|
||||||
console.info(colors.white(' └── ') + colors.magenta('MathJax directory already exists. Task aborted.'))
|
|
||||||
return true
|
|
||||||
}).catch(err => {
|
|
||||||
if (err.code === 'ENOENT') {
|
|
||||||
console.info(colors.white(' └── ') + colors.green('Copy MathJax dependencies to assets...'))
|
|
||||||
return fs.ensureDirAsync('./assets/js/mathjax').then(() => {
|
|
||||||
return fs.copyAsync('./node_modules/mathjax', './assets/js/mathjax', {
|
|
||||||
filter: (src, dest) => {
|
|
||||||
let srcNormalized = src.replace(/\\/g, '/')
|
|
||||||
let shouldCopy = false
|
|
||||||
console.info(colors.white(' ' + srcNormalized))
|
|
||||||
_.forEach([
|
|
||||||
'/node_modules/mathjax',
|
|
||||||
'/node_modules/mathjax/jax',
|
|
||||||
'/node_modules/mathjax/jax/input',
|
|
||||||
'/node_modules/mathjax/jax/output'
|
|
||||||
], chk => {
|
|
||||||
if (srcNormalized.endsWith(chk)) {
|
|
||||||
shouldCopy = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
_.forEach([
|
|
||||||
'/node_modules/mathjax/extensions',
|
|
||||||
'/node_modules/mathjax/MathJax.js',
|
|
||||||
'/node_modules/mathjax/jax/element',
|
|
||||||
'/node_modules/mathjax/jax/input/MathML',
|
|
||||||
'/node_modules/mathjax/jax/input/TeX',
|
|
||||||
'/node_modules/mathjax/jax/output/SVG'
|
|
||||||
], chk => {
|
|
||||||
if (srcNormalized.indexOf(chk) > 0) {
|
|
||||||
shouldCopy = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (shouldCopy && srcNormalized.indexOf('/fonts/') > 0 && srcNormalized.indexOf('/STIX-Web') <= 1) {
|
|
||||||
shouldCopy = false
|
|
||||||
}
|
|
||||||
return shouldCopy
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* i18n
|
|
||||||
*/
|
|
||||||
() => {
|
|
||||||
console.info(colors.white(' └── ') + colors.green('Copying i18n client files...'))
|
|
||||||
return fs.ensureDirAsync('./assets/js/i18n').then(() => {
|
|
||||||
return fs.readJsonAsync('./server/locales/en/browser.json').then(enContent => {
|
|
||||||
return fs.readdirAsync('./server/locales').then(langs => {
|
|
||||||
return Promise.map(langs, lang => {
|
|
||||||
console.info(colors.white(' ' + lang + '.json'))
|
|
||||||
let outputPath = path.join('./assets/js/i18n', lang + '.json')
|
|
||||||
return fs.readJsonAsync(path.join('./server/locales', lang + '.json'), 'utf8').then((content) => {
|
|
||||||
return fs.outputJsonAsync(outputPath, _.defaultsDeep(content, enContent))
|
|
||||||
}).catch(err => { // eslint-disable-line handle-callback-err
|
|
||||||
return fs.outputJsonAsync(outputPath, enContent)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Bundle pre-init scripts
|
|
||||||
*/
|
|
||||||
() => {
|
|
||||||
console.info(colors.white(' └── ') + colors.green('Bundling pre-init scripts...'))
|
|
||||||
let preInitContent = ''
|
|
||||||
return fs.readdirAsync('./client/js/pre-init').map(f => {
|
|
||||||
let fPath = path.join('./client/js/pre-init/', f)
|
|
||||||
return fs.readFileAsync(fPath, 'utf8').then(fContent => {
|
|
||||||
preInitContent += fContent + ';\n'
|
|
||||||
})
|
|
||||||
}).then(() => {
|
|
||||||
return fs.outputFileAsync('./.build/_preinit.js', preInitContent, 'utf8')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Delete Fusebox cache
|
|
||||||
*/
|
|
||||||
() => {
|
|
||||||
console.info(colors.white(' └── ') + colors.green('Clearing fuse-box cache...'))
|
|
||||||
return fs.emptyDirAsync('./.fusebox')
|
|
||||||
}
|
|
||||||
], f => { return f() })
|
|
||||||
|
|
||||||
// ======================================================
|
// ======================================================
|
||||||
// Fuse Tasks
|
// Fuse Tasks
|
||||||
@ -243,7 +88,7 @@ globalTasks.then(() => {
|
|||||||
fsbx.EnvPlugin({ NODE_ENV: (dev) ? 'development' : 'production' }),
|
fsbx.EnvPlugin({ NODE_ENV: (dev) ? 'development' : 'production' }),
|
||||||
fsbx.VuePlugin(),
|
fsbx.VuePlugin(),
|
||||||
['.scss', fsbx.SassPlugin({ outputStyle: (dev) ? 'nested' : 'compressed' }), fsbx.CSSPlugin()],
|
['.scss', fsbx.SassPlugin({ outputStyle: (dev) ? 'nested' : 'compressed' }), fsbx.CSSPlugin()],
|
||||||
dev && fsbx.BabelPlugin({ comments: false, presets: ['es2015'] }),
|
fsbx.BabelPlugin({ comments: false, presets: ['es2015'] }),
|
||||||
fsbx.JSONPlugin(),
|
fsbx.JSONPlugin(),
|
||||||
!dev && fsbx.UglifyESPlugin({
|
!dev && fsbx.UglifyESPlugin({
|
||||||
compress: { unused: false },
|
compress: { unused: false },
|
||||||
@ -261,14 +106,11 @@ globalTasks.then(() => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// const bundleLibs = fuse.bundle('libs').instructions('~ index.js - brace')
|
|
||||||
// const bundleApp = fuse.bundle('app').instructions('!> [index.js]')
|
|
||||||
const bundleApp = fuse.bundle('app').instructions('> index.js')
|
const bundleApp = fuse.bundle('app').instructions('> index.js')
|
||||||
const bundleSetup = fuse.bundle('configure').instructions('> configure.js')
|
const bundleSetup = fuse.bundle('configure').instructions('> configure.js')
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'dev':
|
case 'dev':
|
||||||
// bundleLibs.watch()
|
|
||||||
bundleApp.watch()
|
bundleApp.watch()
|
||||||
break
|
break
|
||||||
case 'dev-configure':
|
case 'dev-configure':
|
||||||
|
@ -90,7 +90,7 @@
|
|||||||
"moment": "^2.18.1",
|
"moment": "^2.18.1",
|
||||||
"moment-timezone": "^0.5.13",
|
"moment-timezone": "^0.5.13",
|
||||||
"mongodb": "^2.2.27",
|
"mongodb": "^2.2.27",
|
||||||
"mongoose": "^4.10.2",
|
"mongoose": "^4.10.3",
|
||||||
"multer": "^1.3.0",
|
"multer": "^1.3.0",
|
||||||
"node-graceful": "^0.2.3",
|
"node-graceful": "^0.2.3",
|
||||||
"ora": "^1.2.0",
|
"ora": "^1.2.0",
|
||||||
@ -156,8 +156,8 @@
|
|||||||
"snyk": "latest",
|
"snyk": "latest",
|
||||||
"twemoji-awesome": "^1.0.6",
|
"twemoji-awesome": "^1.0.6",
|
||||||
"typescript": "^2.3.3",
|
"typescript": "^2.3.3",
|
||||||
"uglify-es": "^3.0.11",
|
"uglify-es": "^3.0.12",
|
||||||
"vee-validate": "^2.0.0-rc.4",
|
"vee-validate": "^2.0.0-rc.5",
|
||||||
"vue": "^2.3.3",
|
"vue": "^2.3.3",
|
||||||
"vue-clipboards": "^1.0.0",
|
"vue-clipboards": "^1.0.0",
|
||||||
"vue-lodash": "^1.0.3",
|
"vue-lodash": "^1.0.3",
|
||||||
|
@ -87,7 +87,10 @@ app.use(mw.security)
|
|||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
|
|
||||||
app.use(favicon(path.join(ROOTPATH, 'assets', 'favicon.ico')))
|
app.use(favicon(path.join(ROOTPATH, 'assets', 'favicon.ico')))
|
||||||
app.use(express.static(path.join(ROOTPATH, 'assets')))
|
app.use(express.static(path.join(ROOTPATH, 'assets'), {
|
||||||
|
index: false,
|
||||||
|
maxAge: '7d'
|
||||||
|
}))
|
||||||
|
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
// Passport Authentication
|
// Passport Authentication
|
||||||
|
@ -9,7 +9,7 @@ block rootNavRight
|
|||||||
a.button.is-outlined(v-on:click='$store.dispatch("modalDiscardPage/open")')
|
a.button.is-outlined(v-on:click='$store.dispatch("modalDiscardPage/open")')
|
||||||
i.icon-cross
|
i.icon-cross
|
||||||
span= t('nav.discard')
|
span= t('nav.discard')
|
||||||
a.button(v-on:click='$root.$emit("editor-save")')
|
a.button(v-on:click='$root.$emit("editor/save")')
|
||||||
i.icon-check
|
i.icon-check
|
||||||
span= t('nav.savechanges')
|
span= t('nav.savechanges')
|
||||||
|
|
||||||
@ -18,5 +18,6 @@ block content
|
|||||||
.editor-area
|
.editor-area
|
||||||
textarea(ref='editorTextArea')= pageData.markdown
|
textarea(ref='editorTextArea')= pageData.markdown
|
||||||
|
|
||||||
|
editor-codeblock
|
||||||
modal-discard-page(mode='edit', current-path=pageData.meta.path)
|
modal-discard-page(mode='edit', current-path=pageData.meta.path)
|
||||||
page-loader(text=t('loading.editor'))
|
page-loader(text=t('loading.editor'))
|
||||||
|
37
yarn.lock
37
yarn.lock
@ -4491,13 +4491,6 @@ moment@2.x.x, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.15, moment@^2.16.1, m
|
|||||||
version "2.18.1"
|
version "2.18.1"
|
||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
|
||||||
|
|
||||||
mongodb-core@2.1.10:
|
|
||||||
version "2.1.10"
|
|
||||||
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.10.tgz#eb290681d196d3346a492161aa2ea0905e63151b"
|
|
||||||
dependencies:
|
|
||||||
bson "~1.0.4"
|
|
||||||
require_optional "~1.0.0"
|
|
||||||
|
|
||||||
mongodb-core@2.1.11:
|
mongodb-core@2.1.11:
|
||||||
version "2.1.11"
|
version "2.1.11"
|
||||||
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.11.tgz#1c38776ceb174997a99c28860eed9028da9b3e1a"
|
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.11.tgz#1c38776ceb174997a99c28860eed9028da9b3e1a"
|
||||||
@ -4505,15 +4498,7 @@ mongodb-core@2.1.11:
|
|||||||
bson "~1.0.4"
|
bson "~1.0.4"
|
||||||
require_optional "~1.0.0"
|
require_optional "~1.0.0"
|
||||||
|
|
||||||
mongodb@2.2.26:
|
mongodb@2.2.27, "mongodb@>= 1.2.0 <3.0.0", mongodb@^2.2.27:
|
||||||
version "2.2.26"
|
|
||||||
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.26.tgz#1bd50c557c277c98e1a05da38c9839c4922b034a"
|
|
||||||
dependencies:
|
|
||||||
es6-promise "3.2.1"
|
|
||||||
mongodb-core "2.1.10"
|
|
||||||
readable-stream "2.2.7"
|
|
||||||
|
|
||||||
"mongodb@>= 1.2.0 <3.0.0", mongodb@^2.2.27:
|
|
||||||
version "2.2.27"
|
version "2.2.27"
|
||||||
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.27.tgz#34122034db66d983bcf6ab5adb26a24a70fef6e6"
|
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.27.tgz#34122034db66d983bcf6ab5adb26a24a70fef6e6"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -4521,15 +4506,15 @@ mongodb@2.2.26:
|
|||||||
mongodb-core "2.1.11"
|
mongodb-core "2.1.11"
|
||||||
readable-stream "2.2.7"
|
readable-stream "2.2.7"
|
||||||
|
|
||||||
mongoose@*, mongoose@^4.10.2:
|
mongoose@*, mongoose@^4.10.3:
|
||||||
version "4.10.2"
|
version "4.10.3"
|
||||||
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.10.2.tgz#c7473ebada5f985cdac8e4182d40776b1aaf5352"
|
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.10.3.tgz#5fbcd6549e67191ef30cab259644ff75f77026f9"
|
||||||
dependencies:
|
dependencies:
|
||||||
async "2.1.4"
|
async "2.1.4"
|
||||||
bson "~1.0.4"
|
bson "~1.0.4"
|
||||||
hooks-fixed "2.0.0"
|
hooks-fixed "2.0.0"
|
||||||
kareem "1.4.1"
|
kareem "1.4.1"
|
||||||
mongodb "2.2.26"
|
mongodb "2.2.27"
|
||||||
mpath "0.2.1"
|
mpath "0.2.1"
|
||||||
mpromise "0.5.5"
|
mpromise "0.5.5"
|
||||||
mquery "2.3.1"
|
mquery "2.3.1"
|
||||||
@ -6863,9 +6848,9 @@ uc.micro@^1.0.1, uc.micro@^1.0.3:
|
|||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192"
|
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192"
|
||||||
|
|
||||||
uglify-es@^3.0.11:
|
uglify-es@^3.0.12:
|
||||||
version "3.0.11"
|
version "3.0.12"
|
||||||
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.0.11.tgz#acc51dfd2eb3681a3620d9c64881c29d9159ef85"
|
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.0.12.tgz#7734f9bb64bbf36dbb1e059358343c58553e52c1"
|
||||||
dependencies:
|
dependencies:
|
||||||
commander "~2.9.0"
|
commander "~2.9.0"
|
||||||
source-map "~0.5.1"
|
source-map "~0.5.1"
|
||||||
@ -7065,9 +7050,9 @@ vasync@^1.6.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
verror "1.6.0"
|
verror "1.6.0"
|
||||||
|
|
||||||
vee-validate@^2.0.0-rc.4:
|
vee-validate@^2.0.0-rc.5:
|
||||||
version "2.0.0-rc.4"
|
version "2.0.0-rc.5"
|
||||||
resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.4.tgz#49234ee481488fad909ab68a3f39edbb87f7a656"
|
resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.5.tgz#1de41866ddab3f8bebae3f3db653ef2c1c782fa0"
|
||||||
|
|
||||||
verror@1.3.6:
|
verror@1.3.6:
|
||||||
version "1.3.6"
|
version "1.3.6"
|
||||||
|
Loading…
Reference in New Issue
Block a user