From 3ddde81e1c9013c8a9af78372ed2083a9515b3dd Mon Sep 17 00:00:00 2001 From: James Brumond Date: Thu, 11 May 2023 18:02:40 -0700 Subject: [PATCH] updates to markdown processing to allow custom elements --- package-lock.json | 24 ++++++++++++------------ src/html-sanitize.ts | 9 ++++----- src/render.ts | 5 +++-- src/renderer.ts | 2 ++ src/vega/data-colors.ts | 35 ++++++++++++++++++++++------------- 5 files changed, 43 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8a28782..b3dec1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -92,9 +92,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.16.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.5.tgz", - "integrity": "sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==", + "version": "18.16.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.6.tgz", + "integrity": "sha512-N7KINmeB8IN3vRR8dhgHEp+YpWvGFcpDoh5XZ8jB5a00AdFKCKEyyGTOPTddUf4JqU1ZKTVxkOxakDvchNVI2Q==", "dev": true }, "node_modules/@types/prismjs": { @@ -989,9 +989,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -2021,9 +2021,9 @@ "dev": true }, "@types/node": { - "version": "18.16.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.5.tgz", - "integrity": "sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==", + "version": "18.16.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.6.tgz", + "integrity": "sha512-N7KINmeB8IN3vRR8dhgHEp+YpWvGFcpDoh5XZ8jB5a00AdFKCKEyyGTOPTddUf4JqU1ZKTVxkOxakDvchNVI2Q==", "dev": true }, "@types/prismjs": { @@ -2674,9 +2674,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "requires": { "whatwg-url": "^5.0.0" }, diff --git a/src/html-sanitize.ts b/src/html-sanitize.ts index e9915a1..233bdb0 100644 --- a/src/html-sanitize.ts +++ b/src/html-sanitize.ts @@ -2,13 +2,12 @@ import { JSDOM } from 'jsdom'; import createDOMPurify = require('dompurify'); -export function sanitize_html(html: string) : string { +export type CustomElementHandling = createDOMPurify.Config['CUSTOM_ELEMENT_HANDLING']; + +export function sanitize_html(html: string, custom_elements?: CustomElementHandling) : string { const { window } = new JSDOM(''); const dom_purify = createDOMPurify(window as any as Window); return dom_purify.sanitize(html, { - CUSTOM_ELEMENT_HANDLING: { - tagNameCheck: (tag_name) => tag_name === 'svg-icon', - attributeNameCheck: (attr_name) => attr_name === 'icon', - } + CUSTOM_ELEMENT_HANDLING: custom_elements }); } diff --git a/src/render.ts b/src/render.ts index 6d63d6d..3f5816e 100644 --- a/src/render.ts +++ b/src/render.ts @@ -4,7 +4,7 @@ import { create_renderer } from './renderer'; import { mark_ext } from './mark'; import { section_ext } from './section'; import { icon_ext } from './icon'; -import { sanitize_html } from './html-sanitize'; +import { CustomElementHandling, sanitize_html } from './html-sanitize'; import { katex_block_ext, katex_inline_ext } from './katex'; import { footnote_list_ext, footnote_ref_ext } from './footnotes'; import { description_list_ext } from './description-list'; @@ -16,6 +16,7 @@ export interface MarkdownOptions { inline?: boolean; katex_macros?: Record; extensions?: MarkdownExtension[]; + custom_elements?: CustomElementHandling; } export interface MarkdownExtension { @@ -64,5 +65,5 @@ export async function render_markdown_to_html(markdown: string, options: Markdow }); }); - return sanitize_html(unsafe_html); + return sanitize_html(unsafe_html, options.custom_elements); } diff --git a/src/renderer.ts b/src/renderer.ts index e26e614..c9424ea 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -90,6 +90,8 @@ function code(renderer: marked.Renderer, opts: MarkdownOptions) { case 'bash:samp': { // Find the first newline that is not preceeded by a "\" const end_of_input = /(? {