From ad9e5837d562077b66120756aa9c083ff3dfe668 Mon Sep 17 00:00:00 2001 From: Kai Johnson <565754+kaidjohnson@users.noreply.github.com> Date: Wed, 5 Jan 2022 14:51:43 -0500 Subject: [PATCH] fix(icons-to-woff.js): enforce deterministic output Ensure builds with the same set of inputs results in an identical font hash for deterministic builds. re #53 --- lib/icons-to-woff.js | 7 +--- test/fixtures/malformed.svg | 1 + test/icons-to-woff.js | 77 +++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 test/fixtures/malformed.svg create mode 100644 test/icons-to-woff.js diff --git a/lib/icons-to-woff.js b/lib/icons-to-woff.js index 9052863..c91d380 100644 --- a/lib/icons-to-woff.js +++ b/lib/icons-to-woff.js @@ -21,10 +21,7 @@ module.exports = function createIconFont (fs, icons, options) { name: options.name, normalize: true, fontHeight: options.enforcedSvgHeight ? options.enforcedSvgHeight : undefined, - log: function () {}, - error: /** @param {any} err */function (err) { - reject(err); - } + log: function () {} }); let svgFont = ''; fontStream @@ -58,7 +55,7 @@ module.exports = function createIconFont (fs, icons, options) { }); fontStream.end(); }) - .then((svgFont) => svg2ttf(svgFont, {}).buffer) + .then((svgFont) => svg2ttf(svgFont, { ts: 0 }).buffer) .then((ttfFont) => ttf2woff(ttfFont).buffer) .then((woffFont) => Buffer.from(woffFont).toString('base64')); }; diff --git a/test/fixtures/malformed.svg b/test/fixtures/malformed.svg new file mode 100644 index 0000000..4f38b19 --- /dev/null +++ b/test/fixtures/malformed.svg @@ -0,0 +1 @@ +I am not an SVG. diff --git a/test/icons-to-woff.js b/test/icons-to-woff.js new file mode 100644 index 0000000..115ddd0 --- /dev/null +++ b/test/icons-to-woff.js @@ -0,0 +1,77 @@ +'use strict'; +/* eslint max-len: off, quotes:off, arrow-parens:off */ +import createIconFont from '../lib/icons-to-woff.js'; +import fs from 'fs'; +import test from 'ava'; + +test('should throw an error when an svg cannot be found', async (t) => { + let error; + try { + await createIconFont(fs, [ + './test/fixtures/does-not-exist.svg' + ], { + name: 'test' + }); + } catch (e) { + error = e.message; + } + + t.is(error.substring(0, 33), 'ENOENT: no such file or directory'); + t.pass(); +}); + +test('should throw an error when a malformed svg is provided', async (t) => { + let error; + try { + await createIconFont(fs, [ + './test/fixtures/malformed.svg' + ], { + name: 'test' + }); + } catch (e) { + error = e.message; + } + + t.is(error.substring(0, 32), 'Non-whitespace before first tag.'); + t.pass(); +}); + +test('should produce the same output when receiving the same input and configuration', async (t) => { + const svgs = [ + './test/fixtures/account-494x512.svg', + './test/fixtures/account-986x1024.svg' + ]; + + const test1 = await createIconFont(fs, svgs, { + name: 'test' + }); + + await new Promise((resolve) => setTimeout(resolve, 1000)); + + const test2 = await createIconFont(fs, svgs, { + name: 'test' + }); + + t.is(test1, test2); + t.pass(); +}); + +test('should produce different output when receiving the same input but different fontHeight', async (t) => { + const svgs = [ + './test/fixtures/account-494x512.svg', + './test/fixtures/account-986x1024.svg' + ]; + + const test1 = await createIconFont(fs, svgs, { + enforcedSvgHeight: 32 + }); + + await new Promise((resolve) => setTimeout(resolve, 1000)); + + const test2 = await createIconFont(fs, svgs, { + enforcedSvgHeight: 16 + }); + + t.not(test1, test2); + t.pass(); +});