Skip to content

Commit c5bcfe6

Browse files
committed
Merge branch 'master' into fence-attrs
2 parents a4ad389 + 00ed0d7 commit c5bcfe6

Some content is hidden

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

66 files changed

+905
-184
lines changed

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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ class MarkdownEditor extends React.Component {
6464
})
6565
}
6666

67+
setValue (value) {
68+
this.refs.code.setValue(value)
69+
}
70+
6771
handleChange (e) {
6872
this.value = this.refs.code.value
6973
this.props.onChange(e)
@@ -300,6 +304,7 @@ class MarkdownEditor extends React.Component {
300304
noteKey={noteKey}
301305
customCSS={config.preview.customCSS}
302306
allowCustomCSS={config.preview.allowCustomCSS}
307+
lineThroughCheckbox={config.preview.lineThroughCheckbox}
303308
/>
304309
</div>
305310
)

browser/components/MarkdownPreview.js

Lines changed: 19 additions & 10 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,
@@ -484,10 +487,6 @@ export default class MarkdownPreview extends React.Component {
484487
eventEmitter.on('export:save-md', this.saveAsMdHandler)
485488
eventEmitter.on('export:save-html', this.saveAsHtmlHandler)
486489
eventEmitter.on('print', this.printHandler)
487-
eventEmitter.on('config-renew', () => {
488-
this.markdown.updateConfig()
489-
this.rewriteIframe()
490-
})
491490
}
492491

493492
componentWillUnmount () {
@@ -531,7 +530,8 @@ export default class MarkdownPreview extends React.Component {
531530
prevProps.smartQuotes !== this.props.smartQuotes ||
532531
prevProps.sanitize !== this.props.sanitize ||
533532
prevProps.smartArrows !== this.props.smartArrows ||
534-
prevProps.breaks !== this.props.breaks
533+
prevProps.breaks !== this.props.breaks ||
534+
prevProps.lineThroughCheckbox !== this.props.lineThroughCheckbox
535535
) {
536536
this.initMarkdown()
537537
this.rewriteIframe()
@@ -864,6 +864,15 @@ export default class MarkdownPreview extends React.Component {
864864
return
865865
}
866866

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+
867876
// this will match the old link format storage.key-note.key
868877
// e.g.
869878
// 877f99c3268608328037-1c211eb7dcb463de6490

browser/components/MarkdownSplitEditor.js

Lines changed: 7 additions & 0 deletions
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
@@ -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'

browser/components/StorageList.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ import styles from './StorageList.styl'
77
import CSSModules from 'browser/lib/CSSModules'
88

99
/**
10-
* @param {Array} storgaeList
10+
* @param {Array} storageList
1111
*/
1212

1313
const StorageList = ({storageList, isFolded}) => (
1414
<div styleName={isFolded ? 'storageList-folded' : 'storageList'}>
1515
{storageList.length > 0 ? storageList : (
16-
<div styleName='storgaeList-empty'>No storage mount.</div>
16+
<div styleName='storageList-empty'>No storage mount.</div>
1717
)}
1818
</div>
1919
)
2020

2121
StorageList.propTypes = {
22-
storgaeList: PropTypes.arrayOf(PropTypes.element).isRequired
22+
storageList: PropTypes.arrayOf(PropTypes.element).isRequired
2323
}
2424
export default CSSModules(StorageList, styles)

browser/components/TagListItem.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import CSSModules from 'browser/lib/CSSModules'
1414
* @param {bool} isRelated
1515
*/
1616

17-
const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, isActive, isRelated, count}) => (
18-
<div styleName='tagList-itemContainer'>
17+
const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, handleContextMenu, isActive, isRelated, count}) => (
18+
<div styleName='tagList-itemContainer' onContextMenu={e => handleContextMenu(e, name)}>
1919
{isRelated
2020
? <button styleName={isActive ? 'tagList-itemNarrow-active' : 'tagList-itemNarrow'} onClick={() => handleClickNarrowToTag(name)}>
2121
<i className={isActive ? 'fa fa-minus-circle' : 'fa fa-plus-circle'} />
@@ -25,7 +25,7 @@ const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, isAc
2525
<button styleName={isActive ? 'tagList-item-active' : 'tagList-item'} onClick={() => handleClickTagListItem(name)}>
2626
<span styleName='tagList-item-name'>
2727
{`# ${name}`}
28-
<span styleName='tagList-item-count'>{count}</span>
28+
<span styleName='tagList-item-count'>{count !== 0 ? count : ''}</span>
2929
</span>
3030
</button>
3131
</div>

browser/components/TodoListPercentage.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,23 @@ import styles from './TodoListPercentage.styl'
1212
*/
1313

1414
const TodoListPercentage = ({
15-
percentageOfTodo
15+
percentageOfTodo, onClearCheckboxClick
1616
}) => (
1717
<div styleName='percentageBar' style={{display: isNaN(percentageOfTodo) ? 'none' : ''}}>
1818
<div styleName='progressBar' style={{width: `${percentageOfTodo}%`}}>
1919
<div styleName='progressBarInner'>
2020
<p styleName='percentageText'>{percentageOfTodo}%</p>
2121
</div>
2222
</div>
23+
<div styleName='todoClear'>
24+
<p styleName='todoClearText' onClick={(e) => onClearCheckboxClick(e)}>clear</p>
25+
</div>
2326
</div>
2427
)
2528

2629
TodoListPercentage.propTypes = {
27-
percentageOfTodo: PropTypes.number.isRequired
30+
percentageOfTodo: PropTypes.number.isRequired,
31+
onClearCheckboxClick: PropTypes.func.isRequired
2832
}
2933

3034
export default CSSModules(TodoListPercentage, styles)

browser/components/TodoListPercentage.styl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.percentageBar
2+
display: flex
23
position absolute
34
top 72px
45
right 0px
@@ -30,6 +31,20 @@
3031
color #f4f4f4
3132
font-weight 600
3233

34+
.todoClear
35+
display flex
36+
justify-content: flex-end
37+
position absolute
38+
z-index 120
39+
width 100%
40+
height 100%
41+
padding 2px 10px
42+
43+
.todoClearText
44+
color #f4f4f4
45+
cursor pointer
46+
font-weight 500
47+
3348
body[data-theme="dark"]
3449
.percentageBar
3550
background-color #444444
@@ -39,6 +54,9 @@ body[data-theme="dark"]
3954

4055
.percentageText
4156
color $ui-dark-text-color
57+
58+
.todoClearText
59+
color $ui-dark-text-color
4260

4361
body[data-theme="solarized-dark"]
4462
.percentageBar
@@ -50,6 +68,9 @@ body[data-theme="solarized-dark"]
5068
.percentageText
5169
color #fdf6e3
5270

71+
.todoClearText
72+
color #fdf6e3
73+
5374
body[data-theme="monokai"]
5475
.percentageBar
5576
background-color: $ui-monokai-borderColor
@@ -69,3 +90,6 @@ body[data-theme="dracula"]
6990

7091
.percentageText
7192
color $ui-dracula-text-color
93+
94+
.percentageText
95+
color $ui-dracula-text-color

browser/lib/Languages.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const languages = [
4949
},
5050
{
5151
name: 'Portuguese',
52-
locale: 'pt'
52+
locale: 'pt-BR'
5353
},
5454
{
5555
name: 'Russian',
@@ -61,6 +61,9 @@ const languages = [
6161
}, {
6262
name: 'Turkish',
6363
locale: 'tr'
64+
}, {
65+
name: 'Thai',
66+
locale: 'th'
6467
}
6568
]
6669

0 commit comments

Comments
 (0)