mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 01:36:22 +00:00
feat: Added Context Menu for markdown preview mode and copy url when hyperlink
This commit is contained in:
committed by
Junyoung Choi
parent
c83e5cc7d8
commit
e85767b4a0
@@ -20,7 +20,7 @@ import styles from '../components/CodeEditor.styl'
|
|||||||
const { ipcRenderer, remote, clipboard } = 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').buildEditorContextMenu
|
||||||
import TurndownService from 'turndown'
|
import TurndownService from 'turndown'
|
||||||
import {languageMaps} from '../lib/CMLanguageList'
|
import {languageMaps} from '../lib/CMLanguageList'
|
||||||
import snippetManager from '../lib/SnippetManager'
|
import snippetManager from '../lib/SnippetManager'
|
||||||
|
|||||||
@@ -18,15 +18,13 @@ import mdurl from 'mdurl'
|
|||||||
import exportNote from 'browser/main/lib/dataApi/exportNote'
|
import exportNote from 'browser/main/lib/dataApi/exportNote'
|
||||||
import { escapeHtmlCharacters } from 'browser/lib/utils'
|
import { escapeHtmlCharacters } from 'browser/lib/utils'
|
||||||
import yaml from 'js-yaml'
|
import yaml from 'js-yaml'
|
||||||
import context from 'browser/lib/context'
|
|
||||||
import i18n from 'browser/lib/i18n'
|
|
||||||
import fs from 'fs'
|
|
||||||
import { render } from 'react-dom'
|
import { render } from 'react-dom'
|
||||||
import Carousel from 'react-image-carousel'
|
import Carousel from 'react-image-carousel'
|
||||||
import ConfigManager from '../main/lib/ConfigManager'
|
import ConfigManager from '../main/lib/ConfigManager'
|
||||||
|
|
||||||
const { remote, shell } = require('electron')
|
const { remote, shell } = require('electron')
|
||||||
const attachmentManagement = require('../main/lib/dataApi/attachmentManagement')
|
const attachmentManagement = require('../main/lib/dataApi/attachmentManagement')
|
||||||
|
const buildMarkdownPreviewContextMenu = require('browser/lib/contextMenuBuilder').buildMarkdownPreviewContextMenu
|
||||||
|
|
||||||
const { app } = remote
|
const { app } = remote
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
@@ -34,8 +32,6 @@ const fileUrl = require('file-url')
|
|||||||
|
|
||||||
const dialog = remote.dialog
|
const dialog = remote.dialog
|
||||||
|
|
||||||
const uri2path = require('file-uri-to-path')
|
|
||||||
|
|
||||||
const markdownStyle = require('!!css!stylus?sourceMap!./markdown.styl')[0][1]
|
const markdownStyle = require('!!css!stylus?sourceMap!./markdown.styl')[0][1]
|
||||||
const appPath = fileUrl(
|
const appPath = fileUrl(
|
||||||
process.env.NODE_ENV === 'production' ? app.getAppPath() : path.resolve()
|
process.env.NODE_ENV === 'production' ? app.getAppPath() : path.resolve()
|
||||||
@@ -250,30 +246,9 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleContextMenu (event) {
|
handleContextMenu (event) {
|
||||||
// If a contextMenu handler was passed to us, use it instead of the self-defined one -> return
|
const menu = buildMarkdownPreviewContextMenu(this, event)
|
||||||
if (_.isFunction(this.props.onContextMenu)) {
|
if (menu != null) {
|
||||||
this.props.onContextMenu(event)
|
setTimeout(() => menu.popup(remote.getCurrentWindow()), 30)
|
||||||
return
|
|
||||||
}
|
|
||||||
// No contextMenu was passed to us -> execute our own link-opener
|
|
||||||
if (event.target.tagName.toLowerCase() === 'a' && event.target.getAttribute('href')) {
|
|
||||||
const href = event.target.href
|
|
||||||
const isLocalFile = href.startsWith('file:')
|
|
||||||
if (isLocalFile) {
|
|
||||||
const absPath = uri2path(href)
|
|
||||||
try {
|
|
||||||
if (fs.lstatSync(absPath).isFile()) {
|
|
||||||
context.popup([
|
|
||||||
{
|
|
||||||
label: i18n.__('Show in explorer'),
|
|
||||||
click: (e) => shell.showItemInFolder(absPath)
|
|
||||||
}
|
|
||||||
])
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log('Error while evaluating if the file is locally available', e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
|
import i18n from 'browser/lib/i18n'
|
||||||
|
import fs from 'fs'
|
||||||
|
|
||||||
const {remote} = require('electron')
|
const {remote} = require('electron')
|
||||||
const {Menu} = remote.require('electron')
|
const {Menu} = remote.require('electron')
|
||||||
|
const {clipboard} = remote.require('electron')
|
||||||
|
const {shell} = remote.require('electron')
|
||||||
const spellcheck = require('./spellcheck')
|
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.
|
* Creates the context menu that is shown when there is a right click in the editor of a (not-snippet) note.
|
||||||
@@ -62,4 +68,61 @@ const buildEditorContextMenu = function (editor, event) {
|
|||||||
return Menu.buildFromTemplate(template)
|
return Menu.buildFromTemplate(template)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = buildEditorContextMenu
|
/**
|
||||||
|
* 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: 'cut'
|
||||||
|
}, {
|
||||||
|
role: 'copy'
|
||||||
|
}, {
|
||||||
|
role: 'paste'
|
||||||
|
}, {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ jest.mock('electron', () => {
|
|||||||
|
|
||||||
const spellcheck = require('browser/lib/spellcheck')
|
const spellcheck = require('browser/lib/spellcheck')
|
||||||
const buildEditorContextMenu = require('browser/lib/contextMenuBuilder')
|
const buildEditorContextMenu = require('browser/lib/contextMenuBuilder')
|
||||||
|
const buildMarkdownPreviewContextMenu = require('browser/lib/contextMenuBuilder')
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
menuBuilderParameter = null
|
menuBuilderParameter = null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Editor Context Menu
|
||||||
it('should make sure that no context menu is build if the passed editor instance was null', function () {
|
it('should make sure that no context menu is build if the passed editor instance was null', function () {
|
||||||
const event = {
|
const event = {
|
||||||
pageX: 12,
|
pageX: 12,
|
||||||
@@ -124,3 +126,13 @@ it('should make sure that word suggestions creates a correct menu if there was a
|
|||||||
expect(menuBuilderParameter[7].role).toEqual('selectall')
|
expect(menuBuilderParameter[7].role).toEqual('selectall')
|
||||||
expect(spellcheck.getSpellingSuggestion).toHaveBeenCalledWith(wordToCorrect)
|
expect(spellcheck.getSpellingSuggestion).toHaveBeenCalledWith(wordToCorrect)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Markdown Preview Context Menu
|
||||||
|
it('should make sure that no context menu is built if the Markdown Preview instance was null', function () {
|
||||||
|
const event = {
|
||||||
|
pageX: 12,
|
||||||
|
pageY: 12
|
||||||
|
}
|
||||||
|
buildMarkdownPreviewContextMenu(null, event)
|
||||||
|
expect(menuBuilderParameter).toEqual(null)
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user