-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
use-fonts.ts
139 lines (111 loc) · 4.04 KB
/
use-fonts.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { cssVar } from '@directus/utils/browser';
import { get } from 'lodash-es';
import type { MaybeRef } from 'vue';
import { computed, unref } from 'vue';
import type { Theme } from '../schemas/theme.js';
import { ThemeSchema } from '../schemas/theme.js';
export const useFonts = (theme: MaybeRef<Theme>) => {
const paths = computed(() => {
const paths: Map<string[], { family: string | null; weight: string | null }> = new Map();
const find = (schema: Record<string, unknown>, path: string[] = []) => {
for (const [key, value] of Object.entries(schema)) {
if (typeof value === 'object' && value !== null) {
if ('type' in value && value.type === 'object' && 'properties' in value) {
find(value.properties as Record<string, unknown>, [...path, key]);
}
if ('$ref' in value && value.$ref === 'FamilyName') {
if (paths.has(path)) {
paths.set(path, { family: key, weight: paths.get(path)!.weight });
} else {
paths.set(path, { family: key, weight: null });
}
}
if ('$ref' in value && value.$ref === 'FontWeight') {
if (paths.has(path)) {
paths.set(path, { family: paths.get(path)!.family, weight: key });
} else {
paths.set(path, { family: null, weight: key });
}
}
}
}
};
find(ThemeSchema.properties.rules.properties);
return paths;
});
const fonts = computed(() => {
/** [family, weight] */
const defs: Map<string, Set<string>> = new Map();
for (const [path, { family, weight }] of paths.value.entries()) {
let familyDefinition = null;
let weightDefinition = null;
if (family) {
familyDefinition = get(unref(theme).rules, [...path, family]) as string;
}
if (weight) {
weightDefinition = get(unref(theme).rules, [...path, weight]) as string;
}
if (familyDefinition) {
const stack = familyDefinition.split(',');
for (const def of stack) {
const trimmed = def.trim();
if (trimmed.startsWith('var(--')) {
stack.push(cssVar(trimmed.slice(6, -1)));
continue;
}
if ((trimmed.startsWith('"') && trimmed.endsWith('"')) === false) {
continue;
}
const noQuotes = trimmed.slice(1, -1);
if (defs.has(noQuotes)) {
defs.get(noQuotes)!.add(weightDefinition ?? '400');
} else {
defs.set(noQuotes, new Set([weightDefinition ?? '400']));
}
}
}
}
return defs;
});
const googleFonts = computed(() => {
const families: string[] = [];
for (const [family, weights] of fonts.value.entries()) {
const localFonts = ['Inter', 'Merriweather', 'Fira Mono'];
if (localFonts.includes(family) === false) {
const weightsParam = Array.from(weights).join(';');
families.push(`${family.replace(' ', '+')}:wght@${weightsParam}`);
}
}
return families;
// return fonts.value
// .filter((font) => {
// /**
// * I (Rijk)'d like the definition to remain valid CSS, so we can't introduce new characters
// * to differentiate. However, both `"font"` and `font` are valid font identifiers, so we
// * could rely on the existence of `""` as a sneaky way to differentiate between Google Font
// * and "regular" font.
// *
// * There's no way in JS to check what fonts exist, so we'll have to assume all custom fonts
// * are coming from Google Fonts.
// */
// if (font.startsWith('"') && font.endsWith('"') && font.includes('var(') === false) {
// /* While Inter/Merriweather/Fira Mono are Google Fonts, we ship them locally as they're
// * used in the default theme. They shouldn't be double-loaded so they're filtered out here.
// */
// const localFonts = ['Inter', 'Merriweather', 'Fira Mono'];
// if (localFonts.includes(font) || localFonts.map((font) => `"${font}"`).includes(font)) {
// return false;
// }
// return true;
// }
// return false;
// })
// .map((font) => {
// if (font.startsWith('"') && font.endsWith('"')) {
// font = font.slice(1, -1);
// }
// return font.replace(' ', '+');
// });
});
return { googleFonts };
};