Files
dsh-web/image/install-misans.mjs
T

34 lines
1.9 KiB
JavaScript

import { createHash } from 'node:crypto';
import { mkdtempSync, writeFileSync, rmSync, mkdirSync } from 'node:fs';
import { tmpdir } from 'node:os';
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'];
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');
}
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 });
}