From 228ee04b090fc46c0f73f2dc4a01058771ca6081 Mon Sep 17 00:00:00 2001 From: Amit Haridas Date: Tue, 30 Jun 2026 23:25:31 +0530 Subject: [PATCH] feat(monospace): ExportCss embeds woff2 as base64 in CSS Self-contained CSS for HTML export and print-preview iframe. --- src/main/ExportCss.js | 34 ++++++++++++++++++++++++++++++++++ tests/export-css.test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/main/ExportCss.js create mode 100644 tests/export-css.test.js diff --git a/src/main/ExportCss.js b/src/main/ExportCss.js new file mode 100644 index 0000000..bab63ba --- /dev/null +++ b/src/main/ExportCss.js @@ -0,0 +1,34 @@ +'use strict'; + +const fs = require('fs'); + +function toDataUri(filePath) { + const buf = fs.readFileSync(filePath); + return `data:font/woff2;base64,${buf.toString('base64')}`; +} + +function build({ activeFontPath, family, weight = 400, ligatures = false }) { + const features = ligatures ? 'normal' : "'liga' 0, 'calt' 0, 'dlig' 0"; + const faceBlock = activeFontPath + ? `@font-face { + font-family: '${family}'; + font-weight: ${weight}; + font-style: normal; + font-display: swap; + src: url('${toDataUri(activeFontPath)}') format('woff2'); +} +` + : ''; + + return `${faceBlock}code, pre, kbd, samp { + font-family: '${family}', monospace; + font-feature-settings: ${features}; +} +pre, code { + white-space: pre; + tab-size: 4; +} +`; +} + +module.exports = { build }; diff --git a/tests/export-css.test.js b/tests/export-css.test.js new file mode 100644 index 0000000..2809512 --- /dev/null +++ b/tests/export-css.test.js @@ -0,0 +1,27 @@ +const fs = require('fs'); +const path = require('path'); +const ExportCss = require('../src/main/ExportCss'); + +describe('ExportCss.build', () => { + const fakeFontPath = path.join(__dirname, 'fixtures', 'fake.woff2'); + const fixture = Buffer.from('woff2-binary-fake-data'); + + beforeAll(() => { + fs.mkdirSync(path.dirname(fakeFontPath), { recursive: true }); + fs.writeFileSync(fakeFontPath, fixture); + }); + afterAll(() => fs.rmSync(path.dirname(fakeFontPath), { recursive: true, force: true })); + + test('emits a self-contained CSS with embedded @font-face', () => { + const css = ExportCss.build({ activeFontPath: fakeFontPath, family: 'JetBrains Mono', weight: 400, ligatures: false }); + expect(css).toMatch(/@font-face\s*\{[^}]*src:\s*url\('data:font\/woff2;base64,/); + expect(css).toContain("font-family: 'JetBrains Mono'"); + expect(css).toMatch(/font-feature-settings:[^;]*liga[^;]*0/); + }); + + test('falls back to family-only CSS when font path is missing', () => { + const css = ExportCss.build({ activeFontPath: null, family: 'Fira Code', weight: 700, ligatures: true }); + expect(css).not.toContain('data:font/woff2;'); + expect(css).toContain("font-family: 'Fira Code'"); + }); +});