mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-19 01:35:18 -04:00

Modern browsers do not support (or will stop supporting) sameSite: none (or no sameSite attribute) without the Secure flag. As we don't want everyone to be able to make requests with our cookies anyway, this commit sets sameSite to strict. See https://developer.mozilla.org/de/docs/Web/HTTP/Headers/Set-Cookie/SameSite Signed-off-by: David Mehren <dmehren1@gmail.com>
651 lines
21 KiB
JavaScript
651 lines
21 KiB
JavaScript
import * as utils from './utils'
|
|
import config from './config'
|
|
import statusBarTemplate from './statusbar.html'
|
|
import toolBarTemplate from './toolbar.html'
|
|
|
|
import '../../../css/ui/toolbar.css'
|
|
|
|
/* config section */
|
|
const isMac = CodeMirror.keyMap.default === CodeMirror.keyMap.macDefault
|
|
const defaultEditorMode = 'gfm'
|
|
const viewportMargin = 20
|
|
|
|
const jumpToAddressBarKeymapName = isMac ? 'Cmd-L' : 'Ctrl-L'
|
|
|
|
export default class Editor {
|
|
constructor () {
|
|
this.editor = null
|
|
this.jumpToAddressBarKeymapValue = null
|
|
this.defaultExtraKeys = {
|
|
F10: function (cm) {
|
|
cm.setOption('fullScreen', !cm.getOption('fullScreen'))
|
|
},
|
|
Esc: function (cm) {
|
|
if (cm.getOption('fullScreen') && !(cm.getOption('keyMap').substr(0, 3) === 'vim')) {
|
|
cm.setOption('fullScreen', false)
|
|
} else {
|
|
return CodeMirror.Pass
|
|
}
|
|
},
|
|
'Cmd-S': function () {
|
|
return false
|
|
},
|
|
'Ctrl-S': function () {
|
|
return false
|
|
},
|
|
Enter: 'newlineAndIndentContinueMarkdownList',
|
|
Tab: function (cm) {
|
|
var tab = '\t'
|
|
|
|
// contruct x length spaces
|
|
var spaces = Array(parseInt(cm.getOption('indentUnit')) + 1).join(' ')
|
|
|
|
// auto indent whole line when in list or blockquote
|
|
var cursor = cm.getCursor()
|
|
var line = cm.getLine(cursor.line)
|
|
|
|
// this regex match the following patterns
|
|
// 1. blockquote starts with "> " or ">>"
|
|
// 2. unorder list starts with *+-
|
|
// 3. order list starts with "1." or "1)"
|
|
var regex = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))/
|
|
|
|
var match
|
|
var multiple = cm.getSelection().split('\n').length > 1 ||
|
|
cm.getSelections().length > 1
|
|
|
|
if (multiple) {
|
|
cm.execCommand('defaultTab')
|
|
} else if ((match = regex.exec(line)) !== null) {
|
|
var ch = match[1].length
|
|
var pos = {
|
|
line: cursor.line,
|
|
ch: ch
|
|
}
|
|
if (cm.getOption('indentWithTabs')) {
|
|
cm.replaceRange(tab, pos, pos, '+input')
|
|
} else {
|
|
cm.replaceRange(spaces, pos, pos, '+input')
|
|
}
|
|
} else {
|
|
if (cm.getOption('indentWithTabs')) {
|
|
cm.execCommand('defaultTab')
|
|
} else {
|
|
cm.replaceSelection(spaces)
|
|
}
|
|
}
|
|
},
|
|
'Cmd-Left': 'goLineLeftSmart',
|
|
'Cmd-Right': 'goLineRight',
|
|
'Home': 'goLineLeftSmart',
|
|
'End': 'goLineRight',
|
|
'Ctrl-C': function (cm) {
|
|
if (!isMac && cm.getOption('keyMap').substr(0, 3) === 'vim') {
|
|
document.execCommand('copy')
|
|
} else {
|
|
return CodeMirror.Pass
|
|
}
|
|
},
|
|
'Ctrl-*': cm => {
|
|
utils.wrapTextWith(this.editor, cm, '*')
|
|
},
|
|
'Shift-Ctrl-8': cm => {
|
|
utils.wrapTextWith(this.editor, cm, '*')
|
|
},
|
|
'Ctrl-_': cm => {
|
|
utils.wrapTextWith(this.editor, cm, '_')
|
|
},
|
|
'Shift-Ctrl--': cm => {
|
|
utils.wrapTextWith(this.editor, cm, '_')
|
|
},
|
|
'Ctrl-~': cm => {
|
|
utils.wrapTextWith(this.editor, cm, '~')
|
|
},
|
|
'Shift-Ctrl-`': cm => {
|
|
utils.wrapTextWith(this.editor, cm, '~')
|
|
},
|
|
'Ctrl-^': cm => {
|
|
utils.wrapTextWith(this.editor, cm, '^')
|
|
},
|
|
'Shift-Ctrl-6': cm => {
|
|
utils.wrapTextWith(this.editor, cm, '^')
|
|
},
|
|
'Ctrl-+': cm => {
|
|
utils.wrapTextWith(this.editor, cm, '+')
|
|
},
|
|
'Shift-Ctrl-=': cm => {
|
|
utils.wrapTextWith(this.editor, cm, '+')
|
|
},
|
|
'Ctrl-=': cm => {
|
|
utils.wrapTextWith(this.editor, cm, '=')
|
|
},
|
|
'Shift-Ctrl-Backspace': cm => {
|
|
utils.wrapTextWith(this.editor, cm, 'Backspace')
|
|
}
|
|
}
|
|
this.eventListeners = {}
|
|
this.config = config
|
|
}
|
|
|
|
on (event, cb) {
|
|
if (!this.eventListeners[event]) {
|
|
this.eventListeners[event] = [cb]
|
|
} else {
|
|
this.eventListeners[event].push(cb)
|
|
}
|
|
|
|
this.editor.on(event, (...args) => {
|
|
this.eventListeners[event].forEach(cb => cb.bind(this)(...args))
|
|
})
|
|
}
|
|
|
|
addToolBar () {
|
|
var inlineAttach = inlineAttachment.editors.codemirror4.attach(this.editor)
|
|
this.toolBar = $(toolBarTemplate)
|
|
this.toolbarPanel = this.editor.addPanel(this.toolBar[0], {
|
|
position: 'top'
|
|
})
|
|
|
|
var makeBold = $('#makeBold')
|
|
var makeItalic = $('#makeItalic')
|
|
var makeStrike = $('#makeStrike')
|
|
var makeHeader = $('#makeHeader')
|
|
var makeCode = $('#makeCode')
|
|
var makeQuote = $('#makeQuote')
|
|
var makeGenericList = $('#makeGenericList')
|
|
var makeOrderedList = $('#makeOrderedList')
|
|
var makeCheckList = $('#makeCheckList')
|
|
var makeLink = $('#makeLink')
|
|
var makeImage = $('#makeImage')
|
|
var makeTable = $('#makeTable')
|
|
var makeLine = $('#makeLine')
|
|
var makeComment = $('#makeComment')
|
|
var uploadImage = $('#uploadImage')
|
|
var makeDiagramUMLSequenc = $('#makeDiagramUMLSequenc')
|
|
var makeDiagramFlow = $('#makeDiagramFlow')
|
|
var makeDiagramGraphviz = $('#makeDiagramGraphviz')
|
|
var makeDiagramMermaidFlowchart = $('#makeDiagramMermaidFlowchart')
|
|
var makeDiagramMermaidSequence = $('#makeDiagramMermaidSequence')
|
|
var makeDiagramMermaidClass = $('#makeDiagramMermaidClass')
|
|
var makeDiagramMermaidState = $('#makeDiagramMermaidState')
|
|
var makeDiagramMermaidGantt = $('#makeDiagramMermaidGantt')
|
|
var makeDiagramMermaidPie = $('#makeDiagramMermaidPie')
|
|
var makeDiagramAbcMusic = $('#makeDiagramAbcMusic')
|
|
|
|
makeBold.click(() => {
|
|
utils.wrapTextWith(this.editor, this.editor, '**')
|
|
this.editor.focus()
|
|
})
|
|
|
|
makeItalic.click(() => {
|
|
utils.wrapTextWith(this.editor, this.editor, '*')
|
|
this.editor.focus()
|
|
})
|
|
|
|
makeStrike.click(() => {
|
|
utils.wrapTextWith(this.editor, this.editor, '~~')
|
|
this.editor.focus()
|
|
})
|
|
|
|
makeHeader.click(() => {
|
|
utils.insertHeader(this.editor)
|
|
})
|
|
|
|
makeCode.click(() => {
|
|
utils.wrapTextWith(this.editor, this.editor, '```')
|
|
this.editor.focus()
|
|
})
|
|
|
|
makeQuote.click(() => {
|
|
utils.insertOnStartOfLines(this.editor, '> ')
|
|
})
|
|
|
|
makeGenericList.click(() => {
|
|
utils.insertOnStartOfLines(this.editor, '* ')
|
|
})
|
|
|
|
makeOrderedList.click(() => {
|
|
utils.insertOnStartOfLines(this.editor, '1. ')
|
|
})
|
|
|
|
makeCheckList.click(() => {
|
|
utils.insertOnStartOfLines(this.editor, '- [ ] ')
|
|
})
|
|
|
|
makeLink.click(() => {
|
|
utils.insertLink(this.editor, false)
|
|
})
|
|
|
|
makeImage.click(() => {
|
|
utils.insertLink(this.editor, true)
|
|
})
|
|
|
|
makeTable.click(() => {
|
|
utils.insertText(this.editor, '\n\n| Column 1 | Column 2 | Column 3 |\n| -------- | -------- | -------- |\n| Text | Text | Text |\n')
|
|
})
|
|
|
|
makeLine.click(() => {
|
|
utils.insertText(this.editor, '\n----\n')
|
|
})
|
|
|
|
makeComment.click(() => {
|
|
utils.insertText(this.editor, '> []')
|
|
})
|
|
|
|
uploadImage.bind('change', function (e) {
|
|
var files = e.target.files || e.dataTransfer.files
|
|
e.dataTransfer = {}
|
|
e.dataTransfer.files = files
|
|
inlineAttach.onDrop(e)
|
|
})
|
|
|
|
makeDiagramUMLSequenc.click(() => {
|
|
utils.insertText(this.editor, '```sequence\nAlice->Bob: Hello Bob, how are you?\nNote right of Bob: Bob thinks\nBob-->Alice: I am good thanks!\nNote left of Alice: Alice responds\nAlice->Bob: Where have you been?\n```\n')
|
|
})
|
|
makeDiagramFlow.click(() => {
|
|
utils.insertText(this.editor, '```flow\nst=>start: Start\ne=>end: End\nop=>operation: My Operation\nop2=>operation: lalala\ncond=>condition: Yes or No?\n\nst->op->op2->cond\ncond(yes)->e\ncond(no)->op2\n```\n')
|
|
})
|
|
makeDiagramGraphviz.click(() => {
|
|
utils.insertText(this.editor, '```graphviz\ndigraph hierarchy {\nnodesep=1.0 // Increases the separation between nodes\n\nnode [color=Red,fontname=Courier,shape=box] // All nodes will this shape and colour\nedge [color=Blue, style=dashed] // All the lines look like this\n\nHeadteacher->{Deputy1 Deputy2 BusinessManager}\nDeputy1->{Teacher1 Teacher2}\nBusinessManager->ITManager\n{rank=same;ITManager Teacher1 Teacher2} // Put them on the same level\n}\n```\n')
|
|
})
|
|
makeDiagramMermaidFlowchart.click(() => {
|
|
utils.insertText(this.editor, '```mermaid\ngraph TB\nc1-->a2\nsubgraph one\na1-->a2\nend\nsubgraph two\nb1-->b2\nend\nc1-->c2\n```\n')
|
|
})
|
|
makeDiagramMermaidSequence.click(() => {
|
|
utils.insertText(this.editor, '```mermaid\nsequenceDiagram\nAlice->>John: Hello John, how are you?\nJohn-->>Alice: Great!\n```')
|
|
})
|
|
makeDiagramMermaidClass.click(() => {
|
|
utils.insertText(this.editor, '```mermaid\nclassDiagram\nAnimal <|-- Duck\nAnimal <|-- Fish\nAnimal <|-- Zebra\nAnimal : +int age\nAnimal : +String gender\nAnimal: +isMammal()\nAnimal: +mate()\nclass Duck{\n+String beakColor\n+swim()\n+quack()\n}\nclass Fish{\n-int sizeInFeet\n-canEat()\n}\nclass Zebra{\n+bool is_wild\n+run()\n}\n```')
|
|
})
|
|
makeDiagramMermaidState.click(() => {
|
|
utils.insertText(this.editor, '```mermaid\nstateDiagram\n[*] --> Still\nStill --> [*]\n\nStill --> Moving\nMoving --> Still\nMoving --> Crash\nCrash --> [*]\n```')
|
|
})
|
|
makeDiagramMermaidGantt.click(() => {
|
|
utils.insertText(this.editor, '```mermaid\ngantt\ntitle A Gantt Diagram\n\nsection Section\nA task: a1, 2014-01-01, 30d\nAnother task: after a1, 20d\n\nsection Another\nTask in sec: 2014-01-12, 12d\nAnother task: 24d\n```\n')
|
|
})
|
|
makeDiagramMermaidPie.click(() => {
|
|
utils.insertText(this.editor, '```mermaid\npie title Pets adopted by volunteers\n"Dogs" : 386\n"Cats" : 85\n"Rats" : 15\n```')
|
|
})
|
|
makeDiagramAbcMusic.click(() => {
|
|
utils.insertText(this.editor, '```abc\nX:1\nT:Speed the Plough\nM:4/4\nC:Trad.\nK:G\n|:GABc dedB|dedB dedB|c2ec B2dB|c2A2 A2BA|\nGABc dedB|dedB dedB|c2ec B2dB|A2F2 G4:|\n|:g2gf gdBd|g2f2 e2d2|c2ec B2dB|c2A2 A2df|\ng2gf g2Bd|g2f2 e2d2|c2ec B2dB|A2F2 G4:|\n```\n')
|
|
})
|
|
}
|
|
|
|
addStatusBar () {
|
|
this.statusBar = $(statusBarTemplate)
|
|
this.statusCursor = this.statusBar.find('.status-cursor > .status-line-column')
|
|
this.statusSelection = this.statusBar.find('.status-cursor > .status-selection')
|
|
this.statusFile = this.statusBar.find('.status-file')
|
|
this.statusIndicators = this.statusBar.find('.status-indicators')
|
|
this.statusIndent = this.statusBar.find('.status-indent')
|
|
this.statusKeymap = this.statusBar.find('.status-keymap')
|
|
this.statusLength = this.statusBar.find('.status-length')
|
|
this.statusTheme = this.statusBar.find('.status-theme')
|
|
this.statusSpellcheck = this.statusBar.find('.status-spellcheck')
|
|
this.statusPreferences = this.statusBar.find('.status-preferences')
|
|
this.statusPanel = this.editor.addPanel(this.statusBar[0], {
|
|
position: 'bottom'
|
|
})
|
|
|
|
this.setIndent()
|
|
this.setKeymap()
|
|
this.setTheme()
|
|
this.setSpellcheck()
|
|
this.setPreferences()
|
|
}
|
|
|
|
updateStatusBar () {
|
|
if (!this.statusBar) return
|
|
|
|
var cursor = this.editor.getCursor()
|
|
var cursorText = 'Line ' + (cursor.line + 1) + ', Columns ' + (cursor.ch + 1)
|
|
this.statusCursor.text(cursorText)
|
|
var fileText = ' — ' + editor.lineCount() + ' Lines'
|
|
this.statusFile.text(fileText)
|
|
var docLength = editor.getValue().length
|
|
this.statusLength.text('Length ' + docLength)
|
|
if (docLength > (config.docmaxlength * 0.95)) {
|
|
this.statusLength.css('color', 'red')
|
|
this.statusLength.attr('title', 'You have almost reached the limit for this document.')
|
|
} else if (docLength > (config.docmaxlength * 0.8)) {
|
|
this.statusLength.css('color', 'orange')
|
|
this.statusLength.attr('title', 'This document is nearly full, consider splitting it or creating a new one.')
|
|
} else {
|
|
this.statusLength.css('color', 'white')
|
|
this.statusLength.attr('title', 'You can write up to ' + config.docmaxlength + ' characters in this document.')
|
|
}
|
|
}
|
|
|
|
setIndent () {
|
|
var cookieIndentType = Cookies.get('indent_type')
|
|
var cookieTabSize = parseInt(Cookies.get('tab_size'))
|
|
var cookieSpaceUnits = parseInt(Cookies.get('space_units'))
|
|
if (cookieIndentType) {
|
|
if (cookieIndentType === 'tab') {
|
|
this.editor.setOption('indentWithTabs', true)
|
|
if (cookieTabSize) {
|
|
this.editor.setOption('indentUnit', cookieTabSize)
|
|
}
|
|
} else if (cookieIndentType === 'space') {
|
|
this.editor.setOption('indentWithTabs', false)
|
|
if (cookieSpaceUnits) {
|
|
this.editor.setOption('indentUnit', cookieSpaceUnits)
|
|
}
|
|
}
|
|
}
|
|
if (cookieTabSize) {
|
|
this.editor.setOption('tabSize', cookieTabSize)
|
|
}
|
|
|
|
var type = this.statusIndicators.find('.indent-type')
|
|
var widthLabel = this.statusIndicators.find('.indent-width-label')
|
|
var widthInput = this.statusIndicators.find('.indent-width-input')
|
|
|
|
const setType = () => {
|
|
if (this.editor.getOption('indentWithTabs')) {
|
|
Cookies.set('indent_type', 'tab', {
|
|
expires: 365,
|
|
sameSite: 'strict'
|
|
})
|
|
type.text('Tab Size:')
|
|
} else {
|
|
Cookies.set('indent_type', 'space', {
|
|
expires: 365,
|
|
sameSite: 'strict'
|
|
})
|
|
type.text('Spaces:')
|
|
}
|
|
}
|
|
setType()
|
|
|
|
const setUnit = () => {
|
|
var unit = this.editor.getOption('indentUnit')
|
|
if (this.editor.getOption('indentWithTabs')) {
|
|
Cookies.set('tab_size', unit, {
|
|
expires: 365,
|
|
sameSite: 'strict'
|
|
})
|
|
} else {
|
|
Cookies.set('space_units', unit, {
|
|
expires: 365,
|
|
sameSite: 'strict'
|
|
})
|
|
}
|
|
widthLabel.text(unit)
|
|
}
|
|
setUnit()
|
|
|
|
type.click(() => {
|
|
if (this.editor.getOption('indentWithTabs')) {
|
|
this.editor.setOption('indentWithTabs', false)
|
|
cookieSpaceUnits = parseInt(Cookies.get('space_units'))
|
|
if (cookieSpaceUnits) {
|
|
this.editor.setOption('indentUnit', cookieSpaceUnits)
|
|
}
|
|
} else {
|
|
this.editor.setOption('indentWithTabs', true)
|
|
cookieTabSize = parseInt(Cookies.get('tab_size'))
|
|
if (cookieTabSize) {
|
|
this.editor.setOption('indentUnit', cookieTabSize)
|
|
this.editor.setOption('tabSize', cookieTabSize)
|
|
}
|
|
}
|
|
setType()
|
|
setUnit()
|
|
})
|
|
widthLabel.click(() => {
|
|
if (widthLabel.is(':visible')) {
|
|
widthLabel.addClass('hidden')
|
|
widthInput.removeClass('hidden')
|
|
widthInput.val(this.editor.getOption('indentUnit'))
|
|
widthInput.select()
|
|
} else {
|
|
widthLabel.removeClass('hidden')
|
|
widthInput.addClass('hidden')
|
|
}
|
|
})
|
|
widthInput.on('change', () => {
|
|
var val = parseInt(widthInput.val())
|
|
if (!val) val = this.editor.getOption('indentUnit')
|
|
if (val < 1) val = 1
|
|
else if (val > 10) val = 10
|
|
|
|
if (this.editor.getOption('indentWithTabs')) {
|
|
this.editor.setOption('tabSize', val)
|
|
}
|
|
this.editor.setOption('indentUnit', val)
|
|
setUnit()
|
|
})
|
|
widthInput.on('blur', function () {
|
|
widthLabel.removeClass('hidden')
|
|
widthInput.addClass('hidden')
|
|
})
|
|
}
|
|
|
|
setKeymap () {
|
|
var cookieKeymap = Cookies.get('keymap')
|
|
if (cookieKeymap) {
|
|
this.editor.setOption('keyMap', cookieKeymap)
|
|
}
|
|
|
|
var label = this.statusIndicators.find('.ui-keymap-label')
|
|
var sublime = this.statusIndicators.find('.ui-keymap-sublime')
|
|
var emacs = this.statusIndicators.find('.ui-keymap-emacs')
|
|
var vim = this.statusIndicators.find('.ui-keymap-vim')
|
|
|
|
const setKeymapLabel = () => {
|
|
var keymap = this.editor.getOption('keyMap')
|
|
Cookies.set('keymap', keymap, {
|
|
expires: 365,
|
|
sameSite: 'strict'
|
|
})
|
|
label.text(keymap)
|
|
this.restoreOverrideEditorKeymap()
|
|
this.setOverrideBrowserKeymap()
|
|
}
|
|
setKeymapLabel()
|
|
|
|
sublime.click(() => {
|
|
this.editor.setOption('keyMap', 'sublime')
|
|
setKeymapLabel()
|
|
})
|
|
emacs.click(() => {
|
|
this.editor.setOption('keyMap', 'emacs')
|
|
setKeymapLabel()
|
|
})
|
|
vim.click(() => {
|
|
this.editor.setOption('keyMap', 'vim')
|
|
setKeymapLabel()
|
|
})
|
|
}
|
|
|
|
setTheme () {
|
|
var cookieTheme = Cookies.get('theme')
|
|
if (cookieTheme) {
|
|
this.editor.setOption('theme', cookieTheme)
|
|
}
|
|
|
|
var themeToggle = this.statusTheme.find('.ui-theme-toggle')
|
|
|
|
const checkTheme = () => {
|
|
var theme = this.editor.getOption('theme')
|
|
if (theme === 'one-dark') {
|
|
themeToggle.removeClass('active')
|
|
} else {
|
|
themeToggle.addClass('active')
|
|
}
|
|
}
|
|
|
|
themeToggle.click(() => {
|
|
var theme = this.editor.getOption('theme')
|
|
if (theme === 'one-dark') {
|
|
theme = 'default'
|
|
} else {
|
|
theme = 'one-dark'
|
|
}
|
|
this.editor.setOption('theme', theme)
|
|
Cookies.set('theme', theme, {
|
|
expires: 365,
|
|
sameSite: 'strict'
|
|
})
|
|
|
|
checkTheme()
|
|
})
|
|
|
|
checkTheme()
|
|
}
|
|
|
|
setSpellcheck () {
|
|
var cookieSpellcheck = Cookies.get('spellcheck')
|
|
if (cookieSpellcheck) {
|
|
var mode = null
|
|
if (cookieSpellcheck === 'true' || cookieSpellcheck === true) {
|
|
mode = 'spell-checker'
|
|
} else {
|
|
mode = defaultEditorMode
|
|
}
|
|
if (mode && mode !== this.editor.getOption('mode')) {
|
|
this.editor.setOption('mode', mode)
|
|
}
|
|
}
|
|
|
|
var spellcheckToggle = this.statusSpellcheck.find('.ui-spellcheck-toggle')
|
|
|
|
const checkSpellcheck = () => {
|
|
var mode = this.editor.getOption('mode')
|
|
if (mode === defaultEditorMode) {
|
|
spellcheckToggle.removeClass('active')
|
|
} else {
|
|
spellcheckToggle.addClass('active')
|
|
}
|
|
}
|
|
|
|
spellcheckToggle.click(() => {
|
|
var mode = this.editor.getOption('mode')
|
|
if (mode === defaultEditorMode) {
|
|
mode = 'spell-checker'
|
|
} else {
|
|
mode = defaultEditorMode
|
|
}
|
|
if (mode && mode !== this.editor.getOption('mode')) {
|
|
this.editor.setOption('mode', mode)
|
|
}
|
|
Cookies.set('spellcheck', mode === 'spell-checker', {
|
|
expires: 365,
|
|
sameSite: 'strict'
|
|
})
|
|
|
|
checkSpellcheck()
|
|
})
|
|
|
|
checkSpellcheck()
|
|
|
|
// workaround spellcheck might not activate beacuse the ajax loading
|
|
if (window.num_loaded < 2) {
|
|
var spellcheckTimer = setInterval(
|
|
() => {
|
|
if (window.num_loaded >= 2) {
|
|
if (this.editor.getOption('mode') === 'spell-checker') {
|
|
this.editor.setOption('mode', 'spell-checker')
|
|
}
|
|
clearInterval(spellcheckTimer)
|
|
}
|
|
},
|
|
100
|
|
)
|
|
}
|
|
}
|
|
|
|
resetEditorKeymapToBrowserKeymap () {
|
|
var keymap = this.editor.getOption('keyMap')
|
|
if (!this.jumpToAddressBarKeymapValue) {
|
|
this.jumpToAddressBarKeymapValue = CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName]
|
|
delete CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName]
|
|
}
|
|
}
|
|
|
|
restoreOverrideEditorKeymap () {
|
|
var keymap = this.editor.getOption('keyMap')
|
|
if (this.jumpToAddressBarKeymapValue) {
|
|
CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName] = this.jumpToAddressBarKeymapValue
|
|
this.jumpToAddressBarKeymapValue = null
|
|
}
|
|
}
|
|
setOverrideBrowserKeymap () {
|
|
var overrideBrowserKeymap = $(
|
|
'.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
|
|
)
|
|
if (overrideBrowserKeymap.is(':checked')) {
|
|
Cookies.set('preferences-override-browser-keymap', true, {
|
|
expires: 365,
|
|
sameSite: 'strict'
|
|
})
|
|
this.restoreOverrideEditorKeymap()
|
|
} else {
|
|
Cookies.remove('preferences-override-browser-keymap')
|
|
this.resetEditorKeymapToBrowserKeymap()
|
|
}
|
|
}
|
|
|
|
setPreferences () {
|
|
var overrideBrowserKeymap = $(
|
|
'.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
|
|
)
|
|
var cookieOverrideBrowserKeymap = Cookies.get(
|
|
'preferences-override-browser-keymap'
|
|
)
|
|
if (cookieOverrideBrowserKeymap && cookieOverrideBrowserKeymap === 'true') {
|
|
overrideBrowserKeymap.prop('checked', true)
|
|
} else {
|
|
overrideBrowserKeymap.prop('checked', false)
|
|
}
|
|
this.setOverrideBrowserKeymap()
|
|
|
|
overrideBrowserKeymap.change(() => {
|
|
this.setOverrideBrowserKeymap()
|
|
})
|
|
}
|
|
|
|
init (textit) {
|
|
this.editor = CodeMirror.fromTextArea(textit, {
|
|
mode: defaultEditorMode,
|
|
backdrop: defaultEditorMode,
|
|
keyMap: 'sublime',
|
|
viewportMargin: viewportMargin,
|
|
styleActiveLine: true,
|
|
lineNumbers: true,
|
|
lineWrapping: true,
|
|
showCursorWhenSelecting: true,
|
|
highlightSelectionMatches: true,
|
|
indentUnit: 4,
|
|
continueComments: 'Enter',
|
|
theme: 'one-dark',
|
|
inputStyle: 'textarea',
|
|
matchBrackets: true,
|
|
autoCloseBrackets: true,
|
|
matchTags: {
|
|
bothTags: true
|
|
},
|
|
autoCloseTags: true,
|
|
foldGutter: true,
|
|
gutters: [
|
|
'CodeMirror-linenumbers',
|
|
'authorship-gutters',
|
|
'CodeMirror-foldgutter'
|
|
],
|
|
extraKeys: this.defaultExtraKeys,
|
|
flattenSpans: true,
|
|
addModeClass: true,
|
|
readOnly: true,
|
|
autoRefresh: true,
|
|
otherCursors: true,
|
|
placeholder: "← Start by entering a title here\n===\nVisit /features if you don't know what to do.\nHappy hacking :)"
|
|
})
|
|
|
|
return this.editor
|
|
}
|
|
|
|
getEditor () {
|
|
return this.editor
|
|
}
|
|
}
|