diff --git a/src/ascii-generator.html b/src/ascii-generator.html
index d8ca42a..942aa1b 100644
--- a/src/ascii-generator.html
+++ b/src/ascii-generator.html
@@ -142,7 +142,10 @@
line-height: 1.3;
color: #00ff00;
white-space: pre;
- font-feature-settings: 'liga' 0, 'calt' 0, 'dlig' 0;
+ font-feature-settings:
+ 'liga' 0,
+ 'calt' 0,
+ 'dlig' 0;
}
.template-grid {
diff --git a/src/main.js b/src/main.js
index 35868e3..563bfcf 100644
--- a/src/main.js
+++ b/src/main.js
@@ -575,7 +575,9 @@ function checkPandocAvailability() {
pandocAvailable = !error;
if (!error) {
const m = String(stdout).match(/pandoc\s+(\d+)\.(\d+)/);
- pandocVersionCache = m ? { major: Number(m[1]), minor: Number(m[2]) } : { major: 0, minor: 0 };
+ pandocVersionCache = m
+ ? { major: Number(m[1]), minor: Number(m[2]) }
+ : { major: 0, minor: 0 };
} else {
pandocVersionCache = { major: 0, minor: 0 };
}
@@ -2786,7 +2788,8 @@ function performExportWithOptions(format, options) {
if (bold) fonts.push({ path: bold, family, weight: 700 });
if (fonts.length) await DocxFontEmbedder.embed(outputFile, fonts);
} catch (embedErr) {
- if (typeof console !== 'undefined') console.warn('[docx] font embed failed:', embedErr.message);
+ if (typeof console !== 'undefined')
+ console.warn('[docx] font embed failed:', embedErr.message);
}
if (tempInputFile) {
try {
@@ -2903,17 +2906,24 @@ function performExportWithOptions(format, options) {
const familyKey = readSettingsJsonCached().monospaceFont || 'jetbrains-mono';
const regular = MonospaceFontConfig.getMonoFontTtfPath(familyKey, 400);
const fonts = [];
- if (regular) fonts.push({ path: regular, family: familyKey === 'fira-code' ? 'Fira Code' : 'JetBrains Mono', weight: 400 });
+ if (regular)
+ fonts.push({
+ path: regular,
+ family: familyKey === 'fira-code' ? 'Fira Code' : 'JetBrains Mono',
+ weight: 400,
+ });
if (fonts.length) {
const patched = await EpubFontEmbedder.patchManifest(outputFile, fonts);
try {
fs.renameSync(patched, outputFile);
} catch (renameErr) {
- if (typeof console !== 'undefined') console.warn('[epub] could not overwrite with patched EPUB:', renameErr.message);
+ if (typeof console !== 'undefined')
+ console.warn('[epub] could not overwrite with patched EPUB:', renameErr.message);
}
}
} catch (patchErr) {
- if (typeof console !== 'undefined') console.warn('[epub] manifest patch failed:', patchErr.message);
+ if (typeof console !== 'undefined')
+ console.warn('[epub] manifest patch failed:', patchErr.message);
}
showExportSuccess(outputFile);
});
@@ -3619,13 +3629,16 @@ ipcMain.on('export-with-options', (event, { format, options }) => {
});
// Handle batch conversion
-ipcMain.on('batch-convert', (event, { inputFolder, outputFolder, format, options, includeSubfolders }) => {
- if (!conversionLimiter()) {
- mainWindow.webContents.send('conversion-status', 'Please wait before converting again...');
- return;
+ipcMain.on(
+ 'batch-convert',
+ (event, { inputFolder, outputFolder, format, options, includeSubfolders }) => {
+ if (!conversionLimiter()) {
+ mainWindow.webContents.send('conversion-status', 'Please wait before converting again...');
+ return;
+ }
+ performBatchConversion(inputFolder, outputFolder, format, options, includeSubfolders);
}
- performBatchConversion(inputFolder, outputFolder, format, options, includeSubfolders);
-});
+);
// Handle folder selection for batch conversion
ipcMain.on('select-folder', (event, type) => {
@@ -3734,7 +3747,13 @@ function extractTablesFromMarkdown(markdown) {
}
return tables;
}
-async function performBatchConversion(inputFolder, outputFolder, format, options, includeSubfolders = true) {
+async function performBatchConversion(
+ inputFolder,
+ outputFolder,
+ format,
+ options,
+ includeSubfolders = true
+) {
if (!fs.existsSync(inputFolder)) {
dialog.showErrorBox('Error', 'Input folder does not exist');
return;
@@ -4093,7 +4112,11 @@ async function performBatchConversion(inputFolder, outputFolder, format, options
}
if (error) {
- console.error(`Batch: Failed to convert ${path.basename(inputFile)}:`, error.message, stderr);
+ console.error(
+ `Batch: Failed to convert ${path.basename(inputFile)}:`,
+ error.message,
+ stderr
+ );
} else {
// Add headers/footers to DOCX if enabled
if (format === 'docx' && headerFooterSettings.enabled) {
diff --git a/src/main/DocxFontEmbedder.js b/src/main/DocxFontEmbedder.js
index 9458c08..52fe820 100644
--- a/src/main/DocxFontEmbedder.js
+++ b/src/main/DocxFontEmbedder.js
@@ -38,8 +38,9 @@ async function patchZipWithFonts(inputPath, fonts) {
`\n` +
`\n` +
fonts
- .map((f, i) =>
- ` `
+ .map(
+ (f, i) =>
+ ` `
)
.join('\n') +
`\n\n`;
@@ -59,11 +60,17 @@ async function patchZipWithFonts(inputPath, fonts) {
const ttfCt = 'application/x-font-ttf';
const filePart = `/word/fonts/${path.basename(f.path)}`;
if (!ct.includes(`PartName="${filePart}"`)) {
- ct = ct.replace('', ``);
+ ct = ct.replace(
+ '',
+ ``
+ );
}
}
if (!ct.includes('Default Extension="ttf"')) {
- ct = ct.replace('', '');
+ ct = ct.replace(
+ '',
+ ''
+ );
}
zip.file(ctPath, ct);
@@ -116,4 +123,4 @@ async function embed(docxPath, fonts) {
return patchZipWithFonts(docxPath, fonts);
}
-module.exports = { embed };
\ No newline at end of file
+module.exports = { embed };
diff --git a/src/main/EpubFontEmbedder.js b/src/main/EpubFontEmbedder.js
index 8895420..bf1eb62 100644
--- a/src/main/EpubFontEmbedder.js
+++ b/src/main/EpubFontEmbedder.js
@@ -41,4 +41,4 @@ async function patchManifest(epubPath, fonts) {
return tmp;
}
-module.exports = { patchManifest };
\ No newline at end of file
+module.exports = { patchManifest };
diff --git a/src/main/MonospaceFontConfig.js b/src/main/MonospaceFontConfig.js
index f9fc2ff..e70d1bd 100644
--- a/src/main/MonospaceFontConfig.js
+++ b/src/main/MonospaceFontConfig.js
@@ -2,12 +2,19 @@
const fs = require('fs');
const path = require('path');
-const { getActiveMonoFont, isLigaturesEnabled, FAMILY_BY_KEY } = require('./settings/monospaceSettings');
+const {
+ getActiveMonoFont,
+ isLigaturesEnabled,
+ FAMILY_BY_KEY,
+} = require('./settings/monospaceSettings');
const WEIGHT_BY_KEY = { 300: 'Light', 400: 'Regular', 500: 'Medium', 600: 'SemiBold', 700: 'Bold' };
function getAppRoot() {
- if (process.resourcesPath && fs.existsSync(path.join(process.resourcesPath, 'app.asar.unpacked'))) {
+ if (
+ process.resourcesPath &&
+ fs.existsSync(path.join(process.resourcesPath, 'app.asar.unpacked'))
+ ) {
return process.resourcesPath;
}
return path.resolve(__dirname, '..', '..');
@@ -32,12 +39,18 @@ function getMonoFontTtfPath(familyKey, weight = 400) {
if (fs.existsSync(p)) return p;
}
const filename = path.basename(candidates[candidates.length - 1]);
- console.warn(`[MonospaceFontConfig] bundled font missing: ${filename}; falling back to system monospace`);
+ console.warn(
+ `[MonospaceFontConfig] bundled font missing: ${filename}; falling back to system monospace`
+ );
return null;
}
-function ligaturesEnabled(settings) { return isLigaturesEnabled(settings); }
+function ligaturesEnabled(settings) {
+ return isLigaturesEnabled(settings);
+}
-function getActiveFamily(settings) { return getActiveMonoFont(settings); }
+function getActiveFamily(settings) {
+ return getActiveMonoFont(settings);
+}
module.exports = { getMonoFontTtfPath, ligaturesEnabled, getActiveFamily };
diff --git a/src/main/PdfFontHeader.js b/src/main/PdfFontHeader.js
index dfcd076..283696b 100644
--- a/src/main/PdfFontHeader.js
+++ b/src/main/PdfFontHeader.js
@@ -44,4 +44,4 @@ function build({ fontTtfPath, boldTtfPath, ligatures }) {
`;
}
-module.exports = { build };
\ No newline at end of file
+module.exports = { build };
diff --git a/src/print-preview.js b/src/print-preview.js
index 6b50da4..78e4b87 100644
--- a/src/print-preview.js
+++ b/src/print-preview.js
@@ -27,7 +27,8 @@ function buildFontFaceBlock(familyKey) {
return `@font-face { font-family: '${family}'; font-weight: 400; font-style: normal; src: url('${dataUri}') format('woff2'); }`;
} catch (err) {
// Non-fatal: fall back to the system monospace stack declared in styles-modern.css.
- if (typeof console !== 'undefined') console.warn('[print-preview] font embed failed:', err.message);
+ if (typeof console !== 'undefined')
+ console.warn('[print-preview] font embed failed:', err.message);
return '';
}
}
@@ -125,7 +126,8 @@ class PrintPreview {
const width = orientation === 'landscape' ? size.height : size.width;
const height = orientation === 'landscape' ? size.width : size.height;
- const family = this._monospaceSettings.monospaceFont === 'fira-code' ? 'Fira Code' : 'JetBrains Mono';
+ const family =
+ this._monospaceSettings.monospaceFont === 'fira-code' ? 'Fira Code' : 'JetBrains Mono';
const ligaturesOn = this._monospaceSettings.monospaceLigatures === true;
const featureSettings = ligaturesOn ? 'normal' : "'liga' 0, 'calt' 0, 'dlig' 0";
const fontFaceBlock = buildFontFaceBlock(this._monospaceSettings.monospaceFont);
diff --git a/src/wordTemplateExporter.js b/src/wordTemplateExporter.js
index 50df038..5ea857b 100644
Binary files a/src/wordTemplateExporter.js and b/src/wordTemplateExporter.js differ
diff --git a/tests/docx-font-embedder.test.js b/tests/docx-font-embedder.test.js
index 308511f..af55eef 100644
--- a/tests/docx-font-embedder.test.js
+++ b/tests/docx-font-embedder.test.js
@@ -12,10 +12,22 @@ describe('DocxFontEmbedder.embed', () => {
fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(fontPath, 'fake-ttf-data');
const zip = new JSZip();
- zip.file('[Content_Types].xml', '');
- zip.file('_rels/.rels', '');
- zip.file('word/document.xml', '');
- zip.file('word/styles.xml', '');
+ zip.file(
+ '[Content_Types].xml',
+ ''
+ );
+ zip.file(
+ '_rels/.rels',
+ ''
+ );
+ zip.file(
+ 'word/document.xml',
+ ''
+ );
+ zip.file(
+ 'word/styles.xml',
+ ''
+ );
fs.writeFileSync(docxPath, await zip.generateAsync({ type: 'nodebuffer' }));
});
@@ -27,7 +39,9 @@ describe('DocxFontEmbedder.embed', () => {
]);
const zip = await JSZip.loadAsync(fs.readFileSync(out));
expect(Object.keys(zip.files).some((f) => f.startsWith('word/fonts/'))).toBe(true);
- const fontTable = zip.file('word/fontTable.xml') ? await zip.file('word/fontTable.xml').async('string') : '';
+ const fontTable = zip.file('word/fontTable.xml')
+ ? await zip.file('word/fontTable.xml').async('string')
+ : '';
expect(fontTable).toContain('JetBrains Mono');
expect(fontTable).toMatch(/ {
});
test('is idempotent: running twice does not double-embed', async () => {
- const once = await DocxFontEmbedder.embed(docxPath, [{ path: fontPath, family: 'JetBrains Mono', weight: 400 }]);
- const twice = await DocxFontEmbedder.embed(once, [{ path: fontPath, family: 'JetBrains Mono', weight: 400 }]);
+ const once = await DocxFontEmbedder.embed(docxPath, [
+ { path: fontPath, family: 'JetBrains Mono', weight: 400 },
+ ]);
+ const twice = await DocxFontEmbedder.embed(once, [
+ { path: fontPath, family: 'JetBrains Mono', weight: 400 },
+ ]);
const zip = await JSZip.loadAsync(fs.readFileSync(twice));
const fontEntries = Object.keys(zip.files).filter((f) => /^word\/fonts\/[^/]+\.ttf$/.test(f));
expect(fontEntries.length).toBe(1);
});
-});
\ No newline at end of file
+});
diff --git a/tests/epub-font-embedder.test.js b/tests/epub-font-embedder.test.js
index b02d078..273c79c 100644
--- a/tests/epub-font-embedder.test.js
+++ b/tests/epub-font-embedder.test.js
@@ -12,7 +12,10 @@ describe('EpubFontEmbedder.patchManifest', () => {
fs.mkdirSync(fixturesDir, { recursive: true });
fs.writeFileSync(fontPath, 'fake-ttf-binary');
const zip = new JSZip();
- zip.file('OEBPS/content.opf', '');
+ zip.file(
+ 'OEBPS/content.opf',
+ ''
+ );
fs.writeFileSync(epubPath, await zip.generateAsync({ type: 'nodebuffer' }));
});
@@ -28,4 +31,4 @@ describe('EpubFontEmbedder.patchManifest', () => {
expect(opf).toMatch(/- ]*href="OEBPS\/fonts\/fake\.ttf"/);
expect(opf).toMatch(/
- ]*media-type="application\/x-font-ttf"/);
});
-});
\ No newline at end of file
+});
diff --git a/tests/export-css.test.js b/tests/export-css.test.js
index 2809512..a74e8f0 100644
--- a/tests/export-css.test.js
+++ b/tests/export-css.test.js
@@ -13,14 +13,24 @@ describe('ExportCss.build', () => {
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 });
+ 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 });
+ 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'");
});
diff --git a/tests/monospace-font-config.test.js b/tests/monospace-font-config.test.js
index 5af8bc3..398d682 100644
--- a/tests/monospace-font-config.test.js
+++ b/tests/monospace-font-config.test.js
@@ -7,7 +7,9 @@ const fs = require('fs');
const MonospaceFontConfig = require('../src/main/MonospaceFontConfig');
describe('MonospaceFontConfig', () => {
- afterEach(() => { jest.clearAllMocks(); });
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
test('returns null when no file exists', () => {
fs.existsSync.mockReturnValue(false);
@@ -16,13 +18,17 @@ describe('MonospaceFontConfig', () => {
});
test('returns dev repo path when dev file exists', () => {
- fs.existsSync.mockImplementation((p) => !p.includes('app.asar.unpacked') && p.endsWith('JetBrainsMono-Regular.ttf'));
+ fs.existsSync.mockImplementation(
+ (p) => !p.includes('app.asar.unpacked') && p.endsWith('JetBrainsMono-Regular.ttf')
+ );
const p = MonospaceFontConfig.getMonoFontTtfPath('jetbrains-mono', 400);
expect(p).toMatch(/assets\/fonts\/JetBrainsMono-Regular\.ttf$/);
});
test('returns packaged asar.unpacked path when present and file exists', () => {
- fs.existsSync.mockImplementation((p) => p.includes('app.asar.unpacked') && p.endsWith('FiraCode-Regular.ttf'));
+ fs.existsSync.mockImplementation(
+ (p) => p.includes('app.asar.unpacked') && p.endsWith('FiraCode-Regular.ttf')
+ );
const p = MonospaceFontConfig.getMonoFontTtfPath('fira-code', 400);
expect(p).toContain('app.asar.unpacked');
expect(p).toContain('FiraCode-Regular.ttf');
diff --git a/tests/monospace-settings.test.js b/tests/monospace-settings.test.js
index 489694b..c2ff0c8 100644
--- a/tests/monospace-settings.test.js
+++ b/tests/monospace-settings.test.js
@@ -1,4 +1,8 @@
-const { getDefaults, getActiveMonoFont, isLigaturesEnabled } = require('../src/main/settings/monospaceSettings');
+const {
+ getDefaults,
+ getActiveMonoFont,
+ isLigaturesEnabled,
+} = require('../src/main/settings/monospaceSettings');
describe('monospaceSettings', () => {
test('getDefaults returns sane defaults', () => {
diff --git a/tests/pdf-font-header.test.js b/tests/pdf-font-header.test.js
index 109e247..0c3303c 100644
--- a/tests/pdf-font-header.test.js
+++ b/tests/pdf-font-header.test.js
@@ -52,4 +52,4 @@ describe('PdfFontHeader.build', () => {
});
expect(tex).toMatch(/\{FiraCode\}/);
});
-});
\ No newline at end of file
+});