Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@prairielearn/html

Package Overview
Dependencies
Maintainers
2
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@prairielearn/html - npm Package Compare versions

Comparing version
4.0.23
to
4.0.24
+6
-0
CHANGELOG.md
# @prairielearn/html
## 4.0.24
### Patch Changes
- 0900843: Switch to the `tsgo` compiler
## 4.0.23

@@ -4,0 +10,0 @@

+1
-1

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA+CA,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;gBAEvB,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;IAKzD,QAAQ,IAAI,MAAM;CAKnB;AAED,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,MAAM,GACN,cAAc,GACd,SAAS,GACT,IAAI,GACJ,SAAS,EAAE,CAAC;AAEhB,wBAAgB,IAAI,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,GAAG,cAAc,CAE1F;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc,CAE/D;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAE,SAAc,GAAG,cAAc,CAEvF"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA+CA,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IAEnC,YAAY,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAGxD;IAED,QAAQ,IAAI,MAAM,CAIjB;CACF;AAED,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,MAAM,GACN,cAAc,GACd,SAAS,GACT,IAAI,GACJ,SAAS,EAAE,CAAC;AAEhB,wBAAgB,IAAI,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,GAAG,cAAc,CAE1F;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc,CAE/D;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAE,SAAc,GAAG,cAAc,CAEvF","sourcesContent":["const ENCODE_HTML_RULES: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&#34;',\n \"'\": '&#39;',\n};\nconst MATCH_HTML = /[&<>'\"]/g;\n\nfunction encodeCharacter(c: string) {\n return ENCODE_HTML_RULES[c] || c;\n}\n\n/**\n * Based on the `escapeXML` function from the `ejs` library.\n */\nfunction escapeHtmlRaw(value: string): string {\n return value == null ? '' : String(value).replaceAll(MATCH_HTML, encodeCharacter);\n}\n\nfunction escapeValue(value: unknown): string {\n if (value instanceof HtmlSafeString) {\n // Already escaped!\n return value.toString();\n } else if (Array.isArray(value)) {\n return value.map((val) => escapeValue(val)).join('');\n } else if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'bigint' ||\n typeof value === 'boolean'\n ) {\n return escapeHtmlRaw(String(value));\n } else if (value == null) {\n // undefined or null -- render nothing\n return '';\n } else if (typeof value === 'object') {\n throw new Error(`Cannot interpolate object in template: ${JSON.stringify(value)}`);\n } else {\n // There shouldn't be any other types\n throw new Error(\n `Unexpected type in template: ${typeof value} for value ${JSON.stringify(value)}`,\n );\n }\n}\n\n// Based on https://github.com/Janpot/escape-html-template-tag\nexport class HtmlSafeString {\n private readonly strings: readonly string[];\n private readonly values: unknown[];\n\n constructor(strings: readonly string[], values: unknown[]) {\n this.strings = strings;\n this.values = values;\n }\n\n toString(): string {\n return this.values.reduce<string>((acc, val, i) => {\n return acc + escapeValue(val) + this.strings[i + 1];\n }, this.strings[0]);\n }\n}\n\nexport type HtmlValue =\n | string\n | number\n | boolean\n | bigint\n | HtmlSafeString\n | undefined\n | null\n | HtmlValue[];\n\nexport function html(strings: TemplateStringsArray, ...values: HtmlValue[]): HtmlSafeString {\n return new HtmlSafeString(strings, values);\n}\n\n/**\n * Pre-escapes the rendered HTML. Useful for when you want to inline the HTML\n * in something else, for instance in a `data-bs-content` attribute for a Bootstrap\n * popover.\n */\nexport function escapeHtml(html: HtmlSafeString): HtmlSafeString {\n return unsafeHtml(escapeHtmlRaw(html.toString()));\n}\n\n/**\n * Will render the provided value without any additional escaping. Use carefully\n * with user-provided data.\n *\n * @param value The value to render.\n * @returns An {@link HtmlSafeString} representing the provided value.\n */\nexport function unsafeHtml(value: string): HtmlSafeString {\n return new HtmlSafeString([value], []);\n}\n\n/**\n * Joins a list of HTML values with a separator.\n *\n * @param values The values to join.\n * @param separator The separator to use between values.\n */\nexport function joinHtml(values: HtmlValue[], separator: HtmlValue = ''): HtmlSafeString {\n return unsafeHtml(values.map(escapeValue).join(escapeValue(separator)));\n}\n"]}

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["const ENCODE_HTML_RULES: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&#34;',\n \"'\": '&#39;',\n};\nconst MATCH_HTML = /[&<>'\"]/g;\n\nfunction encodeCharacter(c: string) {\n return ENCODE_HTML_RULES[c] || c;\n}\n\n/**\n * Based on the `escapeXML` function from the `ejs` library.\n */\nfunction escapeHtmlRaw(value: string): string {\n return value == null ? '' : String(value).replaceAll(MATCH_HTML, encodeCharacter);\n}\n\nfunction escapeValue(value: unknown): string {\n if (value instanceof HtmlSafeString) {\n // Already escaped!\n return value.toString();\n } else if (Array.isArray(value)) {\n return value.map((val) => escapeValue(val)).join('');\n } else if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'bigint' ||\n typeof value === 'boolean'\n ) {\n return escapeHtmlRaw(String(value));\n } else if (value == null) {\n // undefined or null -- render nothing\n return '';\n } else if (typeof value === 'object') {\n throw new Error(`Cannot interpolate object in template: ${JSON.stringify(value)}`);\n } else {\n // There shouldn't be any other types\n throw new Error(\n `Unexpected type in template: ${typeof value} for value ${JSON.stringify(value)}`,\n );\n }\n}\n\n// Based on https://github.com/Janpot/escape-html-template-tag\nexport class HtmlSafeString {\n private readonly strings: readonly string[];\n private readonly values: unknown[];\n\n constructor(strings: readonly string[], values: unknown[]) {\n this.strings = strings;\n this.values = values;\n }\n\n toString(): string {\n return this.values.reduce<string>((acc, val, i) => {\n return acc + escapeValue(val) + this.strings[i + 1];\n }, this.strings[0]);\n }\n}\n\nexport type HtmlValue =\n | string\n | number\n | boolean\n | bigint\n | HtmlSafeString\n | undefined\n | null\n | HtmlValue[];\n\nexport function html(strings: TemplateStringsArray, ...values: HtmlValue[]): HtmlSafeString {\n return new HtmlSafeString(strings, values);\n}\n\n/**\n * Pre-escapes the rendered HTML. Useful for when you want to inline the HTML\n * in something else, for instance in a `data-bs-content` attribute for a Bootstrap\n * popover.\n */\nexport function escapeHtml(html: HtmlSafeString): HtmlSafeString {\n return unsafeHtml(escapeHtmlRaw(html.toString()));\n}\n\n/**\n * Will render the provided value without any additional escaping. Use carefully\n * with user-provided data.\n *\n * @param value The value to render.\n * @returns An {@link HtmlSafeString} representing the provided value.\n */\nexport function unsafeHtml(value: string): HtmlSafeString {\n return new HtmlSafeString([value], []);\n}\n\n/**\n * Joins a list of HTML values with a separator.\n *\n * @param values The values to join.\n * @param separator The separator to use between values.\n */\nexport function joinHtml(values: HtmlValue[], separator: HtmlValue = ''): HtmlSafeString {\n return unsafeHtml(values.map(escapeValue).join(escapeValue(separator)));\n}\n"]}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["const ENCODE_HTML_RULES: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&#34;',\n \"'\": '&#39;',\n};\nconst MATCH_HTML = /[&<>'\"]/g;\n\nfunction encodeCharacter(c: string) {\n return ENCODE_HTML_RULES[c] || c;\n}\n\n/**\n * Based on the `escapeXML` function from the `ejs` library.\n */\nfunction escapeHtmlRaw(value: string): string {\n return value == null ? '' : String(value).replaceAll(MATCH_HTML, encodeCharacter);\n}\n\nfunction escapeValue(value: unknown): string {\n if (value instanceof HtmlSafeString) {\n // Already escaped!\n return value.toString();\n } else if (Array.isArray(value)) {\n return value.map((val) => escapeValue(val)).join('');\n } else if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'bigint' ||\n typeof value === 'boolean'\n ) {\n return escapeHtmlRaw(String(value));\n } else if (value == null) {\n // undefined or null -- render nothing\n return '';\n } else if (typeof value === 'object') {\n throw new Error(`Cannot interpolate object in template: ${JSON.stringify(value)}`);\n } else {\n // There shouldn't be any other types\n throw new Error(\n `Unexpected type in template: ${typeof value} for value ${JSON.stringify(value)}`,\n );\n }\n}\n\n// Based on https://github.com/Janpot/escape-html-template-tag\nexport class HtmlSafeString {\n private readonly strings: readonly string[];\n private readonly values: unknown[];\n\n constructor(strings: readonly string[], values: unknown[]) {\n this.strings = strings;\n this.values = values;\n }\n\n toString(): string {\n return this.values.reduce<string>((acc, val, i) => {\n return acc + escapeValue(val) + this.strings[i + 1];\n }, this.strings[0]);\n }\n}\n\nexport type HtmlValue =\n | string\n | number\n | boolean\n | bigint\n | HtmlSafeString\n | undefined\n | null\n | HtmlValue[];\n\nexport function html(strings: TemplateStringsArray, ...values: HtmlValue[]): HtmlSafeString {\n return new HtmlSafeString(strings, values);\n}\n\n/**\n * Pre-escapes the rendered HTML. Useful for when you want to inline the HTML\n * in something else, for instance in a `data-bs-content` attribute for a Bootstrap\n * popover.\n */\nexport function escapeHtml(html: HtmlSafeString): HtmlSafeString {\n return unsafeHtml(escapeHtmlRaw(html.toString()));\n}\n\n/**\n * Will render the provided value without any additional escaping. Use carefully\n * with user-provided data.\n *\n * @param value The value to render.\n * @returns An {@link HtmlSafeString} representing the provided value.\n */\nexport function unsafeHtml(value: string): HtmlSafeString {\n return new HtmlSafeString([value], []);\n}\n\n/**\n * Joins a list of HTML values with a separator.\n *\n * @param values The values to join.\n * @param separator The separator to use between values.\n */\nexport function joinHtml(values: HtmlValue[], separator: HtmlValue = ''): HtmlSafeString {\n return unsafeHtml(values.map(escapeValue).join(escapeValue(separator)));\n}\n"]}

@@ -1,1 +0,1 @@

{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"","sourcesContent":["import { assert, describe, it } from 'vitest';\n\nimport { escapeHtml, html } from './index.js';\n\ndescribe('html', () => {\n it('escapes string value', () => {\n assert.equal(html`<p>${'<script>'}</p>`.toString(), '<p>&lt;script&gt;</p>');\n });\n\n it('interpolates multiple values', () => {\n assert.equal(html`<p>${'cats'} and ${'dogs'}</p>`.toString(), '<p>cats and dogs</p>');\n });\n\n it('interpolates a number', () => {\n assert.equal(html`<p>${123}</p>`.toString(), '<p>123</p>');\n });\n\n it('interpolates a bigint', () => {\n assert.equal(html`<p>${123n}</p>`.toString(), '<p>123</p>');\n });\n\n it('interpolates a boolean', () => {\n assert.equal(html`<p>${true}</p>`.toString(), '<p>true</p>');\n assert.equal(html`<p>${false}</p>`.toString(), '<p>false</p>');\n });\n\n it('escapes values when rendering array', () => {\n const arr = ['cats>', '<dogs'];\n assert.equal(\n // prettier-ignore\n html`<ul>${arr}</ul>`.toString(),\n '<ul>cats&gt;&lt;dogs</ul>',\n );\n });\n\n it('does not double-escape values when rendering array', () => {\n const arr = ['cats', 'dogs'];\n assert.equal(\n // prettier-ignore\n html`<ul>${arr.map((e) => html`<li>${e}</li>`)}</ul>`.toString(),\n '<ul><li>cats</li><li>dogs</li></ul>',\n );\n });\n\n it('errors when interpolating object', () => {\n assert.throws(\n // @ts-expect-error -- Testing runtime behavior of bad input.\n () => html`<p>${{ foo: 'bar' }}</p>`.toString(),\n 'Cannot interpolate object in template',\n );\n });\n\n it('omits nullish values from template', () => {\n assert.equal(html`<p>${null}${undefined}</p>`.toString(), '<p></p>');\n });\n});\n\ndescribe('escapeHtml', () => {\n it('escapes rendered HTML', () => {\n assert.equal(escapeHtml(html`<p>Hello</p>`).toString(), '&lt;p&gt;Hello&lt;/p&gt;');\n });\n\n it('works when nested inside html tag', () => {\n assert.equal(html`a${escapeHtml(html`<p></p>`)}b`.toString(), 'a&lt;p&gt;&lt;/p&gt;b');\n });\n});\n"]}

@@ -1,1 +0,1 @@

{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert, describe, it } from 'vitest';\n\nimport { escapeHtml, html } from './index.js';\n\ndescribe('html', () => {\n it('escapes string value', () => {\n assert.equal(html`<p>${'<script>'}</p>`.toString(), '<p>&lt;script&gt;</p>');\n });\n\n it('interpolates multiple values', () => {\n assert.equal(html`<p>${'cats'} and ${'dogs'}</p>`.toString(), '<p>cats and dogs</p>');\n });\n\n it('interpolates a number', () => {\n assert.equal(html`<p>${123}</p>`.toString(), '<p>123</p>');\n });\n\n it('interpolates a bigint', () => {\n assert.equal(html`<p>${123n}</p>`.toString(), '<p>123</p>');\n });\n\n it('interpolates a boolean', () => {\n assert.equal(html`<p>${true}</p>`.toString(), '<p>true</p>');\n assert.equal(html`<p>${false}</p>`.toString(), '<p>false</p>');\n });\n\n it('escapes values when rendering array', () => {\n const arr = ['cats>', '<dogs'];\n assert.equal(\n // prettier-ignore\n html`<ul>${arr}</ul>`.toString(),\n '<ul>cats&gt;&lt;dogs</ul>',\n );\n });\n\n it('does not double-escape values when rendering array', () => {\n const arr = ['cats', 'dogs'];\n assert.equal(\n // prettier-ignore\n html`<ul>${arr.map((e) => html`<li>${e}</li>`)}</ul>`.toString(),\n '<ul><li>cats</li><li>dogs</li></ul>',\n );\n });\n\n it('errors when interpolating object', () => {\n assert.throws(\n // @ts-expect-error -- Testing runtime behavior of bad input.\n () => html`<p>${{ foo: 'bar' }}</p>`.toString(),\n 'Cannot interpolate object in template',\n );\n });\n\n it('omits nullish values from template', () => {\n assert.equal(html`<p>${null}${undefined}</p>`.toString(), '<p></p>');\n });\n});\n\ndescribe('escapeHtml', () => {\n it('escapes rendered HTML', () => {\n assert.equal(escapeHtml(html`<p>Hello</p>`).toString(), '&lt;p&gt;Hello&lt;/p&gt;');\n });\n\n it('works when nested inside html tag', () => {\n assert.equal(html`a${escapeHtml(html`<p></p>`)}b`.toString(), 'a&lt;p&gt;&lt;/p&gt;b');\n });\n});\n"]}
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert, describe, it } from 'vitest';\n\nimport { escapeHtml, html } from './index.js';\n\ndescribe('html', () => {\n it('escapes string value', () => {\n assert.equal(html`<p>${'<script>'}</p>`.toString(), '<p>&lt;script&gt;</p>');\n });\n\n it('interpolates multiple values', () => {\n assert.equal(html`<p>${'cats'} and ${'dogs'}</p>`.toString(), '<p>cats and dogs</p>');\n });\n\n it('interpolates a number', () => {\n assert.equal(html`<p>${123}</p>`.toString(), '<p>123</p>');\n });\n\n it('interpolates a bigint', () => {\n assert.equal(html`<p>${123n}</p>`.toString(), '<p>123</p>');\n });\n\n it('interpolates a boolean', () => {\n assert.equal(html`<p>${true}</p>`.toString(), '<p>true</p>');\n assert.equal(html`<p>${false}</p>`.toString(), '<p>false</p>');\n });\n\n it('escapes values when rendering array', () => {\n const arr = ['cats>', '<dogs'];\n assert.equal(\n // prettier-ignore\n html`<ul>${arr}</ul>`.toString(),\n '<ul>cats&gt;&lt;dogs</ul>',\n );\n });\n\n it('does not double-escape values when rendering array', () => {\n const arr = ['cats', 'dogs'];\n assert.equal(\n // prettier-ignore\n html`<ul>${arr.map((e) => html`<li>${e}</li>`)}</ul>`.toString(),\n '<ul><li>cats</li><li>dogs</li></ul>',\n );\n });\n\n it('errors when interpolating object', () => {\n assert.throws(\n // @ts-expect-error -- Testing runtime behavior of bad input.\n () => html`<p>${{ foo: 'bar' }}</p>`.toString(),\n 'Cannot interpolate object in template',\n );\n });\n\n it('omits nullish values from template', () => {\n assert.equal(html`<p>${null}${undefined}</p>`.toString(), '<p></p>');\n });\n});\n\ndescribe('escapeHtml', () => {\n it('escapes rendered HTML', () => {\n assert.equal(escapeHtml(html`<p>Hello</p>`).toString(), '&lt;p&gt;Hello&lt;/p&gt;');\n });\n\n it('works when nested inside html tag', () => {\n assert.equal(html`a${escapeHtml(html`<p></p>`)}b`.toString(), 'a&lt;p&gt;&lt;/p&gt;b');\n });\n});\n"]}
{
"name": "@prairielearn/html",
"version": "4.0.23",
"version": "4.0.24",
"type": "module",

@@ -12,4 +12,4 @@ "repository": {

"scripts": {
"build": "tsc",
"dev": "tsc --watch --preserveWatchOutput",
"build": "tsgo",
"dev": "tsgo --watch --preserveWatchOutput",
"test": "vitest run --coverage"

@@ -19,9 +19,10 @@ },

"@prairielearn/tsconfig": "^0.0.0",
"@types/node": "^22.19.3",
"@vitest/coverage-v8": "^4.0.16",
"@types/node": "^22.19.5",
"@typescript/native-preview": "^7.0.0-dev.20260106.1",
"@vitest/coverage-v8": "^4.0.17",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"vitest": "^4.0.16"
"vitest": "^4.0.17"
},
"sideEffects": false
}