Tracking now comes from androidx's TypeScaleTokens.kt as sp/16 rem, so Display Large is -0.0125rem, Title Medium and Body Medium 0.0125rem where material-web's pre-Expressive numbers stood. The emphasized set gets its own --md-sys-typescale-emphasized-<style>-tracking, which the emphasized utilities read: M3 widens four of them and takes Display Large back to zero. Every regular utility sets `font-variation-settings: normal`, because the property inherits and body copy inside an emphasized heading is meant to read as itself. bin/check-font.mjs (fontkit) prints the packaged woff2's fvar axes, so a re-subset cannot silently drop the ROND axis the emphasized styles depend on; `npm run check:font` runs it and tests/Feature/FontTest.php runs it through the configured node binary, skipping when node cannot run (PHP cannot open a woff2 without Brotli). Plan: docs/plans/material-3-alignment.md step 4, findings core C5, C6, C7. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
42 lines
1.8 KiB
PHP
42 lines
1.8 KiB
PHP
<?php
|
|
|
|
use Illuminate\Support\Facades\Process;
|
|
|
|
/**
|
|
* PHP cannot open a woff2 without the Brotli extension, so the axes are read by Node:
|
|
* bin/check-font.mjs (fontkit) prints them as JSON. Without Node the test is skipped, the
|
|
* way `material:scheme` reports the same missing binary instead of guessing.
|
|
*/
|
|
it('keeps the variable axes the typescale depends on in the packaged font', function () {
|
|
$node = config('livewire-material.node', 'node');
|
|
|
|
if (Process::run([$node, '--version'])->failed()) {
|
|
$this->markTestSkipped("Node ({$node}) could not run; `npm run check:font` reads the woff2's axes.");
|
|
}
|
|
|
|
$result = Process::run([$node, __DIR__.'/../../bin/check-font.mjs']);
|
|
|
|
expect($result->successful())->toBeTrue($result->errorOutput());
|
|
|
|
$font = json_decode($result->output(), true, flags: JSON_THROW_ON_ERROR);
|
|
|
|
expect($font['axes'])->toHaveKeys(['wght', 'ROND'])
|
|
// font.css declares `font-weight: 400 700`; every typescale weight is inside it.
|
|
->and($font['axes']['wght'])->toMatchArray(['min' => 400, 'max' => 700])
|
|
// The axis every `type-emphasized-*` utility sets to 100; a re-subset must keep it.
|
|
->and($font['axes']['ROND'])->toMatchArray(['min' => 0, 'max' => 100]);
|
|
});
|
|
|
|
it('fails loudly when the font has no variable axes at all', function () {
|
|
$node = config('livewire-material.node', 'node');
|
|
|
|
if (Process::run([$node, '--version'])->failed()) {
|
|
$this->markTestSkipped("Node ({$node}) could not run; `npm run check:font` reads the woff2's axes.");
|
|
}
|
|
|
|
$result = Process::run([$node, __DIR__.'/../../bin/check-font.mjs', __DIR__.'/../Fixtures/no-such-font.woff2']);
|
|
|
|
expect($result->failed())->toBeTrue()
|
|
->and($result->errorOutput())->toContain('no-such-font.woff2');
|
|
});
|