|
1 | 1 | /**
|
2 |
| - * @typedef {import('mdast').Root} Root |
3 | 2 | * @typedef {import('hast-util-sanitize').Schema} Schema
|
4 |
| - * |
| 3 | + * @typedef {import('hast-util-to-html').Options} ToHtmlOptions |
| 4 | + * @typedef {import('mdast').Root} Root |
| 5 | + * @typedef {import('mdast-util-to-hast').Handlers} Handlers |
| 6 | + * @typedef {import('unified').Compiler<Root, string>} Compiler |
| 7 | + * @typedef {import('unified').Processor<undefined, undefined, undefined, Root, string>} Processor |
| 8 | + */ |
| 9 | + |
| 10 | +/** |
5 | 11 | * @typedef ExtraOptionsFields
|
6 |
| - * Configuration (optional). |
7 |
| - * @property {boolean|Schema|null} [sanitize] |
8 |
| - * How to sanitize the output. |
9 |
| - * @property {import('mdast-util-to-hast').Handlers} [handlers={}] |
10 |
| - * Object mapping mdast nodes to functions handling them. |
| 12 | + * Extra fields. |
| 13 | + * @property {Readonly<Handlers> | null | undefined} [handlers] |
| 14 | + * How to turn mdast nodes into hast nodes (optional); |
| 15 | + * passed to `mdast-util-to-hast`. |
| 16 | + * @property {Readonly<Schema> | boolean | null | undefined} [sanitize] |
| 17 | + * Sanitize the output, and how (default: `true`). |
11 | 18 | *
|
12 |
| - * @typedef {import('hast-util-to-html').Options & ExtraOptionsFields} Options |
| 19 | + * @typedef {ToHtmlOptions & ExtraOptionsFields} Options |
| 20 | + * Configuration. |
13 | 21 | */
|
14 | 22 |
|
15 |
| -import {toHtml} from 'hast-util-to-html' |
16 | 23 | import {sanitize} from 'hast-util-sanitize'
|
17 | 24 | import {toHast} from 'mdast-util-to-hast'
|
| 25 | +import {toHtml} from 'hast-util-to-html' |
| 26 | + |
| 27 | +/** @type {Readonly<Options>} */ |
| 28 | +const emptyOptions = {} |
18 | 29 |
|
19 | 30 | /**
|
20 |
| - * Plugin to serialize markdown as HTML. |
| 31 | + * Serialize markdown as HTML. |
21 | 32 | *
|
22 |
| - * @this {import('unified').Processor} |
23 |
| - * @type {import('unified').Plugin<[Options?] | [], Root, string>} |
| 33 | + * @param {Readonly<Options> | null | undefined} [options] |
| 34 | + * Configuration (optional). |
| 35 | + * @returns {undefined} |
| 36 | + * Nothing. |
24 | 37 | */
|
25 |
| -export default function remarkHtml(settings = {}) { |
26 |
| - const options = {...settings} |
27 |
| - /** @type {boolean|undefined} */ |
28 |
| - let clean |
29 |
| - |
30 |
| - if (typeof options.sanitize === 'boolean') { |
31 |
| - clean = options.sanitize |
32 |
| - // @ts-expect-error: to do: fix. |
33 |
| - options.sanitize = undefined |
34 |
| - } |
| 38 | +export default function remarkHtml(options) { |
| 39 | + /** @type {Processor} */ |
| 40 | + // @ts-expect-error: TS in JSDoc generates wrong types if `this` is typed regularly. |
| 41 | + // eslint-disable-next-line unicorn/no-this-assignment |
| 42 | + const self = this |
| 43 | + const {handlers, sanitize: clean, ...toHtmlOptions} = options || emptyOptions |
| 44 | + let allowDangerousHtml = false |
| 45 | + /** @type {Readonly<Schema> | undefined} */ |
| 46 | + let schema |
35 | 47 |
|
36 |
| - if (typeof clean !== 'boolean') { |
37 |
| - clean = true |
| 48 | + if (typeof clean === 'boolean') { |
| 49 | + allowDangerousHtml = !clean |
| 50 | + } else if (clean) { |
| 51 | + schema = clean |
38 | 52 | }
|
39 | 53 |
|
40 |
| - Object.assign(this, {compiler}) |
| 54 | + self.compiler = compiler |
41 | 55 |
|
42 | 56 | /**
|
43 |
| - * @type {import('unified').Compiler<Root, string>} |
| 57 | + * @type {Compiler} |
44 | 58 | */
|
45 |
| - function compiler(node, file) { |
46 |
| - const hast = toHast(node, { |
47 |
| - allowDangerousHtml: !clean, |
48 |
| - handlers: options.handlers |
49 |
| - }) |
50 |
| - // @ts-expect-error: to do: no longer boolean. |
51 |
| - const cleanHast = clean ? sanitize(hast, options.sanitize) : hast |
52 |
| - const result = toHtml( |
53 |
| - cleanHast, |
54 |
| - Object.assign({}, options, {allowDangerousHtml: !clean}) |
55 |
| - ) |
| 59 | + function compiler(tree, file) { |
| 60 | + const hast = toHast(tree, {handlers, allowDangerousHtml}) |
| 61 | + const safeHast = allowDangerousHtml ? hast : sanitize(hast, schema) |
| 62 | + const result = toHtml(safeHast, {...toHtmlOptions, allowDangerousHtml}) |
56 | 63 |
|
57 | 64 | if (file.extname) {
|
58 | 65 | file.extname = '.html'
|
59 | 66 | }
|
60 | 67 |
|
61 | 68 | // Add an eof eol.
|
62 |
| - return node && |
63 |
| - node.type && |
64 |
| - node.type === 'root' && |
| 69 | + return tree && |
| 70 | + tree.type === 'root' && |
65 | 71 | result &&
|
66 | 72 | /[^\r\n]/.test(result.charAt(result.length - 1))
|
67 | 73 | ? result + '\n'
|
|
0 commit comments