diff --git a/packages/app-desktop/gui/NoteEditor/utils/index.ts b/packages/app-desktop/gui/NoteEditor/utils/index.ts index 3de653439b2..04070dfd875 100644 --- a/packages/app-desktop/gui/NoteEditor/utils/index.ts +++ b/packages/app-desktop/gui/NoteEditor/utils/index.ts @@ -1,11 +1,11 @@ import { FormNote } from './types'; -import HtmlToMd from '@joplin/lib/HtmlToMd'; +import HtmlToMd, { ParseOptions } from '@joplin/lib/HtmlToMd'; import Note from '@joplin/lib/models/Note'; import { NoteEntity } from '@joplin/lib/services/database/types'; const { MarkupToHtml } = require('@joplin/renderer'); -export async function htmlToMarkdown(markupLanguage: number, html: string, originalCss: string): Promise { +export async function htmlToMarkdown(markupLanguage: number, html: string, originalCss: string, parseOptions: ParseOptions = null): Promise { let newBody = ''; if (markupLanguage === MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN) { @@ -14,6 +14,7 @@ export async function htmlToMarkdown(markupLanguage: number, html: string, origi preserveImageTagsWithSize: true, preserveNestedTables: true, preserveColorStyles: true, + ...parseOptions, }); newBody = await Note.replaceResourceExternalToInternalLinks(newBody, { useAbsolutePaths: true }); } else { diff --git a/packages/app-desktop/gui/NoteEditor/utils/resourceHandling.ts b/packages/app-desktop/gui/NoteEditor/utils/resourceHandling.ts index 8b2602af0e6..0e1528c9167 100644 --- a/packages/app-desktop/gui/NoteEditor/utils/resourceHandling.ts +++ b/packages/app-desktop/gui/NoteEditor/utils/resourceHandling.ts @@ -180,7 +180,7 @@ export async function processPastedHtml(html: string, htmlToMd: HtmlToMarkdownHa // TinyMCE, but lost once the note is saved. So here we convert the HTML to Markdown then back // to HTML to ensure that the content we paste will be handled correctly by the app. if (htmlToMd && mdToHtml) { - const md = await htmlToMd(MarkupLanguage.Markdown, html, ''); + const md = await htmlToMd(MarkupLanguage.Markdown, html, '', { preserveColorStyles: Setting.value('editor.pastePreserveColors') }); html = (await mdToHtml(MarkupLanguage.Markdown, md, markupRenderOptions({ bodyOnly: true }))).html; // When plugins that add to the end of rendered content are installed, bodyOnly can diff --git a/packages/app-desktop/gui/NoteEditor/utils/types.ts b/packages/app-desktop/gui/NoteEditor/utils/types.ts index f5a498ed7a6..7a9935a89c4 100644 --- a/packages/app-desktop/gui/NoteEditor/utils/types.ts +++ b/packages/app-desktop/gui/NoteEditor/utils/types.ts @@ -7,6 +7,7 @@ import { Dispatch } from 'redux'; import { ProcessResultsRow } from '@joplin/lib/services/search/SearchEngine'; import { DropHandler } from './useDropHandler'; import { SearchMarkers } from './useSearchMarkers'; +import { ParseOptions } from '@joplin/lib/HtmlToMd'; export interface AllAssetsOptions { contentMaxWidthTarget?: string; @@ -85,7 +86,7 @@ export interface MarkupToHtmlOptions { } export type MarkupToHtmlHandler = (markupLanguage: MarkupLanguage, markup: string, options: MarkupToHtmlOptions)=> Promise; -export type HtmlToMarkdownHandler = (markupLanguage: number, html: string, originalCss: string)=> Promise; +export type HtmlToMarkdownHandler = (markupLanguage: number, html: string, originalCss: string, parseOptions?: ParseOptions)=> Promise; export interface NoteBodyEditorProps { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied diff --git a/packages/lib/models/settings/builtInMetadata.ts b/packages/lib/models/settings/builtInMetadata.ts index d39652cb44d..2ba224b2e1d 100644 --- a/packages/lib/models/settings/builtInMetadata.ts +++ b/packages/lib/models/settings/builtInMetadata.ts @@ -658,6 +658,16 @@ const builtInMetadata = (Setting: typeof SettingType) => { storage: SettingStorage.File, isGlobal: true, }, + 'editor.pastePreserveColors': { + value: false, + type: SettingItemType.Bool, + public: true, + section: 'note', + appTypes: [AppType.Desktop], + label: () => _('Preserve colours when pasting text in Rich Text Editor'), + storage: SettingStorage.File, + isGlobal: true, + }, 'notes.columns': { value: defaultListColumns(), public: false,