diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 9859716d..492ba7b3 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -9,7 +9,7 @@ import iconv from 'iconv-lite' import crypto from 'crypto' import consts from 'browser/lib/consts' import fs from 'fs' -const { ipcRenderer, remote } = require('electron') +const { ipcRenderer } = require('electron') CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js' @@ -201,11 +201,11 @@ export default class CodeEditor extends React.Component { for (let i = 0; i < snippets.length; i++) { if (snippets[i].prefix.indexOf(wordBeforeCursor.text) !== -1) { if (snippets[i].content.indexOf(templateCursorString) !== -1) { - let snippetLines = snippets[i].content.split('\n') + const snippetLines = snippets[i].content.split('\n') let cursorLineNumber = 0 let cursorLinePosition = 0 for (let j = 0; j < snippetLines.length; j++) { - let cursorIndex = snippetLines[j].indexOf(templateCursorString) + const cursorIndex = snippetLines[j].indexOf(templateCursorString) if (cursorIndex !== -1) { cursorLineNumber = j cursorLinePosition = cursorIndex diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index aa920975..55d85bea 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -393,7 +393,7 @@ export default class MarkdownPreview extends React.Component { value = value.replace(codeBlock, htmlTextHelper.encodeEntities(codeBlock)) }) } - let renderedHTML = this.markdown.render(value) + const renderedHTML = this.markdown.render(value) this.refs.root.contentWindow.document.body.innerHTML = attachmentManagement.fixLocalURLS(renderedHTML, storagePath) _.forEach(this.refs.root.contentWindow.document.querySelectorAll('a'), (el) => { diff --git a/browser/lib/consts.js b/browser/lib/consts.js index 3837ef44..e744e87a 100644 --- a/browser/lib/consts.js +++ b/browser/lib/consts.js @@ -2,7 +2,6 @@ const path = require('path') const fs = require('sander') const { remote } = require('electron') const { app } = remote -const os = require('os') const themePath = process.env.NODE_ENV === 'production' ? path.join(app.getAppPath(), './node_modules/codemirror/theme') diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index 6b53478e..0e6bb088 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -183,7 +183,7 @@ class SideNav extends React.Component { ).filter( note => activeTags.every(tag => note.tags.includes(tag)) ) - let relatedTags = new Set() + const relatedTags = new Set() relatedNotes.forEach(note => note.tags.map(tag => relatedTags.add(tag))) return relatedTags } @@ -222,7 +222,7 @@ class SideNav extends React.Component { handleClickNarrowToTag (tag) { const { router } = this.context const { location } = this.props - let listOfTags = this.getActiveTags(location.pathname) + const listOfTags = this.getActiveTags(location.pathname) const indexOfTag = listOfTags.indexOf(tag) if (indexOfTag > -1) { listOfTags.splice(indexOfTag, 1) diff --git a/browser/main/lib/dataApi/attachmentManagement.js b/browser/main/lib/dataApi/attachmentManagement.js index 6d4d7406..ac0986e1 100644 --- a/browser/main/lib/dataApi/attachmentManagement.js +++ b/browser/main/lib/dataApi/attachmentManagement.js @@ -104,8 +104,8 @@ function handleAttachmentDrop (codeEditor, storageKey, noteKey, dropEvent) { const fileType = file['type'] copyAttachment(filePath, storageKey, noteKey).then((fileName) => { - let showPreview = fileType.startsWith('image') - let imageMd = generateAttachmentMarkdown(originalFileName, path.join(STORAGE_FOLDER_PLACEHOLDER, noteKey, fileName), showPreview) + const showPreview = fileType.startsWith('image') + const imageMd = generateAttachmentMarkdown(originalFileName, path.join(STORAGE_FOLDER_PLACEHOLDER, noteKey, fileName), showPreview) codeEditor.insertAttachmentMd(imageMd) }) } @@ -139,7 +139,7 @@ function handlePastImageEvent (codeEditor, storageKey, noteKey, dataTransferItem const destinationDir = path.join(targetStorage.path, DESTINATION_FOLDER, noteKey) createAttachmentDestinationFolder(targetStorage.path, noteKey) - let imageName = `${uniqueSlug()}.png` + const imageName = `${uniqueSlug()}.png` const imagePath = path.join(destinationDir, imageName) reader.onloadend = function () { @@ -147,7 +147,7 @@ function handlePastImageEvent (codeEditor, storageKey, noteKey, dataTransferItem base64data += base64data.replace('+', ' ') const binaryData = new Buffer(base64data, 'base64').toString('binary') fs.writeFile(imagePath, binaryData, 'binary') - let imageMd = generateAttachmentMarkdown(imageName, imagePath, true) + const imageMd = generateAttachmentMarkdown(imageName, imagePath, true) codeEditor.insertAttachmentMd(imageMd) } reader.readAsDataURL(blob) diff --git a/browser/main/lib/dataApi/fetchSnippet.js b/browser/main/lib/dataApi/fetchSnippet.js index 8d5a6efe..456a5090 100644 --- a/browser/main/lib/dataApi/fetchSnippet.js +++ b/browser/main/lib/dataApi/fetchSnippet.js @@ -1,5 +1,4 @@ import fs from 'fs' -import crypto from 'crypto' import consts from 'browser/lib/consts' function fetchSnippet (id, snippetFile) { diff --git a/browser/main/modals/PreferencesModal/SnippetEditor.js b/browser/main/modals/PreferencesModal/SnippetEditor.js index 250b0e78..010dcac8 100644 --- a/browser/main/modals/PreferencesModal/SnippetEditor.js +++ b/browser/main/modals/PreferencesModal/SnippetEditor.js @@ -1,8 +1,6 @@ import CodeMirror from 'codemirror' import React from 'react' import _ from 'lodash' -import fs from 'fs' -import consts from 'browser/lib/consts' import dataApi from 'browser/main/lib/dataApi' const defaultEditorFontFamily = ['Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'monospace'] @@ -71,10 +69,7 @@ export default class SnippetEditor extends React.Component { return (
) } diff --git a/browser/main/modals/PreferencesModal/SnippetList.js b/browser/main/modals/PreferencesModal/SnippetList.js new file mode 100644 index 00000000..3cf28cf6 --- /dev/null +++ b/browser/main/modals/PreferencesModal/SnippetList.js @@ -0,0 +1,87 @@ +import React from 'react' +import styles from './SnippetTab.styl' +import CSSModules from 'browser/lib/CSSModules' +import dataApi from 'browser/main/lib/dataApi' +import i18n from 'browser/lib/i18n' +import eventEmitter from 'browser/main/lib/eventEmitter' +const { remote } = require('electron') +const { Menu, MenuItem } = remote + +class SnippetList extends React.Component { + constructor (props) { + super(props) + this.state = { + snippets: [] + } + } + + componentDidMount () { + this.reloadSnippetList() + eventEmitter.on('snippetList:reload', this.reloadSnippetList.bind(this)) + } + + reloadSnippetList () { + dataApi.fetchSnippet().then(snippets => this.setState({snippets})) + } + + handleSnippetContextMenu (snippet) { + const menu = new Menu() + menu.append(new MenuItem({ + label: i18n.__('Delete snippet'), + click: () => { + this.deleteSnippet(snippet) + } + })) + menu.popup() + } + + deleteSnippet (snippet) { + dataApi.deleteSnippet(snippet).then(() => { + this.reloadSnippetList() + this.props.onSnippetDeleted(snippet) + }).catch(err => { throw err }) + } + + handleSnippetClick (snippet) { + this.props.onSnippetClick(snippet) + } + + createSnippet () { + dataApi.createSnippet().then(() => { + this.reloadSnippetList() + // scroll to end of list when added new snippet + const snippetList = document.getElementById('snippets') + snippetList.scrollTop = snippetList.scrollHeight + }).catch(err => { throw err }) + } + + render () { + const { snippets } = this.state + return ( +
+
+
+ +
+
+
    + { + snippets.map((snippet) => ( +
  • this.handleSnippetContextMenu(snippet)} + onClick={() => this.handleSnippetClick(snippet)}> + {snippet.name} +
  • + )) + } +
+
+ ) + } +} + +export default CSSModules(SnippetList, styles) diff --git a/browser/main/modals/PreferencesModal/SnippetTab.js b/browser/main/modals/PreferencesModal/SnippetTab.js index ddbfc1b0..67e9ace6 100644 --- a/browser/main/modals/PreferencesModal/SnippetTab.js +++ b/browser/main/modals/PreferencesModal/SnippetTab.js @@ -1,33 +1,33 @@ import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './SnippetTab.styl' -import fs from 'fs' import SnippetEditor from './SnippetEditor' import i18n from 'browser/lib/i18n' import dataApi from 'browser/main/lib/dataApi' -import consts from 'browser/lib/consts' - -const { remote } = require('electron') - -const { Menu, MenuItem } = remote +import SnippetList from './SnippetList' +import eventEmitter from 'browser/main/lib/eventEmitter' class SnippetTab extends React.Component { constructor (props) { super(props) - this.state = { - snippets: [], currentSnippet: null } this.changeDelay = null } - componentDidMount () { - this.reloadSnippetList() + handleSnippetNameOrPrefixChange () { + clearTimeout(this.changeDelay) + this.changeDelay = setTimeout(() => { + // notify the snippet editor that the name or prefix of snippet has been changed + this.snippetEditor.onSnippetNameOrPrefixChanged(this.state.currentSnippet) + eventEmitter.emit('snippetList:reload') + }, 500) } handleSnippetClick (snippet) { - if (this.state.currentSnippet === null || this.state.currentSnippet.id !== snippet.id) { + const { currentSnippet } = this.state + if (currentSnippet === null || currentSnippet.id !== snippet.id) { dataApi.fetchSnippet(snippet.id).then(changedSnippet => { // notify the snippet editor to load the content of the new snippet this.snippetEditor.onSnippetChanged(changedSnippet) @@ -36,70 +36,27 @@ class SnippetTab extends React.Component { } } - handleSnippetNameOrPrefixChange () { - clearTimeout(this.changeDelay) - this.changeDelay = setTimeout(() => { - // notify the snippet editor that the name or prefix of snippet has been changed - this.snippetEditor.onSnippetNameOrPrefixChanged(this.state.currentSnippet) - this.reloadSnippetList() - }, 500) + onSnippetNameOrPrefixChanged (e, type) { + const newSnippet = Object.assign({}, this.state.currentSnippet) + if (type === 'name') { + newSnippet.name = e.target.value + } else { + newSnippet.prefix = e.target.value + } + this.setState({ currentSnippet: newSnippet }) + this.handleSnippetNameOrPrefixChange() } - handleSnippetContextMenu (snippet) { - const menu = new Menu() - menu.append(new MenuItem({ - label: i18n.__('Delete snippet'), - click: () => { - this.deleteSnippet(snippet) - } - })) - menu.popup() - } - - reloadSnippetList () { - dataApi.fetchSnippet().then(snippets => this.setState({snippets})) - } - - deleteSnippet (snippet) { - dataApi.deleteSnippet(snippet).then(() => { - this.reloadSnippetList() - // prevent old snippet still display when deleted - if (snippet.id === this.state.currentSnippet.id) { - this.setState({currentSnippet: null}) - } - }).catch(err => { throw err }) - } - - createSnippet () { - dataApi.createSnippet().then(() => { - this.reloadSnippetList() - // scroll to end of list when added new snippet - const snippetList = document.getElementById('snippets') - snippetList.scrollTop = snippetList.scrollHeight - }).catch(err => { throw err }) - } - - renderSnippetList () { - const { snippets } = this.state - return ( - - ) + handleDeleteSnippet (snippet) { + // prevent old snippet still display when deleted + if (snippet.id === this.state.currentSnippet.id) { + this.setState({currentSnippet: null}) + } } render () { - const { config } = this.props + const { config, storageKey } = this.props + const { currentSnippet } = this.state let editorFontSize = parseInt(config.editor.fontSize, 10) if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14 @@ -108,29 +65,17 @@ class SnippetTab extends React.Component { return (
{i18n.__('Snippets')}
-
-
-
- -
-
- {this.renderSnippetList()} -
-
+ +
{i18n.__('Snippet name')}
{ - const newSnippet = Object.assign({}, this.state.currentSnippet) - newSnippet.name = e.target.value - this.setState({ currentSnippet: newSnippet }) - this.handleSnippetNameOrPrefixChange() - }} + value={currentSnippet ? currentSnippet.name : ''} + onChange={e => { this.onSnippetNameOrPrefixChanged(e, 'name') }} type='text' />
@@ -139,19 +84,14 @@ class SnippetTab extends React.Component {
{ - const newSnippet = Object.assign({}, this.state.currentSnippet) - newSnippet.prefix = e.target.value - this.setState({ currentSnippet: newSnippet }) - this.handleSnippetNameOrPrefixChange() - }} + value={currentSnippet ? currentSnippet.prefix : ''} + onChange={e => { this.onSnippetNameOrPrefixChanged(e, 'prefix') }} type='text' />
{ .then(function assert (data) { data = data[0] const snippets = JSON.parse(sander.readFileSync(snippetFile)) - const snippet = snippets.find(currentSnippet => currentSnippet.id === data.id) t.is(snippets.length, 0) }) }) diff --git a/yarn.lock b/yarn.lock index a0e4d96f..a8817ebd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2550,6 +2550,12 @@ doctrine@^2.0.0: esutils "^2.0.2" isarray "^1.0.0" +doctrine@^2.0.2: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + dependencies: + esutils "^2.0.2" + dom-serializer@0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" @@ -2963,13 +2969,14 @@ eslint-plugin-promise@~3.4.0: version "3.4.2" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.4.2.tgz#1be2793eafe2d18b5b123b8136c269f804fe7122" -eslint-plugin-react@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.2.0.tgz#25c77a4ec307e3eebb248ea3350960e372ab6406" +eslint-plugin-react@^7.8.2: + version "7.8.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.8.2.tgz#e95c9c47fece55d2303d1a67c9d01b930b88a51d" dependencies: - doctrine "^2.0.0" + doctrine "^2.0.2" has "^1.0.1" - jsx-ast-utils "^2.0.0" + jsx-ast-utils "^2.0.1" + prop-types "^15.6.0" eslint-plugin-react@~6.7.1: version "6.7.1" @@ -5330,9 +5337,9 @@ jsx-ast-utils@^1.3.3: version "1.4.1" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1" -jsx-ast-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.0.tgz#ec06a3d60cf307e5e119dac7bad81e89f096f0f8" +jsx-ast-utils@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f" dependencies: array-includes "^3.0.3" @@ -6962,6 +6969,14 @@ prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8: loose-envify "^1.3.1" object-assign "^4.1.1" +prop-types@^15.6.0: + version "15.6.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.3.1" + object-assign "^4.1.1" + prop-types@~15.5.7: version "15.5.10" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154"