cursedbelt 5.79.3 → 5.79.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/looks.css +43 -5
- package/package.json +1 -1
- package/src/looks.css +43 -5
- package/src/looks.spec.ts +42 -3
package/dist/looks.css
CHANGED
|
@@ -252,10 +252,22 @@
|
|
|
252
252
|
* node_modules, which a library preview (tools/lib-preview.ts) never installs into, and which a
|
|
253
253
|
* nested install would miss. LATIN ONLY, one variable file for
|
|
254
254
|
* every weight: the fleet's copy is English, and the rest of the alphabet falls through to the
|
|
255
|
-
* system stack behind it.
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
255
|
+
* system stack behind it. cv11 is the single-storey a, ss01 the open digits — the pair Linear sets.
|
|
256
|
+
*
|
|
257
|
+
* `font-display: swap` paints at once in a fallback and swaps when the file lands — and the
|
|
258
|
+
* system face is NOT close enough to swap from: SF sets the same English 14% narrower than Inter,
|
|
259
|
+
* so on a slow load every line re-wrapped when the face came (0.0037 of layout shift at 390 in
|
|
260
|
+
* family's tree, and its TopBar moved 0.0023 under a loaded machine — forge task 3177). So the
|
|
261
|
+
* stack's second entry is 'Inter Fallback': Arial, which every Mac, iPhone and Windows box has,
|
|
262
|
+
* scaled with `size-adjust` and given Inter's own ascent and descent, the technique `next/font` and
|
|
263
|
+
* Fontaine ship. Measured in Chromium against this file with cv11 + ss01 on: within ±0.5% of
|
|
264
|
+
* Inter's width at 400, 500, 600 and 700 (SF: −14%), and the same line box. Two faces, because
|
|
265
|
+
* Arial has two weights: Regular stands for 100–549 and Bold for 550–900, each sized to the middle
|
|
266
|
+
* of its band, so no weight is synthesised. The overrides are Inter's metrics over the size-adjust
|
|
267
|
+
* (ascent 0.96875 em, descent 0.2412 em, no line gap). Same `unicode-range` as the face, so what
|
|
268
|
+
* Inter does not cover still falls through to the system stack, unscaled. Android has no Arial:
|
|
269
|
+
* the face fails there and the swap is from Roboto, as before. Re-measure if the woff2 is bumped
|
|
270
|
+
* (the family app's font browser test holds the swap's shift to nothing, with the file held back).
|
|
259
271
|
*/
|
|
260
272
|
@font-face {
|
|
261
273
|
font-family: 'Inter Variable';
|
|
@@ -267,8 +279,34 @@
|
|
|
267
279
|
U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
268
280
|
}
|
|
269
281
|
|
|
282
|
+
@font-face {
|
|
283
|
+
font-family: 'Inter Fallback';
|
|
284
|
+
font-style: normal;
|
|
285
|
+
font-weight: 100 549;
|
|
286
|
+
src: local('Arial'), local('ArialMT');
|
|
287
|
+
size-adjust: 106.25%;
|
|
288
|
+
ascent-override: 91.18%;
|
|
289
|
+
descent-override: 22.7%;
|
|
290
|
+
line-gap-override: 0%;
|
|
291
|
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
|
|
292
|
+
U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
@font-face {
|
|
296
|
+
font-family: 'Inter Fallback';
|
|
297
|
+
font-style: normal;
|
|
298
|
+
font-weight: 550 900;
|
|
299
|
+
src: local('Arial Bold'), local('Arial-BoldMT');
|
|
300
|
+
size-adjust: 101.2%;
|
|
301
|
+
ascent-override: 95.73%;
|
|
302
|
+
descent-override: 23.83%;
|
|
303
|
+
line-gap-override: 0%;
|
|
304
|
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
|
|
305
|
+
U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
306
|
+
}
|
|
307
|
+
|
|
270
308
|
.cb-font-inter {
|
|
271
|
-
--font-sans: 'Inter Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
|
|
309
|
+
--font-sans: 'Inter Variable', 'Inter Fallback', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
|
|
272
310
|
'Noto Sans', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
|
273
311
|
/* Tailwind's preflight reads these two on <html>; re-run them here, where --font-sans changed. */
|
|
274
312
|
--default-font-family: var(--font-sans);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursedbelt",
|
|
3
|
-
"version": "5.79.
|
|
3
|
+
"version": "5.79.4",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
|
package/src/looks.css
CHANGED
|
@@ -252,10 +252,22 @@
|
|
|
252
252
|
* node_modules, which a library preview (tools/lib-preview.ts) never installs into, and which a
|
|
253
253
|
* nested install would miss. LATIN ONLY, one variable file for
|
|
254
254
|
* every weight: the fleet's copy is English, and the rest of the alphabet falls through to the
|
|
255
|
-
* system stack behind it.
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
255
|
+
* system stack behind it. cv11 is the single-storey a, ss01 the open digits — the pair Linear sets.
|
|
256
|
+
*
|
|
257
|
+
* `font-display: swap` paints at once in a fallback and swaps when the file lands — and the
|
|
258
|
+
* system face is NOT close enough to swap from: SF sets the same English 14% narrower than Inter,
|
|
259
|
+
* so on a slow load every line re-wrapped when the face came (0.0037 of layout shift at 390 in
|
|
260
|
+
* family's tree, and its TopBar moved 0.0023 under a loaded machine — forge task 3177). So the
|
|
261
|
+
* stack's second entry is 'Inter Fallback': Arial, which every Mac, iPhone and Windows box has,
|
|
262
|
+
* scaled with `size-adjust` and given Inter's own ascent and descent, the technique `next/font` and
|
|
263
|
+
* Fontaine ship. Measured in Chromium against this file with cv11 + ss01 on: within ±0.5% of
|
|
264
|
+
* Inter's width at 400, 500, 600 and 700 (SF: −14%), and the same line box. Two faces, because
|
|
265
|
+
* Arial has two weights: Regular stands for 100–549 and Bold for 550–900, each sized to the middle
|
|
266
|
+
* of its band, so no weight is synthesised. The overrides are Inter's metrics over the size-adjust
|
|
267
|
+
* (ascent 0.96875 em, descent 0.2412 em, no line gap). Same `unicode-range` as the face, so what
|
|
268
|
+
* Inter does not cover still falls through to the system stack, unscaled. Android has no Arial:
|
|
269
|
+
* the face fails there and the swap is from Roboto, as before. Re-measure if the woff2 is bumped
|
|
270
|
+
* (the family app's font browser test holds the swap's shift to nothing, with the file held back).
|
|
259
271
|
*/
|
|
260
272
|
@font-face {
|
|
261
273
|
font-family: 'Inter Variable';
|
|
@@ -267,8 +279,34 @@
|
|
|
267
279
|
U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
268
280
|
}
|
|
269
281
|
|
|
282
|
+
@font-face {
|
|
283
|
+
font-family: 'Inter Fallback';
|
|
284
|
+
font-style: normal;
|
|
285
|
+
font-weight: 100 549;
|
|
286
|
+
src: local('Arial'), local('ArialMT');
|
|
287
|
+
size-adjust: 106.25%;
|
|
288
|
+
ascent-override: 91.18%;
|
|
289
|
+
descent-override: 22.7%;
|
|
290
|
+
line-gap-override: 0%;
|
|
291
|
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
|
|
292
|
+
U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
@font-face {
|
|
296
|
+
font-family: 'Inter Fallback';
|
|
297
|
+
font-style: normal;
|
|
298
|
+
font-weight: 550 900;
|
|
299
|
+
src: local('Arial Bold'), local('Arial-BoldMT');
|
|
300
|
+
size-adjust: 101.2%;
|
|
301
|
+
ascent-override: 95.73%;
|
|
302
|
+
descent-override: 23.83%;
|
|
303
|
+
line-gap-override: 0%;
|
|
304
|
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
|
|
305
|
+
U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
306
|
+
}
|
|
307
|
+
|
|
270
308
|
.cb-font-inter {
|
|
271
|
-
--font-sans: 'Inter Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
|
|
309
|
+
--font-sans: 'Inter Variable', 'Inter Fallback', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
|
|
272
310
|
'Noto Sans', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
|
273
311
|
/* Tailwind's preflight reads these two on <html>; re-run them here, where --font-sans changed. */
|
|
274
312
|
--default-font-family: var(--font-sans);
|
package/src/looks.spec.ts
CHANGED
|
@@ -135,7 +135,14 @@ describe('looks.css', () => {
|
|
|
135
135
|
* package without re-copying the file is red here rather than a stale face in every app.
|
|
136
136
|
*/
|
|
137
137
|
describe('cb-font-inter', () => {
|
|
138
|
-
const
|
|
138
|
+
const allFaces = [...LOOKS_CSS.replace(/\/\*[\s\S]*?\*\//g, '').matchAll(/@font-face\s*\{([^}]*)\}/g)].map((m) => m[1] ?? '');
|
|
139
|
+
const faces = allFaces.filter((face) => face.includes("'Inter Variable'"));
|
|
140
|
+
const fallbacks = allFaces.filter((face) => face.includes("'Inter Fallback'"));
|
|
141
|
+
|
|
142
|
+
/** One descriptor of a face, as written. */
|
|
143
|
+
const descriptor = (face: string, name: string): string | undefined =>
|
|
144
|
+
face.match(new RegExp(`(?:^|;)\\s*${name}:\\s*([^;]+);`))?.[1]?.replace(/\s+/g, ' ').trim();
|
|
145
|
+
const percent = (face: string, name: string): number => Number.parseFloat(descriptor(face, name) ?? 'NaN');
|
|
139
146
|
|
|
140
147
|
/** Every face's `src: url(…)`, as written. */
|
|
141
148
|
const urls = (css: string[]): string[] => css.flatMap((face) => [...face.matchAll(/url\('([^']+)'\)/g)].map((m) => m[1] as string));
|
|
@@ -171,9 +178,41 @@ describe('cb-font-inter', () => {
|
|
|
171
178
|
for (const url of urls(stale)) expect(await Bun.file(onDisk(url)).exists()).toBe(false);
|
|
172
179
|
});
|
|
173
180
|
|
|
174
|
-
|
|
181
|
+
/*
|
|
182
|
+
* The swap's fallback (forge task 3177): the system face sets English 14% narrower than Inter,
|
|
183
|
+
* so a late woff2 re-wrapped every line. The numbers were measured in Chromium (looks.css says
|
|
184
|
+
* how); this holds the shape that makes them mean anything. The family app's font browser test
|
|
185
|
+
* is what holds the swap's shift to nothing.
|
|
186
|
+
*/
|
|
187
|
+
test("the swap is from 'Inter Fallback': Arial scaled to Inter, Regular and Bold, no file", () => {
|
|
188
|
+
expect(allFaces).toHaveLength(faces.length + fallbacks.length);
|
|
189
|
+
expect(fallbacks.map((face) => descriptor(face, 'font-weight'))).toEqual(['100 549', '550 900']);
|
|
190
|
+
expect(fallbacks.map((face) => descriptor(face, 'src'))).toEqual([
|
|
191
|
+
"local('Arial'), local('ArialMT')",
|
|
192
|
+
"local('Arial Bold'), local('Arial-BoldMT')",
|
|
193
|
+
]);
|
|
194
|
+
for (const face of fallbacks) {
|
|
195
|
+
expect(face).not.toContain('url(');
|
|
196
|
+
// What Inter does not cover falls through to the system stack, not to a scaled Arial.
|
|
197
|
+
expect(descriptor(face, 'unicode-range')).toBe(descriptor(faces[0] as string, 'unicode-range'));
|
|
198
|
+
// Inter's own line box (ascent 0.96875 em, descent 0.2412 em, no gap), over the scale.
|
|
199
|
+
const scale = percent(face, 'size-adjust') / 100;
|
|
200
|
+
expect(scale).toBeGreaterThan(1);
|
|
201
|
+
expect(percent(face, 'ascent-override')).toBeCloseTo(96.875 / scale, 1);
|
|
202
|
+
expect(percent(face, 'descent-override')).toBeCloseTo(24.12 / scale, 1);
|
|
203
|
+
expect(descriptor(face, 'line-gap-override')).toBe('0%');
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test('🔴 the failure path: a fallback whose overrides ignore its size-adjust is caught', () => {
|
|
208
|
+
const unscaled = (fallbacks[0] as string).replace(/ascent-override:\s*[^;]+;/, 'ascent-override: 96.88%;');
|
|
209
|
+
const scale = percent(unscaled, 'size-adjust') / 100;
|
|
210
|
+
expect(percent(unscaled, 'ascent-override')).not.toBeCloseTo(96.875 / scale, 1);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test('re-binds the sans stack with Inter first, its fallback second, and the cv11 + ss01 features', () => {
|
|
175
214
|
const decls = declarationsOf(LOOKS_CSS, '.cb-font-inter');
|
|
176
|
-
expect(decls?.get('--font-sans')).toStartWith("'Inter Variable',");
|
|
215
|
+
expect(decls?.get('--font-sans')).toStartWith("'Inter Variable', 'Inter Fallback', -apple-system,");
|
|
177
216
|
expect(decls?.get('--default-font-family')).toBe('var(--font-sans)');
|
|
178
217
|
expect(decls?.get('--default-font-feature-settings')).toBe("'cv11', 'ss01'");
|
|
179
218
|
});
|