Skip to content

Commit d125bd0

Browse files
committed
Merge branch 'master' into feature-tag-links
2 parents 2e380ce + d010c55 commit d125bd0

File tree

112 files changed

+5479
-3855
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+5479
-3855
lines changed

.eslintrc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
"globals": {
1919
"FileReader": true,
2020
"localStorage": true,
21-
"fetch": true
21+
"fetch": true,
22+
"Image": true,
23+
"MutationObserver": true
2224
},
2325
"env": {
2426
"jest": true

.github/FUNDING.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
custom: https://issuehunt.io/r/BoostIo/Boostnote
1+
issuehunt: BoostIo/Boostnote

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ node_modules/*
99
/secret
1010
*.log
1111
.idea
12-
.vscode
12+
.vscode
13+
package-lock.json

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ node_js:
33
- 8
44
script:
55
- npm run lint && npm run test
6-
- yarn jest
76
- 'if [[ ${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} = "master" ]]; then npm install -g grunt [email protected] && grunt pre-build; fi'
87
after_success:
98
- openssl aes-256-cbc -K $encrypted_440d7f9a3c38_key -iv $encrypted_440d7f9a3c38_iv

browser/components/CodeEditor.js

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ import styles from '../components/CodeEditor.styl'
2020
const { ipcRenderer, remote, clipboard } = require('electron')
2121
import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
2222
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'
2525
import {languageMaps} from '../lib/CMLanguageList'
2626
import snippetManager from '../lib/SnippetManager'
2727
import {generateInEditor, tocExistsInEditor} from 'browser/lib/markdown-toc-generator'
2828
import markdownlint from 'markdownlint'
2929
import Jsonlint from 'jsonlint-mod'
3030
import { DEFAULT_CONFIG } from '../main/lib/ConfigManager'
31+
import prettier from 'prettier'
3132

3233
CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js'
3334

@@ -53,6 +54,7 @@ export default class CodeEditor extends React.Component {
5354
this.focusHandler = () => {
5455
ipcRenderer.send('editor:focused', true)
5556
}
57+
const debouncedDeletionOfAttachments = _.debounce(attachmentManagement.deleteAttachmentsNotPresentInNote, 30000)
5658
this.blurHandler = (editor, e) => {
5759
ipcRenderer.send('editor:focused', false)
5860
if (e == null) return null
@@ -64,16 +66,13 @@ export default class CodeEditor extends React.Component {
6466
el = el.parentNode
6567
}
6668
this.props.onBlur != null && this.props.onBlur(e)
67-
6869
const {
6970
storageKey,
7071
noteKey
7172
} = 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+
}
7776
}
7877
this.pasteHandler = (editor, e) => {
7978
e.preventDefault()
@@ -102,15 +101,15 @@ export default class CodeEditor extends React.Component {
102101

103102
this.editorActivityHandler = () => this.handleEditorActivity()
104103

105-
this.turndownService = new TurndownService()
104+
this.turndownService = createTurndownService()
106105
}
107106

108107
handleSearch (msg) {
109108
const cm = this.editor
110109
const component = this
111110

112111
if (component.searchState) cm.removeOverlay(component.searchState)
113-
if (msg.length < 3) return
112+
if (msg.length < 1) return
114113

115114
cm.operation(function () {
116115
component.searchState = makeOverlay(msg, 'searching')
@@ -205,23 +204,11 @@ export default class CodeEditor extends React.Component {
205204
'Cmd-T': function (cm) {
206205
// Do nothing
207206
},
208-
'Ctrl-/': function (cm) {
209-
if (global.process.platform === 'darwin') { return }
207+
[translateHotkey(hotkey.insertDate)]: function (cm) {
210208
const dateNow = new Date()
211209
cm.replaceSelection(dateNow.toLocaleDateString())
212210
},
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) {
225212
const dateNow = new Date()
226213
cm.replaceSelection(dateNow.toLocaleString())
227214
},
@@ -232,6 +219,37 @@ export default class CodeEditor extends React.Component {
232219
}
233220
return CodeMirror.Pass
234221
},
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+
},
235253
[translateHotkey(hotkey.pasteSmartly)]: cm => {
236254
this.handlePaste(cm, true)
237255
}
@@ -267,7 +285,7 @@ export default class CodeEditor extends React.Component {
267285
value: this.props.value,
268286
linesHighlighted: this.props.linesHighlighted,
269287
lineNumbers: this.props.displayLineNumbers,
270-
lineWrapping: true,
288+
lineWrapping: this.props.lineWrapping,
271289
theme: this.props.theme,
272290
indentUnit: this.props.indentSize,
273291
tabSize: this.props.indentSize,
@@ -285,7 +303,8 @@ export default class CodeEditor extends React.Component {
285303
explode: this.props.explodingPairs,
286304
override: true
287305
},
288-
extraKeys: this.defaultKeyMap
306+
extraKeys: this.defaultKeyMap,
307+
prettierConfig: this.props.prettierConfig
289308
})
290309

291310
document.querySelector('.CodeMirror-lint-markers').style.display = enableMarkdownLint ? 'inline-block' : 'none'
@@ -566,6 +585,10 @@ export default class CodeEditor extends React.Component {
566585
this.editor.setOption('lineNumbers', this.props.displayLineNumbers)
567586
}
568587

588+
if (prevProps.lineWrapping !== this.props.lineWrapping) {
589+
this.editor.setOption('lineWrapping', this.props.lineWrapping)
590+
}
591+
569592
if (prevProps.scrollPastEnd !== this.props.scrollPastEnd) {
570593
this.editor.setOption('scrollPastEnd', this.props.scrollPastEnd)
571594
}
@@ -620,6 +643,9 @@ export default class CodeEditor extends React.Component {
620643
this.editor.addPanel(this.createSpellCheckPanel(), {position: 'bottom'})
621644
}
622645
}
646+
if (prevProps.deleteUnusedAttachments !== this.props.deleteUnusedAttachments) {
647+
this.editor.setOption('deleteUnusedAttachments', this.props.deleteUnusedAttachments)
648+
}
623649

624650
if (needRefresh) {
625651
this.editor.refresh()
@@ -848,6 +874,17 @@ export default class CodeEditor extends React.Component {
848874
this.editor.setCursor(cursor)
849875
}
850876

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+
851888
handleDropImage (dropEvent) {
852889
dropEvent.preventDefault()
853890
const {
@@ -1181,7 +1218,8 @@ CodeEditor.propTypes = {
11811218
autoDetect: PropTypes.bool,
11821219
spellCheck: PropTypes.bool,
11831220
enableMarkdownLint: PropTypes.bool,
1184-
customMarkdownLintConfig: PropTypes.string
1221+
customMarkdownLintConfig: PropTypes.string,
1222+
deleteUnusedAttachments: PropTypes.bool
11851223
}
11861224

11871225
CodeEditor.defaultProps = {
@@ -1195,5 +1233,7 @@ CodeEditor.defaultProps = {
11951233
autoDetect: false,
11961234
spellCheck: false,
11971235
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
11991239
}

browser/components/MarkdownEditor.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,24 +159,25 @@ class MarkdownEditor extends React.Component {
159159
e.preventDefault()
160160
e.stopPropagation()
161161
const idMatch = /checkbox-([0-9]+)/
162-
const checkedMatch = /^\s*[\+\-\*] \[x\]/i
163-
const uncheckedMatch = /^\s*[\+\-\*] \[ \]/
164-
const checkReplace = /\[x\]/i
165-
const uncheckReplace = /\[ \]/
162+
const checkedMatch = /^(\s*>?)*\s*[+\-*] \[x]/i
163+
const uncheckedMatch = /^(\s*>?)*\s*[+\-*] \[ ]/
164+
const checkReplace = /\[x]/i
165+
const uncheckReplace = /\[ ]/
166166
if (idMatch.test(e.target.getAttribute('id'))) {
167167
const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
168168
const lines = this.refs.code.value
169169
.split('\n')
170170

171171
const targetLine = lines[lineIndex]
172+
let newLine = targetLine
172173

173174
if (targetLine.match(checkedMatch)) {
174-
lines[lineIndex] = targetLine.replace(checkReplace, '[ ]')
175+
newLine = targetLine.replace(checkReplace, '[ ]')
175176
}
176177
if (targetLine.match(uncheckedMatch)) {
177-
lines[lineIndex] = targetLine.replace(uncheckReplace, '[x]')
178+
newLine = targetLine.replace(uncheckReplace, '[x]')
178179
}
179-
this.refs.code.setValue(lines.join('\n'))
180+
this.refs.code.setLineContent(lineIndex, newLine)
180181
}
181182
}
182183

@@ -304,6 +305,7 @@ class MarkdownEditor extends React.Component {
304305
enableRulers={config.editor.enableRulers}
305306
rulers={config.editor.rulers}
306307
displayLineNumbers={config.editor.displayLineNumbers}
308+
lineWrapping
307309
matchingPairs={config.editor.matchingPairs}
308310
matchingTriples={config.editor.matchingTriples}
309311
explodingPairs={config.editor.explodingPairs}
@@ -321,6 +323,8 @@ class MarkdownEditor extends React.Component {
321323
switchPreview={config.editor.switchPreview}
322324
enableMarkdownLint={config.editor.enableMarkdownLint}
323325
customMarkdownLintConfig={config.editor.customMarkdownLintConfig}
326+
prettierConfig={config.editor.prettierConfig}
327+
deleteUnusedAttachments={config.editor.deleteUnusedAttachments}
324328
/>
325329
<MarkdownPreview styleName={this.state.status === 'PREVIEW'
326330
? 'preview'
@@ -340,6 +344,7 @@ class MarkdownEditor extends React.Component {
340344
smartArrows={config.preview.smartArrows}
341345
breaks={config.preview.breaks}
342346
sanitize={config.preview.sanitize}
347+
mermaidHTMLLabel={config.preview.mermaidHTMLLabel}
343348
ref='preview'
344349
onContextMenu={(e) => this.handleContextMenu(e)}
345350
onDoubleClick={(e) => this.handleDoubleClick(e)}

0 commit comments

Comments
 (0)