@@ -20,14 +20,15 @@ import styles from '../components/CodeEditor.styl'
20
20
const { ipcRenderer, remote, clipboard } = require ( 'electron' )
21
21
import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
22
22
const spellcheck = require ( 'browser/lib/spellcheck' )
23
- const buildEditorContextMenu = require ( 'browser/lib/contextMenuBuilder' )
24
- import TurndownService from 'turndown'
23
+ const buildEditorContextMenu = require ( 'browser/lib/contextMenuBuilder' ) . buildEditorContextMenu
24
+ import { createTurndownService } from '../lib/ turndown'
25
25
import { languageMaps } from '../lib/CMLanguageList'
26
26
import snippetManager from '../lib/SnippetManager'
27
27
import { generateInEditor , tocExistsInEditor } from 'browser/lib/markdown-toc-generator'
28
28
import markdownlint from 'markdownlint'
29
29
import Jsonlint from 'jsonlint-mod'
30
30
import { DEFAULT_CONFIG } from '../main/lib/ConfigManager'
31
+ import prettier from 'prettier'
31
32
32
33
CodeMirror . modeURL = '../node_modules/codemirror/mode/%N/%N.js'
33
34
@@ -53,6 +54,7 @@ export default class CodeEditor extends React.Component {
53
54
this . focusHandler = ( ) => {
54
55
ipcRenderer . send ( 'editor:focused' , true )
55
56
}
57
+ const debouncedDeletionOfAttachments = _ . debounce ( attachmentManagement . deleteAttachmentsNotPresentInNote , 30000 )
56
58
this . blurHandler = ( editor , e ) => {
57
59
ipcRenderer . send ( 'editor:focused' , false )
58
60
if ( e == null ) return null
@@ -64,16 +66,13 @@ export default class CodeEditor extends React.Component {
64
66
el = el . parentNode
65
67
}
66
68
this . props . onBlur != null && this . props . onBlur ( e )
67
-
68
69
const {
69
70
storageKey,
70
71
noteKey
71
72
} = this . props
72
- attachmentManagement . deleteAttachmentsNotPresentInNote (
73
- this . editor . getValue ( ) ,
74
- storageKey ,
75
- noteKey
76
- )
73
+ if ( this . props . deleteUnusedAttachments === true ) {
74
+ debouncedDeletionOfAttachments ( this . editor . getValue ( ) , storageKey , noteKey )
75
+ }
77
76
}
78
77
this . pasteHandler = ( editor , e ) => {
79
78
e . preventDefault ( )
@@ -102,15 +101,15 @@ export default class CodeEditor extends React.Component {
102
101
103
102
this . editorActivityHandler = ( ) => this . handleEditorActivity ( )
104
103
105
- this . turndownService = new TurndownService ( )
104
+ this . turndownService = createTurndownService ( )
106
105
}
107
106
108
107
handleSearch ( msg ) {
109
108
const cm = this . editor
110
109
const component = this
111
110
112
111
if ( component . searchState ) cm . removeOverlay ( component . searchState )
113
- if ( msg . length < 3 ) return
112
+ if ( msg . length < 1 ) return
114
113
115
114
cm . operation ( function ( ) {
116
115
component . searchState = makeOverlay ( msg , 'searching' )
@@ -205,23 +204,11 @@ export default class CodeEditor extends React.Component {
205
204
'Cmd-T' : function ( cm ) {
206
205
// Do nothing
207
206
} ,
208
- 'Ctrl-/' : function ( cm ) {
209
- if ( global . process . platform === 'darwin' ) { return }
207
+ [ translateHotkey ( hotkey . insertDate ) ] : function ( cm ) {
210
208
const dateNow = new Date ( )
211
209
cm . replaceSelection ( dateNow . toLocaleDateString ( ) )
212
210
} ,
213
- 'Cmd-/' : function ( cm ) {
214
- if ( global . process . platform !== 'darwin' ) { return }
215
- const dateNow = new Date ( )
216
- cm . replaceSelection ( dateNow . toLocaleDateString ( ) )
217
- } ,
218
- 'Shift-Ctrl-/' : function ( cm ) {
219
- if ( global . process . platform === 'darwin' ) { return }
220
- const dateNow = new Date ( )
221
- cm . replaceSelection ( dateNow . toLocaleString ( ) )
222
- } ,
223
- 'Shift-Cmd-/' : function ( cm ) {
224
- if ( global . process . platform !== 'darwin' ) { return }
211
+ [ translateHotkey ( hotkey . insertDateTime ) ] : function ( cm ) {
225
212
const dateNow = new Date ( )
226
213
cm . replaceSelection ( dateNow . toLocaleString ( ) )
227
214
} ,
@@ -232,6 +219,28 @@ export default class CodeEditor extends React.Component {
232
219
}
233
220
return CodeMirror . Pass
234
221
} ,
222
+ [ translateHotkey ( hotkey . prettifyMarkdown ) ] : cm => {
223
+ // Default / User configured prettier options
224
+ const currentConfig = JSON . parse ( self . props . prettierConfig )
225
+
226
+ // Parser type will always need to be markdown so we override the option before use
227
+ currentConfig . parser = 'markdown'
228
+
229
+ // Get current cursor position
230
+ const cursorPos = cm . getCursor ( )
231
+ currentConfig . cursorOffset = cm . doc . indexFromPos ( cursorPos )
232
+
233
+ // Prettify contents of editor
234
+ const formattedTextDetails = prettier . formatWithCursor ( cm . doc . getValue ( ) , currentConfig )
235
+
236
+ const formattedText = formattedTextDetails . formatted
237
+ const formattedCursorPos = formattedTextDetails . cursorOffset
238
+ cm . doc . setValue ( formattedText )
239
+
240
+ // Reset Cursor position to be at the same markdown as was before prettifying
241
+ const newCursorPos = cm . doc . posFromIndex ( formattedCursorPos )
242
+ cm . doc . setCursor ( newCursorPos )
243
+ } ,
235
244
[ translateHotkey ( hotkey . pasteSmartly ) ] : cm => {
236
245
this . handlePaste ( cm , true )
237
246
}
@@ -267,7 +276,7 @@ export default class CodeEditor extends React.Component {
267
276
value : this . props . value ,
268
277
linesHighlighted : this . props . linesHighlighted ,
269
278
lineNumbers : this . props . displayLineNumbers ,
270
- lineWrapping : true ,
279
+ lineWrapping : this . props . lineWrapping ,
271
280
theme : this . props . theme ,
272
281
indentUnit : this . props . indentSize ,
273
282
tabSize : this . props . indentSize ,
@@ -285,7 +294,8 @@ export default class CodeEditor extends React.Component {
285
294
explode : this . props . explodingPairs ,
286
295
override : true
287
296
} ,
288
- extraKeys : this . defaultKeyMap
297
+ extraKeys : this . defaultKeyMap ,
298
+ prettierConfig : this . props . prettierConfig
289
299
} )
290
300
291
301
document . querySelector ( '.CodeMirror-lint-markers' ) . style . display = enableMarkdownLint ? 'inline-block' : 'none'
@@ -566,6 +576,10 @@ export default class CodeEditor extends React.Component {
566
576
this . editor . setOption ( 'lineNumbers' , this . props . displayLineNumbers )
567
577
}
568
578
579
+ if ( prevProps . lineWrapping !== this . props . lineWrapping ) {
580
+ this . editor . setOption ( 'lineWrapping' , this . props . lineWrapping )
581
+ }
582
+
569
583
if ( prevProps . scrollPastEnd !== this . props . scrollPastEnd ) {
570
584
this . editor . setOption ( 'scrollPastEnd' , this . props . scrollPastEnd )
571
585
}
@@ -620,6 +634,9 @@ export default class CodeEditor extends React.Component {
620
634
this . editor . addPanel ( this . createSpellCheckPanel ( ) , { position : 'bottom' } )
621
635
}
622
636
}
637
+ if ( prevProps . deleteUnusedAttachments !== this . props . deleteUnusedAttachments ) {
638
+ this . editor . setOption ( 'deleteUnusedAttachments' , this . props . deleteUnusedAttachments )
639
+ }
623
640
624
641
if ( needRefresh ) {
625
642
this . editor . refresh ( )
@@ -848,6 +865,17 @@ export default class CodeEditor extends React.Component {
848
865
this . editor . setCursor ( cursor )
849
866
}
850
867
868
+ /**
869
+ * Update content of one line
870
+ * @param {Number } lineNumber
871
+ * @param {String } content
872
+ */
873
+ setLineContent ( lineNumber , content ) {
874
+ const prevContent = this . editor . getLine ( lineNumber )
875
+ const prevContentLength = prevContent ? prevContent . length : 0
876
+ this . editor . replaceRange ( content , { line : lineNumber , ch : 0 } , { line : lineNumber , ch : prevContentLength } )
877
+ }
878
+
851
879
handleDropImage ( dropEvent ) {
852
880
dropEvent . preventDefault ( )
853
881
const {
@@ -1186,7 +1214,8 @@ CodeEditor.propTypes = {
1186
1214
autoDetect : PropTypes . bool ,
1187
1215
spellCheck : PropTypes . bool ,
1188
1216
enableMarkdownLint : PropTypes . bool ,
1189
- customMarkdownLintConfig : PropTypes . string
1217
+ customMarkdownLintConfig : PropTypes . string ,
1218
+ deleteUnusedAttachments : PropTypes . bool
1190
1219
}
1191
1220
1192
1221
CodeEditor . defaultProps = {
@@ -1200,5 +1229,7 @@ CodeEditor.defaultProps = {
1200
1229
autoDetect : false ,
1201
1230
spellCheck : false ,
1202
1231
enableMarkdownLint : DEFAULT_CONFIG . editor . enableMarkdownLint ,
1203
- customMarkdownLintConfig : DEFAULT_CONFIG . editor . customMarkdownLintConfig
1232
+ customMarkdownLintConfig : DEFAULT_CONFIG . editor . customMarkdownLintConfig ,
1233
+ prettierConfig : DEFAULT_CONFIG . editor . prettierConfig ,
1234
+ deleteUnusedAttachments : DEFAULT_CONFIG . editor . deleteUnusedAttachments
1204
1235
}
0 commit comments