diff --git a/src/builtin-filters.js b/src/builtin-filters.js index 0217454..3f62be1 100644 --- a/src/builtin-filters.js +++ b/src/builtin-filters.js @@ -89,7 +89,7 @@ export function last(amount = 1) { * @returns escaped html */ export function htmlentities(str) { - return str.replace(/\&/, '&').replace(//gm, '>'); + return str?.replace(/\&/gm, '&').replace(//gm, '>'); } /** diff --git a/tests/builtin-filters.test.js b/tests/builtin-filters.test.js index 7e574d5..16c3af0 100644 --- a/tests/builtin-filters.test.js +++ b/tests/builtin-filters.test.js @@ -3,67 +3,82 @@ import assert from 'node:assert/strict'; import path from 'node:path' import { handleTemplateFile } from '../src/transforms/template-data.js'; import { SissiConfig } from '../src/sissi-config.js'; +import { htmlentities } from '../src/builtin-filters.js'; describe('builtin filters', () => { const dummyResolver = (map) => (...paths) => map.get(path.normalize(path.join(...paths))); - it('should format numbers', async () => { - const config = new SissiConfig(); + describe('htmlentities', () => { + it('should not crash when nullish value is passed', () => { + assert.equal(htmlentities(undefined), undefined); + }); - const vFS = new Map(); - vFS.set('index.html', '{{ thousandPi | numberFormat: numberFormatOptions, "de-DE" }}'); - - config.resolve = dummyResolver(vFS); - - const data = { thousandPi: Math.PI * 1e3, numberFormatOptions: {maximumFractionDigits: 2, minimumFractionDigits: 2} }; - - const result = await handleTemplateFile(config, data, 'index.html'); - - assert.equal(result.content, '3.141,59'); - }); - - it('should format currencies', async () => { - const config = new SissiConfig(); - - const vFS = new Map(); - vFS.set('index.html', '{{ million | currency: "eur", "de-DE" }}'); - - config.resolve = dummyResolver(vFS); - - const data = { million: 1e6 }; - - const result = await handleTemplateFile(config, data, 'index.html'); - - assert.equal(result.content, '1.000.000,00 €'); + it('should escape HTML', () => { + const expected = '<h1>Hello World</h1>\n<p>Cow & Son</p>' + const result = htmlentities('

Hello World

\n

Cow & Son

'); + assert.equal(result, expected); + }); }); - it('should format dates', async () => { - const config = new SissiConfig(); - - const vFS = new Map(); - vFS.set('index.html', '{{ newYear | date: dateFormatOptions, "de-DE" }}'); - - config.resolve = dummyResolver(vFS); - - const data = { newYear: new Date('2025-04-01'), dateFormatOptions: {"day": "2-digit", "month": "2-digit", "year": "numeric"} }; - - const result = await handleTemplateFile(config, data, 'index.html'); - - assert.equal(result.content, '01.04.2025'); - }); - - it('should serialize json', async () => { - const config = new SissiConfig(); - - const vFS = new Map(); - vFS.set('index.html', '{{ answer | json }}'); - - config.resolve = dummyResolver(vFS); - - const data = { answer: {result: 42} }; - - const result = await handleTemplateFile(config, data, 'index.html'); - - assert.equal(result.content, '{"result":42}'); + describe('integration with template engine', () => { + it('should format numbers via numberFormat filter', async () => { + const config = new SissiConfig(); + + const vFS = new Map(); + vFS.set('index.html', '{{ thousandPi | numberFormat: numberFormatOptions, "de-DE" }}'); + + config.resolve = dummyResolver(vFS); + + const data = { thousandPi: Math.PI * 1e3, numberFormatOptions: {maximumFractionDigits: 2, minimumFractionDigits: 2} }; + + const result = await handleTemplateFile(config, data, 'index.html'); + + assert.equal(result.content, '3.141,59'); + }); + + it('should format currencies via currency filter', async () => { + const config = new SissiConfig(); + + const vFS = new Map(); + vFS.set('index.html', '{{ million | currency: "eur", "de-DE" }}'); + + config.resolve = dummyResolver(vFS); + + const data = { million: 1e6 }; + + const result = await handleTemplateFile(config, data, 'index.html'); + + assert.equal(result.content, '1.000.000,00 €'); + }); + + it('should format dates via date filter', async () => { + const config = new SissiConfig(); + + const vFS = new Map(); + vFS.set('index.html', '{{ newYear | date: dateFormatOptions, "de-DE" }}'); + + config.resolve = dummyResolver(vFS); + + const data = { newYear: new Date('2025-04-01'), dateFormatOptions: {"day": "2-digit", "month": "2-digit", "year": "numeric"} }; + + const result = await handleTemplateFile(config, data, 'index.html'); + + assert.equal(result.content, '01.04.2025'); + }); + + it('should serialize json', async () => { + const config = new SissiConfig(); + + const vFS = new Map(); + vFS.set('index.html', '{{ answer | json }}'); + + config.resolve = dummyResolver(vFS); + + const data = { answer: {result: 42} }; + + const result = await handleTemplateFile(config, data, 'index.html'); + + assert.equal(result.content, '{"result":42}'); + }); }); });