Skip to content

Commit 5855cdf

Browse files
Merge branch 'master' into improve-french-translations
2 parents 52bea8f + 3793378 commit 5855cdf

File tree

106 files changed

+2212
-316
lines changed

Some content is hidden

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

106 files changed

+2212
-316
lines changed

ISSUE_TEMPLATE.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
11
# Current behavior
22

33
<!--
4-
Please paste some **screenshots** with the **developer tool** open (console tab) when you report a bug.
4+
Let us know what is currently happening.
55
6-
If your issue is regarding boostnote mobile, move to https://github.com/BoostIO/boostnote-mobile.
6+
Please include some **screenshots** with the **developer tools** open (console tab) when you report a bug.
7+
8+
If your issue is regarding Boostnote mobile, please open an issue in the Boostnote Mobile repo 👉 https://github.com/BoostIO/boostnote-mobile.
79
-->
810

911
# Expected behavior
1012

13+
<!--
14+
Let us know what you think should happen!
15+
-->
16+
1117
# Steps to reproduce
1218

19+
<!--
20+
Please be thorough, issues we can reproduce are easier to fix!
21+
-->
22+
1323
1.
1424
2.
1525
3.

browser/components/CodeEditor.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import consts from 'browser/lib/consts'
1414
import fs from 'fs'
1515
const { ipcRenderer } = require('electron')
1616
import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
17+
import TurndownService from 'turndown'
18+
import { gfm } from 'turndown-plugin-gfm'
1719

1820
CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js'
1921

@@ -57,6 +59,7 @@ export default class CodeEditor extends React.Component {
5759
}
5860
this.searchHandler = (e, msg) => this.handleSearch(msg)
5961
this.searchState = null
62+
this.scrollToLineHandeler = this.scrollToLine.bind(this)
6063

6164
this.formatTable = () => this.handleFormatTable()
6265
this.editorActivityHandler = () => this.handleEditorActivity()
@@ -125,6 +128,7 @@ export default class CodeEditor extends React.Component {
125128
componentDidMount () {
126129
const { rulers, enableRulers } = this.props
127130
const expandSnippet = this.expandSnippet.bind(this)
131+
eventEmitter.on('line:jump', this.scrollToLineHandeler)
128132

129133
const defaultSnippet = [
130134
{
@@ -475,7 +479,13 @@ export default class CodeEditor extends React.Component {
475479

476480
moveCursorTo (row, col) {}
477481

478-
scrollToLine (num) {}
482+
scrollToLine (event, num) {
483+
const cursor = {
484+
line: num,
485+
ch: 1
486+
}
487+
this.editor.setCursor(cursor)
488+
}
479489

480490
focus () {
481491
this.editor.focus()
@@ -538,7 +548,11 @@ export default class CodeEditor extends React.Component {
538548
)
539549
return prevChar === '](' && nextChar === ')'
540550
}
541-
if (dataTransferItem.type.match('image')) {
551+
552+
const pastedHtml = clipboardData.getData('text/html')
553+
if (pastedHtml !== '') {
554+
this.handlePasteHtml(e, editor, pastedHtml)
555+
} else if (dataTransferItem.type.match('image')) {
542556
attachmentManagement.handlePastImageEvent(
543557
this,
544558
storageKey,
@@ -608,6 +622,12 @@ export default class CodeEditor extends React.Component {
608622
})
609623
}
610624

625+
handlePasteHtml (e, editor, pastedHtml) {
626+
e.preventDefault()
627+
const markdown = this.turndownService.turndown(pastedHtml)
628+
editor.replaceSelection(markdown)
629+
}
630+
611631
mapNormalResponse (response, pastedTxt) {
612632
return this.decodeResponse(response).then(body => {
613633
return new Promise((resolve, reject) => {

browser/components/MarkdownEditor.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import CodeEditor from 'browser/components/CodeEditor'
66
import MarkdownPreview from 'browser/components/MarkdownPreview'
77
import eventEmitter from 'browser/main/lib/eventEmitter'
88
import { findStorage } from 'browser/lib/findStorage'
9+
import ConfigManager from 'browser/main/lib/ConfigManager'
910

1011
class MarkdownEditor extends React.Component {
1112
constructor (props) {
@@ -18,7 +19,7 @@ class MarkdownEditor extends React.Component {
1819
this.supportMdSelectionBold = [16, 17, 186]
1920

2021
this.state = {
21-
status: 'PREVIEW',
22+
status: props.config.editor.switchPreview === 'RIGHTCLICK' ? props.config.editor.delfaultStatus : 'PREVIEW',
2223
renderValue: props.value,
2324
keyPressed: new Set(),
2425
isLocked: false
@@ -64,6 +65,10 @@ class MarkdownEditor extends React.Component {
6465
})
6566
}
6667

68+
setValue (value) {
69+
this.refs.code.setValue(value)
70+
}
71+
6772
handleChange (e) {
6873
this.value = this.refs.code.value
6974
this.props.onChange(e)
@@ -72,9 +77,7 @@ class MarkdownEditor extends React.Component {
7277
handleContextMenu (e) {
7378
const { config } = this.props
7479
if (config.editor.switchPreview === 'RIGHTCLICK') {
75-
const newStatus = this.state.status === 'PREVIEW'
76-
? 'CODE'
77-
: 'PREVIEW'
80+
const newStatus = this.state.status === 'PREVIEW' ? 'CODE' : 'PREVIEW'
7881
this.setState({
7982
status: newStatus
8083
}, () => {
@@ -84,6 +87,10 @@ class MarkdownEditor extends React.Component {
8487
this.refs.preview.focus()
8588
}
8689
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
90+
91+
const newConfig = Object.assign({}, config)
92+
newConfig.editor.delfaultStatus = newStatus
93+
ConfigManager.set(newConfig)
8794
})
8895
}
8996
}
@@ -250,7 +257,7 @@ class MarkdownEditor extends React.Component {
250257
: 'codeEditor--hide'
251258
}
252259
ref='code'
253-
mode='GitHub Flavored Markdown'
260+
mode='Boost Flavored Markdown'
254261
value={value}
255262
theme={config.editor.theme}
256263
keyMap={config.editor.keyMap}
@@ -300,6 +307,7 @@ class MarkdownEditor extends React.Component {
300307
noteKey={noteKey}
301308
customCSS={config.preview.customCSS}
302309
allowCustomCSS={config.preview.allowCustomCSS}
310+
lineThroughCheckbox={config.preview.lineThroughCheckbox}
303311
/>
304312
</div>
305313
)

browser/components/MarkdownEditor.styl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
.preview
1717
display block
1818
absolute top bottom left right
19-
z-index 100
2019
background-color white
2120
height 100%
2221
width 100%

browser/components/MarkdownPreview.js

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import convertModeName from 'browser/lib/convertModeName'
1616
import copy from 'copy-to-clipboard'
1717
import mdurl from 'mdurl'
1818
import exportNote from 'browser/main/lib/dataApi/exportNote'
19-
import { escapeHtmlCharacters } from 'browser/lib/utils'
2019
import context from 'browser/lib/context'
2120
import i18n from 'browser/lib/i18n'
2221
import fs from 'fs'
@@ -80,14 +79,18 @@ function buildStyle (
8079
url('${appPath}/resources/fonts/MaterialIcons-Regular.woff') format('woff'),
8180
url('${appPath}/resources/fonts/MaterialIcons-Regular.ttf') format('truetype');
8281
}
83-
${allowCustomCSS ? customCSS : ''}
8482
${markdownStyle}
8583
8684
body {
8785
font-family: '${fontFamily.join("','")}';
8886
font-size: ${fontSize}px;
8987
${scrollPastEnd && 'padding-bottom: 90vh;'}
9088
}
89+
@media print {
90+
body {
91+
padding-bottom: initial;
92+
}
93+
}
9194
code {
9295
font-family: '${codeBlockFontFamily.join("','")}';
9396
background-color: rgba(0,0,0,0.04);
@@ -144,6 +147,8 @@ body p {
144147
display: none
145148
}
146149
}
150+
151+
${allowCustomCSS ? customCSS : ''}
147152
`
148153
}
149154

@@ -325,9 +330,7 @@ export default class MarkdownPreview extends React.Component {
325330
allowCustomCSS,
326331
customCSS
327332
)
328-
let body = this.markdown.render(
329-
escapeHtmlCharacters(noteContent, { detectCodeBlock: true })
330-
)
333+
let body = this.markdown.render(noteContent)
331334
const files = [this.GetCodeThemeLink(codeBlockTheme), ...CSS_FILES]
332335
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(
333336
noteContent,
@@ -425,6 +428,7 @@ export default class MarkdownPreview extends React.Component {
425428
case 'dark':
426429
case 'solarized-dark':
427430
case 'monokai':
431+
case 'dracula':
428432
return scrollBarDarkStyle
429433
default:
430434
return scrollBarStyle
@@ -526,7 +530,8 @@ export default class MarkdownPreview extends React.Component {
526530
prevProps.smartQuotes !== this.props.smartQuotes ||
527531
prevProps.sanitize !== this.props.sanitize ||
528532
prevProps.smartArrows !== this.props.smartArrows ||
529-
prevProps.breaks !== this.props.breaks
533+
prevProps.breaks !== this.props.breaks ||
534+
prevProps.lineThroughCheckbox !== this.props.lineThroughCheckbox
530535
) {
531536
this.initMarkdown()
532537
this.rewriteIframe()
@@ -732,7 +737,6 @@ export default class MarkdownPreview extends React.Component {
732737
el.addEventListener('click', this.linkClickHandler)
733738
})
734739
} catch (e) {
735-
console.error(e)
736740
el.className = 'flowchart-error'
737741
el.innerHTML = 'Flowchart parse error: ' + e.message
738742
}
@@ -753,7 +757,6 @@ export default class MarkdownPreview extends React.Component {
753757
el.addEventListener('click', this.linkClickHandler)
754758
})
755759
} catch (e) {
756-
console.error(e)
757760
el.className = 'sequence-error'
758761
el.innerHTML = 'Sequence diagram parse error: ' + e.message
759762
}
@@ -766,12 +769,18 @@ export default class MarkdownPreview extends React.Component {
766769
try {
767770
const chartConfig = JSON.parse(el.innerHTML)
768771
el.innerHTML = ''
769-
var canvas = document.createElement('canvas')
772+
773+
const canvas = document.createElement('canvas')
770774
el.appendChild(canvas)
771-
/* eslint-disable no-new */
772-
new Chart(canvas, chartConfig)
775+
776+
const height = el.attributes.getNamedItem('data-height')
777+
if (height && height.value !== 'undefined') {
778+
el.style.height = height.value + 'vh'
779+
canvas.height = height.value + 'vh'
780+
}
781+
782+
const chart = new Chart(canvas, chartConfig)
773783
} catch (e) {
774-
console.error(e)
775784
el.className = 'chart-error'
776785
el.innerHTML = 'chartjs diagram parse error: ' + e.message
777786
}
@@ -855,6 +864,15 @@ export default class MarkdownPreview extends React.Component {
855864
return
856865
}
857866

867+
const regexIsLine = /^:line:[0-9]/
868+
if (regexIsLine.test(linkHash)) {
869+
const numberPattern = /\d+/g
870+
871+
const lineNumber = parseInt(linkHash.match(numberPattern)[0])
872+
eventEmitter.emit('line:jump', lineNumber)
873+
return
874+
}
875+
858876
// this will match the old link format storage.key-note.key
859877
// e.g.
860878
// 877f99c3268608328037-1c211eb7dcb463de6490

browser/components/MarkdownSplitEditor.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,18 @@ class MarkdownSplitEditor extends React.Component {
2020
}
2121
}
2222

23+
setValue (value) {
24+
this.refs.code.setValue(value)
25+
}
26+
2327
handleOnChange () {
2428
this.value = this.refs.code.value
2529
this.props.onChange()
2630
}
2731

2832
handleScroll (e) {
33+
if (!this.props.config.preview.scrollSync) return
34+
2935
const previewDoc = _.get(this, 'refs.preview.refs.root.contentWindow.document')
3036
const codeDoc = _.get(this, 'refs.code.editor.doc')
3137
let srcTop, srcHeight, targetTop, targetHeight
@@ -145,7 +151,7 @@ class MarkdownSplitEditor extends React.Component {
145151
styleName='codeEditor'
146152
ref='code'
147153
width={this.state.codeEditorWidthInPercent + '%'}
148-
mode='GitHub Flavored Markdown'
154+
mode='Boost Flavored Markdown'
149155
value={value}
150156
theme={config.editor.theme}
151157
keyMap={config.editor.keyMap}
@@ -192,6 +198,7 @@ class MarkdownSplitEditor extends React.Component {
192198
noteKey={noteKey}
193199
customCSS={config.preview.customCSS}
194200
allowCustomCSS={config.preview.allowCustomCSS}
201+
lineThroughCheckbox={config.preview.lineThroughCheckbox}
195202
/>
196203
</div>
197204
)

browser/components/NoteItem.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,19 @@ const TagElement = ({ tagName }) => (
2424
/**
2525
* @description Tag element list component.
2626
* @param {Array|null} tags
27+
* @param {boolean} showTagsAlphabetically
2728
* @return {React.Component}
2829
*/
29-
const TagElementList = tags => {
30+
const TagElementList = (tags, showTagsAlphabetically) => {
3031
if (!isArray(tags)) {
3132
return []
3233
}
3334

34-
const tagElements = tags.map(tag => TagElement({ tagName: tag }))
35-
36-
return tagElements
35+
if (showTagsAlphabetically) {
36+
return _.sortBy(tags).map(tag => TagElement({ tagName: tag }))
37+
} else {
38+
return tags.map(tag => TagElement({ tagName: tag }))
39+
}
3740
}
3841

3942
/**
@@ -55,7 +58,8 @@ const NoteItem = ({
5558
pathname,
5659
storageName,
5760
folderName,
58-
viewType
61+
viewType,
62+
showTagsAlphabetically
5963
}) => (
6064
<div
6165
styleName={isActive ? 'item--active' : 'item'}
@@ -93,7 +97,7 @@ const NoteItem = ({
9397
<div styleName='item-bottom'>
9498
<div styleName='item-bottom-tagList'>
9599
{note.tags.length > 0
96-
? TagElementList(note.tags)
100+
? TagElementList(note.tags, showTagsAlphabetically)
97101
: <span
98102
style={{ fontStyle: 'italic', opacity: 0.5 }}
99103
styleName='item-bottom-tagList-empty'

0 commit comments

Comments
 (0)