diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index d7b16001..5bec7557 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -8,13 +8,13 @@ import convertModeName from 'browser/lib/convertModeName' import eventEmitter from 'browser/main/lib/eventEmitter' import iconv from 'iconv-lite' -const { ipcRenderer } = require('electron') +const {ipcRenderer} = require('electron') CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js' const defaultEditorFontFamily = ['Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'monospace'] const buildCMRulers = (rulers, enableRulers) => - enableRulers ? rulers.map(ruler => ({ column: ruler })) : [] + enableRulers ? rulers.map(ruler => ({column: ruler})) : [] export default class CodeEditor extends React.Component { constructor (props) { @@ -80,7 +80,7 @@ export default class CodeEditor extends React.Component { } componentDidMount () { - const { rulers, enableRulers } = this.props + const {rulers, enableRulers} = this.props this.value = this.props.value this.editor = CodeMirror(this.refs.root, { @@ -174,7 +174,7 @@ export default class CodeEditor extends React.Component { componentDidUpdate (prevProps, prevState) { let needRefresh = false - const { rulers, enableRulers } = this.props + const {rulers, enableRulers} = this.props if (prevProps.mode !== this.props.mode) { this.setMode(this.props.mode) } @@ -274,6 +274,7 @@ export default class CodeEditor extends React.Component { handlePaste (editor, e) { const clipboardData = e.clipboardData + const {storageKey, noteKey} = this.props const dataTransferItem = clipboardData.items[0] const pastedTxt = clipboardData.getData('text') const isURL = (str) => { @@ -283,22 +284,28 @@ export default class CodeEditor extends React.Component { const isInLinkTag = (editor) => { const startCursor = editor.getCursor('start') const prevChar = editor.getRange( - { line: startCursor.line, ch: startCursor.ch - 2 }, - { line: startCursor.line, ch: startCursor.ch } + {line: startCursor.line, ch: startCursor.ch - 2}, + {line: startCursor.line, ch: startCursor.ch} ) const endCursor = editor.getCursor('end') const nextChar = editor.getRange( - { line: endCursor.line, ch: endCursor.ch }, - { line: endCursor.line, ch: endCursor.ch + 1 } + {line: endCursor.line, ch: endCursor.ch}, + {line: endCursor.line, ch: endCursor.ch + 1} ) return prevChar === '](' && nextChar === ')' } if (dataTransferItem.type.match('image')) { - const {storageKey, noteKey} = this.props attachmentManagement.handlePastImageEvent(this, storageKey, noteKey, dataTransferItem) } else if (this.props.fetchUrlTitle && isURL(pastedTxt) && !isInLinkTag(editor)) { this.handlePasteUrl(e, editor, pastedTxt) } + if (attachmentManagement.isAttachmentLink(pastedTxt)) { + attachmentManagement.handleAttachmentLinkPaste(storageKey, noteKey, pastedTxt) + .then((modifiedText) => { + this.editor.replaceSelection(modifiedText) + }) + e.preventDefault() + } } handleScroll (e) { @@ -322,7 +329,7 @@ export default class CodeEditor extends React.Component { const cursor = editor.getCursor() const LinkWithTitle = `[${parsedResponse.title}](${pastedTxt})` const newValue = value.replace(taggedUrl, LinkWithTitle) - const newCursor = Object.assign({}, cursor, { ch: cursor.ch + newValue.length - value.length }) + const newCursor = Object.assign({}, cursor, {ch: cursor.ch + newValue.length - value.length}) editor.setValue(newValue) editor.setCursor(newCursor) }).catch((e) => { @@ -360,7 +367,7 @@ export default class CodeEditor extends React.Component { } render () { - const { className, fontSize } = this.props + const {className, fontSize} = this.props let fontFamily = this.props.fontFamily fontFamily = _.isString(fontFamily) && fontFamily.length > 0 ? [fontFamily].concat(defaultEditorFontFamily) diff --git a/browser/main/lib/dataApi/attachmentManagement.js b/browser/main/lib/dataApi/attachmentManagement.js index 893e03d1..bcb7b312 100644 --- a/browser/main/lib/dataApi/attachmentManagement.js +++ b/browser/main/lib/dataApi/attachmentManagement.js @@ -6,6 +6,7 @@ const mdurl = require('mdurl') const fse = require('fs-extra') const escapeStringRegexp = require('escape-string-regexp') const sander = require('sander') +import i18n from 'browser/lib/i18n' const STORAGE_FOLDER_PLACEHOLDER = ':storage' const DESTINATION_FOLDER = 'attachments' @@ -258,7 +259,7 @@ function deleteAttachmentsNotPresentInNote (markdownContent, storageKey, noteKey if (fs.existsSync(attachmentFolder)) { fs.readdir(attachmentFolder, (err, files) => { if (err) { - console.error("Error reading directory '" + attachmentFolder + "'. Error:") + console.error('Error reading directory "' + attachmentFolder + '". Error:') console.error(err) return } @@ -267,17 +268,17 @@ function deleteAttachmentsNotPresentInNote (markdownContent, storageKey, noteKey const absolutePathOfFile = path.join(targetStorage.path, DESTINATION_FOLDER, noteKey, file) fs.unlink(absolutePathOfFile, (err) => { if (err) { - console.error("Could not delete '%s'", absolutePathOfFile) + console.error('Could not delete "%s"', absolutePathOfFile) console.error(err) return } - console.info("File '" + absolutePathOfFile + "' deleted because it was not included in the content of the note") + console.info('File "' + absolutePathOfFile + '" deleted because it was not included in the content of the note') }) } }) }) } else { - console.info("Attachment folder ('" + attachmentFolder + "') did not exist..") + console.info('Attachment folder ("' + attachmentFolder + '") did not exist..') } } @@ -308,6 +309,71 @@ function cloneAttachments (oldNote, newNote) { } } +function generateFileNotFoundMarkdown () { + return '**' + i18n.__('⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠') + '**' +} + +/** + * Determines whether a given text is a link to an boostnote attachment + * @param text Text that might contain a attachment link + * @return {Boolean} Result of the test + */ +function isAttachmentLink (text) { + if (text) { + return text.match(new RegExp('.*\\[.*\\]\\( *' + escapeStringRegexp(STORAGE_FOLDER_PLACEHOLDER) + escapeStringRegexp(path.sep) + '.*\\).*', 'gi')) != null + } + return false +} + +/** + * @description Handles the paste of an attachment link. Copies the referenced attachment to the location belonging to the new note. + * Returns a modified version of the pasted text so that it matches the copied attachment (resp. the new location) + * @param storageKey StorageKey of the current note + * @param noteKey NoteKey of the currentNote + * @param linkText Text that was pasted + * @return {Promise} Promise returning the modified text + */ +function handleAttachmentLinkPaste (storageKey, noteKey, linkText) { + if (storageKey != null && noteKey != null && linkText != null) { + const storagePath = findStorage.findStorage(storageKey).path + const attachments = getAttachmentsInContent(linkText) || [] + const replaceInstructions = [] + const copies = [] + for (const attachment of attachments) { + const absPathOfAttachment = attachment.replace(new RegExp(STORAGE_FOLDER_PLACEHOLDER, 'g'), path.join(storagePath, DESTINATION_FOLDER)) + copies.push( + sander.exists(absPathOfAttachment) + .then((fileExists) => { + if (!fileExists) { + const fileNotFoundRegexp = new RegExp('!?' + escapeStringRegexp('[') + '[\\w|\\d|\\s|\\.]*\\]\\(\\s*' + STORAGE_FOLDER_PLACEHOLDER + '[\\w|\\d|\\-|' + escapeStringRegexp(path.sep) + ']*' + escapeStringRegexp(path.basename(absPathOfAttachment)) + escapeStringRegexp(')')) + replaceInstructions.push({regexp: fileNotFoundRegexp, replacement: this.generateFileNotFoundMarkdown()}) + return Promise.resolve() + } + return this.copyAttachment(absPathOfAttachment, storageKey, noteKey) + .then((fileName) => { + const replaceLinkRegExp = new RegExp(escapeStringRegexp('(') + ' *' + STORAGE_FOLDER_PLACEHOLDER + '[\\w|\\d|\\-|' + escapeStringRegexp(path.sep) + ']*' + escapeStringRegexp(path.basename(absPathOfAttachment)) + ' *' + escapeStringRegexp(')')) + replaceInstructions.push({ + regexp: replaceLinkRegExp, + replacement: '(' + path.join(STORAGE_FOLDER_PLACEHOLDER, noteKey, fileName) + ')' + }) + return Promise.resolve() + }) + }) + ) + } + return Promise.all(copies).then(() => { + let modifiedLinkText = linkText + for (const replaceInstruction of replaceInstructions) { + modifiedLinkText = modifiedLinkText.replace(replaceInstruction.regexp, replaceInstruction.replacement) + } + return modifiedLinkText + }) + } else { + console.log('One if the parameters was null -> Do nothing..') + return Promise.resolve(linkText) + } +} + module.exports = { copyAttachment, fixLocalURLS, @@ -321,6 +387,9 @@ module.exports = { deleteAttachmentsNotPresentInNote, moveAttachments, cloneAttachments, + isAttachmentLink, + handleAttachmentLinkPaste, + generateFileNotFoundMarkdown, STORAGE_FOLDER_PLACEHOLDER, DESTINATION_FOLDER } diff --git a/locales/da.json b/locales/da.json index 314058cb..1efaab0f 100644 --- a/locales/da.json +++ b/locales/da.json @@ -150,5 +150,6 @@ "Sanitization": "Sanitization", "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", "Allow styles": "Allow styles", - "Allow dangerous html tags": "Allow dangerous html tags" + "Allow dangerous html tags": "Allow dangerous html tags", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/de.json b/locales/de.json index 7e7da1f3..e7bb196e 100644 --- a/locales/de.json +++ b/locales/de.json @@ -205,5 +205,6 @@ "Unnamed": "Unbenannt", "Rename": "Umbenennen", "Folder Name": "Ordnername", - "No tags": "Keine Tags" + "No tags": "Keine Tags", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/en.json b/locales/en.json index e40035ae..4cdf91b6 100644 --- a/locales/en.json +++ b/locales/en.json @@ -174,5 +174,6 @@ "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", "Render newlines in Markdown paragraphs as
": "Render newlines in Markdown paragraphs as
", "Allow styles": "Allow styles", - "Allow dangerous html tags": "Allow dangerous html tags" + "Allow dangerous html tags": "Allow dangerous html tags", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/es-ES.json b/locales/es-ES.json index 0fa27713..5795a5e0 100644 --- a/locales/es-ES.json +++ b/locales/es-ES.json @@ -150,5 +150,6 @@ "Sanitization": "Saneamiento", "Only allow secure html tags (recommended)": "Solo permitir etiquetas html seguras (recomendado)", "Allow styles": "Permitir estilos", - "Allow dangerous html tags": "Permitir etiquetas html peligrosas" + "Allow dangerous html tags": "Permitir etiquetas html peligrosas", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/fa.json b/locales/fa.json index 125056a6..7d8dd05d 100644 --- a/locales/fa.json +++ b/locales/fa.json @@ -153,5 +153,6 @@ "Sanitization": "پاکسازی کردن", "Only allow secure html tags (recommended)": "(فقط تگ های امن اچ تی ام ال مجاز اند.(پیشنهاد میشود", "Allow styles": "حالت های مجاز", - "Allow dangerous html tags": "تگ های خطرناک اچ‌ تی ام ال مجاز اند" + "Allow dangerous html tags": "تگ های خطرناک اچ‌ تی ام ال مجاز اند", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } \ No newline at end of file diff --git a/locales/fr.json b/locales/fr.json index d285a29c..7d4c8209 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -150,5 +150,6 @@ "Sanitization": "Sanitization", "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", "Allow styles": "Allow styles", - "Allow dangerous html tags": "Allow dangerous html tags" + "Allow dangerous html tags": "Allow dangerous html tags", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/hu.json b/locales/hu.json index d02a6810..48a4bb22 100644 --- a/locales/hu.json +++ b/locales/hu.json @@ -174,5 +174,6 @@ "Only allow secure html tags (recommended)": "Csak a biztonságos html tag-ek engedélyezése (ajánlott)", "Render newlines in Markdown paragraphs as
": "Az újsor karaktert
soremelésként jelenítse meg a Markdown jegyzetekben", "Allow styles": "Stílusok engedélyezése", - "Allow dangerous html tags": "Veszélyes html tag-ek engedélyezése" + "Allow dangerous html tags": "Veszélyes html tag-ek engedélyezése", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/it.json b/locales/it.json index 10c97c94..d00c8001 100644 --- a/locales/it.json +++ b/locales/it.json @@ -153,5 +153,6 @@ "Sanitization": "Bonifica", "Only allow secure html tags (recommended)": "Consenti solo tag HTML sicuri (raccomandato)", "Allow styles": "Consenti stili", - "Allow dangerous html tags": "Consenti tag HTML pericolosi" -}" + "Allow dangerous html tags": "Consenti tag HTML pericolosi", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" +} diff --git a/locales/ja.json b/locales/ja.json index 987f11e5..eb2534ef 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -150,5 +150,6 @@ "Sanitization": "サニタイズ", "Only allow secure html tags (recommended)": "安全なHTMLタグのみ利用を許可する(推奨)", "Allow styles": "スタイルを許可する", - "Allow dangerous html tags": "安全でないHTMLタグの利用を許可する" + "Allow dangerous html tags": "安全でないHTMLタグの利用を許可する", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/ko.json b/locales/ko.json index 3360f269..002fb8e7 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -156,5 +156,6 @@ "Sanitization": "허용 태그 범위", "Only allow secure html tags (recommended)": "안전한 HTML 태그만 허용 (추천)", "Allow styles": "style 태그, 속성까지 허용", - "Allow dangerous html tags": "모든 위험한 태그 허용" + "Allow dangerous html tags": "모든 위험한 태그 허용", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/no.json b/locales/no.json index 1ec74f0e..90eee777 100644 --- a/locales/no.json +++ b/locales/no.json @@ -149,5 +149,6 @@ "Sanitization": "Sanitization", "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", "Allow styles": "Allow styles", - "Allow dangerous html tags": "Allow dangerous html tags" + "Allow dangerous html tags": "Allow dangerous html tags", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/pl.json b/locales/pl.json index 1ec74f0e..90eee777 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -149,5 +149,6 @@ "Sanitization": "Sanitization", "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", "Allow styles": "Allow styles", - "Allow dangerous html tags": "Allow dangerous html tags" + "Allow dangerous html tags": "Allow dangerous html tags", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/pt-BR.json b/locales/pt-BR.json index 1f8361af..bc17b12e 100644 --- a/locales/pt-BR.json +++ b/locales/pt-BR.json @@ -149,5 +149,6 @@ "Sanitization": "Sanitização", "Only allow secure html tags (recommended)": "Permitir apenas tags html seguras (recomendado)", "Allow styles": "Permitir estilos", - "Allow dangerous html tags": "Permitir tags html perigosas" + "Allow dangerous html tags": "Permitir tags html perigosas", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/pt-PT.json b/locales/pt-PT.json index 1ec74f0e..90eee777 100644 --- a/locales/pt-PT.json +++ b/locales/pt-PT.json @@ -149,5 +149,6 @@ "Sanitization": "Sanitization", "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", "Allow styles": "Allow styles", - "Allow dangerous html tags": "Allow dangerous html tags" + "Allow dangerous html tags": "Allow dangerous html tags", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/ru.json b/locales/ru.json index 0f3696d2..5d98c9bd 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -146,5 +146,6 @@ "Russian": "Русский", "Editor Rulers": "Editor Rulers", "Enable": "Enable", - "Disable": "Disable" + "Disable": "Disable", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/sq.json b/locales/sq.json index 01a6fe0b..529a7d0c 100644 --- a/locales/sq.json +++ b/locales/sq.json @@ -148,5 +148,6 @@ "Sanitization": "Sanitization", "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", "Allow styles": "Allow styles", - "Allow dangerous html tags": "Allow dangerous html tags" + "Allow dangerous html tags": "Allow dangerous html tags", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/zh-CN.json b/locales/zh-CN.json index b736520d..6b13cb6b 100755 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -148,5 +148,6 @@ "Sanitization": "代码处理", "Only allow secure html tags (recommended)": "只允许安全的html标签(推荐)", "Allow styles": "允许样式", - "Allow dangerous html tags": "允许危险的html标签" + "Allow dangerous html tags": "允许危险的html标签", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/locales/zh-TW.json b/locales/zh-TW.json index bc60cfcc..315fb30a 100755 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -148,5 +148,6 @@ "Sanitization": "過濾 HTML 程式碼", "Only allow secure html tags (recommended)": "只允許安全的 HTML 標籤 (建議)", "Allow styles": "允許樣式", - "Allow dangerous html tags": "允許危險的 HTML 標籤" + "Allow dangerous html tags": "允許危險的 HTML 標籤", + "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠" } diff --git a/tests/dataApi/attachmentManagement.test.js b/tests/dataApi/attachmentManagement.test.js index b61d8bf9..ff263fc4 100644 --- a/tests/dataApi/attachmentManagement.test.js +++ b/tests/dataApi/attachmentManagement.test.js @@ -467,3 +467,239 @@ it('should test that cloneAttachments finds all attachments and copies them to t expect(findStorage.findStorage).not.toHaveBeenCalled() expect(sander.copyFileSync).not.toHaveBeenCalled() }) + +it('should test that isAttachmentLink works correctly', function () { + expect(systemUnderTest.isAttachmentLink('text')).toBe(false) + expect(systemUnderTest.isAttachmentLink('text [linkText](link)')).toBe(false) + expect(systemUnderTest.isAttachmentLink('text ![linkText](link)')).toBe(false) + expect(systemUnderTest.isAttachmentLink('[linkText](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + 'noteKey' + path.sep + 'pdf.pdf)')).toBe(true) + expect(systemUnderTest.isAttachmentLink('![linkText](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + 'noteKey' + path.sep + 'pdf.pdf )')).toBe(true) + expect(systemUnderTest.isAttachmentLink('text [ linkText](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + 'noteKey' + path.sep + 'pdf.pdf)')).toBe(true) + expect(systemUnderTest.isAttachmentLink('text ![linkText ](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + 'noteKey' + path.sep + 'pdf.pdf)')).toBe(true) + expect(systemUnderTest.isAttachmentLink('[linkText](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + 'noteKey' + path.sep + 'pdf.pdf) test')).toBe(true) + expect(systemUnderTest.isAttachmentLink('![linkText](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + 'noteKey' + path.sep + 'pdf.pdf) test')).toBe(true) + expect(systemUnderTest.isAttachmentLink('text [linkText](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + 'noteKey' + path.sep + 'pdf.pdf) test')).toBe(true) + expect(systemUnderTest.isAttachmentLink('text ![linkText](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + 'noteKey' + path.sep + 'pdf.pdf) test')).toBe(true) +}) + +it('should test that handleAttachmentLinkPaste copies the attachments to the new location', function () { + const dummyStorage = {path: 'dummyStoragePath'} + findStorage.findStorage = jest.fn(() => dummyStorage) + const pastedNoteKey = 'b1e06f81-8266-49b9-b438-084003c2e723' + const newNoteKey = 'abc234-8266-49b9-b438-084003c2e723' + const pasteText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'pdf.pdf)' + const storageKey = 'storageKey' + const expectedSourceFilePath = path.join(dummyStorage.path, systemUnderTest.DESTINATION_FOLDER, pastedNoteKey, 'pdf.pdf') + + sander.exists = jest.fn(() => Promise.resolve(true)) + systemUnderTest.copyAttachment = jest.fn(() => Promise.resolve('dummyNewFileName')) + + return systemUnderTest.handleAttachmentLinkPaste(storageKey, newNoteKey, pasteText) + .then(() => { + expect(findStorage.findStorage).toHaveBeenCalledWith(storageKey) + expect(sander.exists).toHaveBeenCalledWith(expectedSourceFilePath) + expect(systemUnderTest.copyAttachment).toHaveBeenCalledWith(expectedSourceFilePath, storageKey, newNoteKey) + }) +}) + +it('should test that handleAttachmentLinkPaste don\'t try to copy the file if it does not exist', function () { + const dummyStorage = {path: 'dummyStoragePath'} + findStorage.findStorage = jest.fn(() => dummyStorage) + const pastedNoteKey = 'b1e06f81-8266-49b9-b438-084003c2e723' + const newNoteKey = 'abc234-8266-49b9-b438-084003c2e723' + const pasteText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'pdf.pdf)' + const storageKey = 'storageKey' + const expectedSourceFilePath = path.join(dummyStorage.path, systemUnderTest.DESTINATION_FOLDER, pastedNoteKey, 'pdf.pdf') + + sander.exists = jest.fn(() => Promise.resolve(false)) + systemUnderTest.copyAttachment = jest.fn() + systemUnderTest.generateFileNotFoundMarkdown = jest.fn() + + return systemUnderTest.handleAttachmentLinkPaste(storageKey, newNoteKey, pasteText) + .then(() => { + expect(findStorage.findStorage).toHaveBeenCalledWith(storageKey) + expect(sander.exists).toHaveBeenCalledWith(expectedSourceFilePath) + expect(systemUnderTest.copyAttachment).not.toHaveBeenCalled() + }) +}) + +it('should test that handleAttachmentLinkPaste copies multiple attachments if multiple were pasted', function () { + const dummyStorage = {path: 'dummyStoragePath'} + findStorage.findStorage = jest.fn(() => dummyStorage) + const pastedNoteKey = 'b1e06f81-8266-49b9-b438-084003c2e723' + const newNoteKey = 'abc234-8266-49b9-b438-084003c2e723' + const pasteText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'pdf.pdf) ..' + + '![secondAttachment](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'img.jpg)' + const storageKey = 'storageKey' + const expectedSourceFilePathOne = path.join(dummyStorage.path, systemUnderTest.DESTINATION_FOLDER, pastedNoteKey, 'pdf.pdf') + const expectedSourceFilePathTwo = path.join(dummyStorage.path, systemUnderTest.DESTINATION_FOLDER, pastedNoteKey, 'img.jpg') + + sander.exists = jest.fn(() => Promise.resolve(true)) + systemUnderTest.copyAttachment = jest.fn(() => Promise.resolve('dummyNewFileName')) + + return systemUnderTest.handleAttachmentLinkPaste(storageKey, newNoteKey, pasteText) + .then(() => { + expect(findStorage.findStorage).toHaveBeenCalledWith(storageKey) + expect(sander.exists).toHaveBeenCalledWith(expectedSourceFilePathOne) + expect(sander.exists).toHaveBeenCalledWith(expectedSourceFilePathTwo) + expect(systemUnderTest.copyAttachment).toHaveBeenCalledWith(expectedSourceFilePathOne, storageKey, newNoteKey) + expect(systemUnderTest.copyAttachment).toHaveBeenCalledWith(expectedSourceFilePathTwo, storageKey, newNoteKey) + }) +}) + +it('should test that handleAttachmentLinkPaste returns the correct modified paste text', function () { + const dummyStorage = {path: 'dummyStoragePath'} + findStorage.findStorage = jest.fn(() => dummyStorage) + const pastedNoteKey = 'b1e06f81-8266-49b9-b438-084003c2e723' + const newNoteKey = 'abc234-8266-49b9-b438-084003c2e723' + const dummyNewFileName = 'dummyNewFileName' + const pasteText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'pdf.pdf)' + const expectedText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + newNoteKey + path.sep + dummyNewFileName + ')' + const storageKey = 'storageKey' + + sander.exists = jest.fn(() => Promise.resolve(true)) + systemUnderTest.copyAttachment = jest.fn(() => Promise.resolve(dummyNewFileName)) + + return systemUnderTest.handleAttachmentLinkPaste(storageKey, newNoteKey, pasteText) + .then((returnedPastedText) => { + expect(returnedPastedText).toBe(expectedText) + }) +}) + +it('should test that handleAttachmentLinkPaste returns the correct modified paste text if multiple links are posted', function () { + const dummyStorage = {path: 'dummyStoragePath'} + findStorage.findStorage = jest.fn(() => dummyStorage) + const pastedNoteKey = 'b1e06f81-8266-49b9-b438-084003c2e723' + const newNoteKey = 'abc234-8266-49b9-b438-084003c2e723' + const dummyNewFileNameOne = 'dummyNewFileName' + const dummyNewFileNameTwo = 'dummyNewFileNameTwo' + const pasteText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'pdf.pdf) ' + + '![secondImage](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'img.jpg)' + const expectedText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + newNoteKey + path.sep + dummyNewFileNameOne + ') ' + + '![secondImage](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + newNoteKey + path.sep + dummyNewFileNameTwo + ')' + const storageKey = 'storageKey' + + sander.exists = jest.fn(() => Promise.resolve(true)) + systemUnderTest.copyAttachment = jest.fn() + systemUnderTest.copyAttachment.mockReturnValueOnce(Promise.resolve(dummyNewFileNameOne)) + systemUnderTest.copyAttachment.mockReturnValue(Promise.resolve(dummyNewFileNameTwo)) + + return systemUnderTest.handleAttachmentLinkPaste(storageKey, newNoteKey, pasteText) + .then((returnedPastedText) => { + expect(returnedPastedText).toBe(expectedText) + }) +}) + +it('should test that handleAttachmentLinkPaste calls the copy method correct if multiple links are posted where one file was found and one was not', function () { + const dummyStorage = {path: 'dummyStoragePath'} + findStorage.findStorage = jest.fn(() => dummyStorage) + const pastedNoteKey = 'b1e06f81-8266-49b9-b438-084003c2e723' + const newNoteKey = 'abc234-8266-49b9-b438-084003c2e723' + const pasteText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'pdf.pdf) ..' + + '![secondAttachment](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'img.jpg)' + const storageKey = 'storageKey' + const expectedSourceFilePathOne = path.join(dummyStorage.path, systemUnderTest.DESTINATION_FOLDER, pastedNoteKey, 'pdf.pdf') + const expectedSourceFilePathTwo = path.join(dummyStorage.path, systemUnderTest.DESTINATION_FOLDER, pastedNoteKey, 'img.jpg') + + sander.exists = jest.fn() + sander.exists.mockReturnValueOnce(Promise.resolve(false)) + sander.exists.mockReturnValue(Promise.resolve(true)) + systemUnderTest.copyAttachment = jest.fn(() => Promise.resolve('dummyNewFileName')) + systemUnderTest.generateFileNotFoundMarkdown = jest.fn() + + return systemUnderTest.handleAttachmentLinkPaste(storageKey, newNoteKey, pasteText) + .then(() => { + expect(findStorage.findStorage).toHaveBeenCalledWith(storageKey) + expect(sander.exists).toHaveBeenCalledWith(expectedSourceFilePathOne) + expect(sander.exists).toHaveBeenCalledWith(expectedSourceFilePathTwo) + expect(systemUnderTest.copyAttachment).toHaveBeenCalledTimes(1) + expect(systemUnderTest.copyAttachment).toHaveBeenCalledWith(expectedSourceFilePathTwo, storageKey, newNoteKey) + }) +}) + +it('should test that handleAttachmentLinkPaste returns the correct modified paste text if the file was not found', function () { + const dummyStorage = {path: 'dummyStoragePath'} + findStorage.findStorage = jest.fn(() => dummyStorage) + const pastedNoteKey = 'b1e06f81-8266-49b9-b438-084003c2e723' + const newNoteKey = 'abc234-8266-49b9-b438-084003c2e723' + const pasteText = 'text ![alt.png](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'pdf.pdf)' + const storageKey = 'storageKey' + const fileNotFoundMD = 'file not found' + const expectedPastText = 'text ' + fileNotFoundMD + + systemUnderTest.generateFileNotFoundMarkdown = jest.fn(() => fileNotFoundMD) + sander.exists = jest.fn(() => Promise.resolve(false)) + + return systemUnderTest.handleAttachmentLinkPaste(storageKey, newNoteKey, pasteText) + .then((returnedPastedText) => { + expect(returnedPastedText).toBe(expectedPastText) + }) +}) + +it('should test that handleAttachmentLinkPaste returns the correct modified paste text if multiple files were not found', function () { + const dummyStorage = {path: 'dummyStoragePath'} + findStorage.findStorage = jest.fn(() => dummyStorage) + const pastedNoteKey = 'b1e06f81-8266-49b9-b438-084003c2e723' + const newNoteKey = 'abc234-8266-49b9-b438-084003c2e723' + const pasteText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'pdf.pdf) ' + + '![secondImage](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'img.jpg)' + const storageKey = 'storageKey' + const fileNotFoundMD = 'file not found' + const expectedPastText = 'text ' + fileNotFoundMD + ' ' + fileNotFoundMD + systemUnderTest.generateFileNotFoundMarkdown = jest.fn(() => fileNotFoundMD) + + sander.exists = jest.fn(() => Promise.resolve(false)) + + return systemUnderTest.handleAttachmentLinkPaste(storageKey, newNoteKey, pasteText) + .then((returnedPastedText) => { + expect(returnedPastedText).toBe(expectedPastText) + }) +}) + +it('should test that handleAttachmentLinkPaste returns the correct modified paste text if one file was found and one was not found', function () { + const dummyStorage = {path: 'dummyStoragePath'} + findStorage.findStorage = jest.fn(() => dummyStorage) + const pastedNoteKey = 'b1e06f81-8266-49b9-b438-084003c2e723' + const newNoteKey = 'abc234-8266-49b9-b438-084003c2e723' + const dummyFoundFileName = 'dummyFileName' + const fileNotFoundMD = 'file not found' + const pasteText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'pdf.pdf) .. ' + + '![secondAttachment](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'img.jpg)' + const storageKey = 'storageKey' + const expectedPastText = 'text ' + fileNotFoundMD + ' .. ![secondAttachment](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + newNoteKey + path.sep + dummyFoundFileName + ')' + + sander.exists = jest.fn() + sander.exists.mockReturnValueOnce(Promise.resolve(false)) + sander.exists.mockReturnValue(Promise.resolve(true)) + systemUnderTest.copyAttachment = jest.fn(() => Promise.resolve(dummyFoundFileName)) + systemUnderTest.generateFileNotFoundMarkdown = jest.fn(() => fileNotFoundMD) + + return systemUnderTest.handleAttachmentLinkPaste(storageKey, newNoteKey, pasteText) + .then((returnedPastedText) => { + expect(returnedPastedText).toBe(expectedPastText) + }) +}) + +it('should test that handleAttachmentLinkPaste returns the correct modified paste text if one file was found and one was not found', function () { + const dummyStorage = {path: 'dummyStoragePath'} + findStorage.findStorage = jest.fn(() => dummyStorage) + const pastedNoteKey = 'b1e06f81-8266-49b9-b438-084003c2e723' + const newNoteKey = 'abc234-8266-49b9-b438-084003c2e723' + const dummyFoundFileName = 'dummyFileName' + const fileNotFoundMD = 'file not found' + const pasteText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'pdf.pdf) .. ' + + '![secondAttachment](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + pastedNoteKey + path.sep + 'img.jpg)' + const storageKey = 'storageKey' + const expectedPastText = 'text ![alt](' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + newNoteKey + path.sep + dummyFoundFileName + ') .. ' + fileNotFoundMD + + sander.exists = jest.fn() + sander.exists.mockReturnValueOnce(Promise.resolve(true)) + sander.exists.mockReturnValue(Promise.resolve(false)) + systemUnderTest.copyAttachment = jest.fn(() => Promise.resolve(dummyFoundFileName)) + systemUnderTest.generateFileNotFoundMarkdown = jest.fn(() => fileNotFoundMD) + + return systemUnderTest.handleAttachmentLinkPaste(storageKey, newNoteKey, pasteText) + .then((returnedPastedText) => { + expect(returnedPastedText).toBe(expectedPastText) + }) +})