pattern-dump 0.2.0-alpha.0 → 0.4.0
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/CHANGELOG.md +83 -0
- package/README.md +12 -7
- package/dist/chunks/{chunk-ESMZAOP2.js → chunk-DIDJPCLS.js} +177 -18
- package/dist/index.js +1 -1
- package/dist/pd.js +1689 -766
- package/dist/types/config/index.d.ts +21 -6
- package/dist/types/config/own-manifest.d.ts +9 -0
- package/dist/types/config/validate.d.ts +15 -2
- package/dist/types/contracts/dev-protocol.d.ts +1 -1
- package/package.json +1 -1
- package/templates/storefront/.github/workflows/pages.yml +3 -2
- package/templates/storefront/pages/articles/hello.md +10 -0
- package/templates/storefront/pages/articles/index.md +10 -0
- package/templates/storefront/src/patterns/layouts/listing/listing.hbs +16 -0
- package/templates/storefront/src/patterns/layouts/listing/listing.json +13 -0
- package/templates/storefront/src/patterns/layouts/listing/listing.md +7 -0
- package/templates/storefront/src/patterns/layouts/listing/listing.schema.json +18 -0
- package/templates/storefront/src/patterns/layouts/page/page.hbs +1 -0
- package/templates/storefront/src/patterns/layouts/page/page.json +1 -1
- package/templates/storefront/src/patterns/layouts/page/page.md +2 -1
- package/templates/storefront/src/patterns/layouts/page/page.schema.json +3 -1
- package/templates/storefront/src/styles/layouts/listing.scss +15 -0
- package/templates/storefront/src/styles/layouts/page.scss +3 -0
- package/templates/storefront-fills/config.txt +4 -1
- package/templates/storefront-fills/readme.md +11 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,88 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `pd build --browser` also checks a storefront's pages in Chromium, at a desktop and a phone width: colour contrast
|
|
8
|
+
and the other accessibility rules that need a rendered page (a critical or serious finding stops the build), and
|
|
9
|
+
each image's variant against the box it is laid out in (a warning when its slot's `sizes` doesn't match). It uses
|
|
10
|
+
the project's own Playwright: `npm install --save-dev playwright`, then `npx playwright install chromium`.
|
|
11
|
+
- Collections: a folder of storefront pages is a collection. A layout that declares `page.children` lists the
|
|
12
|
+
folder's pages on its `index.md` (route, title, description, date, image, tags), newest first with `sort: date`;
|
|
13
|
+
a page without a description is listed with the first paragraph of its body. `partials/base` can list folders
|
|
14
|
+
under `site.collections` to show their pages on every page, such as a home page's latest articles. Layouts can
|
|
15
|
+
show a page's own `page.date` and `page.tags`.
|
|
16
|
+
- A storefront can be published under a path, such as a GitHub project page: `storefront.url` takes the full
|
|
17
|
+
address (`https://example.github.io/project/`). Every page, stylesheet, script and image is then served under the
|
|
18
|
+
path, in `pd dev` too, with links still written from the site's root; canonical URLs, Open Graph, JSON-LD and the
|
|
19
|
+
sitemap carry it. Every page names its path in `<meta name="pd-base-path">` for a skin's own scripts, and
|
|
20
|
+
`pd build --browser` stops on a request outside the path. Under a path there is no `robots.txt` (the build says what
|
|
21
|
+
the host's own needs) and previews carry a robots `noindex` tag, as a workbench's do when it is built with `--base`.
|
|
22
|
+
- A project that is a pattern package itself (a style guide with its own workbench) describes its folders once: its
|
|
23
|
+
config takes each folder it doesn't name from its `package.json`'s `patternDump` field (patterns, data, helpers,
|
|
24
|
+
assets, styles with `entry` and `documentBase`, themes, scripts, `globalScripts`, `exclude`). A folder named in
|
|
25
|
+
both with different values is a config error naming both files.
|
|
26
|
+
- `storefront.head`: a site's own additions to every page's head (an analytics script, a verification tag), a
|
|
27
|
+
Handlebars file rendered with `site` after the skin's `partials/head` and checked like it. For a site whose skin
|
|
28
|
+
is a shared package.
|
|
29
|
+
- A `HELPER_SHADOW` warning on a component whose template has a bare `{{name}}` that calls a registered helper
|
|
30
|
+
while its data has a field of that name, at any depth: `{{id}}` inside `{{#each palettes}}` showed the `id`
|
|
31
|
+
helper's output instead of each palette's `id`, silently. Read the field as `{{this.id}}`, or rename it.
|
|
32
|
+
- `pd init --storefront` writes an `articles/` collection (a listing page and one dated, tagged article) with a
|
|
33
|
+
`listing` layout, shows a page's date and tags in its page layout, and its config shows a `storefront.url` for a
|
|
34
|
+
subfolder.
|
|
35
|
+
- `date`, `tags` and `draft` in a page's frontmatter. `date` (`YYYY-MM-DD`) is the page's date for listings and its
|
|
36
|
+
JSON-LD `datePublished`, which falls back to the page's first commit. `draft: true` shows a page in `pd dev` and
|
|
37
|
+
leaves it out of `pd build`, which names the drafts it left out.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- A storefront page loads the behaviour scripts its components bring (`requireScript` of its layout's components and
|
|
42
|
+
of the components it places, and `globalScripts`), as their workbench previews do. Before, only the markup and CSS
|
|
43
|
+
reached the page.
|
|
44
|
+
- A code block on a storefront page, or in a component's `<pre>`, keeps its lines as written when its partial is
|
|
45
|
+
included on an indented line (as a skin's `{{> @partial-block }}` usually is). Handlebars indented every line after
|
|
46
|
+
the first by the include's indentation.
|
|
47
|
+
- A schema field named like a registered helper (`id`, `eq`, …) is no longer an error only the workbench's Diagnostics
|
|
48
|
+
tab shows: `pd dev` and `pd build` say it in the terminal, a storefront page that places the component fails (as
|
|
49
|
+
one whose layout has such a field already did), and `pd audit` re-audits a component when its schema changes
|
|
50
|
+
instead of reusing a verdict cached before.
|
|
51
|
+
- An image in a site page's markdown from a pattern package's assets, when that package's folder is the site's only
|
|
52
|
+
asset folder, gets its variants. Before, the page failed with "is not an image in the assets" for a URL that was
|
|
53
|
+
served.
|
|
54
|
+
- `pd dev` no longer keeps base-layer rules that a component's stylesheet stopped writing (through a mixin) until it is
|
|
55
|
+
restarted.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- **Breaking:** `date`, `tags`, `draft` and `sort` are now frontmatter keys of the build, like `layout` and
|
|
60
|
+
`image`. A layout whose schema declares one of them fails every page that uses it; rename the field in the
|
|
61
|
+
layout's schema (and show the page's date or tags through `page.date` and `page.tags`).
|
|
62
|
+
- A storefront page's JSON-LD carries `datePublished`.
|
|
63
|
+
|
|
64
|
+
## 0.3.0
|
|
65
|
+
|
|
66
|
+
From this release Pattern Dump is published as plain 0.x versions under npm's `latest` tag: install it with
|
|
67
|
+
`npx pattern-dump init`, without `@alpha`. Being at 0.x, breaking changes are possible between minor versions, and
|
|
68
|
+
this changelog names them.
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
- `sourceDir`, `patternsDir` and `styles` are optional. A site whose components, skin and styles all come from
|
|
73
|
+
pattern packages names none of them; they default to `./src`, `./src/patterns` and `./src/styles`, and the folders
|
|
74
|
+
don't have to exist.
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
|
|
78
|
+
- `pd build` now checks every page of a storefront with axe before it writes anything, and **stops on an
|
|
79
|
+
accessibility error**: a WCAG rule rated critical or serious (an image without alt text, a button with no name, a
|
|
80
|
+
page without a language), or a page without exactly one `<main>` and one `<h1>`. Each error is printed with its
|
|
81
|
+
page, the rule, the elements it was found on and a link to the rule's explanation; moderate and minor findings,
|
|
82
|
+
and axe's best practices, are listed as warnings and don't stop the build. To see them before a build, run
|
|
83
|
+
`pd build` locally: nothing is written while there are errors. In `pd dev`, a page without one `<main>` and one
|
|
84
|
+
`<h1>` is a warning in the terminal.
|
|
85
|
+
|
|
3
86
|
## 0.2.0-alpha.0
|
|
4
87
|
|
|
5
88
|
The storefront: a website written as markdown pages, dressed by a skin made of ordinary components, served by
|
package/README.md
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
# Pattern Dump
|
|
2
2
|
|
|
3
|
-
A workbench for HTML and CSS design systems, and a successor to
|
|
3
|
+
A workbench for HTML and CSS design systems, and a successor to Pattern Lab. Write components as
|
|
4
4
|
Handlebars templates with SCSS, data and Markdown docs; Pattern Dump shows them live, checks them, maps
|
|
5
5
|
how they relate, and publishes the result as a static site.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
**Demo:** a style guide and the website built from it, at https://lab.n8d.studio/pattern-dump-demo/
|
|
8
|
+
|
|
9
|
+
> **0.4.0.** Pattern Dump is at 0.x, so breaking changes are possible between minor versions (0.3 to 0.4);
|
|
10
|
+
> the [changelog](https://github.com/n8design/pattern-dump/blob/main/CHANGELOG.md) names them.
|
|
11
|
+
|
|
12
|
+
**Coming from Pattern Lab?** Point `patternsDir` at your patterns folder: Handlebars templates, `.json` data and
|
|
13
|
+
`~` variants work as they are, and no build step of your own is needed.
|
|
9
14
|
|
|
10
15
|
## Requirements
|
|
11
16
|
|
|
12
|
-
Node.js
|
|
17
|
+
Node.js 22.22 or later, and npm.
|
|
13
18
|
|
|
14
19
|
## Quick start
|
|
15
20
|
|
|
16
21
|
Create a new project:
|
|
17
22
|
|
|
18
23
|
```bash
|
|
19
|
-
npx pattern-dump
|
|
24
|
+
npx pattern-dump init my-design-system
|
|
20
25
|
cd my-design-system
|
|
21
26
|
npm run dev # → http://localhost:4000
|
|
22
27
|
```
|
|
@@ -24,7 +29,7 @@ npm run dev # → http://localhost:4000
|
|
|
24
29
|
Or add Pattern Dump to an existing project:
|
|
25
30
|
|
|
26
31
|
```bash
|
|
27
|
-
npm install --save-dev pattern-dump
|
|
32
|
+
npm install --save-dev pattern-dump
|
|
28
33
|
npx pd init
|
|
29
34
|
```
|
|
30
35
|
|
|
@@ -35,7 +40,7 @@ overwrites an existing file.
|
|
|
35
40
|
### Installing `pd` globally
|
|
36
41
|
|
|
37
42
|
```bash
|
|
38
|
-
npm install --global pattern-dump
|
|
43
|
+
npm install --global pattern-dump
|
|
39
44
|
pd init my-design-system
|
|
40
45
|
```
|
|
41
46
|
|
|
@@ -54,12 +54,13 @@ var SHAPE = {
|
|
|
54
54
|
lang: "lang",
|
|
55
55
|
index: "boolean",
|
|
56
56
|
image: "asset-path",
|
|
57
|
-
images: IMAGES
|
|
57
|
+
images: IMAGES,
|
|
58
|
+
head: "hbs-file"
|
|
58
59
|
},
|
|
59
60
|
required: ["pagesDir", "outDir"]
|
|
60
61
|
}
|
|
61
62
|
};
|
|
62
|
-
var REQUIRED = ["
|
|
63
|
+
var REQUIRED = ["outDir"];
|
|
63
64
|
var WORKBENCH_PATH = /^\/(?:(?!\.{1,2}(?:\/|$))[a-z0-9._~-]+\/?)+$/i;
|
|
64
65
|
var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
65
66
|
var isStrings = (v) => Array.isArray(v) && v.every((x) => typeof x === "string");
|
|
@@ -90,25 +91,25 @@ function suggest(key, known) {
|
|
|
90
91
|
const sameStart = key.slice(0, 3).toLowerCase() === best.slice(0, 3).toLowerCase();
|
|
91
92
|
return bestD <= 2 || bestD <= 3 && sameStart ? best : void 0;
|
|
92
93
|
}
|
|
93
|
-
function checkObject(value, shape, required,
|
|
94
|
+
function checkObject(value, shape, required, at2, problems) {
|
|
94
95
|
const known = Object.keys(shape);
|
|
95
96
|
const unknown = Object.keys(value).filter((k) => !(k in shape));
|
|
96
97
|
for (const key of required) {
|
|
97
98
|
if (value[key] !== void 0) continue;
|
|
98
99
|
const near = unknown.find((u) => suggest(u, [key]) === key);
|
|
99
|
-
problems.push(near ? `missing required "${
|
|
100
|
+
problems.push(near ? `missing required "${at2}${key}" (found "${at2}${near}" \u2014 did you mean "${at2}${key}"?)` : `missing required "${at2}${key}"`);
|
|
100
101
|
}
|
|
101
102
|
for (const key of unknown) {
|
|
102
103
|
const near = suggest(key, known);
|
|
103
104
|
if (near && required.includes(near) && value[near] === void 0) continue;
|
|
104
|
-
problems.push(`unknown key "${
|
|
105
|
+
problems.push(`unknown key "${at2}${key}"${near ? ` \u2014 did you mean "${at2}${near}"?` : ""}`);
|
|
105
106
|
}
|
|
106
107
|
for (const key of known) {
|
|
107
|
-
if (value[key] !== void 0) checkValue(value[key], shape[key], `${
|
|
108
|
+
if (value[key] !== void 0) checkValue(value[key], shape[key], `${at2}${key}`, problems);
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
|
-
function checkValue(value, rule,
|
|
111
|
-
const fail = (expected) => problems.push(`"${
|
|
111
|
+
function checkValue(value, rule, at2, problems) {
|
|
112
|
+
const fail = (expected) => problems.push(`"${at2}" must be ${expected}`);
|
|
112
113
|
if (rule === "string") {
|
|
113
114
|
if (typeof value !== "string") fail("a string");
|
|
114
115
|
return;
|
|
@@ -154,12 +155,12 @@ function checkValue(value, rule, at, problems) {
|
|
|
154
155
|
if (typeof value === "string") {
|
|
155
156
|
try {
|
|
156
157
|
const url = new URL(value);
|
|
157
|
-
ok = /^https?:$/.test(url.protocol) && url.
|
|
158
|
+
ok = /^https?:$/.test(url.protocol) && url.search === "" && url.hash === "" && !/[?#]/.test(value) && !/\/\/./.test(url.pathname);
|
|
158
159
|
} catch {
|
|
159
160
|
ok = false;
|
|
160
161
|
}
|
|
161
162
|
}
|
|
162
|
-
if (!ok) fail(`the site's absolute http(s) address, with no
|
|
163
|
+
if (!ok) fail(`the site's absolute http(s) address, with no query or fragment, such as "https://example.com/", or "https://example.github.io/project/" for a site published under a path`);
|
|
163
164
|
return;
|
|
164
165
|
}
|
|
165
166
|
if (rule === "lang") {
|
|
@@ -168,6 +169,12 @@ function checkValue(value, rule, at, problems) {
|
|
|
168
169
|
}
|
|
169
170
|
return;
|
|
170
171
|
}
|
|
172
|
+
if (rule === "hbs-file") {
|
|
173
|
+
if (typeof value !== "string" || !/\.hbs$/.test(value) || /^(?:\/|[a-zA-Z]:)/.test(value)) {
|
|
174
|
+
fail(`a Handlebars file relative to the project's root, such as "./head.hbs"`);
|
|
175
|
+
}
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
171
178
|
if (rule === "asset-path") {
|
|
172
179
|
if (typeof value !== "string" || !/^\/assets\/[^?#]+[^/?#]$/.test(value)) {
|
|
173
180
|
fail(`a path to a file in the assets, such as "/assets/images/share.png"`);
|
|
@@ -194,7 +201,7 @@ function checkValue(value, rule, at, problems) {
|
|
|
194
201
|
}
|
|
195
202
|
if ("values" in rule) {
|
|
196
203
|
if (typeof value === "string" && rule.unsupported?.includes(value)) {
|
|
197
|
-
problems.push(`"${
|
|
204
|
+
problems.push(`"${at2}": "${value}" is not supported yet \u2014 use ${rule.values.map((v) => `"${v}"`).join(" or ")}, or leave it out`);
|
|
198
205
|
} else if (typeof value !== "string" || !rule.values.includes(value)) {
|
|
199
206
|
fail(rule.values.map((v) => `"${v}"`).join(" or "));
|
|
200
207
|
}
|
|
@@ -204,7 +211,7 @@ function checkValue(value, rule, at, problems) {
|
|
|
204
211
|
fail("an object");
|
|
205
212
|
return;
|
|
206
213
|
}
|
|
207
|
-
checkObject(value, rule.keys, rule.required ?? [], `${
|
|
214
|
+
checkObject(value, rule.keys, rule.required ?? [], `${at2}.`, problems);
|
|
208
215
|
}
|
|
209
216
|
var ConfigError = class extends Error {
|
|
210
217
|
name = "ConfigError";
|
|
@@ -218,8 +225,8 @@ function checkRelations(raw, problems) {
|
|
|
218
225
|
["storefront.outDir", sf.outDir]
|
|
219
226
|
];
|
|
220
227
|
const root = resolve(sep, "pd-root");
|
|
221
|
-
const inside = (
|
|
222
|
-
const rel = relative(parent,
|
|
228
|
+
const inside = (child2, parent) => {
|
|
229
|
+
const rel = relative(parent, child2);
|
|
223
230
|
return rel !== "" && !rel.startsWith("..") && !rel.startsWith(sep) && !/^[a-zA-Z]:/.test(rel);
|
|
224
231
|
};
|
|
225
232
|
for (let i = 0; i < folders.length; i++) {
|
|
@@ -242,17 +249,28 @@ function configProblems(raw) {
|
|
|
242
249
|
return problems;
|
|
243
250
|
}
|
|
244
251
|
var withOneTrailingSlash = (url) => `${url.replace(/\/+$/, "")}/`;
|
|
252
|
+
function withSourceDefaults(config) {
|
|
253
|
+
if (config.sourceDir !== void 0 && config.patternsDir !== void 0 && config.styles !== void 0) return config;
|
|
254
|
+
const sourceDir = config.sourceDir ?? "./src";
|
|
255
|
+
const base = sourceDir.replace(/\/+$/, "");
|
|
256
|
+
return {
|
|
257
|
+
...config,
|
|
258
|
+
sourceDir,
|
|
259
|
+
patternsDir: config.patternsDir ?? `${base}/patterns`,
|
|
260
|
+
styles: config.styles ?? { strategy: "parallel", dir: `${base}/styles` }
|
|
261
|
+
};
|
|
262
|
+
}
|
|
245
263
|
function validateConfig(raw, source) {
|
|
246
264
|
const problems = configProblems(raw);
|
|
247
265
|
if (problems.length > 0) {
|
|
248
266
|
throw new ConfigError(`${source}: invalid config
|
|
249
267
|
${problems.map((p) => ` - ${p}`).join("\n")}`);
|
|
250
268
|
}
|
|
251
|
-
const config = raw;
|
|
269
|
+
const config = withSourceDefaults(raw);
|
|
252
270
|
const sf = config.storefront;
|
|
253
271
|
if (!sf) return config;
|
|
254
272
|
const workbenchUrl = sf.workbenchUrl !== void 0 ? withOneTrailingSlash(sf.workbenchUrl) : void 0;
|
|
255
|
-
const url = sf.url !== void 0 ?
|
|
273
|
+
const url = sf.url !== void 0 ? siteUrlForm(sf.url) : void 0;
|
|
256
274
|
if (workbenchUrl === sf.workbenchUrl && url === sf.url) return config;
|
|
257
275
|
return { ...config, storefront: {
|
|
258
276
|
...sf,
|
|
@@ -260,24 +278,165 @@ ${problems.map((p) => ` - ${p}`).join("\n")}`);
|
|
|
260
278
|
...url !== void 0 ? { url } : {}
|
|
261
279
|
} };
|
|
262
280
|
}
|
|
281
|
+
function siteUrlForm(value) {
|
|
282
|
+
const u = new URL(value);
|
|
283
|
+
return `${u.origin}${withOneTrailingSlash(u.pathname)}`;
|
|
284
|
+
}
|
|
285
|
+
function storefrontBasePath(storefront) {
|
|
286
|
+
return storefront?.url === void 0 ? "/" : new URL(storefront.url).pathname;
|
|
287
|
+
}
|
|
263
288
|
function sameHostWorkbenchPath(storefront) {
|
|
264
289
|
const w = storefront?.workbenchUrl;
|
|
265
290
|
if (w === void 0) return void 0;
|
|
266
291
|
if (w.startsWith("/")) return w;
|
|
267
292
|
if (storefront?.url === void 0) return void 0;
|
|
268
293
|
const u = new URL(w);
|
|
269
|
-
return
|
|
294
|
+
return u.origin === new URL(storefront.url).origin ? u.pathname : void 0;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// packages/config/src/own-manifest.ts
|
|
298
|
+
var isObject2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
299
|
+
var child = (o, key) => {
|
|
300
|
+
if (!isObject2(o[key])) o[key] = {};
|
|
301
|
+
return o[key];
|
|
302
|
+
};
|
|
303
|
+
var at = (o, ...keys) => keys.reduce((v, k) => isObject2(v) ? v[k] : void 0, o);
|
|
304
|
+
var top = (from, to, paths = true) => ({
|
|
305
|
+
from,
|
|
306
|
+
get: (m) => m[from],
|
|
307
|
+
to,
|
|
308
|
+
read: (c) => c[to],
|
|
309
|
+
write: (c, v) => {
|
|
310
|
+
c[to] = v;
|
|
311
|
+
},
|
|
312
|
+
paths
|
|
313
|
+
});
|
|
314
|
+
var FIELDS = [
|
|
315
|
+
top("patterns", "patternsDir"),
|
|
316
|
+
top("data", "dataDir"),
|
|
317
|
+
top("helpers", "helpers"),
|
|
318
|
+
top("scripts", "scriptsDir"),
|
|
319
|
+
top("globalScripts", "globalScripts", false),
|
|
320
|
+
top("exclude", "exclude", false),
|
|
321
|
+
{
|
|
322
|
+
from: "assets",
|
|
323
|
+
get: (m) => m["assets"],
|
|
324
|
+
to: "assets.dir",
|
|
325
|
+
read: (c) => at(c, "assets", "dir"),
|
|
326
|
+
write: (c, v) => {
|
|
327
|
+
child(c, "assets")["dir"] = v;
|
|
328
|
+
},
|
|
329
|
+
paths: true
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
from: "styles.dir",
|
|
333
|
+
get: (m) => at(m, "styles", "dir"),
|
|
334
|
+
to: "styles.dir",
|
|
335
|
+
read: (c) => at(c, "styles", "dir"),
|
|
336
|
+
write: (c, v) => {
|
|
337
|
+
child(c, "styles")["dir"] = v;
|
|
338
|
+
},
|
|
339
|
+
paths: true
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
from: "styles.entry",
|
|
343
|
+
get: (m) => at(m, "styles", "entry"),
|
|
344
|
+
to: "styles.entry",
|
|
345
|
+
read: (c) => at(c, "styles", "entry"),
|
|
346
|
+
write: (c, v) => {
|
|
347
|
+
child(c, "styles")["entry"] = v;
|
|
348
|
+
},
|
|
349
|
+
paths: true
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
from: "styles.documentBase",
|
|
353
|
+
get: (m) => at(m, "styles", "documentBase"),
|
|
354
|
+
to: "documentBase",
|
|
355
|
+
read: (c) => c["documentBase"],
|
|
356
|
+
write: (c, v) => {
|
|
357
|
+
c["documentBase"] = v;
|
|
358
|
+
},
|
|
359
|
+
paths: true
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
from: "themes.dir",
|
|
363
|
+
get: (m) => at(m, "themes", "dir"),
|
|
364
|
+
to: "themes.dir",
|
|
365
|
+
read: (c) => at(c, "themes", "dir"),
|
|
366
|
+
write: (c, v) => {
|
|
367
|
+
child(c, "themes")["dir"] = v;
|
|
368
|
+
},
|
|
369
|
+
paths: true
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
from: "themes.default",
|
|
373
|
+
get: (m) => at(m, "themes", "default"),
|
|
374
|
+
to: "themes.default",
|
|
375
|
+
read: (c) => at(c, "themes", "default"),
|
|
376
|
+
write: (c, v) => {
|
|
377
|
+
child(c, "themes")["default"] = v;
|
|
378
|
+
},
|
|
379
|
+
paths: false
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
from: "themes.switch",
|
|
383
|
+
get: (m) => at(m, "themes", "switch"),
|
|
384
|
+
to: "themes.switch",
|
|
385
|
+
read: (c) => at(c, "themes", "switch"),
|
|
386
|
+
write: (c, v) => {
|
|
387
|
+
child(c, "themes")["switch"] = v;
|
|
388
|
+
},
|
|
389
|
+
paths: false
|
|
390
|
+
}
|
|
391
|
+
];
|
|
392
|
+
function samePath(p) {
|
|
393
|
+
const parts = [];
|
|
394
|
+
for (const seg of p.replace(/\\/g, "/").split("/")) {
|
|
395
|
+
if (seg === "" || seg === ".") continue;
|
|
396
|
+
if (seg === ".." && parts.length && parts[parts.length - 1] !== "..") parts.pop();
|
|
397
|
+
else parts.push(seg);
|
|
398
|
+
}
|
|
399
|
+
return parts.join("/") || ".";
|
|
400
|
+
}
|
|
401
|
+
function comparable(v, paths) {
|
|
402
|
+
const list = Array.isArray(v) ? v : [v];
|
|
403
|
+
return JSON.stringify(paths ? list.map((x) => typeof x === "string" ? samePath(x) : x) : Array.isArray(v) ? v : [v]);
|
|
404
|
+
}
|
|
405
|
+
var shown = (v) => JSON.stringify(v);
|
|
406
|
+
function withOwnManifest(raw, manifest, where) {
|
|
407
|
+
if (!isObject2(raw) || !isObject2(manifest)) return raw;
|
|
408
|
+
const config = structuredClone(raw);
|
|
409
|
+
const conflicts = [];
|
|
410
|
+
for (const f of FIELDS) {
|
|
411
|
+
const value = f.get(manifest);
|
|
412
|
+
if (value === void 0) continue;
|
|
413
|
+
const own = f.read(config);
|
|
414
|
+
if (own === void 0) {
|
|
415
|
+
f.write(config, structuredClone(value));
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (comparable(own, f.paths) !== comparable(value, f.paths)) {
|
|
419
|
+
conflicts.push(`"${f.to}" is ${shown(own)} in ${where.config}, but "patternDump.${f.from}" is ${shown(value)} in ${where.manifest}: name it in one of them, or give both the same value`);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (conflicts.length) {
|
|
423
|
+
throw new ConfigError(`${where.config}: the config and the project's own package manifest disagree
|
|
424
|
+
${conflicts.map((c) => ` - ${c}`).join("\n")}`);
|
|
425
|
+
}
|
|
426
|
+
return config;
|
|
270
427
|
}
|
|
271
428
|
|
|
272
429
|
// packages/config/src/index.ts
|
|
273
430
|
function defineConfig(config) {
|
|
274
|
-
return config;
|
|
431
|
+
return withSourceDefaults(config);
|
|
275
432
|
}
|
|
276
433
|
|
|
277
434
|
export {
|
|
278
435
|
suggest,
|
|
279
436
|
ConfigError,
|
|
280
437
|
validateConfig,
|
|
438
|
+
storefrontBasePath,
|
|
281
439
|
sameHostWorkbenchPath,
|
|
440
|
+
withOwnManifest,
|
|
282
441
|
defineConfig
|
|
283
442
|
};
|