/
typograph.ts
89 lines (78 loc) · 2.41 KB
/
typograph.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import {execAsync, isMacOS, Log} from '@diez/cli-core';
import {camelCase, pascalCase} from 'change-case';
import {join} from 'path';
import {GeneratedFont, SerializedTypographData} from './api';
import {objectToSource} from './utils';
interface FontLookup {
name: string;
style: string;
}
const fontCache = new Map<string, GeneratedFont>();
/**
* Provides a best-effort lookup for a font in a given font family.
*/
export const locateFont = async (
fontFamily: string,
lookup: Partial<FontLookup>,
): Promise<GeneratedFont | undefined> => {
const fontHash = `${fontFamily}|${lookup.name}|${lookup.style}`;
if (fontCache.has(fontHash)) {
return fontCache.get(fontHash);
}
if (isMacOS()) {
const candidates: GeneratedFont[] = [];
try {
candidates.push(...JSON.parse(await execAsync(`./MacFonts '${fontFamily}'`, {
cwd: join(__dirname, '..', 'tools', 'mac-fonts', 'bin'),
})));
} catch (error) {
// Noop. For some reason, we were not able to run the MacFonts binary on this machine.
}
if (!candidates.length) {
return;
}
if (lookup.name) {
const match = candidates.find(({name}) => name === lookup.name);
if (match) {
fontCache.set(fontHash, match);
return match;
}
}
switch (lookup.style) {
case 'italic':
const italic = candidates.find(({style}) => style === 'Italic');
if (italic) {
fontCache.set(fontHash, italic);
return italic;
}
break;
case 'normal':
const normal = candidates.find(({style}) => style === 'Regular');
if (normal) {
fontCache.set(fontHash, normal);
return normal;
}
break;
}
fontCache.set(fontHash, candidates[0]);
return candidates[0];
}
Log.warning('Font location is not implemented on your platform.');
return;
};
/**
* Returns a color initializer based on primitive values.
* @ignore
*/
export const getTypographInitializer = (
designLanguageName: string,
candidateFont: GeneratedFont | undefined,
fontName: string,
typographData: Partial<SerializedTypographData>,
) => {
const font = candidateFont ?
`${camelCase(`${designLanguageName} Fonts`)}.${pascalCase(candidateFont.family)}.${pascalCase(candidateFont.style)}` :
`new Font({name: "${fontName}"})`;
Object.assign(typographData, {font});
return `new Typograph(${objectToSource(typographData)})`;
};