@rblabs-dev/axiom 1.2.1 → 1.2.3
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/README.md +39 -13
- package/app-shell/package.json +4 -0
- package/brand-lockup/package.json +4 -0
- package/central-sign-in/package.json +4 -0
- package/cli/build-brand-assets.mjs +12 -18
- package/cli/project.mjs +6 -0
- package/cli/verify-production-assets.mjs +71 -6
- package/confirm-dialog/package.json +4 -0
- package/core/package.json +4 -0
- package/empty-state/package.json +4 -0
- package/fesm2022/rblabs-dev-axiom-app-shell.mjs +375 -0
- package/fesm2022/rblabs-dev-axiom-app-shell.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-brand-lockup.mjs +154 -0
- package/fesm2022/rblabs-dev-axiom-brand-lockup.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-central-sign-in.mjs +375 -0
- package/fesm2022/rblabs-dev-axiom-central-sign-in.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-confirm-dialog.mjs +329 -0
- package/fesm2022/rblabs-dev-axiom-confirm-dialog.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-core.mjs +181 -0
- package/fesm2022/rblabs-dev-axiom-core.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-empty-state.mjs +252 -0
- package/fesm2022/rblabs-dev-axiom-empty-state.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-message.mjs +194 -0
- package/fesm2022/rblabs-dev-axiom-message.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-monogram.mjs +102 -0
- package/fesm2022/rblabs-dev-axiom-monogram.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-page-header.mjs +199 -0
- package/fesm2022/rblabs-dev-axiom-page-header.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-panel.mjs +207 -0
- package/fesm2022/rblabs-dev-axiom-panel.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-public-shell.mjs +165 -0
- package/fesm2022/rblabs-dev-axiom-public-shell.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-shell-footer.mjs +73 -0
- package/fesm2022/rblabs-dev-axiom-shell-footer.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-status-chip.mjs +161 -0
- package/fesm2022/rblabs-dev-axiom-status-chip.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-technical-value.mjs +173 -0
- package/fesm2022/rblabs-dev-axiom-technical-value.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom-theme-toggle.mjs +117 -0
- package/fesm2022/rblabs-dev-axiom-theme-toggle.mjs.map +1 -0
- package/fesm2022/rblabs-dev-axiom.mjs +15 -2955
- package/fonts/LICENSE +93 -0
- package/fonts/inter-latin-ext-wght-normal.woff2 +0 -0
- package/fonts/inter-latin-wght-normal.woff2 +0 -0
- package/message/package.json +4 -0
- package/monogram/package.json +4 -0
- package/package.json +77 -2
- package/page-header/package.json +4 -0
- package/panel/package.json +4 -0
- package/public-shell/package.json +4 -0
- package/shell-footer/package.json +4 -0
- package/status-chip/package.json +4 -0
- package/styles/_fonts.scss +7 -7
- package/styles/_index.scss +1 -1
- package/technical-value/package.json +4 -0
- package/theme-toggle/package.json +4 -0
- package/types/rblabs-dev-axiom-app-shell.d.ts +50 -0
- package/types/rblabs-dev-axiom-brand-lockup.d.ts +35 -0
- package/types/rblabs-dev-axiom-central-sign-in.d.ts +82 -0
- package/types/rblabs-dev-axiom-confirm-dialog.d.ts +76 -0
- package/types/rblabs-dev-axiom-core.d.ts +116 -0
- package/types/rblabs-dev-axiom-empty-state.d.ts +55 -0
- package/types/rblabs-dev-axiom-message.d.ts +48 -0
- package/types/rblabs-dev-axiom-monogram.d.ts +12 -0
- package/types/rblabs-dev-axiom-page-header.d.ts +44 -0
- package/types/rblabs-dev-axiom-panel.d.ts +44 -0
- package/types/rblabs-dev-axiom-public-shell.d.ts +28 -0
- package/types/rblabs-dev-axiom-shell-footer.d.ts +17 -0
- package/types/rblabs-dev-axiom-status-chip.d.ts +40 -0
- package/types/rblabs-dev-axiom-technical-value.d.ts +35 -0
- package/types/rblabs-dev-axiom-theme-toggle.d.ts +12 -0
- package/types/rblabs-dev-axiom.d.ts +15 -675
- package/fesm2022/rblabs-dev-axiom.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -23,7 +23,8 @@ This README covers installing the package and wiring it into an app.
|
|
|
23
23
|
npm install @rblabs-dev/axiom @angular/material@<major> @angular/cdk@<major>
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Inter Variable
|
|
26
|
+
Inter Variable ships in the package's `fonts/` folder, and the app serves it (step 3). Nothing loads
|
|
27
|
+
from a CDN.
|
|
27
28
|
|
|
28
29
|
## Set up an app
|
|
29
30
|
|
|
@@ -54,7 +55,25 @@ Run these steps from the folder that holds the app's `angular.json`.
|
|
|
54
55
|
`NOTICE.txt`. `angular.json` must serve `public/` (`{ "glob": "**/*", "input": "public" }`, the
|
|
55
56
|
Angular CLI default); no other asset entry is needed.
|
|
56
57
|
|
|
57
|
-
3. **
|
|
58
|
+
3. **Inter.** Serve the package's Inter files at `/fonts/` with this entry in the build `assets` of
|
|
59
|
+
`angular.json`:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{ "glob": "*.woff2", "input": "node_modules/@rblabs-dev/axiom/fonts", "output": "fonts" }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Then preload the Latin file in the `<head>` of `src/index.html`:
|
|
66
|
+
|
|
67
|
+
```html
|
|
68
|
+
<link rel="preload" href="/fonts/inter-latin-wght-normal.woff2" as="font" type="font/woff2" crossorigin />
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The kit declares Inter with `font-display: optional`, so a first visit gets Inter only if the
|
|
72
|
+
file arrives within about 100 ms of the first render; the preload starts it with the HTML instead
|
|
73
|
+
of after the global stylesheet. Keep `crossorigin`: without it the browser does not reuse the
|
|
74
|
+
preloaded file. `axiom verify-production-assets` fails the build when either step is missing.
|
|
75
|
+
|
|
76
|
+
4. **Global styles.** Call the entry mixin once, at the top of `src/styles.scss`, with the subset's
|
|
58
77
|
file name (later runs of `build:icon-font` update it):
|
|
59
78
|
|
|
60
79
|
```scss
|
|
@@ -67,7 +86,7 @@ Run these steps from the folder that holds the app's `angular.json`.
|
|
|
67
86
|
`$scope: '.rb-scope'` applies the kit only inside that class, for an app that still has global
|
|
68
87
|
styles of its own. The module also forwards `rb.below()`, `rb.above()` and `$breakpoints`.
|
|
69
88
|
|
|
70
|
-
|
|
89
|
+
5. **Providers.** In `app.config.ts`:
|
|
71
90
|
|
|
72
91
|
```ts
|
|
73
92
|
import { provideRbDesignSystem } from '@rblabs-dev/axiom';
|
|
@@ -81,7 +100,7 @@ Run these steps from the folder that holds the app's `angular.json`.
|
|
|
81
100
|
`<mat-icon>` font. `provideRbDesignSystem({ forcedTheme: 'dark' })` keeps an app dark-only
|
|
82
101
|
while it migrates, and `legacyStorageKeys` moves a theme choice stored under an older key.
|
|
83
102
|
|
|
84
|
-
|
|
103
|
+
6. **Showcase route.** Route `/design-system` to the showcase, lazily, so it stays out of the
|
|
85
104
|
initial bundle:
|
|
86
105
|
|
|
87
106
|
```ts
|
|
@@ -93,7 +112,7 @@ Run these steps from the folder that holds the app's `angular.json`.
|
|
|
93
112
|
}
|
|
94
113
|
```
|
|
95
114
|
|
|
96
|
-
|
|
115
|
+
7. **Favicon and document head.** Write the app's favicon from the brand template, then reference
|
|
97
116
|
it in `index.html` with the theme colors:
|
|
98
117
|
|
|
99
118
|
```bash
|
|
@@ -106,7 +125,7 @@ Run these steps from the folder that holds the app's `angular.json`.
|
|
|
106
125
|
<meta name="theme-color" content="#08111d" media="(prefers-color-scheme: dark)" />
|
|
107
126
|
```
|
|
108
127
|
|
|
109
|
-
|
|
128
|
+
8. **Build.** `npm run build` builds the app and runs `axiom verify-production-assets`.
|
|
110
129
|
|
|
111
130
|
Then use the components and kit classes in templates:
|
|
112
131
|
|
|
@@ -130,19 +149,26 @@ each pull request needs.
|
|
|
130
149
|
| `@rblabs-dev/axiom/showcase` | `DesignSystemShowcaseComponent`, the `/design-system` page |
|
|
131
150
|
| `@use '@rblabs-dev/axiom'` (SCSS) | `rb.design-system()`, `rb.below()`, `rb.above()`, `$breakpoints` and `$version`; emits no CSS until the mixin is called |
|
|
132
151
|
| `axiom` (command) | The four commands below |
|
|
152
|
+
| `fonts/` | Inter Variable (Latin and Latin Extended WOFF2) and its license, served by the app at `/fonts/` |
|
|
133
153
|
| `brand/`, `material-symbols-icons.txt` | Brand templates and the kit's icon inventory, read by the commands |
|
|
134
154
|
|
|
155
|
+
Import the TypeScript API from `@rblabs-dev/axiom`. Inside the package, each component, shell and
|
|
156
|
+
brand component is its own secondary entry point (`@rblabs-dev/axiom/panel`, …), so your bundler
|
|
157
|
+
puts it, with the Material code it uses, in the lazy chunk of the routes that use it, and only
|
|
158
|
+
`provideRbDesignSystem()` and the theme service join your initial bundle. Those entry points are
|
|
159
|
+
how the package is laid out, not an API: a release may rename, merge or split them.
|
|
160
|
+
|
|
135
161
|
## The `axiom` command
|
|
136
162
|
|
|
137
163
|
Each command reads the app's source root, `public/` folder and build output from `angular.json`.
|
|
138
164
|
With several applications in one workspace, pass `--project <name>`. `npx axiom help` lists them.
|
|
139
165
|
|
|
140
|
-
| Command | What it does
|
|
141
|
-
| --------------------------------------------------------- |
|
|
142
|
-
| `axiom build-icon-font [--output <dir>]` | Downloads the Material Symbols subset for the kit's and the app's icons, replaces the previous one in `public/fonts/` and updates its name in `src/**/*.scss`
|
|
143
|
-
| `axiom build-brand-assets --app <name> [--out-dir <dir>]` | Writes `public/favicon.svg`. With `--og-image <out.svg> --description <text> --domain <host>`, also writes the social preview SVG
|
|
144
|
-
| `axiom verify-production-assets [--scan <dir>]...` | After a production build, fails on Google Fonts references, a missing favicon or icon font, or an icon used in `src/` that no inventory lists
|
|
145
|
-
| `axiom check-style-literals` | Fails on hex, `rgb()` or `hsl()` color literals in `src/**/*.scss` that `style-literals.allowlist.json` does not list
|
|
166
|
+
| Command | What it does |
|
|
167
|
+
| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
168
|
+
| `axiom build-icon-font [--output <dir>]` | Downloads the Material Symbols subset for the kit's and the app's icons, replaces the previous one in `public/fonts/` and updates its name in `src/**/*.scss` |
|
|
169
|
+
| `axiom build-brand-assets --app <name> [--out-dir <dir>]` | Writes `public/favicon.svg`. With `--og-image <out.svg> --description <text> --domain <host>`, also writes the social preview SVG |
|
|
170
|
+
| `axiom verify-production-assets [--scan <dir>]...` | After a production build, fails on Google Fonts references, a missing favicon, Inter preload or font file, a missing icon font, or an icon used in `src/` that no inventory lists |
|
|
171
|
+
| `axiom check-style-literals` | Fails on hex, `rgb()` or `hsl()` color literals in `src/**/*.scss` that `style-literals.allowlist.json` does not list |
|
|
146
172
|
|
|
147
173
|
## Versions
|
|
148
174
|
|
|
@@ -153,4 +179,4 @@ showcase and `RB_DESIGN_SYSTEM_VERSION` report. Release notes are on the
|
|
|
153
179
|
## License
|
|
154
180
|
|
|
155
181
|
MIT. The icon font that `axiom build-icon-font` downloads is Material Symbols (Apache License 2.0),
|
|
156
|
-
and Inter Variable is licensed under the SIL Open Font License 1.1.
|
|
182
|
+
and Inter Variable, in `fonts/`, is licensed under the SIL Open Font License 1.1 (`fonts/LICENSE`).
|
|
@@ -8,19 +8,23 @@
|
|
|
8
8
|
//
|
|
9
9
|
// ... --og-image <out.svg> --description "<at most 60 characters>" --domain <host>
|
|
10
10
|
// also writes the filled social preview template to <out.svg>, for export to the app's
|
|
11
|
-
// public/og-image.png (1200x630). The SVG loads Inter from
|
|
12
|
-
// machine that generated it.
|
|
11
|
+
// public/og-image.png (1200x630). The SVG loads Inter from this package's fonts/ folder, so
|
|
12
|
+
// export it on the machine that generated it.
|
|
13
13
|
//
|
|
14
14
|
// The output is per-app and lives in the app; commit its public/favicon.svg and og-image.png.
|
|
15
15
|
|
|
16
16
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
17
|
-
import { createRequire } from 'node:module';
|
|
18
17
|
import path from 'node:path';
|
|
19
18
|
import { pathToFileURL } from 'node:url';
|
|
20
19
|
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
import {
|
|
21
|
+
brandDir,
|
|
22
|
+
fontsDir,
|
|
23
|
+
interFontFiles,
|
|
24
|
+
parseOptions,
|
|
25
|
+
relativeToCwd,
|
|
26
|
+
resolveProject,
|
|
27
|
+
} from './project.mjs';
|
|
24
28
|
|
|
25
29
|
// Section 12.3. Badge colors exist only in favicons; they are not UI tokens.
|
|
26
30
|
export const RB_APPS = {
|
|
@@ -55,15 +59,6 @@ function readTemplate(name) {
|
|
|
55
59
|
return readFileSync(path.join(brandDir, name), 'utf8');
|
|
56
60
|
}
|
|
57
61
|
|
|
58
|
-
// The variable Inter file the og-image template embeds, from this package's dependency.
|
|
59
|
-
function interFontPath() {
|
|
60
|
-
try {
|
|
61
|
-
return require.resolve('@fontsource-variable/inter/files/inter-latin-wght-normal.woff2');
|
|
62
|
-
} catch {
|
|
63
|
-
throw new Error('Cannot find @fontsource-variable/inter; run npm install first.');
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
62
|
export function run(argv) {
|
|
68
63
|
const options = parseOptions(argv);
|
|
69
64
|
const app = RB_APPS[options.app];
|
|
@@ -77,7 +72,6 @@ export function run(argv) {
|
|
|
77
72
|
? path.resolve(options['out-dir'])
|
|
78
73
|
: resolveProject(options.project).publicDir;
|
|
79
74
|
if (!existsSync(outDir)) throw new Error(`${relativeToCwd(outDir)} does not exist.`);
|
|
80
|
-
let interFont;
|
|
81
75
|
if (options['og-image']) {
|
|
82
76
|
if (!description || !domain) {
|
|
83
77
|
throw new Error('--og-image needs --description and --domain.');
|
|
@@ -87,7 +81,6 @@ export function run(argv) {
|
|
|
87
81
|
`--description has ${description.length} characters; the limit is ${maxDescriptionLength}.`,
|
|
88
82
|
);
|
|
89
83
|
}
|
|
90
|
-
interFont = interFontPath();
|
|
91
84
|
}
|
|
92
85
|
|
|
93
86
|
const faviconPath = path.join(outDir, 'favicon.svg');
|
|
@@ -108,7 +101,8 @@ export function run(argv) {
|
|
|
108
101
|
appName: app.name,
|
|
109
102
|
description,
|
|
110
103
|
domain,
|
|
111
|
-
|
|
104
|
+
// The Latin file covers the template's text.
|
|
105
|
+
interFontUrl: pathToFileURL(path.join(fontsDir, interFontFiles[0])).href,
|
|
112
106
|
}),
|
|
113
107
|
);
|
|
114
108
|
console.log(`Wrote ${relativeToCwd(ogPath)}; export it to public/og-image.png at 1200x630.`);
|
package/cli/project.mjs
CHANGED
|
@@ -11,6 +11,12 @@ import { fileURLToPath } from 'node:url';
|
|
|
11
11
|
export const kitDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
12
12
|
export const kitInventoryPath = path.join(kitDir, 'material-symbols-icons.txt');
|
|
13
13
|
export const brandDir = path.join(kitDir, 'brand');
|
|
14
|
+
// The Inter Variable files the kit's @font-face rules load from /fonts/<name> (section 6.1).
|
|
15
|
+
export const fontsDir = path.join(kitDir, 'fonts');
|
|
16
|
+
export const interFontFiles = [
|
|
17
|
+
'inter-latin-wght-normal.woff2',
|
|
18
|
+
'inter-latin-ext-wght-normal.woff2',
|
|
19
|
+
];
|
|
14
20
|
|
|
15
21
|
// Parses `--name value` pairs. Options listed in `repeatable` collect every value in an array.
|
|
16
22
|
export function parseOptions(argv, { repeatable = [] } = {}) {
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
//
|
|
8
8
|
// - the built index.html references Google Fonts;
|
|
9
9
|
// - the favicon is missing or not referenced;
|
|
10
|
+
// - the built index.html does not preload /fonts/inter-latin-wght-normal.woff2 (as="font",
|
|
11
|
+
// type="font/woff2", crossorigin), the build output does not hold the kit's Inter files at
|
|
12
|
+
// /fonts/ unchanged, or the built stylesheet does not load Inter from there (section 6.1);
|
|
10
13
|
// - the app's public/fonts/ does not hold exactly one Material Symbols subset, the built
|
|
11
14
|
// stylesheet does not reference it, its name's content hash does not match its bytes, or it
|
|
12
15
|
// exceeds 16 KB;
|
|
@@ -22,7 +25,20 @@ import { createHash } from 'node:crypto';
|
|
|
22
25
|
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
23
26
|
import path from 'node:path';
|
|
24
27
|
|
|
25
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
fontsDir,
|
|
30
|
+
interFontFiles,
|
|
31
|
+
parseOptions,
|
|
32
|
+
readIconInventories,
|
|
33
|
+
relativeToCwd,
|
|
34
|
+
resolveProject,
|
|
35
|
+
} from './project.mjs';
|
|
36
|
+
|
|
37
|
+
const interPreloadUrl = `/fonts/${interFontFiles[0]}`;
|
|
38
|
+
const interPreloadTag = `<link rel="preload" href="${interPreloadUrl}" as="font" type="font/woff2" crossorigin />`;
|
|
39
|
+
|
|
40
|
+
const linkTagPattern = /<link\b[^>]*>/giu;
|
|
41
|
+
const attributePattern = /([^\s=/>]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/gu;
|
|
26
42
|
|
|
27
43
|
const fontPattern = /^material-symbols-outlined-.+\.woff2$/u;
|
|
28
44
|
const hashedFontPattern = /\.([0-9a-f]{8})\.woff2$/u;
|
|
@@ -51,6 +67,33 @@ function listFiles(directory, predicate) {
|
|
|
51
67
|
return files;
|
|
52
68
|
}
|
|
53
69
|
|
|
70
|
+
// The attributes of every <link> in an HTML document outside comments, as name → value maps
|
|
71
|
+
// (lowercase names; an attribute without a value maps to '').
|
|
72
|
+
export function linkTags(html) {
|
|
73
|
+
const markup = html.replace(/<!--[\s\S]*?-->/gu, '');
|
|
74
|
+
return [...markup.matchAll(linkTagPattern)].map(([tag]) => {
|
|
75
|
+
const attributes = new Map();
|
|
76
|
+
for (const match of tag.slice('<link'.length).matchAll(attributePattern)) {
|
|
77
|
+
attributes.set(match[1].toLowerCase(), match[2] ?? match[3] ?? match[4] ?? '');
|
|
78
|
+
}
|
|
79
|
+
return attributes;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Whether an HTML document preloads the Latin Inter file so that the kit's @font-face rule reuses
|
|
84
|
+
// the request: same URL, as="font", type="font/woff2" and an anonymous CORS request, which is how
|
|
85
|
+
// browsers fetch fonts.
|
|
86
|
+
export function preloadsInter(html) {
|
|
87
|
+
return linkTags(html).some(
|
|
88
|
+
(link) =>
|
|
89
|
+
link.get('rel')?.toLowerCase().split(/\s+/u).includes('preload') &&
|
|
90
|
+
link.get('href') === interPreloadUrl &&
|
|
91
|
+
link.get('as')?.toLowerCase() === 'font' &&
|
|
92
|
+
link.get('type')?.toLowerCase() === 'font/woff2' &&
|
|
93
|
+
['', 'anonymous'].includes(link.get('crossorigin')?.toLowerCase()),
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
54
97
|
// Icon names used by one template or component source.
|
|
55
98
|
export function iconNamesInSource(source) {
|
|
56
99
|
const names = new Set();
|
|
@@ -97,6 +140,24 @@ export function run(argv) {
|
|
|
97
140
|
if (!existsSync(path.join(browserDir, 'favicon.svg')))
|
|
98
141
|
fail(`Missing favicon asset in ${relativeToCwd(browserDir)}.`);
|
|
99
142
|
|
|
143
|
+
if (!preloadsInter(indexHtml)) {
|
|
144
|
+
fail(
|
|
145
|
+
`Production index does not preload Inter. Add to the app's index.html: ${interPreloadTag}`,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
for (const name of interFontFiles) {
|
|
149
|
+
const interPath = path.join(browserDir, 'fonts', name);
|
|
150
|
+
if (!existsSync(interPath)) {
|
|
151
|
+
fail(
|
|
152
|
+
`Missing ${relativeToCwd(interPath)}. Copy the kit's Inter files with this angular.json ` +
|
|
153
|
+
'assets entry: { "glob": "*.woff2", "input": "node_modules/@rblabs-dev/axiom/fonts", "output": "fonts" }',
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
if (!readFileSync(interPath).equals(readFileSync(path.join(fontsDir, name)))) {
|
|
157
|
+
fail(`${relativeToCwd(interPath)} differs from the kit's copy; serve the package's file.`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
100
161
|
const publicFontsDir = path.join(project.publicDir, 'fonts');
|
|
101
162
|
if (!existsSync(publicFontsDir))
|
|
102
163
|
fail(`Missing ${relativeToCwd(publicFontsDir)}; run axiom build-icon-font.`);
|
|
@@ -124,10 +185,14 @@ export function run(argv) {
|
|
|
124
185
|
|
|
125
186
|
const stylesheets = readdirSync(browserDir).filter((name) => /^styles-[^/]+\.css$/u.test(name));
|
|
126
187
|
if (stylesheets.length === 0) fail('Missing hashed production stylesheet.');
|
|
127
|
-
const
|
|
128
|
-
readFileSync(path.join(browserDir, name), 'utf8')
|
|
188
|
+
const stylesheetSources = stylesheets.map((name) =>
|
|
189
|
+
readFileSync(path.join(browserDir, name), 'utf8'),
|
|
129
190
|
);
|
|
130
|
-
|
|
191
|
+
for (const url of [`/fonts/${fontName}`, interPreloadUrl]) {
|
|
192
|
+
if (!stylesheetSources.some((source) => source.includes(url))) {
|
|
193
|
+
fail(`Production stylesheet does not reference ${url}.`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
131
196
|
|
|
132
197
|
const inventory = new Set(readIconInventories(project).names);
|
|
133
198
|
const scanned = [project.sourceDir, ...options.scan.map((directory) => path.resolve(directory))];
|
|
@@ -140,7 +205,7 @@ export function run(argv) {
|
|
|
140
205
|
}
|
|
141
206
|
|
|
142
207
|
console.log(
|
|
143
|
-
`Production asset verification passed: favicon present,
|
|
144
|
-
|
|
208
|
+
`Production asset verification passed: favicon present, Inter preloaded, ` +
|
|
209
|
+
`${inventory.size} icon names tracked, icon font ${fontName} is ${statSync(fontPath).size} bytes.`,
|
|
145
210
|
);
|
|
146
211
|
}
|