Skip to content

Commit a11b0f1

Browse files
committed
Merge branch 'master' into fix-issue#2644-and-#2662
2 parents 13857d4 + 7a3cab8 commit a11b0f1

33 files changed

+712
-293
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# EditorConfig is awesome: http://EditorConfig.org
1+
# EditorConfig is awesome: https://EditorConfig.org
22

33
# top-most EditorConfig file
44
root = true

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"${workspaceFolder}/index.js"
1818
],
1919
"windows": {
20-
"runtimeExecutable": "${workspaceFolder}/node_modeules/.bin/electron.cmd"
20+
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
2121
}
2222
},
2323
{

Backers.md

Lines changed: 0 additions & 72 deletions
This file was deleted.

browser/components/CodeEditor.js

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export default class CodeEditor extends React.Component {
3838
trailing: true
3939
})
4040
this.changeHandler = (editor, changeObject) => this.handleChange(editor, changeObject)
41+
this.highlightHandler = (editor, changeObject) => this.handleHighlight(editor, changeObject)
4142
this.focusHandler = () => {
4243
ipcRenderer.send('editor:focused', true)
4344
}
@@ -177,6 +178,9 @@ export default class CodeEditor extends React.Component {
177178
}
178179
}
179180
},
181+
'Cmd-Left': function (cm) {
182+
cm.execCommand('goLineLeft')
183+
},
180184
'Cmd-T': function (cm) {
181185
// Do nothing
182186
},
@@ -235,6 +239,7 @@ export default class CodeEditor extends React.Component {
235239
this.editor = CodeMirror(this.refs.root, {
236240
rulers: buildCMRulers(rulers, enableRulers),
237241
value: this.props.value,
242+
linesHighlighted: this.props.linesHighlighted,
238243
lineNumbers: this.props.displayLineNumbers,
239244
lineWrapping: true,
240245
theme: this.props.theme,
@@ -261,6 +266,7 @@ export default class CodeEditor extends React.Component {
261266
this.editor.on('focus', this.focusHandler)
262267
this.editor.on('blur', this.blurHandler)
263268
this.editor.on('change', this.changeHandler)
269+
this.editor.on('gutterClick', this.highlightHandler)
264270
this.editor.on('paste', this.pasteHandler)
265271
if (this.props.switchPreview !== 'RIGHTCLICK') {
266272
this.editor.on('contextmenu', this.contextMenuHandler)
@@ -339,6 +345,8 @@ export default class CodeEditor extends React.Component {
339345
this.setState({
340346
clientWidth: this.refs.root.clientWidth
341347
})
348+
349+
this.initialHighlighting()
342350
}
343351

344352
expandSnippet (line, cursor, cm, snippets) {
@@ -537,12 +545,96 @@ export default class CodeEditor extends React.Component {
537545

538546
handleChange (editor, changeObject) {
539547
spellcheck.handleChange(editor, changeObject)
548+
549+
this.updateHighlight(editor, changeObject)
550+
540551
this.value = editor.getValue()
541552
if (this.props.onChange) {
542553
this.props.onChange(editor)
543554
}
544555
}
545556

557+
incrementLines (start, linesAdded, linesRemoved, editor) {
558+
let highlightedLines = editor.options.linesHighlighted
559+
560+
const totalHighlightedLines = highlightedLines.length
561+
562+
let offset = linesAdded - linesRemoved
563+
564+
// Store new items to be added as we're changing the lines
565+
let newLines = []
566+
567+
let i = totalHighlightedLines
568+
569+
while (i--) {
570+
const lineNumber = highlightedLines[i]
571+
572+
// Interval that will need to be updated
573+
// Between start and (start + offset) remove highlight
574+
if (lineNumber >= start) {
575+
highlightedLines.splice(highlightedLines.indexOf(lineNumber), 1)
576+
577+
// Lines that need to be relocated
578+
if (lineNumber >= (start + linesRemoved)) {
579+
newLines.push(lineNumber + offset)
580+
}
581+
}
582+
}
583+
584+
// Adding relocated lines
585+
highlightedLines.push(...newLines)
586+
587+
if (this.props.onChange) {
588+
this.props.onChange(editor)
589+
}
590+
}
591+
592+
handleHighlight (editor, changeObject) {
593+
const lines = editor.options.linesHighlighted
594+
595+
if (!lines.includes(changeObject)) {
596+
lines.push(changeObject)
597+
editor.addLineClass(changeObject, 'text', 'CodeMirror-activeline-background')
598+
} else {
599+
lines.splice(lines.indexOf(changeObject), 1)
600+
editor.removeLineClass(changeObject, 'text', 'CodeMirror-activeline-background')
601+
}
602+
if (this.props.onChange) {
603+
this.props.onChange(editor)
604+
}
605+
}
606+
607+
updateHighlight (editor, changeObject) {
608+
const linesAdded = changeObject.text.length - 1
609+
const linesRemoved = changeObject.removed.length - 1
610+
611+
// If no lines added or removed return
612+
if (linesAdded === 0 && linesRemoved === 0) {
613+
return
614+
}
615+
616+
let start = changeObject.from.line
617+
618+
switch (changeObject.origin) {
619+
case '+insert", "undo':
620+
start += 1
621+
break
622+
623+
case 'paste':
624+
case '+delete':
625+
case '+input':
626+
if (changeObject.to.ch !== 0 || changeObject.from.ch !== 0) {
627+
start += 1
628+
}
629+
break
630+
631+
default:
632+
return
633+
}
634+
635+
this.incrementLines(start, linesAdded, linesRemoved, editor)
636+
}
637+
546638
moveCursorTo (row, col) {}
547639

548640
scrollToLine (event, num) {
@@ -567,6 +659,7 @@ export default class CodeEditor extends React.Component {
567659
this.value = this.props.value
568660
this.editor.setValue(this.props.value)
569661
this.editor.clearHistory()
662+
this.restartHighlighting()
570663
this.editor.on('change', this.changeHandler)
571664
this.editor.refresh()
572665
}
@@ -758,6 +851,29 @@ export default class CodeEditor extends React.Component {
758851
})
759852
}
760853

854+
initialHighlighting () {
855+
if (this.editor.options.linesHighlighted == null) {
856+
return
857+
}
858+
859+
const totalHighlightedLines = this.editor.options.linesHighlighted.length
860+
const totalAvailableLines = this.editor.lineCount()
861+
862+
for (let i = 0; i < totalHighlightedLines; i++) {
863+
const lineNumber = this.editor.options.linesHighlighted[i]
864+
if (lineNumber > totalAvailableLines) {
865+
// make sure that we skip the invalid lines althrough this case should not be happened.
866+
continue
867+
}
868+
this.editor.addLineClass(lineNumber, 'text', 'CodeMirror-activeline-background')
869+
}
870+
}
871+
872+
restartHighlighting () {
873+
this.editor.options.linesHighlighted = this.props.linesHighlighted
874+
this.initialHighlighting()
875+
}
876+
761877
mapImageResponse (response, pastedTxt) {
762878
return new Promise((resolve, reject) => {
763879
try {

browser/components/MarkdownEditor.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import MarkdownPreview from 'browser/components/MarkdownPreview'
77
import eventEmitter from 'browser/main/lib/eventEmitter'
88
import { findStorage } from 'browser/lib/findStorage'
99
import ConfigManager from 'browser/main/lib/ConfigManager'
10+
import attachmentManagement from 'browser/main/lib/dataApi/attachmentManagement'
1011

1112
class MarkdownEditor extends React.Component {
1213
constructor (props) {
@@ -221,6 +222,28 @@ class MarkdownEditor extends React.Component {
221222
this.refs.code.editor.replaceSelection(`${mdElement}${this.refs.code.editor.getSelection()}${mdElement}`)
222223
}
223224

225+
handleDropImage (dropEvent) {
226+
dropEvent.preventDefault()
227+
const { storageKey, noteKey } = this.props
228+
229+
this.setState({
230+
status: 'CODE'
231+
}, () => {
232+
this.refs.code.focus()
233+
234+
this.refs.code.editor.execCommand('goDocEnd')
235+
this.refs.code.editor.execCommand('goLineEnd')
236+
this.refs.code.editor.execCommand('newlineAndIndent')
237+
238+
attachmentManagement.handleAttachmentDrop(
239+
this.refs.code,
240+
storageKey,
241+
noteKey,
242+
dropEvent
243+
)
244+
})
245+
}
246+
224247
handleKeyUp (e) {
225248
const keyPressed = this.state.keyPressed
226249
keyPressed.delete(e.keyCode)
@@ -232,7 +255,7 @@ class MarkdownEditor extends React.Component {
232255
}
233256

234257
render () {
235-
const {className, value, config, storageKey, noteKey} = this.props
258+
const {className, value, config, storageKey, noteKey, linesHighlighted} = this.props
236259

237260
let editorFontSize = parseInt(config.editor.fontSize, 10)
238261
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
@@ -275,6 +298,7 @@ class MarkdownEditor extends React.Component {
275298
noteKey={noteKey}
276299
fetchUrlTitle={config.editor.fetchUrlTitle}
277300
enableTableEditor={config.editor.enableTableEditor}
301+
linesHighlighted={linesHighlighted}
278302
onChange={(e) => this.handleChange(e)}
279303
onBlur={(e) => this.handleBlur(e)}
280304
spellCheck={config.editor.spellcheck}
@@ -314,6 +338,7 @@ class MarkdownEditor extends React.Component {
314338
customCSS={config.preview.customCSS}
315339
allowCustomCSS={config.preview.allowCustomCSS}
316340
lineThroughCheckbox={config.preview.lineThroughCheckbox}
341+
onDrop={(e) => this.handleDropImage(e)}
317342
/>
318343
</div>
319344
)

0 commit comments

Comments
 (0)