Skip to content

Commit fe19d96

Browse files
authored
Merge branch 'master' into translation-pt
2 parents f18e8c5 + 3793378 commit fe19d96

Some content is hidden

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

69 files changed

+1159
-276
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: 12 additions & 4 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
}
@@ -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/MarkdownPreview.js

Lines changed: 29 additions & 16 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()
@@ -737,7 +737,6 @@ export default class MarkdownPreview extends React.Component {
737737
el.addEventListener('click', this.linkClickHandler)
738738
})
739739
} catch (e) {
740-
console.error(e)
741740
el.className = 'flowchart-error'
742741
el.innerHTML = 'Flowchart parse error: ' + e.message
743742
}
@@ -758,7 +757,6 @@ export default class MarkdownPreview extends React.Component {
758757
el.addEventListener('click', this.linkClickHandler)
759758
})
760759
} catch (e) {
761-
console.error(e)
762760
el.className = 'sequence-error'
763761
el.innerHTML = 'Sequence diagram parse error: ' + e.message
764762
}
@@ -771,12 +769,18 @@ export default class MarkdownPreview extends React.Component {
771769
try {
772770
const chartConfig = JSON.parse(el.innerHTML)
773771
el.innerHTML = ''
774-
var canvas = document.createElement('canvas')
772+
773+
const canvas = document.createElement('canvas')
775774
el.appendChild(canvas)
776-
/* eslint-disable no-new */
777-
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)
778783
} catch (e) {
779-
console.error(e)
780784
el.className = 'chart-error'
781785
el.innerHTML = 'chartjs diagram parse error: ' + e.message
782786
}
@@ -860,6 +864,15 @@ export default class MarkdownPreview extends React.Component {
860864
return
861865
}
862866

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+
863876
// this will match the old link format storage.key-note.key
864877
// e.g.
865878
// 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)

0 commit comments

Comments
 (0)