updates to markdown processing to allow custom elements
This commit is contained in:
		
							
								
								
									
										24
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										24
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -92,9 +92,9 @@
 | 
				
			|||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/@types/node": {
 | 
					    "node_modules/@types/node": {
 | 
				
			||||||
      "version": "18.16.5",
 | 
					      "version": "18.16.6",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.5.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.6.tgz",
 | 
				
			||||||
      "integrity": "sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==",
 | 
					      "integrity": "sha512-N7KINmeB8IN3vRR8dhgHEp+YpWvGFcpDoh5XZ8jB5a00AdFKCKEyyGTOPTddUf4JqU1ZKTVxkOxakDvchNVI2Q==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/@types/prismjs": {
 | 
					    "node_modules/@types/prismjs": {
 | 
				
			||||||
@@ -989,9 +989,9 @@
 | 
				
			|||||||
      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
 | 
					      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/node-fetch": {
 | 
					    "node_modules/node-fetch": {
 | 
				
			||||||
      "version": "2.6.9",
 | 
					      "version": "2.6.11",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
 | 
				
			||||||
      "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==",
 | 
					      "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==",
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "whatwg-url": "^5.0.0"
 | 
					        "whatwg-url": "^5.0.0"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
@@ -2021,9 +2021,9 @@
 | 
				
			|||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "@types/node": {
 | 
					    "@types/node": {
 | 
				
			||||||
      "version": "18.16.5",
 | 
					      "version": "18.16.6",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.5.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.6.tgz",
 | 
				
			||||||
      "integrity": "sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==",
 | 
					      "integrity": "sha512-N7KINmeB8IN3vRR8dhgHEp+YpWvGFcpDoh5XZ8jB5a00AdFKCKEyyGTOPTddUf4JqU1ZKTVxkOxakDvchNVI2Q==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "@types/prismjs": {
 | 
					    "@types/prismjs": {
 | 
				
			||||||
@@ -2674,9 +2674,9 @@
 | 
				
			|||||||
      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
 | 
					      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node-fetch": {
 | 
					    "node-fetch": {
 | 
				
			||||||
      "version": "2.6.9",
 | 
					      "version": "2.6.11",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
 | 
				
			||||||
      "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==",
 | 
					      "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "whatwg-url": "^5.0.0"
 | 
					        "whatwg-url": "^5.0.0"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,13 +2,12 @@
 | 
				
			|||||||
import { JSDOM } from 'jsdom';
 | 
					import { JSDOM } from 'jsdom';
 | 
				
			||||||
import createDOMPurify = require('dompurify');
 | 
					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 { window } = new JSDOM('');
 | 
				
			||||||
	const dom_purify = createDOMPurify(window as any as Window);
 | 
						const dom_purify = createDOMPurify(window as any as Window);
 | 
				
			||||||
	return dom_purify.sanitize(html, {
 | 
						return dom_purify.sanitize(html, {
 | 
				
			||||||
		CUSTOM_ELEMENT_HANDLING: {
 | 
							CUSTOM_ELEMENT_HANDLING: custom_elements
 | 
				
			||||||
			tagNameCheck: (tag_name) => tag_name === 'svg-icon',
 | 
					 | 
				
			||||||
			attributeNameCheck: (attr_name) => attr_name === 'icon',
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ import { create_renderer } from './renderer';
 | 
				
			|||||||
import { mark_ext } from './mark';
 | 
					import { mark_ext } from './mark';
 | 
				
			||||||
import { section_ext } from './section';
 | 
					import { section_ext } from './section';
 | 
				
			||||||
import { icon_ext } from './icon';
 | 
					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 { katex_block_ext, katex_inline_ext } from './katex';
 | 
				
			||||||
import { footnote_list_ext, footnote_ref_ext } from './footnotes';
 | 
					import { footnote_list_ext, footnote_ref_ext } from './footnotes';
 | 
				
			||||||
import { description_list_ext } from './description-list';
 | 
					import { description_list_ext } from './description-list';
 | 
				
			||||||
@@ -16,6 +16,7 @@ export interface MarkdownOptions {
 | 
				
			|||||||
	inline?: boolean;
 | 
						inline?: boolean;
 | 
				
			||||||
	katex_macros?: Record<string, string>;
 | 
						katex_macros?: Record<string, string>;
 | 
				
			||||||
	extensions?: MarkdownExtension[];
 | 
						extensions?: MarkdownExtension[];
 | 
				
			||||||
 | 
						custom_elements?: CustomElementHandling;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface MarkdownExtension {
 | 
					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);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -91,6 +91,8 @@ function code(renderer: marked.Renderer, opts: MarkdownOptions) {
 | 
				
			|||||||
				// Find the first newline that is not preceeded by a "\"
 | 
									// Find the first newline that is not preceeded by a "\"
 | 
				
			||||||
				const end_of_input = /(?<!\\)(?:\r\n|\r|\n)/.exec(code);
 | 
									const end_of_input = /(?<!\\)(?:\r\n|\r|\n)/.exec(code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// todo: handling for multi-line heredocs?
 | 
				
			||||||
 | 
						
 | 
				
			||||||
				// If there is no such newline, the whole content is input
 | 
									// If there is no such newline, the whole content is input
 | 
				
			||||||
				if (! end_of_input) {
 | 
									if (! end_of_input) {
 | 
				
			||||||
					return figure(`<pre class="language-bash">${render_prism(code, 'bash')}</pre>`);
 | 
										return figure(`<pre class="language-bash">${render_prism(code, 'bash')}</pre>`);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,18 +1,27 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// note: fallback colors come from "category10" scheme
 | 
					 | 
				
			||||||
// https://vega.github.io/vega/docs/schemes/#category10
 | 
					 | 
				
			||||||
// todo: css variables
 | 
					 | 
				
			||||||
export const chart_data_colors = [
 | 
					export const chart_data_colors = [
 | 
				
			||||||
	'var(--theme-chart-data-0, #1f77b4)',
 | 
						'var(--theme-chart-shape-red-fill, #feaea5)',
 | 
				
			||||||
	'var(--theme-chart-data-1, #ff7f0e)',
 | 
						'var(--theme-chart-shape-orange-fill, #fad6bc)',
 | 
				
			||||||
	'var(--theme-chart-data-2, #2ca02c)',
 | 
						'var(--theme-chart-shape-yellow-fill, #fffec6)',
 | 
				
			||||||
	'var(--theme-chart-data-3, #d62728)',
 | 
						'var(--theme-chart-shape-green-fill, #d6f9d5)',
 | 
				
			||||||
	'var(--theme-chart-data-4, #9467bd)',
 | 
						'var(--theme-chart-shape-teal-fill, #b0ebe9)',
 | 
				
			||||||
	'var(--theme-chart-data-5, #8c564b)',
 | 
						'var(--theme-chart-shape-pink-fill, #ffcae2)',
 | 
				
			||||||
	'var(--theme-chart-data-6, #e377c2)',
 | 
						'var(--theme-chart-shape-purple-fill, #efdeff)',
 | 
				
			||||||
	'var(--theme-chart-data-7, #7f7f7f)',
 | 
						'var(--theme-chart-shape-blue-fill, #caebff)',
 | 
				
			||||||
	'var(--theme-chart-data-8, #bcbd22)',
 | 
						'var(--theme-chart-shape-indigo-fill, #c2d6f9)',
 | 
				
			||||||
	'var(--theme-chart-data-9, #17becf)',
 | 
						'var(--theme-chart-shape-magenta-fill, #ebb5cd)',
 | 
				
			||||||
 | 
						'var(--theme-chart-shape-brown-fill, #e1c3b8)',
 | 
				
			||||||
 | 
					  	'var(--theme-chart-shape-red-line, #ff806d)',
 | 
				
			||||||
 | 
					  	'var(--theme-chart-shape-orange-line, #ffb780)',
 | 
				
			||||||
 | 
					  	'var(--theme-chart-shape-yellow-line, #e1dc18)',
 | 
				
			||||||
 | 
					  	'var(--theme-chart-shape-green-line, #66cc66)',
 | 
				
			||||||
 | 
					  	'var(--theme-chart-shape-teal-line, #66cdcc)',
 | 
				
			||||||
 | 
					  	'var(--theme-chart-shape-pink-line, #ff99cb)',
 | 
				
			||||||
 | 
					  	'var(--theme-chart-shape-purple-line, #cc99fe)',
 | 
				
			||||||
 | 
					  	'var(--theme-chart-shape-blue-line, #66cbff)',
 | 
				
			||||||
 | 
					  	'var(--theme-chart-shape-indigo-line, #6295ee)',
 | 
				
			||||||
 | 
					  	'var(--theme-chart-shape-magenta-line, #cc6698)',
 | 
				
			||||||
 | 
					  	'var(--theme-chart-shape-brown-line, #bf8c71)',
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function* chart_data_color_generator() : Generator<string, never> {
 | 
					export function* chart_data_color_generator() : Generator<string, never> {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user