mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-02 12:47:41 +02:00
Desktop: Add support for strikethrough, sub, sup and insert formatting on Rich Text editor
This commit is contained in:
parent
f3b2ca4752
commit
8ba49c6fdf
@ -397,6 +397,9 @@ packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js.map
|
|||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.d.ts
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.d.ts
|
||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js.map
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js.map
|
||||||
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.d.ts
|
||||||
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.js
|
||||||
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.js.map
|
||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.d.ts
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.d.ts
|
||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
|
||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js.map
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js.map
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -384,6 +384,9 @@ packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js.map
|
|||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.d.ts
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.d.ts
|
||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js.map
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js.map
|
||||||
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.d.ts
|
||||||
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.js
|
||||||
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.js.map
|
||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.d.ts
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.d.ts
|
||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
|
||||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js.map
|
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js.map
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
X<sub>1</sub> X<sup>1</sup> <ins>Insert</ins> <s>Strike</s>
|
@ -0,0 +1 @@
|
|||||||
|
X<sub>1</sub> X<sup>1</sup> <ins>Insert</ins> ~~Strike~~
|
@ -18,6 +18,7 @@ const { MarkupToHtml } = require('@joplin/renderer');
|
|||||||
const taboverride = require('taboverride');
|
const taboverride = require('taboverride');
|
||||||
import { reg } from '@joplin/lib/registry';
|
import { reg } from '@joplin/lib/registry';
|
||||||
import BaseItem from '@joplin/lib/models/BaseItem';
|
import BaseItem from '@joplin/lib/models/BaseItem';
|
||||||
|
import setupToolbarButtons from './utils/setupToolbarButtons';
|
||||||
const { themeStyle } = require('@joplin/lib/theme');
|
const { themeStyle } = require('@joplin/lib/theme');
|
||||||
const { clipboard } = require('electron');
|
const { clipboard } = require('electron');
|
||||||
const supportedLocales = require('./supportedLocales');
|
const supportedLocales = require('./supportedLocales');
|
||||||
@ -543,7 +544,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
|||||||
const toolbarPluginButtons = pluginCommandNames.length ? ` | ${pluginCommandNames.join(' ')}` : '';
|
const toolbarPluginButtons = pluginCommandNames.length ? ` | ${pluginCommandNames.join(' ')}` : '';
|
||||||
|
|
||||||
const toolbar = [
|
const toolbar = [
|
||||||
'bold', 'italic', 'joplinHighlight', '|',
|
'bold', 'italic', 'joplinHighlight', 'joplinStrikethrough', 'formattingExtras', '|',
|
||||||
'link', 'joplinInlineCode', 'joplinCodeBlock', 'joplinAttach', '|',
|
'link', 'joplinInlineCode', 'joplinCodeBlock', 'joplinAttach', '|',
|
||||||
'bullist', 'numlist', 'joplinChecklist', '|',
|
'bullist', 'numlist', 'joplinChecklist', '|',
|
||||||
'h1', 'h2', 'h3', 'hr', 'blockquote', 'table', `joplinInsertDateTime${toolbarPluginButtons}`,
|
'h1', 'h2', 'h3', 'hr', 'blockquote', 'table', `joplinInsertDateTime${toolbarPluginButtons}`,
|
||||||
@ -572,7 +573,11 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
|||||||
contextmenu: false,
|
contextmenu: false,
|
||||||
browser_spellcheck: true,
|
browser_spellcheck: true,
|
||||||
formats: {
|
formats: {
|
||||||
'joplin-highlight': { inline: 'mark', remove: 'all' },
|
joplinHighlight: { inline: 'mark', remove: 'all' },
|
||||||
|
joplinStrikethrough: { inline: 's', remove: 'all' },
|
||||||
|
joplinInsert: { inline: 'ins', remove: 'all' },
|
||||||
|
joplinSub: { inline: 'sub', remove: 'all' },
|
||||||
|
joplinSup: { inline: 'sup', remove: 'all' },
|
||||||
},
|
},
|
||||||
setup: (editor: any) => {
|
setup: (editor: any) => {
|
||||||
|
|
||||||
@ -647,18 +652,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.ui.registry.addToggleButton('joplinHighlight', {
|
setupToolbarButtons(editor);
|
||||||
tooltip: _('Highlight'),
|
|
||||||
icon: 'highlight-bg-color',
|
|
||||||
onAction: async function() {
|
|
||||||
editor.execCommand('mceToggleFormat', false, 'joplin-highlight');
|
|
||||||
},
|
|
||||||
onSetup: function(api: any) {
|
|
||||||
editor.formatter.formatChanged('joplin-highlight', function(state: boolean) {
|
|
||||||
api.setActive(state);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
editor.ui.registry.addButton('joplinCodeBlock', {
|
editor.ui.registry.addButton('joplinCodeBlock', {
|
||||||
tooltip: _('Code Block'),
|
tooltip: _('Code Block'),
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
import { _ } from '@joplin/lib/locale';
|
||||||
|
|
||||||
|
interface ButtonDefinition {
|
||||||
|
name: string;
|
||||||
|
tooltip: string;
|
||||||
|
icon: string;
|
||||||
|
grouped?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buttonDefinitions(): ButtonDefinition[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: 'joplinHighlight',
|
||||||
|
tooltip: _('Highlight'),
|
||||||
|
icon: 'highlight-bg-color',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'joplinStrikethrough',
|
||||||
|
tooltip: _('Strikethrough'),
|
||||||
|
icon: 'strike-through',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'joplinInsert',
|
||||||
|
tooltip: _('Insert'),
|
||||||
|
icon: 'underline',
|
||||||
|
grouped: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'joplinSup',
|
||||||
|
tooltip: _('Superscript'),
|
||||||
|
icon: 'superscript',
|
||||||
|
grouped: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'joplinSub',
|
||||||
|
tooltip: _('Subscript'),
|
||||||
|
icon: 'subscript',
|
||||||
|
grouped: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function(editor: any) {
|
||||||
|
const definitions = buttonDefinitions();
|
||||||
|
|
||||||
|
for (const def of definitions) {
|
||||||
|
editor.ui.registry.addToggleButton(def.name, {
|
||||||
|
tooltip: def.tooltip,
|
||||||
|
icon: def.icon,
|
||||||
|
onAction: async function() {
|
||||||
|
editor.execCommand('mceToggleFormat', false, def.name);
|
||||||
|
},
|
||||||
|
onSetup: function(api: any) {
|
||||||
|
editor.formatter.formatChanged(def.name, function(state: boolean) {
|
||||||
|
api.setActive(state);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const items: string[] = definitions.filter(d => !!d.grouped).map(d => d.name);
|
||||||
|
|
||||||
|
editor.ui.registry.addGroupToolbarButton('formattingExtras', {
|
||||||
|
icon: 'image-options',
|
||||||
|
items: items.join(' '),
|
||||||
|
});
|
||||||
|
}
|
@ -788,12 +788,12 @@ class Setting extends BaseModel {
|
|||||||
'markdown.plugin.mark': { storage: SettingStorage.File, value: true, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable ==mark== syntax')}${wysiwygYes}` },
|
'markdown.plugin.mark': { storage: SettingStorage.File, value: true, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable ==mark== syntax')}${wysiwygYes}` },
|
||||||
'markdown.plugin.footnote': { storage: SettingStorage.File, value: true, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable footnotes')}${wysiwygNo}` },
|
'markdown.plugin.footnote': { storage: SettingStorage.File, value: true, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable footnotes')}${wysiwygNo}` },
|
||||||
'markdown.plugin.toc': { storage: SettingStorage.File, value: true, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable table of contents extension')}${wysiwygNo}` },
|
'markdown.plugin.toc': { storage: SettingStorage.File, value: true, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable table of contents extension')}${wysiwygNo}` },
|
||||||
'markdown.plugin.sub': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable ~sub~ syntax')}${wysiwygNo}` },
|
'markdown.plugin.sub': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable ~sub~ syntax')}${wysiwygYes}` },
|
||||||
'markdown.plugin.sup': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable ^sup^ syntax')}${wysiwygNo}` },
|
'markdown.plugin.sup': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable ^sup^ syntax')}${wysiwygYes}` },
|
||||||
'markdown.plugin.deflist': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable deflist syntax')}${wysiwygNo}` },
|
'markdown.plugin.deflist': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable deflist syntax')}${wysiwygNo}` },
|
||||||
'markdown.plugin.abbr': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable abbreviation syntax')}${wysiwygNo}` },
|
'markdown.plugin.abbr': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable abbreviation syntax')}${wysiwygNo}` },
|
||||||
'markdown.plugin.emoji': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable markdown emoji')}${wysiwygNo}` },
|
'markdown.plugin.emoji': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable markdown emoji')}${wysiwygNo}` },
|
||||||
'markdown.plugin.insert': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable ++insert++ syntax')}${wysiwygNo}` },
|
'markdown.plugin.insert': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable ++insert++ syntax')}${wysiwygYes}` },
|
||||||
'markdown.plugin.multitable': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable multimarkdown table extension')}${wysiwygNo}` },
|
'markdown.plugin.multitable': { storage: SettingStorage.File, value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable multimarkdown table extension')}${wysiwygNo}` },
|
||||||
|
|
||||||
// Tray icon (called AppIndicator) doesn't work in Ubuntu
|
// Tray icon (called AppIndicator) doesn't work in Ubuntu
|
||||||
|
@ -2,7 +2,7 @@ export default function strikethrough (turndownService) {
|
|||||||
turndownService.addRule('strikethrough', {
|
turndownService.addRule('strikethrough', {
|
||||||
filter: ['del', 's', 'strike'],
|
filter: ['del', 's', 'strike'],
|
||||||
replacement: function (content) {
|
replacement: function (content) {
|
||||||
return '~' + content + '~'
|
return '~~' + content + '~~'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,36 @@ rules.highlight = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unlike strikethrough and mark formatting, insert, sup and sub aren't
|
||||||
|
// widespread enough to automatically convert them to Markdown, but keep them as
|
||||||
|
// HTML anyway. Another issue is that we use "~" for subscript but that's
|
||||||
|
// actually the syntax for strikethrough on GitHub, so it's best to keep it as
|
||||||
|
// HTML to avoid any ambiguity.
|
||||||
|
|
||||||
|
rules.insert = {
|
||||||
|
filter: 'ins',
|
||||||
|
|
||||||
|
replacement: function (content, node, options) {
|
||||||
|
return '<ins>' + content + '</ins>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rules.superscript = {
|
||||||
|
filter: 'sup',
|
||||||
|
|
||||||
|
replacement: function (content, node, options) {
|
||||||
|
return '<sup>' + content + '</sup>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rules.subscript = {
|
||||||
|
filter: 'sub',
|
||||||
|
|
||||||
|
replacement: function (content, node, options) {
|
||||||
|
return '<sub>' + content + '</sub>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ==============================
|
// ==============================
|
||||||
// END Joplin format support
|
// END Joplin format support
|
||||||
// ==============================
|
// ==============================
|
||||||
|
Loading…
Reference in New Issue
Block a user