fix(runtime): download pinned MiSans fonts individually for 7.5
This commit is contained in:
+22
-26
@@ -1,33 +1,29 @@
|
||||
import { createHash } from 'node:crypto';
|
||||
import { mkdtempSync, writeFileSync, rmSync, mkdirSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
|
||||
const url = 'https://hyperos.mi.com/font-download/MiSans.zip';
|
||||
const sha256 = 'b6aa1fc827035922612df8edf36e5609bca1c5441e25cd57572204569b7b81d9';
|
||||
const weights = ['Thin', 'ExtraLight', 'Light', 'Normal', 'Regular', 'Medium', 'Demibold', 'Semibold', 'Bold', 'Heavy'];
|
||||
// Third-party mirror, pinned to a reviewed commit; Xiaomi's font license applies.
|
||||
const base = 'https://raw.githubusercontent.com/boyan01/mi_sans_font/68f3ec3fee5830ce8a1d955d462fa0df401a5341/lib/fonts/';
|
||||
const fonts = [
|
||||
['MiSans-Regular.ttf', '7172aa1b5c703780ee12df3fe4c50481dde01f3b125a045a398000a88d032ae5', 'Regular'],
|
||||
['MiSans-Bold.ttf', '250fb5c8d4657f103e332b0b948a995e45f2c159beb8d0528424e2d32ae421be', 'Bold'],
|
||||
];
|
||||
const destination = '/usr/local/share/fonts/misans';
|
||||
const temporary = mkdtempSync(join(tmpdir(), 'misans-'));
|
||||
try {
|
||||
const response = await fetch(url, { signal: AbortSignal.timeout(300000) });
|
||||
if (!response.ok) throw new Error(`MiSans download failed: ${response.status}`);
|
||||
const archive = Buffer.from(await response.arrayBuffer());
|
||||
if (createHash('sha256').update(archive).digest('hex') !== sha256) {
|
||||
throw new Error('MiSans archive checksum mismatch; review upstream changes before updating');
|
||||
mkdirSync(destination, { recursive: true });
|
||||
for (const [name, sha256] of fonts) {
|
||||
console.log('Downloading ' + name);
|
||||
const response = await fetch(base + name, { signal: AbortSignal.timeout(120000) });
|
||||
if (!response.ok) throw new Error('MiSans download failed: ' + name + ' HTTP ' + response.status);
|
||||
const font = Buffer.from(await response.arrayBuffer());
|
||||
if (createHash('sha256').update(font).digest('hex') !== sha256) {
|
||||
throw new Error('MiSans checksum mismatch: ' + name);
|
||||
}
|
||||
const archivePath = join(temporary, 'MiSans.zip');
|
||||
writeFileSync(archivePath, archive);
|
||||
mkdirSync(destination, { recursive: true });
|
||||
for (const weight of weights) {
|
||||
const name = `MiSans-${weight}.ttf`;
|
||||
// Extract only fixed, reviewed filenames; never unpack arbitrary archive paths.
|
||||
const font = execFileSync('python3', ['-c', 'import sys, zipfile; sys.stdout.buffer.write(zipfile.ZipFile(sys.argv[1]).read(sys.argv[2]))', archivePath, `MiSans/ttf/${name}`], { maxBuffer: 16000000 });
|
||||
writeFileSync(join(destination, name), font, { mode: 0o644 });
|
||||
}
|
||||
execFileSync('fc-cache', ['-f', destination], { stdio: 'inherit' });
|
||||
const family = execFileSync('fc-match', ['-f', '%{family}', 'MiSans'], { encoding: 'utf8' });
|
||||
if (!family.split(',').includes('MiSans')) throw new Error(`MiSans font lookup failed: ${family}`);
|
||||
} finally {
|
||||
rmSync(temporary, { recursive: true, force: true });
|
||||
writeFileSync(join(destination, name), font, { mode: 0o644 });
|
||||
}
|
||||
execFileSync('fc-cache', ['-f', destination], { stdio: 'inherit' });
|
||||
for (const [name, , style] of fonts) {
|
||||
const file = execFileSync('fc-match', ['-f', '%{file}', 'MiSans:style=' + style], { encoding: 'utf8' });
|
||||
if (file !== join(destination, name)) throw new Error('MiSans font lookup failed: ' + style + ': ' + file);
|
||||
}
|
||||
console.log('Installed MiSans Regular and Bold (SHA-256 verified)');
|
||||
|
||||
Reference in New Issue
Block a user