mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-11 18:24:43 +02:00
This commit is contained in:
parent
4e09b6f2a4
commit
7e8c87e908
@ -40,6 +40,10 @@ describe('HtmlToMd', () => {
|
|||||||
htmlToMdOptions.preserveNestedTables = true;
|
htmlToMdOptions.preserveNestedTables = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (htmlFilename.indexOf('text_color') === 0) {
|
||||||
|
htmlToMdOptions.preserveColorStyles = true;
|
||||||
|
}
|
||||||
|
|
||||||
const html = await readFile(htmlPath, 'utf8');
|
const html = await readFile(htmlPath, 'utf8');
|
||||||
let expectedMd = await readFile(mdPath, 'utf8');
|
let expectedMd = await readFile(mdPath, 'utf8');
|
||||||
|
|
||||||
|
1
packages/app-cli/tests/html_to_md/text_color.html
Normal file
1
packages/app-cli/tests/html_to_md/text_color.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<p>Text <span style="color: #fff000;">Text</span></p>
|
1
packages/app-cli/tests/html_to_md/text_color.md
Normal file
1
packages/app-cli/tests/html_to_md/text_color.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Text <span style="color: #fff000;">Text</span>
|
@ -377,6 +377,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
|||||||
.tox .tox-dialog,
|
.tox .tox-dialog,
|
||||||
.tox textarea,
|
.tox textarea,
|
||||||
.tox input,
|
.tox input,
|
||||||
|
.tox .tox-menu,
|
||||||
.tox .tox-dialog__footer {
|
.tox .tox-dialog__footer {
|
||||||
background-color: ${theme.backgroundColor} !important;
|
background-color: ${theme.backgroundColor} !important;
|
||||||
}
|
}
|
||||||
@ -385,6 +386,12 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
|||||||
color: ${theme.color};
|
color: ${theme.color};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tox .tox-menu {
|
||||||
|
/* Ensures that popover menus (the color swatch menu) has a visible border
|
||||||
|
even in dark mode. */
|
||||||
|
border: 1px solid rgba(140, 140, 140, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
When creating dialogs, TinyMCE doesn't seem to offer a way to style the components or to assign classes to them.
|
When creating dialogs, TinyMCE doesn't seem to offer a way to style the components or to assign classes to them.
|
||||||
We want the code dialog box text area to be monospace, and since we can't target this precisely, we apply the style
|
We want the code dialog box text area to be monospace, and since we can't target this precisely, we apply the style
|
||||||
@ -406,6 +413,8 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
|||||||
|
|
||||||
.tox .tox-tbtn,
|
.tox .tox-tbtn,
|
||||||
.tox .tox-tbtn svg,
|
.tox .tox-tbtn svg,
|
||||||
|
.tox .tox-menu button > svg,
|
||||||
|
.tox .tox-split-button,
|
||||||
.tox .tox-dialog__header,
|
.tox .tox-dialog__header,
|
||||||
.tox .tox-button--icon .tox-icon svg,
|
.tox .tox-button--icon .tox-icon svg,
|
||||||
.tox .tox-button.tox-button--icon .tox-icon svg,
|
.tox .tox-button.tox-button--icon .tox-icon svg,
|
||||||
@ -427,7 +436,9 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tox .tox-tbtn--enabled,
|
.tox .tox-tbtn--enabled,
|
||||||
.tox .tox-tbtn--enabled:hover {
|
.tox .tox-tbtn--enabled:hover,
|
||||||
|
.tox .tox-menu button:hover,
|
||||||
|
.tox .tox-split-button {
|
||||||
background-color: ${theme.selectedColor};
|
background-color: ${theme.selectedColor};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,11 +446,13 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
|||||||
background-color: ${theme.backgroundColor} !important;
|
background-color: ${theme.backgroundColor} !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tox .tox-tbtn:focus {
|
.tox .tox-tbtn:focus,
|
||||||
|
.tox .tox-split-button:focus {
|
||||||
background-color: ${theme.backgroundColor3}
|
background-color: ${theme.backgroundColor3}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tox .tox-tbtn:hover {
|
.tox .tox-tbtn:hover,
|
||||||
|
.tox .tox-menu button:hover > svg {
|
||||||
color: ${theme.colorHover3} !important;
|
color: ${theme.colorHover3} !important;
|
||||||
fill: ${theme.colorHover3} !important;
|
fill: ${theme.colorHover3} !important;
|
||||||
background-color: ${theme.backgroundColorHover3}
|
background-color: ${theme.backgroundColorHover3}
|
||||||
@ -470,6 +483,10 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
|||||||
background-color: ${theme.backgroundColor3} !important;
|
background-color: ${theme.backgroundColor3} !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tox .tox-split-button:hover {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
.tox-tinymce,
|
.tox-tinymce,
|
||||||
.tox .tox-toolbar__group,
|
.tox .tox-toolbar__group,
|
||||||
.tox.tox-tinymce-aux .tox-toolbar__overflow,
|
.tox.tox-tinymce-aux .tox-toolbar__overflow,
|
||||||
@ -613,6 +630,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
|||||||
joplinSub: { inline: 'sub', remove: 'all' },
|
joplinSub: { inline: 'sub', remove: 'all' },
|
||||||
joplinSup: { inline: 'sup', remove: 'all' },
|
joplinSup: { inline: 'sup', remove: 'all' },
|
||||||
code: { inline: 'code', remove: 'all', attributes: { spellcheck: false } },
|
code: { inline: 'code', remove: 'all', attributes: { spellcheck: false } },
|
||||||
|
forecolor: { inline: 'span', styles: { color: '%value' } },
|
||||||
},
|
},
|
||||||
setup: (editor: Editor) => {
|
setup: (editor: Editor) => {
|
||||||
editor.addCommand('joplinAttach', () => {
|
editor.addCommand('joplinAttach', () => {
|
||||||
@ -1036,7 +1054,15 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
|||||||
//
|
//
|
||||||
// Any maybe others, so to catch them all we only check the prefix
|
// Any maybe others, so to catch them all we only check the prefix
|
||||||
|
|
||||||
const changeCommands = ['mceBlockQuote', 'ToggleJoplinChecklistItem', 'Bold', 'Italic', 'Underline', 'Paragraph'];
|
const changeCommands = [
|
||||||
|
'mceBlockQuote',
|
||||||
|
'ToggleJoplinChecklistItem',
|
||||||
|
'Bold',
|
||||||
|
'Italic',
|
||||||
|
'Underline',
|
||||||
|
'Paragraph',
|
||||||
|
'mceApplyTextcolor',
|
||||||
|
];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
changeCommands.includes(c) ||
|
changeCommands.includes(c) ||
|
||||||
|
@ -60,6 +60,9 @@ export default function(editor: any) {
|
|||||||
|
|
||||||
const items: string[] = definitions.filter(d => !!d.grouped).map(d => d.name);
|
const items: string[] = definitions.filter(d => !!d.grouped).map(d => d.name);
|
||||||
|
|
||||||
|
// Additional built-in buttons to show in the formatting sub-menu:
|
||||||
|
items.push('forecolor');
|
||||||
|
|
||||||
editor.ui.registry.addGroupToolbarButton('formattingExtras', {
|
editor.ui.registry.addGroupToolbarButton('formattingExtras', {
|
||||||
icon: 'image-options',
|
icon: 'image-options',
|
||||||
items: items.join(' '),
|
items: items.join(' '),
|
||||||
|
@ -12,6 +12,7 @@ export async function htmlToMarkdown(markupLanguage: number, html: string, origi
|
|||||||
newBody = htmlToMd.parse(html, {
|
newBody = htmlToMd.parse(html, {
|
||||||
preserveImageTagsWithSize: true,
|
preserveImageTagsWithSize: true,
|
||||||
preserveNestedTables: true,
|
preserveNestedTables: true,
|
||||||
|
preserveColorStyles: true,
|
||||||
});
|
});
|
||||||
newBody = await Note.replaceResourceExternalToInternalLinks(newBody, { useAbsolutePaths: true });
|
newBody = await Note.replaceResourceExternalToInternalLinks(newBody, { useAbsolutePaths: true });
|
||||||
} else {
|
} else {
|
||||||
|
@ -8,6 +8,7 @@ export interface ParseOptions {
|
|||||||
anchorNames?: string[];
|
anchorNames?: string[];
|
||||||
preserveImageTagsWithSize?: boolean;
|
preserveImageTagsWithSize?: boolean;
|
||||||
preserveNestedTables?: boolean;
|
preserveNestedTables?: boolean;
|
||||||
|
preserveColorStyles?: boolean;
|
||||||
baseUrl?: string;
|
baseUrl?: string;
|
||||||
disableEscapeContent?: boolean;
|
disableEscapeContent?: boolean;
|
||||||
convertEmbeddedPdfsToLinks?: boolean;
|
convertEmbeddedPdfsToLinks?: boolean;
|
||||||
@ -22,6 +23,7 @@ export default class HtmlToMd {
|
|||||||
codeBlockStyle: 'fenced',
|
codeBlockStyle: 'fenced',
|
||||||
preserveImageTagsWithSize: !!options.preserveImageTagsWithSize,
|
preserveImageTagsWithSize: !!options.preserveImageTagsWithSize,
|
||||||
preserveNestedTables: !!options.preserveNestedTables,
|
preserveNestedTables: !!options.preserveNestedTables,
|
||||||
|
preserveColorStyles: !!options.preserveColorStyles,
|
||||||
bulletListMarker: '-',
|
bulletListMarker: '-',
|
||||||
emDelimiter: '*',
|
emDelimiter: '*',
|
||||||
strongDelimiter: '**',
|
strongDelimiter: '**',
|
||||||
|
@ -127,6 +127,19 @@ rules.subscript = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handles foreground color changes as created by the rich text editor.
|
||||||
|
// We intentionally don't handle the general style="color: colorhere" case as
|
||||||
|
// this may leave unwanted formatting when saving websites as markdown.
|
||||||
|
rules.foregroundColor = {
|
||||||
|
filter: function (node, options) {
|
||||||
|
return options.preserveColorStyles && node.nodeName === 'SPAN' && getStyleProp(node, 'color');
|
||||||
|
},
|
||||||
|
|
||||||
|
replacement: function (content, node, options) {
|
||||||
|
return `<span style="color: ${htmlentities(getStyleProp(node, 'color'))};">${content}</span>`;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// ==============================
|
// ==============================
|
||||||
// END Joplin format support
|
// END Joplin format support
|
||||||
// ==============================
|
// ==============================
|
||||||
|
@ -40,6 +40,7 @@ export default function TurndownService (options) {
|
|||||||
disableEscapeContent: false,
|
disableEscapeContent: false,
|
||||||
preformattedCode: false,
|
preformattedCode: false,
|
||||||
preserveNestedTables: false,
|
preserveNestedTables: false,
|
||||||
|
preserveColorStyles: false,
|
||||||
blankReplacement: function (content, node) {
|
blankReplacement: function (content, node) {
|
||||||
return node.isBlock ? '\n\n' : ''
|
return node.isBlock ? '\n\n' : ''
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user