@@ -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,37 @@ 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
+ } ,
244
+ [ translateHotkey ( hotkey . sortLines ) ] : cm => {
245
+ const selection = cm . doc . getSelection ( )
246
+ const appendLineBreak = / \n $ / . test ( selection )
247
+
248
+ const sorted = _ . split ( selection . trim ( ) , '\n' ) . sort ( )
249
+ const sortedString = _ . join ( sorted , '\n' ) + ( appendLineBreak ? '\n' : '' )
250
+
251
+ cm . doc . replaceSelection ( sortedString )
252
+ } ,
235
253
[ translateHotkey ( hotkey . pasteSmartly ) ] : cm => {
236
254
this . handlePaste ( cm , true )
237
255
}
@@ -267,7 +285,7 @@ export default class CodeEditor extends React.Component {
267
285
value : this . props . value ,
268
286
linesHighlighted : this . props . linesHighlighted ,
269
287
lineNumbers : this . props . displayLineNumbers ,
270
- lineWrapping : true ,
288
+ lineWrapping : this . props . lineWrapping ,
271
289
theme : this . props . theme ,
272
290
indentUnit : this . props . indentSize ,
273
291
tabSize : this . props . indentSize ,
@@ -285,7 +303,8 @@ export default class CodeEditor extends React.Component {
285
303
explode : this . props . explodingPairs ,
286
304
override : true
287
305
} ,
288
- extraKeys : this . defaultKeyMap
306
+ extraKeys : this . defaultKeyMap ,
307
+ prettierConfig : this . props . prettierConfig
289
308
} )
290
309
291
310
document . querySelector ( '.CodeMirror-lint-markers' ) . style . display = enableMarkdownLint ? 'inline-block' : 'none'
@@ -566,6 +585,10 @@ export default class CodeEditor extends React.Component {
566
585
this . editor . setOption ( 'lineNumbers' , this . props . displayLineNumbers )
567
586
}
568
587
588
+ if ( prevProps . lineWrapping !== this . props . lineWrapping ) {
589
+ this . editor . setOption ( 'lineWrapping' , this . props . lineWrapping )
590
+ }
591
+
569
592
if ( prevProps . scrollPastEnd !== this . props . scrollPastEnd ) {
570
593
this . editor . setOption ( 'scrollPastEnd' , this . props . scrollPastEnd )
571
594
}
@@ -620,6 +643,9 @@ export default class CodeEditor extends React.Component {
620
643
this . editor . addPanel ( this . createSpellCheckPanel ( ) , { position : 'bottom' } )
621
644
}
622
645
}
646
+ if ( prevProps . deleteUnusedAttachments !== this . props . deleteUnusedAttachments ) {
647
+ this . editor . setOption ( 'deleteUnusedAttachments' , this . props . deleteUnusedAttachments )
648
+ }
623
649
624
650
if ( needRefresh ) {
625
651
this . editor . refresh ( )
@@ -848,6 +874,17 @@ export default class CodeEditor extends React.Component {
848
874
this . editor . setCursor ( cursor )
849
875
}
850
876
877
+ /**
878
+ * Update content of one line
879
+ * @param {Number } lineNumber
880
+ * @param {String } content
881
+ */
882
+ setLineContent ( lineNumber , content ) {
883
+ const prevContent = this . editor . getLine ( lineNumber )
884
+ const prevContentLength = prevContent ? prevContent . length : 0
885
+ this . editor . replaceRange ( content , { line : lineNumber , ch : 0 } , { line : lineNumber , ch : prevContentLength } )
886
+ }
887
+
851
888
handleDropImage ( dropEvent ) {
852
889
dropEvent . preventDefault ( )
853
890
const {
@@ -1181,7 +1218,8 @@ CodeEditor.propTypes = {
1181
1218
autoDetect : PropTypes . bool ,
1182
1219
spellCheck : PropTypes . bool ,
1183
1220
enableMarkdownLint : PropTypes . bool ,
1184
- customMarkdownLintConfig : PropTypes . string
1221
+ customMarkdownLintConfig : PropTypes . string ,
1222
+ deleteUnusedAttachments : PropTypes . bool
1185
1223
}
1186
1224
1187
1225
CodeEditor . defaultProps = {
@@ -1195,5 +1233,7 @@ CodeEditor.defaultProps = {
1195
1233
autoDetect : false ,
1196
1234
spellCheck : false ,
1197
1235
enableMarkdownLint : DEFAULT_CONFIG . editor . enableMarkdownLint ,
1198
- customMarkdownLintConfig : DEFAULT_CONFIG . editor . customMarkdownLintConfig
1236
+ customMarkdownLintConfig : DEFAULT_CONFIG . editor . customMarkdownLintConfig ,
1237
+ prettierConfig : DEFAULT_CONFIG . editor . prettierConfig ,
1238
+ deleteUnusedAttachments : DEFAULT_CONFIG . editor . deleteUnusedAttachments
1199
1239
}
0 commit comments