mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-08-23 23:10:17 +05:30
feat(monospace): add MonospaceFontConfig path resolver
Resolves dev vs packaged (asar.unpacked) TTF paths. Logs warn, returns null when bundled font is missing.
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const { app } = require('electron');
|
||||||
|
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'))) {
|
||||||
|
return process.resourcesPath;
|
||||||
|
}
|
||||||
|
return path.resolve(__dirname, '..', '..');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCandidatePaths(family, weight) {
|
||||||
|
const familyDir = family === 'Fira Code' ? 'FiraCode' : 'JetBrainsMono';
|
||||||
|
const weightName = WEIGHT_BY_KEY[weight] || 'Regular';
|
||||||
|
const filename = `${familyDir}-${weightName}.ttf`;
|
||||||
|
|
||||||
|
const candidates = [];
|
||||||
|
candidates.push(path.resolve(getAppRoot(), 'assets', 'fonts', filename));
|
||||||
|
const packagedRoot = process.resourcesPath || getAppRoot();
|
||||||
|
candidates.push(path.join(packagedRoot, 'app.asar.unpacked', 'assets', 'fonts', filename));
|
||||||
|
return candidates;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMonoFontTtfPath(familyKey, weight = 400) {
|
||||||
|
const family = FAMILY_BY_KEY[familyKey] || 'JetBrains Mono';
|
||||||
|
const candidates = getCandidatePaths(family, weight);
|
||||||
|
for (const p of candidates) {
|
||||||
|
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`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ligaturesEnabled(settings) { return isLigaturesEnabled(settings); }
|
||||||
|
|
||||||
|
function getActiveFamily(settings) { return getActiveMonoFont(settings); }
|
||||||
|
|
||||||
|
module.exports = { getMonoFontTtfPath, ligaturesEnabled, getActiveFamily };
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
jest.mock('electron', () => ({
|
||||||
|
app: { getPath: () => '/fake/userData' },
|
||||||
|
}));
|
||||||
|
jest.mock('fs', () => ({ existsSync: jest.fn(), statSync: jest.fn() }));
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const MonospaceFontConfig = require('../src/main/MonospaceFontConfig');
|
||||||
|
|
||||||
|
describe('MonospaceFontConfig', () => {
|
||||||
|
afterEach(() => { jest.clearAllMocks(); });
|
||||||
|
|
||||||
|
test('returns null when no file exists', () => {
|
||||||
|
fs.existsSync.mockReturnValue(false);
|
||||||
|
const p = MonospaceFontConfig.getMonoFontTtfPath('jetbrains-mono', 400);
|
||||||
|
expect(p).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns dev repo path when dev file exists', () => {
|
||||||
|
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'));
|
||||||
|
const p = MonospaceFontConfig.getMonoFontTtfPath('fira-code', 400);
|
||||||
|
expect(p).toContain('app.asar.unpacked');
|
||||||
|
expect(p).toContain('FiraCode-Regular.ttf');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns null and warns when file is missing', () => {
|
||||||
|
const warn = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
||||||
|
fs.existsSync.mockReturnValue(false);
|
||||||
|
const p = MonospaceFontConfig.getMonoFontTtfPath('fira-code', 700);
|
||||||
|
expect(p).toBeNull();
|
||||||
|
expect(warn).toHaveBeenCalledWith(expect.stringMatching(/FiraCode-Bold\.ttf/));
|
||||||
|
warn.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('ligaturesEnabled maps from settings', () => {
|
||||||
|
expect(MonospaceFontConfig.ligaturesEnabled({ monospaceLigatures: true })).toBe(true);
|
||||||
|
expect(MonospaceFontConfig.ligaturesEnabled({ monospaceLigatures: false })).toBe(false);
|
||||||
|
expect(MonospaceFontConfig.ligaturesEnabled({})).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user