import i18n from 'browser/lib/i18n' import fs from 'fs' const { remote } = require('electron') const { Menu } = remote.require('electron') const { clipboard } = remote.require('electron') const { shell } = remote.require('electron') const spellcheck = require('./spellcheck') const uri2path = require('file-uri-to-path') /** * Creates the context menu that is shown when there is a right click in the editor of a (not-snippet) note. * If the word is does not contains a spelling error (determined by the 'error style'), no suggestions for corrections are requested * => they are not visible in the context menu * @param editor CodeMirror editor * @param {MouseEvent} event that has triggered the creation of the context menu * @returns {Electron.Menu} The created electron context menu */ const buildEditorContextMenu = function(editor, event) { if ( editor == null || event == null || event.pageX == null || event.pageY == null ) { return null } const cursor = editor.coordsChar({ left: event.pageX, top: event.pageY }) const wordRange = editor.findWordAt(cursor) const word = editor.getRange(wordRange.anchor, wordRange.head) const existingMarks = editor.findMarks(wordRange.anchor, wordRange.head) || [] let isMisspelled = false for (const mark of existingMarks) { if (mark.className === spellcheck.getCSSClassName()) { isMisspelled = true break } } let suggestion = [] if (isMisspelled) { suggestion = spellcheck.getSpellingSuggestion(word) } const selection = { isMisspelled: isMisspelled, spellingSuggestions: suggestion } const template = [ { role: 'cut' }, { role: 'copy' }, { role: 'paste' }, { role: 'selectall' } ] if (selection.isMisspelled) { const suggestions = selection.spellingSuggestions template.unshift.apply( template, suggestions .map(function(suggestion) { return { label: suggestion, click: function(suggestion) { if (editor != null) { editor.replaceRange( suggestion.label, wordRange.anchor, wordRange.head ) } } } }) .concat({ type: 'separator' }) ) } return Menu.buildFromTemplate(template) } /** * Creates the context menu that is shown when there is a right click Markdown preview of a (not-snippet) note. * @param {MarkdownPreview} markdownPreview * @param {MouseEvent} event that has triggered the creation of the context menu * @returns {Electron.Menu} The created electron context menu */ const buildMarkdownPreviewContextMenu = function(markdownPreview, event) { if ( markdownPreview == null || event == null || event.pageX == null || event.pageY == null ) { return null } // Default context menu inclusions const template = [ { role: 'copy' }, { role: 'selectall' } ] if ( event.target.tagName.toLowerCase() === 'a' && event.target.getAttribute('href') ) { // Link opener for files on the local system pointed to by href const href = event.target.href const isLocalFile = href.startsWith('file:') if (isLocalFile) { const absPath = uri2path(href) try { if (fs.lstatSync(absPath).isFile()) { template.push({ label: i18n.__('Show in explorer'), click: e => shell.showItemInFolder(absPath) }) } } catch (e) { console.log( 'Error while evaluating if the file is locally available', e ) } } // Add option to context menu to copy url template.push({ label: i18n.__('Copy Url'), click: e => clipboard.writeText(href) }) } return Menu.buildFromTemplate(template) } module.exports = { buildEditorContextMenu: buildEditorContextMenu, buildMarkdownPreviewContextMenu: buildMarkdownPreviewContextMenu }