From 4b8e7ae769d5ddbb249fc42a1741c790ff02d267 Mon Sep 17 00:00:00 2001 From: Daniel Stefanovic Date: Tue, 25 Jan 2022 13:53:44 +0100 Subject: [PATCH 1/3] Add options.afterTransform --- lib/index.js | 37 ++++++++++++++++++++++++------------- readme.md | 4 ++++ test/index.js | 19 +++++++++++++++++++ 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/lib/index.js b/lib/index.js index 625ee6e..ec6c18c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -12,12 +12,14 @@ * @property {boolean} [fragment=false] Whether a DOM fragment should be returned * @property {Document} [document] Document interface to use (default: `globalThis.document`) * @property {string} [namespace] `namespace` to use to create elements + * @property {(node: HastNode, transformed: Node) => void} [afterTransform] Callback invoked after each node transformation * * @typedef Context * @property {Document} doc * @property {boolean} [fragment=false] * @property {string} [namespace] * @property {string} [impliedNamespace] + * @property {Options['afterTransform']} [afterTransform] */ import {webNamespaces} from 'web-namespaces' @@ -30,19 +32,28 @@ import {find, html, svg} from 'property-information' * @param {Context} ctx */ function transform(node, ctx) { - switch (node.type) { - case 'root': - return root(node, ctx) - case 'text': - return text(node, ctx) - case 'element': - return element(node, ctx) - case 'doctype': - return doctype(node, ctx) - case 'comment': - return comment(node, ctx) - default: - return element(node, ctx) + const transformed = transformer(node) + ctx.afterTransform?.(node, transformed) + return transformed + + /** + * @param {HastNode} node + */ + function transformer(node) { + switch (node.type) { + case 'root': + return root(node, ctx) + case 'text': + return text(node, ctx) + case 'element': + return element(node, ctx) + case 'doctype': + return doctype(node, ctx) + case 'comment': + return comment(node, ctx) + default: + return element(node, ctx) + } } } diff --git a/readme.md b/readme.md index ba487b4..61c655c 100644 --- a/readme.md +++ b/readme.md @@ -88,6 +88,10 @@ Document interface to use (default: `globalThis.document`). `namespace` to use to create [*elements*][element]. +###### `options.afterTransform(node, transformed)` + +Callback invoked after each node transformation (`Function`). + ## Security Use of `hast-util-to-dom` can open you up to a diff --git a/test/index.js b/test/index.js index cb00e96..23adafc 100644 --- a/test/index.js +++ b/test/index.js @@ -359,6 +359,25 @@ test('hast-util-to-dom', (t) => { 'encodes data properties when string' ) + t.deepEqual( + (() => { + /** @type {Array<[HastNode, string]>} */ + const calls = [] + toDom(h('html', [h('title', 'Hi')]), { + afterTransform: (node, transformed) => { + calls.push([node, serializeNodeToHtmlString(transformed)]) + } + }) + return calls + })(), + [ + [{type: 'text', value: 'Hi'}, 'Hi'], + [h('title', 'Hi'), 'Hi'], + [h('html', [h('title', 'Hi')]), 'Hi'] + ], + 'should invoke afterTransform' + ) + t.end() }) From 1a729b64ecc65cdb975194288bb66483cf168fa2 Mon Sep 17 00:00:00 2001 From: Daniel Stefanovic Date: Tue, 25 Jan 2022 14:04:36 +0100 Subject: [PATCH 2/3] Replace optional chaining (not supported on lts/erbium) --- lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index ec6c18c..9ecf92e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -33,7 +33,7 @@ import {find, html, svg} from 'property-information' */ function transform(node, ctx) { const transformed = transformer(node) - ctx.afterTransform?.(node, transformed) + if (ctx.afterTransform) ctx.afterTransform(node, transformed) return transformed /** From 6a25c14e2789978f5cf14c26ccfbba33cfc64802 Mon Sep 17 00:00:00 2001 From: Daniel Stefanovic Date: Tue, 25 Jan 2022 16:43:52 +0100 Subject: [PATCH 3/3] Improve code style and documentation --- lib/index.js | 61 +++++++++++++++++++++++++++++++--------------------- readme.md | 6 ++++-- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/lib/index.js b/lib/index.js index 9ecf92e..0761e0f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -8,18 +8,30 @@ * @typedef {HastParent['children'][number]} HastChild * @typedef {HastChild|HastRoot} HastNode * + * @callback AfterTransform + * Function called when a hast node is transformed into a DOM node + * @param {HastNode} hastNode + * The hast node that was handled + * @param {Node} domNode + * The corresponding DOM node + * @returns {void} + * * @typedef Options - * @property {boolean} [fragment=false] Whether a DOM fragment should be returned - * @property {Document} [document] Document interface to use (default: `globalThis.document`) - * @property {string} [namespace] `namespace` to use to create elements - * @property {(node: HastNode, transformed: Node) => void} [afterTransform] Callback invoked after each node transformation + * @property {boolean} [fragment=false] + * Whether a DOM fragment should be returned + * @property {Document} [document] + * Document interface to use (default: `globalThis.document`) + * @property {string} [namespace] + * `namespace` to use to create elements + * @property {AfterTransform} [afterTransform] + * Callback invoked after each node transformation * * @typedef Context * @property {Document} doc * @property {boolean} [fragment=false] * @property {string} [namespace] * @property {string} [impliedNamespace] - * @property {Options['afterTransform']} [afterTransform] + * @property {AfterTransform} [afterTransform] */ import {webNamespaces} from 'web-namespaces' @@ -32,28 +44,29 @@ import {find, html, svg} from 'property-information' * @param {Context} ctx */ function transform(node, ctx) { - const transformed = transformer(node) + const transformed = one(node, ctx) if (ctx.afterTransform) ctx.afterTransform(node, transformed) return transformed +} - /** - * @param {HastNode} node - */ - function transformer(node) { - switch (node.type) { - case 'root': - return root(node, ctx) - case 'text': - return text(node, ctx) - case 'element': - return element(node, ctx) - case 'doctype': - return doctype(node, ctx) - case 'comment': - return comment(node, ctx) - default: - return element(node, ctx) - } +/** + * @param {HastNode} node + * @param {Context} ctx + */ +function one(node, ctx) { + switch (node.type) { + case 'root': + return root(node, ctx) + case 'text': + return text(node, ctx) + case 'element': + return element(node, ctx) + case 'doctype': + return doctype(node, ctx) + case 'comment': + return comment(node, ctx) + default: + return element(node, ctx) } } diff --git a/readme.md b/readme.md index 61c655c..eb05134 100644 --- a/readme.md +++ b/readme.md @@ -88,9 +88,11 @@ Document interface to use (default: `globalThis.document`). `namespace` to use to create [*elements*][element]. -###### `options.afterTransform(node, transformed)` +###### `options.afterTransform` -Callback invoked after each node transformation (`Function`). +Function called when a hast node is transformed into a DOM node (`Function?`). +Given the hast node that was handled as the first parameter and the +corresponding DOM node as the second parameter. ## Security