From 6af3709e03692d4623aa6cd031fbf13ec2f6b2ce Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Wed, 3 Apr 2024 21:18:03 +0800 Subject: [PATCH 1/3] Refactor to improve performance w/ hoisted regex Closes GH-39. Reviewed-by: Titus Wormer --- lib/handle/comment.js | 14 +++++++++++--- lib/handle/text.js | 5 ++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/handle/comment.js b/lib/handle/comment.js index 6e16d1f..95ff4aa 100644 --- a/lib/handle/comment.js +++ b/lib/handle/comment.js @@ -7,6 +7,12 @@ import {stringifyEntities} from 'stringify-entities' +const htmlCommentRegex = /^>|^->||--!>|'] +const commentEntitySubset = ['<', '>'] + /** * Serialize a comment. * @@ -27,10 +33,12 @@ export function comment(node, _1, _2, state) { ? '']}) + Object.assign({}, state.settings.characterReferences, { + subset: bogusCommentEntitySubset + }) ) + '>' - : '|--!>|' + : '' /** * @param {string} $0 @@ -39,7 +47,7 @@ export function comment(node, _1, _2, state) { return stringifyEntities( $0, Object.assign({}, state.settings.characterReferences, { - subset: ['<', '>'] + subset: commentEntitySubset }) ) } diff --git a/lib/handle/text.js b/lib/handle/text.js index de25941..af08b28 100644 --- a/lib/handle/text.js +++ b/lib/handle/text.js @@ -9,6 +9,9 @@ import {stringifyEntities} from 'stringify-entities' +// Declare array as variable so it can be cached by `stringifyEntities` +const textEntitySubset = ['<', '&'] + /** * Serialize a text node. * @@ -32,7 +35,7 @@ export function text(node, _, parent, state) { : stringifyEntities( node.value, Object.assign({}, state.settings.characterReferences, { - subset: ['<', '&'] + subset: textEntitySubset }) ) } From 080eb732d2a2c5217b9827d74212b09bd1e781bf Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Wed, 3 Apr 2024 15:28:02 +0200 Subject: [PATCH 2/3] Update dev-dependencies --- lib/handle/element.js | 20 ++++++++++---------- package.json | 6 +++--- test/omission-opening-body.js | 2 +- test/text.js | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/handle/element.js b/lib/handle/element.js index 0d78677..217f105 100644 --- a/lib/handle/element.js +++ b/lib/handle/element.js @@ -76,7 +76,7 @@ export function element(node, index, parent, state) { state.schema = svg } - const attrs = serializeAttributes(state, node.properties) + const attributes = serializeAttributes(state, node.properties) const content = state.all( schema.space === 'html' && node.tagName === 'template' ? node.content : node @@ -92,14 +92,14 @@ export function element(node, index, parent, state) { // longer void. if (content) selfClosing = false - if (attrs || !omit || !opening(node, index, parent)) { - parts.push('<', node.tagName, attrs ? ' ' + attrs : '') + if (attributes || !omit || !opening(node, index, parent)) { + parts.push('<', node.tagName, attributes ? ' ' + attributes : '') if ( selfClosing && (schema.space === 'svg' || state.settings.closeSelfClosing) ) { - last = attrs.charAt(attrs.length - 1) + last = attributes.charAt(attributes.length - 1) if ( !state.settings.tightSelfClosing || last === '/' || @@ -125,20 +125,20 @@ export function element(node, index, parent, state) { /** * @param {State} state - * @param {Properties | null | undefined} props + * @param {Properties | null | undefined} properties * @returns {string} */ -function serializeAttributes(state, props) { +function serializeAttributes(state, properties) { /** @type {Array} */ const values = [] let index = -1 /** @type {string} */ let key - if (props) { - for (key in props) { - if (props[key] !== null && props[key] !== undefined) { - const value = serializeAttribute(state, key, props[key]) + if (properties) { + for (key in properties) { + if (properties[key] !== null && properties[key] !== undefined) { + const value = serializeAttribute(state, key, properties[key]) if (value) values.push(value) } } diff --git a/package.json b/package.json index 7596569..f5a3ba7 100644 --- a/package.json +++ b/package.json @@ -48,15 +48,15 @@ }, "devDependencies": { "@types/node": "^20.0.0", - "c8": "^8.0.0", - "hastscript": "^8.0.0", + "c8": "^9.0.0", + "hastscript": "^9.0.0", "prettier": "^3.0.0", "remark-cli": "^11.0.0", "remark-preset-wooorm": "^9.0.0", "type-coverage": "^2.0.0", "typescript": "^5.0.0", "unist-builder": "^4.0.0", - "xo": "^0.55.0" + "xo": "^0.58.0" }, "scripts": { "prepack": "npm run build && npm run format", diff --git a/test/omission-opening-body.js b/test/omission-opening-body.js index cd2e509..40a0e67 100644 --- a/test/omission-opening-body.js +++ b/test/omission-opening-body.js @@ -13,7 +13,7 @@ test('`body` (opening)', async function (t) { 'should not omit tag if the head is a `comment`', async function () { assert.deepEqual( - toHtml(h('body', u('comment', 'alpha')), {omitOptionalTags: true}), + toHtml(h('body', [u('comment', 'alpha')]), {omitOptionalTags: true}), '' ) } diff --git a/test/text.js b/test/text.js index 748d8f6..5f69275 100644 --- a/test/text.js +++ b/test/text.js @@ -15,19 +15,19 @@ test('`text`', async function (t) { await t.test('should not encode `text`s in `style`', async function () { assert.deepEqual( - toHtml(h('style', u('text', '*:before {content: "3 < 5"}'))), + toHtml(h('style', [u('text', '*:before {content: "3 < 5"}')])), '' ) }) await t.test('should not encode `text`s in `script`', async function () { assert.deepEqual( - toHtml(h('script', u('text', 'alert("3 < 5")'))), + toHtml(h('script', [u('text', 'alert("3 < 5")')])), '' ) }) await t.test('should encode `text`s in other nodes', async function () { - assert.deepEqual(toHtml(h('b', u('text', '3 < 5'))), '3 < 5') + assert.deepEqual(toHtml(h('b', [u('text', '3 < 5')])), '3 < 5') }) }) From 9e14697e18cba052491181550794929b84f6703f Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Wed, 3 Apr 2024 15:29:17 +0200 Subject: [PATCH 3/3] 9.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f5a3ba7..3638e73 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hast-util-to-html", - "version": "9.0.0", + "version": "9.0.1", "description": "hast utility to serialize to HTML", "license": "MIT", "keywords": [