mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-08-23 23:10:17 +05:30
feat(monospace): add PdfFontHeader builder for xelatex fontspec
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
// fontspec accepts forward-slash paths on all platforms (TeX normalizes).
|
||||
// Normalize Windows backslashes so we can reliably build Path/filename.
|
||||
function toPosix(p) {
|
||||
return String(p).replace(/\\/g, '/');
|
||||
}
|
||||
|
||||
function escape(s) {
|
||||
// fontspec values: braces are the only TeX-significant chars we might emit
|
||||
// from a basename. Backslashes are converted to '/' upstream by toPosix().
|
||||
return String(s).replace(/[{}]/g, '\\$&');
|
||||
}
|
||||
|
||||
function dirOf(p) {
|
||||
return toPosix(p).replace(/\/[^/]+$/, '') + '/';
|
||||
}
|
||||
|
||||
function baseName(p) {
|
||||
return toPosix(p).split('/').pop();
|
||||
}
|
||||
|
||||
// Strip a weight-style suffix from a TTF filename to get the family prefix
|
||||
// (e.g. JetBrainsMono-Regular.ttf -> JetBrainsMono). Used as the `\setmonofont`
|
||||
// argument so `*-Regular` / `*-Bold` globs resolve to the right files.
|
||||
function weightPrefix(p) {
|
||||
return baseName(p).replace(/-(Regular|Bold|Light|Medium|SemiBold|Italic)\.ttf$/i, '');
|
||||
}
|
||||
|
||||
function build({ fontTtfPath, boldTtfPath, ligatures }) {
|
||||
if (!fontTtfPath) {
|
||||
return '% Monospace font path unavailable; TeX will use its default monospace.\n';
|
||||
}
|
||||
|
||||
const ligValue = ligatures ? 'Ligatures=TeX' : 'Ligatures=NoCommon';
|
||||
const prefix = escape(weightPrefix(fontTtfPath));
|
||||
|
||||
return `\\usepackage{fontspec}
|
||||
\\setmonofont[Path=${escape(dirOf(fontTtfPath))},Extension=.ttf,UprightFont=*-Regular,BoldFont=*-Bold,${ligValue}]{${prefix}}
|
||||
`;
|
||||
}
|
||||
|
||||
module.exports = { build };
|
||||
@@ -0,0 +1,55 @@
|
||||
const PdfFontHeader = require('../src/main/PdfFontHeader');
|
||||
|
||||
describe('PdfFontHeader.build', () => {
|
||||
test('emits fontspec with Path, family prefix, weight globs, and Ligatures=NoCommon when off', () => {
|
||||
const tex = PdfFontHeader.build({
|
||||
fontTtfPath: '/abs/path/JetBrainsMono-Regular.ttf',
|
||||
boldTtfPath: '/abs/path/JetBrainsMono-Bold.ttf',
|
||||
ligatures: false,
|
||||
});
|
||||
expect(tex).toContain('\\usepackage{fontspec}');
|
||||
// \setmonofont uses the family prefix (weight suffix stripped)
|
||||
expect(tex).toMatch(/\\setmonofont\[[^\]]*\]\{JetBrainsMono\}/);
|
||||
// Path is the directory (no trailing filename)
|
||||
expect(tex).toContain('Path=/abs/path/');
|
||||
// No programming ligatures
|
||||
expect(tex).toContain('Ligatures=NoCommon');
|
||||
// Upright/Bold use the family-prefixed glob
|
||||
expect(tex).toContain('UprightFont=*-Regular');
|
||||
expect(tex).toContain('BoldFont=*-Bold');
|
||||
});
|
||||
|
||||
test('emits Ligatures=TeX when on (preserves --/--- but no programming ligatures)', () => {
|
||||
const tex = PdfFontHeader.build({
|
||||
fontTtfPath: '/abs/JBM-Regular.ttf',
|
||||
boldTtfPath: '/abs/JBM-Bold.ttf',
|
||||
ligatures: true,
|
||||
});
|
||||
expect(tex).toContain('Ligatures=TeX');
|
||||
expect(tex).not.toContain('Ligatures=NoCommon');
|
||||
});
|
||||
|
||||
test('returns a no-op stub when font path is missing', () => {
|
||||
const tex = PdfFontHeader.build({ fontTtfPath: null, boldTtfPath: null, ligatures: false });
|
||||
expect(tex).toContain('% Monospace font path unavailable');
|
||||
});
|
||||
|
||||
test('normalizes Windows backslashes to forward slashes', () => {
|
||||
const tex = PdfFontHeader.build({
|
||||
fontTtfPath: 'C:\\Users\\foo\\JetBrainsMono-Regular.ttf',
|
||||
boldTtfPath: 'C:\\Users\\foo\\JetBrainsMono-Bold.ttf',
|
||||
ligatures: false,
|
||||
});
|
||||
expect(tex).toContain('Path=C:/Users/foo/');
|
||||
expect(tex).toMatch(/\{JetBrainsMono\}/);
|
||||
});
|
||||
|
||||
test('strips the FiraCode weight suffix to derive the family prefix', () => {
|
||||
const tex = PdfFontHeader.build({
|
||||
fontTtfPath: '/abs/FiraCode-Regular.ttf',
|
||||
boldTtfPath: '/abs/FiraCode-Bold.ttf',
|
||||
ligatures: false,
|
||||
});
|
||||
expect(tex).toMatch(/\{FiraCode\}/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user