mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
Merge pull request #2641 from daiyam/fix-paste-code
fix pasting into fenced code block
This commit is contained in:
@@ -13,7 +13,7 @@ import crypto from 'crypto'
|
|||||||
import consts from 'browser/lib/consts'
|
import consts from 'browser/lib/consts'
|
||||||
import styles from '../components/CodeEditor.styl'
|
import styles from '../components/CodeEditor.styl'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
const { ipcRenderer, remote } = require('electron')
|
const { ipcRenderer, remote, clipboard } = require('electron')
|
||||||
import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
|
import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
|
||||||
const spellcheck = require('browser/lib/spellcheck')
|
const spellcheck = require('browser/lib/spellcheck')
|
||||||
const buildEditorContextMenu = require('browser/lib/contextMenuBuilder')
|
const buildEditorContextMenu = require('browser/lib/contextMenuBuilder')
|
||||||
@@ -25,6 +25,10 @@ CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js'
|
|||||||
const buildCMRulers = (rulers, enableRulers) =>
|
const buildCMRulers = (rulers, enableRulers) =>
|
||||||
(enableRulers ? rulers.map(ruler => ({ column: ruler })) : [])
|
(enableRulers ? rulers.map(ruler => ({ column: ruler })) : [])
|
||||||
|
|
||||||
|
function translateHotkey (hotkey) {
|
||||||
|
return hotkey.replace(/\s*\+\s*/g, '-').replace(/Command/g, 'Cmd').replace(/Control/g, 'Ctrl')
|
||||||
|
}
|
||||||
|
|
||||||
export default class CodeEditor extends React.Component {
|
export default class CodeEditor extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
@@ -56,7 +60,11 @@ export default class CodeEditor extends React.Component {
|
|||||||
noteKey
|
noteKey
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
this.pasteHandler = (editor, e) => this.handlePaste(editor, e)
|
this.pasteHandler = (editor, e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
this.handlePaste(editor, false)
|
||||||
|
}
|
||||||
this.loadStyleHandler = e => {
|
this.loadStyleHandler = e => {
|
||||||
this.editor.refresh()
|
this.editor.refresh()
|
||||||
}
|
}
|
||||||
@@ -124,42 +132,9 @@ export default class CodeEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTableEditorState () {
|
updateDefaultKeyMap () {
|
||||||
const active = this.tableEditor.cursorIsInTable(this.tableEditorOptions)
|
const { hotkey } = this.props
|
||||||
if (active) {
|
|
||||||
if (this.extraKeysMode !== 'editor') {
|
|
||||||
this.extraKeysMode = 'editor'
|
|
||||||
this.editor.setOption('extraKeys', this.editorKeyMap)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.extraKeysMode !== 'default') {
|
|
||||||
this.extraKeysMode = 'default'
|
|
||||||
this.editor.setOption('extraKeys', this.defaultKeyMap)
|
|
||||||
this.tableEditor.resetSmartCursor()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
const { rulers, enableRulers, switchPreview } = this.props
|
|
||||||
const expandSnippet = this.expandSnippet.bind(this)
|
const expandSnippet = this.expandSnippet.bind(this)
|
||||||
eventEmitter.on('line:jump', this.scrollToLineHandeler)
|
|
||||||
|
|
||||||
const defaultSnippet = [
|
|
||||||
{
|
|
||||||
id: crypto.randomBytes(16).toString('hex'),
|
|
||||||
name: 'Dummy text',
|
|
||||||
prefix: ['lorem', 'ipsum'],
|
|
||||||
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
if (!fs.existsSync(consts.SNIPPET_FILE)) {
|
|
||||||
fs.writeFileSync(
|
|
||||||
consts.SNIPPET_FILE,
|
|
||||||
JSON.stringify(defaultSnippet, null, 4),
|
|
||||||
'utf8'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.defaultKeyMap = CodeMirror.normalizeKeyMap({
|
this.defaultKeyMap = CodeMirror.normalizeKeyMap({
|
||||||
Tab: function (cm) {
|
Tab: function (cm) {
|
||||||
@@ -211,8 +186,50 @@ export default class CodeEditor extends React.Component {
|
|||||||
document.execCommand('copy')
|
document.execCommand('copy')
|
||||||
}
|
}
|
||||||
return CodeMirror.Pass
|
return CodeMirror.Pass
|
||||||
|
},
|
||||||
|
[translateHotkey(hotkey.pasteSmartly)]: cm => {
|
||||||
|
this.handlePaste(cm, true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTableEditorState () {
|
||||||
|
const active = this.tableEditor.cursorIsInTable(this.tableEditorOptions)
|
||||||
|
if (active) {
|
||||||
|
if (this.extraKeysMode !== 'editor') {
|
||||||
|
this.extraKeysMode = 'editor'
|
||||||
|
this.editor.setOption('extraKeys', this.editorKeyMap)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.extraKeysMode !== 'default') {
|
||||||
|
this.extraKeysMode = 'default'
|
||||||
|
this.editor.setOption('extraKeys', this.defaultKeyMap)
|
||||||
|
this.tableEditor.resetSmartCursor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
const { rulers, enableRulers } = this.props
|
||||||
|
eventEmitter.on('line:jump', this.scrollToLineHandeler)
|
||||||
|
|
||||||
|
const defaultSnippet = [
|
||||||
|
{
|
||||||
|
id: crypto.randomBytes(16).toString('hex'),
|
||||||
|
name: 'Dummy text',
|
||||||
|
prefix: ['lorem', 'ipsum'],
|
||||||
|
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
if (!fs.existsSync(consts.SNIPPET_FILE)) {
|
||||||
|
fs.writeFileSync(
|
||||||
|
consts.SNIPPET_FILE,
|
||||||
|
JSON.stringify(defaultSnippet, null, 4),
|
||||||
|
'utf8'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateDefaultKeyMap()
|
||||||
|
|
||||||
this.value = this.props.value
|
this.value = this.props.value
|
||||||
this.editor = CodeMirror(this.refs.root, {
|
this.editor = CodeMirror(this.refs.root, {
|
||||||
@@ -245,7 +262,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.editor.on('blur', this.blurHandler)
|
this.editor.on('blur', this.blurHandler)
|
||||||
this.editor.on('change', this.changeHandler)
|
this.editor.on('change', this.changeHandler)
|
||||||
this.editor.on('paste', this.pasteHandler)
|
this.editor.on('paste', this.pasteHandler)
|
||||||
if (switchPreview !== 'RIGHTCLICK') {
|
if (this.props.switchPreview !== 'RIGHTCLICK') {
|
||||||
this.editor.on('contextmenu', this.contextMenuHandler)
|
this.editor.on('contextmenu', this.contextMenuHandler)
|
||||||
}
|
}
|
||||||
eventEmitter.on('top:search', this.searchHandler)
|
eventEmitter.on('top:search', this.searchHandler)
|
||||||
@@ -479,6 +496,14 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.editor.setOption('extraKeys', this.defaultKeyMap)
|
this.editor.setOption('extraKeys', this.defaultKeyMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prevProps.hotkey !== this.props.hotkey) {
|
||||||
|
this.updateDefaultKeyMap()
|
||||||
|
|
||||||
|
if (this.extraKeysMode === 'default') {
|
||||||
|
this.editor.setOption('extraKeys', this.defaultKeyMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.state.clientWidth !== this.refs.root.clientWidth) {
|
if (this.state.clientWidth !== this.refs.root.clientWidth) {
|
||||||
this.setState({
|
this.setState({
|
||||||
clientWidth: this.refs.root.clientWidth
|
clientWidth: this.refs.root.clientWidth
|
||||||
@@ -567,15 +592,14 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.editor.replaceSelection(imageMd)
|
this.editor.replaceSelection(imageMd)
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePaste (editor, e) {
|
handlePaste (editor, forceSmartPaste) {
|
||||||
const clipboardData = e.clipboardData
|
const { storageKey, noteKey, fetchUrlTitle, enableSmartPaste } = this.props
|
||||||
const { storageKey, noteKey } = this.props
|
|
||||||
const dataTransferItem = clipboardData.items[0]
|
|
||||||
const pastedTxt = clipboardData.getData('text')
|
|
||||||
const isURL = str => {
|
const isURL = str => {
|
||||||
const matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/
|
const matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/
|
||||||
return matcher.test(str)
|
return matcher.test(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
const isInLinkTag = editor => {
|
const isInLinkTag = editor => {
|
||||||
const startCursor = editor.getCursor('start')
|
const startCursor = editor.getCursor('start')
|
||||||
const prevChar = editor.getRange(
|
const prevChar = editor.getRange(
|
||||||
@@ -590,30 +614,73 @@ export default class CodeEditor extends React.Component {
|
|||||||
return prevChar === '](' && nextChar === ')'
|
return prevChar === '](' && nextChar === ')'
|
||||||
}
|
}
|
||||||
|
|
||||||
const pastedHtml = clipboardData.getData('text/html')
|
const isInFencedCodeBlock = editor => {
|
||||||
if (pastedHtml !== '') {
|
const cursor = editor.getCursor()
|
||||||
this.handlePasteHtml(e, editor, pastedHtml)
|
|
||||||
} else if (dataTransferItem.type.match('image')) {
|
let token = editor.getTokenAt(cursor)
|
||||||
attachmentManagement.handlePastImageEvent(
|
if (token.state.fencedState) {
|
||||||
this,
|
return true
|
||||||
storageKey,
|
}
|
||||||
noteKey,
|
|
||||||
dataTransferItem
|
let line = line = cursor.line - 1
|
||||||
)
|
while (line >= 0) {
|
||||||
} else if (
|
token = editor.getTokenAt({
|
||||||
this.props.fetchUrlTitle &&
|
ch: 3,
|
||||||
isURL(pastedTxt) &&
|
line
|
||||||
!isInLinkTag(editor)
|
})
|
||||||
) {
|
|
||||||
this.handlePasteUrl(e, editor, pastedTxt)
|
if (token.start === token.end) {
|
||||||
|
--line
|
||||||
|
} else if (token.type === 'comment') {
|
||||||
|
if (line > 0) {
|
||||||
|
token = editor.getTokenAt({
|
||||||
|
ch: 3,
|
||||||
|
line: line - 1
|
||||||
|
})
|
||||||
|
|
||||||
|
return token.type !== 'comment'
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
if (attachmentManagement.isAttachmentLink(pastedTxt)) {
|
|
||||||
|
const pastedTxt = clipboard.readText()
|
||||||
|
|
||||||
|
if (isInFencedCodeBlock(editor)) {
|
||||||
|
this.handlePasteText(editor, pastedTxt)
|
||||||
|
} else if (fetchUrlTitle && isURL(pastedTxt) && !isInLinkTag(editor)) {
|
||||||
|
this.handlePasteUrl(editor, pastedTxt)
|
||||||
|
} else if (enableSmartPaste || forceSmartPaste) {
|
||||||
|
const image = clipboard.readImage()
|
||||||
|
if (!image.isEmpty()) {
|
||||||
|
attachmentManagement.handlePastNativeImage(
|
||||||
|
this,
|
||||||
|
storageKey,
|
||||||
|
noteKey,
|
||||||
|
image
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
const pastedHtml = clipboard.readHTML()
|
||||||
|
if (pastedHtml.length > 0) {
|
||||||
|
this.handlePasteHtml(editor, pastedHtml)
|
||||||
|
} else {
|
||||||
|
this.handlePasteText(editor, pastedTxt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (attachmentManagement.isAttachmentLink(pastedTxt)) {
|
||||||
attachmentManagement
|
attachmentManagement
|
||||||
.handleAttachmentLinkPaste(storageKey, noteKey, pastedTxt)
|
.handleAttachmentLinkPaste(storageKey, noteKey, pastedTxt)
|
||||||
.then(modifiedText => {
|
.then(modifiedText => {
|
||||||
this.editor.replaceSelection(modifiedText)
|
this.editor.replaceSelection(modifiedText)
|
||||||
})
|
})
|
||||||
e.preventDefault()
|
} else {
|
||||||
|
this.handlePasteText(editor, pastedTxt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,8 +690,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePasteUrl (e, editor, pastedTxt) {
|
handlePasteUrl (editor, pastedTxt) {
|
||||||
e.preventDefault()
|
|
||||||
const taggedUrl = `<${pastedTxt}>`
|
const taggedUrl = `<${pastedTxt}>`
|
||||||
editor.replaceSelection(taggedUrl)
|
editor.replaceSelection(taggedUrl)
|
||||||
|
|
||||||
@@ -663,12 +729,15 @@ export default class CodeEditor extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePasteHtml (e, editor, pastedHtml) {
|
handlePasteHtml (editor, pastedHtml) {
|
||||||
e.preventDefault()
|
|
||||||
const markdown = this.turndownService.turndown(pastedHtml)
|
const markdown = this.turndownService.turndown(pastedHtml)
|
||||||
editor.replaceSelection(markdown)
|
editor.replaceSelection(markdown)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handlePasteText (editor, pastedTxt) {
|
||||||
|
editor.replaceSelection(pastedTxt)
|
||||||
|
}
|
||||||
|
|
||||||
mapNormalResponse (response, pastedTxt) {
|
mapNormalResponse (response, pastedTxt) {
|
||||||
return this.decodeResponse(response).then(body => {
|
return this.decodeResponse(response).then(body => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|||||||
@@ -278,6 +278,8 @@ class MarkdownEditor extends React.Component {
|
|||||||
onChange={(e) => this.handleChange(e)}
|
onChange={(e) => this.handleChange(e)}
|
||||||
onBlur={(e) => this.handleBlur(e)}
|
onBlur={(e) => this.handleBlur(e)}
|
||||||
spellCheck={config.editor.spellcheck}
|
spellCheck={config.editor.spellcheck}
|
||||||
|
enableSmartPaste={config.editor.enableSmartPaste}
|
||||||
|
hotkey={config.hotkey}
|
||||||
switchPreview={config.editor.switchPreview}
|
switchPreview={config.editor.switchPreview}
|
||||||
/>
|
/>
|
||||||
<MarkdownPreview styleName={this.state.status === 'PREVIEW'
|
<MarkdownPreview styleName={this.state.status === 'PREVIEW'
|
||||||
|
|||||||
@@ -172,6 +172,8 @@ class MarkdownSplitEditor extends React.Component {
|
|||||||
onChange={this.handleOnChange.bind(this)}
|
onChange={this.handleOnChange.bind(this)}
|
||||||
onScroll={this.handleScroll.bind(this)}
|
onScroll={this.handleScroll.bind(this)}
|
||||||
spellCheck={config.editor.spellcheck}
|
spellCheck={config.editor.spellcheck}
|
||||||
|
enableSmartPaste={config.editor.enableSmartPaste}
|
||||||
|
hotkey={config.hotkey}
|
||||||
switchPreview={config.editor.switchPreview}
|
switchPreview={config.editor.switchPreview}
|
||||||
/>
|
/>
|
||||||
<div styleName='slider' style={{left: this.state.codeEditorWidthInPercent + '%'}} onMouseDown={e => this.handleMouseDown(e)} >
|
<div styleName='slider' style={{left: this.state.codeEditorWidthInPercent + '%'}} onMouseDown={e => this.handleMouseDown(e)} >
|
||||||
|
|||||||
@@ -724,6 +724,8 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
enableTableEditor={config.editor.enableTableEditor}
|
enableTableEditor={config.editor.enableTableEditor}
|
||||||
onChange={(e) => this.handleCodeChange(index)(e)}
|
onChange={(e) => this.handleCodeChange(index)(e)}
|
||||||
ref={'code-' + index}
|
ref={'code-' + index}
|
||||||
|
enableSmartPaste={config.editor.enableSmartPaste}
|
||||||
|
hotkey={config.hotkey}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ export const DEFAULT_CONFIG = {
|
|||||||
hotkey: {
|
hotkey: {
|
||||||
toggleMain: OSX ? 'Command + Alt + L' : 'Super + Alt + E',
|
toggleMain: OSX ? 'Command + Alt + L' : 'Super + Alt + E',
|
||||||
toggleMode: OSX ? 'Command + Alt + M' : 'Ctrl + M',
|
toggleMode: OSX ? 'Command + Alt + M' : 'Ctrl + M',
|
||||||
deleteNote: OSX ? 'Command + Shift + Backspace' : 'Ctrl + Shift + Backspace'
|
deleteNote: OSX ? 'Command + Shift + Backspace' : 'Ctrl + Shift + Backspace',
|
||||||
|
pasteSmartly: OSX ? 'Command + Shift + V' : 'Ctrl + Shift + V'
|
||||||
},
|
},
|
||||||
ui: {
|
ui: {
|
||||||
language: 'en',
|
language: 'en',
|
||||||
@@ -52,7 +53,8 @@ export const DEFAULT_CONFIG = {
|
|||||||
enableTableEditor: false,
|
enableTableEditor: false,
|
||||||
enableFrontMatterTitle: true,
|
enableFrontMatterTitle: true,
|
||||||
frontMatterTitleField: 'title',
|
frontMatterTitleField: 'title',
|
||||||
spellcheck: false
|
spellcheck: false,
|
||||||
|
enableSmartPaste: false
|
||||||
},
|
},
|
||||||
preview: {
|
preview: {
|
||||||
fontSize: '14',
|
fontSize: '14',
|
||||||
|
|||||||
@@ -316,6 +316,44 @@ function handlePastImageEvent (codeEditor, storageKey, noteKey, dataTransferItem
|
|||||||
reader.readAsDataURL(blob)
|
reader.readAsDataURL(blob)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Creates a new file in the storage folder belonging to the current note and inserts the correct markdown code
|
||||||
|
* @param {CodeEditor} codeEditor Markdown editor. Its insertAttachmentMd() method will be called to include the markdown code
|
||||||
|
* @param {String} storageKey Key of the current storage
|
||||||
|
* @param {String} noteKey Key of the current note
|
||||||
|
* @param {NativeImage} image The native image
|
||||||
|
*/
|
||||||
|
function handlePastNativeImage (codeEditor, storageKey, noteKey, image) {
|
||||||
|
if (!codeEditor) {
|
||||||
|
throw new Error('codeEditor has to be given')
|
||||||
|
}
|
||||||
|
if (!storageKey) {
|
||||||
|
throw new Error('storageKey has to be given')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!noteKey) {
|
||||||
|
throw new Error('noteKey has to be given')
|
||||||
|
}
|
||||||
|
if (!image) {
|
||||||
|
throw new Error('image has to be given')
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetStorage = findStorage.findStorage(storageKey)
|
||||||
|
const destinationDir = path.join(targetStorage.path, DESTINATION_FOLDER, noteKey)
|
||||||
|
|
||||||
|
createAttachmentDestinationFolder(targetStorage.path, noteKey)
|
||||||
|
|
||||||
|
const imageName = `${uniqueSlug()}.png`
|
||||||
|
const imagePath = path.join(destinationDir, imageName)
|
||||||
|
|
||||||
|
const binaryData = image.toPNG()
|
||||||
|
fs.writeFileSync(imagePath, binaryData, 'binary')
|
||||||
|
|
||||||
|
const imageReferencePath = path.join(STORAGE_FOLDER_PLACEHOLDER, noteKey, imageName)
|
||||||
|
const imageMd = generateAttachmentMarkdown(imageName, imageReferencePath, true)
|
||||||
|
codeEditor.insertAttachmentMd(imageMd)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Returns all attachment paths of the given markdown
|
* @description Returns all attachment paths of the given markdown
|
||||||
* @param {String} markdownContent content in which the attachment paths should be found
|
* @param {String} markdownContent content in which the attachment paths should be found
|
||||||
@@ -539,6 +577,7 @@ module.exports = {
|
|||||||
generateAttachmentMarkdown,
|
generateAttachmentMarkdown,
|
||||||
handleAttachmentDrop,
|
handleAttachmentDrop,
|
||||||
handlePastImageEvent,
|
handlePastImageEvent,
|
||||||
|
handlePastNativeImage,
|
||||||
getAttachmentsInMarkdownContent,
|
getAttachmentsInMarkdownContent,
|
||||||
getAbsolutePathsOfAttachmentsInContent,
|
getAbsolutePathsOfAttachmentsInContent,
|
||||||
removeStorageAndNoteReferences,
|
removeStorageAndNoteReferences,
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ class HotkeyTab extends React.Component {
|
|||||||
config.hotkey = {
|
config.hotkey = {
|
||||||
toggleMain: this.refs.toggleMain.value,
|
toggleMain: this.refs.toggleMain.value,
|
||||||
toggleMode: this.refs.toggleMode.value,
|
toggleMode: this.refs.toggleMode.value,
|
||||||
deleteNote: this.refs.deleteNote.value
|
deleteNote: this.refs.deleteNote.value,
|
||||||
|
pasteSmartly: this.refs.pasteSmartly.value
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
config
|
config
|
||||||
@@ -149,6 +150,17 @@ class HotkeyTab extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>{i18n.__('Paste Smartly')}</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<input styleName='group-section-control-input'
|
||||||
|
onChange={(e) => this.handleHotkeyChange(e)}
|
||||||
|
ref='pasteSmartly'
|
||||||
|
value={config.hotkey.pasteSmartly}
|
||||||
|
type='text'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div styleName='group-control'>
|
<div styleName='group-control'>
|
||||||
<button styleName='group-control-leftButton'
|
<button styleName='group-control-leftButton'
|
||||||
onClick={(e) => this.handleHintToggleButtonClick(e)}
|
onClick={(e) => this.handleHintToggleButtonClick(e)}
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ class UiTab extends React.Component {
|
|||||||
enableTableEditor: this.refs.enableTableEditor.checked,
|
enableTableEditor: this.refs.enableTableEditor.checked,
|
||||||
enableFrontMatterTitle: this.refs.enableFrontMatterTitle.checked,
|
enableFrontMatterTitle: this.refs.enableFrontMatterTitle.checked,
|
||||||
frontMatterTitleField: this.refs.frontMatterTitleField.value,
|
frontMatterTitleField: this.refs.frontMatterTitleField.value,
|
||||||
spellcheck: this.refs.spellcheck.checked
|
spellcheck: this.refs.spellcheck.checked,
|
||||||
|
enableSmartPaste: this.refs.enableSmartPaste.checked
|
||||||
},
|
},
|
||||||
preview: {
|
preview: {
|
||||||
fontSize: this.refs.previewFontSize.value,
|
fontSize: this.refs.previewFontSize.value,
|
||||||
@@ -552,6 +553,18 @@ class UiTab extends React.Component {
|
|||||||
{i18n.__('Enable smart table editor')}
|
{i18n.__('Enable smart table editor')}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div styleName='group-checkBoxSection'>
|
||||||
|
<label>
|
||||||
|
<input onChange={(e) => this.handleUIChange(e)}
|
||||||
|
checked={this.state.config.editor.enableSmartPaste}
|
||||||
|
ref='enableSmartPaste'
|
||||||
|
type='checkbox'
|
||||||
|
/>
|
||||||
|
{i18n.__('Enable smart paste')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div styleName='group-checkBoxSection'>
|
<div styleName='group-checkBoxSection'>
|
||||||
<label>
|
<label>
|
||||||
<input onChange={(e) => this.handleUIChange(e)}
|
<input onChange={(e) => this.handleUIChange(e)}
|
||||||
|
|||||||
Reference in New Issue
Block a user