pattern-dump 0.1.0-alpha.2 → 0.1.0-alpha.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/CHANGELOG.md +18 -0
- package/README.md +1 -1
- package/dist/pd.js +154 -124
- package/dist/types/contracts/dev-protocol.d.ts +2 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0-alpha.3
|
|
4
|
+
|
|
5
|
+
Fixes found while moving a second PatternLab styleguide (n8d) to Pattern Dump.
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- A numbered `templates` or `pages` folder now gets the `full` preview layout its category promises.
|
|
10
|
+
The category was matched with its ordering prefix still attached, so a PatternLab tree
|
|
11
|
+
(`04-templates`, `05-pages`) could never hit the documented default — only a per-folder
|
|
12
|
+
`preview: full` could. Folder *labels* still keep the number: `2-col` is a name and `04-templates`
|
|
13
|
+
a prefix, and nothing in the string tells them apart, so a numbered folder sets `title:` for a
|
|
14
|
+
clean label.
|
|
15
|
+
- A `requireScript` or `globalScripts` id with no matching `<scriptsDir>/<id>.ts` is reported instead
|
|
16
|
+
of failing inside the preview. `pd dev` names every unresolvable id at startup — with the component
|
|
17
|
+
for a `requireScript` — and the script's URL answers 404 saying which file it expected and where,
|
|
18
|
+
rather than embedding a raw `ENOENT`. Scripts are TypeScript, so a `.js` file of the same name does
|
|
19
|
+
not satisfy an id; that is the common case this hid.
|
|
20
|
+
|
|
3
21
|
## 0.1.0-alpha.2
|
|
4
22
|
|
|
5
23
|
Fixes found while moving a PatternLab styleguide to Pattern Dump, and the changes they needed.
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ A workbench for HTML and CSS design systems, and a successor to PatternLab. Writ
|
|
|
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
|
-
> **Alpha (0.1.0-alpha.
|
|
7
|
+
> **Alpha (0.1.0-alpha.3).** Published under the `alpha` tag. Options and file conventions can still change
|
|
8
8
|
> between releases.
|
|
9
9
|
|
|
10
10
|
## Requirements
|
package/dist/pd.js
CHANGED
|
@@ -30,10 +30,12 @@ function collapseComponentId(relNoExt) {
|
|
|
30
30
|
const parent = dirname(relNoExt);
|
|
31
31
|
return stem === basename(parent) ? parent : relNoExt;
|
|
32
32
|
}
|
|
33
|
+
function stripOrderPrefixes(path) {
|
|
34
|
+
return path.split("/").map((seg) => seg.replace(/^\d+[-_]/, "")).join("/");
|
|
35
|
+
}
|
|
33
36
|
function deriveHandle(id) {
|
|
34
|
-
const parts = id.split("/");
|
|
35
|
-
|
|
36
|
-
return `${unnumbered(parts[0])}-${unnumbered(parts[parts.length - 1])}`;
|
|
37
|
+
const parts = stripOrderPrefixes(id).split("/");
|
|
38
|
+
return `${parts[0]}-${parts[parts.length - 1]}`;
|
|
37
39
|
}
|
|
38
40
|
async function buildDiscoveryMap(roots) {
|
|
39
41
|
const rootList = typeof roots === "string" ? [{ dir: roots }] : roots;
|
|
@@ -1453,7 +1455,6 @@ function joinCssChunks(chunks) {
|
|
|
1453
1455
|
}
|
|
1454
1456
|
return [...charset.slice(0, 1), ...imports, ...rest].join("\n");
|
|
1455
1457
|
}
|
|
1456
|
-
var stripOrderPrefixes = (path) => path.split("/").map((seg) => seg.replace(/^\d+[-_]/, "")).join("/");
|
|
1457
1458
|
var strippedIdCache = /* @__PURE__ */ new WeakMap();
|
|
1458
1459
|
function strippedIds(componentIds) {
|
|
1459
1460
|
let map = strippedIdCache.get(componentIds);
|
|
@@ -2358,6 +2359,99 @@ async function buildStaticSite(config, root, opts) {
|
|
|
2358
2359
|
return report;
|
|
2359
2360
|
}
|
|
2360
2361
|
|
|
2362
|
+
// packages/dev-server/src/requires.ts
|
|
2363
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
2364
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
2365
|
+
import { basename as basename3, join as join12, relative as relative5 } from "node:path";
|
|
2366
|
+
function normalizeScriptId(raw) {
|
|
2367
|
+
let s = raw.trim().replace(/^\[(.+)\]$/, "$1").trim();
|
|
2368
|
+
s = basename3(s);
|
|
2369
|
+
s = s.replace(/\.(ts|js)$/, "");
|
|
2370
|
+
return s;
|
|
2371
|
+
}
|
|
2372
|
+
function parseFrontmatterList(md, key) {
|
|
2373
|
+
const values = [];
|
|
2374
|
+
const re = new RegExp(`^${key}:\\s*(.+)$`, "mg");
|
|
2375
|
+
for (const [, val] of md.matchAll(re)) {
|
|
2376
|
+
values.push(val.trim());
|
|
2377
|
+
}
|
|
2378
|
+
return values;
|
|
2379
|
+
}
|
|
2380
|
+
async function aggregateRequires(componentId, patternsDir, flatNameToPath, discoveryMap, visited = /* @__PURE__ */ new Set()) {
|
|
2381
|
+
if (visited.has(componentId)) return { scripts: [], assets: [] };
|
|
2382
|
+
visited.add(componentId);
|
|
2383
|
+
const entry = discoveryMap.get(componentId);
|
|
2384
|
+
let ownScripts = [];
|
|
2385
|
+
let ownAssets = [];
|
|
2386
|
+
if (entry?.mdPath) {
|
|
2387
|
+
try {
|
|
2388
|
+
const md = await readFile8(entry.mdPath, "utf-8");
|
|
2389
|
+
ownScripts = parseFrontmatterList(md, "requireScript").map(normalizeScriptId);
|
|
2390
|
+
ownAssets = parseFrontmatterList(md, "requireAssets").map((v) => v.trim().replace(/^\[(.+)\]$/, "$1").trim());
|
|
2391
|
+
} catch {
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
const allScripts = [...ownScripts];
|
|
2395
|
+
const allAssets = [...ownAssets];
|
|
2396
|
+
const hbsPath = entry?.hbsPath ?? "";
|
|
2397
|
+
let hbs = "";
|
|
2398
|
+
try {
|
|
2399
|
+
hbs = hbsPath ? await readFile8(hbsPath, "utf-8") : "";
|
|
2400
|
+
} catch {
|
|
2401
|
+
}
|
|
2402
|
+
for (const flatName of parsePartialsFromHbs(hbs)) {
|
|
2403
|
+
const childPath = flatNameToPath.get(flatName);
|
|
2404
|
+
if (childPath) {
|
|
2405
|
+
const child = await aggregateRequires(childPath, patternsDir, flatNameToPath, discoveryMap, visited);
|
|
2406
|
+
allScripts.push(...child.scripts);
|
|
2407
|
+
allAssets.push(...child.assets);
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
return {
|
|
2411
|
+
scripts: [...new Set(allScripts)],
|
|
2412
|
+
assets: [...new Set(allAssets)]
|
|
2413
|
+
};
|
|
2414
|
+
}
|
|
2415
|
+
async function loadSvgAssets(ids, assetsDir) {
|
|
2416
|
+
const contents = [];
|
|
2417
|
+
for (const id of ids) {
|
|
2418
|
+
for (const candidate of [`${id}.svg`, `images/${id}.svg`]) {
|
|
2419
|
+
try {
|
|
2420
|
+
const raw = await readFile8(join12(assetsDir, candidate), "utf-8");
|
|
2421
|
+
contents.push(hideSvg(raw));
|
|
2422
|
+
break;
|
|
2423
|
+
} catch {
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
return contents;
|
|
2428
|
+
}
|
|
2429
|
+
function hideSvg(svg) {
|
|
2430
|
+
return svg.replace(/<svg(\s|>)/, '<svg$1style="display:none;position:absolute" aria-hidden="true" ');
|
|
2431
|
+
}
|
|
2432
|
+
async function reportUnresolvableScripts(discoveryMap, scriptsDirs, globalScripts, cwd) {
|
|
2433
|
+
const resolves = (id) => scriptsDirs.some((d) => existsSync3(join12(d, `${id}.ts`)));
|
|
2434
|
+
const where = scriptsDirs.length ? scriptsDirs.map((d) => relative5(cwd, d) || d).join(" or ") : "no scriptsDir configured";
|
|
2435
|
+
for (const id of globalScripts) {
|
|
2436
|
+
if (id.includes("://") || resolves(normalizeScriptId(id))) continue;
|
|
2437
|
+
console.warn(`[dev-server] globalScripts "${id}": no ${normalizeScriptId(id)}.ts in ${where}`);
|
|
2438
|
+
}
|
|
2439
|
+
for (const [componentId, entry] of discoveryMap) {
|
|
2440
|
+
if (!entry.mdPath) continue;
|
|
2441
|
+
let md;
|
|
2442
|
+
try {
|
|
2443
|
+
md = await readFile8(entry.mdPath, "utf-8");
|
|
2444
|
+
} catch {
|
|
2445
|
+
continue;
|
|
2446
|
+
}
|
|
2447
|
+
for (const raw of parseFrontmatterList(md, "requireScript")) {
|
|
2448
|
+
const id = normalizeScriptId(raw);
|
|
2449
|
+
if (resolves(id)) continue;
|
|
2450
|
+
console.warn(`[dev-server] requireScript "${raw}" on ${componentId}: no ${id}.ts in ${where}`);
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2361
2455
|
// packages/dev-server/src/server-state.ts
|
|
2362
2456
|
function createServerState() {
|
|
2363
2457
|
return {
|
|
@@ -2399,25 +2493,25 @@ function applyStyleData(state, data) {
|
|
|
2399
2493
|
}
|
|
2400
2494
|
|
|
2401
2495
|
// packages/dev-server/src/routes.ts
|
|
2402
|
-
import { basename as basename4, extname as extname2, join as join18 } from "node:path";
|
|
2496
|
+
import { basename as basename4, extname as extname2, join as join18, relative as relative6 } from "node:path";
|
|
2403
2497
|
import { readFile as readFile15, stat as stat4 } from "node:fs/promises";
|
|
2404
|
-
import { existsSync as
|
|
2498
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
2405
2499
|
|
|
2406
2500
|
// packages/dev-server/src/component-tree.ts
|
|
2501
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
2502
|
+
import { join as join15 } from "node:path";
|
|
2503
|
+
|
|
2504
|
+
// packages/dev-server/src/layout-mode.ts
|
|
2407
2505
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
2408
2506
|
import { join as join14 } from "node:path";
|
|
2409
2507
|
|
|
2410
|
-
// packages/dev-server/src/
|
|
2508
|
+
// packages/dev-server/src/pattern-dirs.ts
|
|
2411
2509
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
2412
2510
|
import { join as join13 } from "node:path";
|
|
2413
|
-
|
|
2414
|
-
// packages/dev-server/src/pattern-dirs.ts
|
|
2415
|
-
import { readFile as readFile8 } from "node:fs/promises";
|
|
2416
|
-
import { join as join12 } from "node:path";
|
|
2417
2511
|
async function readFolderFile(dirs, rel) {
|
|
2418
2512
|
for (const dir of typeof dirs === "string" ? [dirs] : dirs) {
|
|
2419
2513
|
try {
|
|
2420
|
-
return await
|
|
2514
|
+
return await readFile9(join13(dir, rel), "utf-8");
|
|
2421
2515
|
} catch {
|
|
2422
2516
|
}
|
|
2423
2517
|
}
|
|
@@ -2429,8 +2523,8 @@ var FULL_CATEGORIES = /* @__PURE__ */ new Set(["pages", "templates"]);
|
|
|
2429
2523
|
async function resolveLayoutMode(componentId, patternsDir, discoveryMap) {
|
|
2430
2524
|
const parts = componentId.split("/");
|
|
2431
2525
|
const category = parts[0];
|
|
2432
|
-
let layout = FULL_CATEGORIES.has(category) ? "full" : "centered";
|
|
2433
|
-
const categoryIndex = await readFolderFile(patternsDir,
|
|
2526
|
+
let layout = FULL_CATEGORIES.has(stripOrderPrefixes(category)) ? "full" : "centered";
|
|
2527
|
+
const categoryIndex = await readFolderFile(patternsDir, join14(category, "index.md"));
|
|
2434
2528
|
if (categoryIndex !== null) {
|
|
2435
2529
|
const m = categoryIndex.match(/^preview:\s*(centered|full)$/m);
|
|
2436
2530
|
if (m) layout = m[1];
|
|
@@ -2438,7 +2532,7 @@ async function resolveLayoutMode(componentId, patternsDir, discoveryMap) {
|
|
|
2438
2532
|
const mdPath = discoveryMap?.get(componentId)?.mdPath;
|
|
2439
2533
|
if (mdPath) {
|
|
2440
2534
|
try {
|
|
2441
|
-
const md = await
|
|
2535
|
+
const md = await readFile10(mdPath, "utf-8");
|
|
2442
2536
|
const m = md.match(/^preview:\s*(centered|full)$/m);
|
|
2443
2537
|
if (m) layout = m[1];
|
|
2444
2538
|
} catch {
|
|
@@ -2531,7 +2625,7 @@ function folderTitle(segment) {
|
|
|
2531
2625
|
const text = words.join(" ");
|
|
2532
2626
|
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
2533
2627
|
}
|
|
2534
|
-
var readText = (path) =>
|
|
2628
|
+
var readText = (path) => readFile11(path, "utf-8").catch(() => null);
|
|
2535
2629
|
function orderOf(md) {
|
|
2536
2630
|
return md === null ? void 0 : parseOrder(readFrontmatter(md)["order"]);
|
|
2537
2631
|
}
|
|
@@ -2582,7 +2676,7 @@ async function buildTreeNodeFromMap(nodePath, idsUnderPath, patternsDir, overvie
|
|
|
2582
2676
|
if (o && "weight" in o) weight = o.weight;
|
|
2583
2677
|
}
|
|
2584
2678
|
}
|
|
2585
|
-
const indexMd = await readFolderFile(patternsDir,
|
|
2679
|
+
const indexMd = await readFolderFile(patternsDir, join15(nodePath, "index.md"));
|
|
2586
2680
|
const folderOrder = orderOf(indexMd);
|
|
2587
2681
|
const built = [];
|
|
2588
2682
|
for (const childPath of directChildPaths(nodePath, idsUnderPath)) {
|
|
@@ -2630,7 +2724,7 @@ async function buildTreeNodeFromMap(nodePath, idsUnderPath, patternsDir, overvie
|
|
|
2630
2724
|
import { readFile as readFile14 } from "node:fs/promises";
|
|
2631
2725
|
|
|
2632
2726
|
// packages/dev-server/src/markdown.ts
|
|
2633
|
-
import { readFile as
|
|
2727
|
+
import { readFile as readFile12 } from "node:fs/promises";
|
|
2634
2728
|
import MarkdownIt from "markdown-it";
|
|
2635
2729
|
var _md = new MarkdownIt({ html: false, linkify: false });
|
|
2636
2730
|
_md.validateLink = (url) => {
|
|
@@ -2719,7 +2813,7 @@ async function _resolveFence(info, content, idx, renderComponent, out, discovery
|
|
|
2719
2813
|
return;
|
|
2720
2814
|
}
|
|
2721
2815
|
try {
|
|
2722
|
-
const src = await
|
|
2816
|
+
const src = await readFile12(entry.hbsPath, "utf-8");
|
|
2723
2817
|
out.set(idx, wrapWithCopyButton(highlight(src, "handlebars"), src));
|
|
2724
2818
|
} catch (e) {
|
|
2725
2819
|
console.warn(`[dev-server] src-template read error [${spec}]:`, e);
|
|
@@ -2744,8 +2838,8 @@ async function _resolveFence(info, content, idx, renderComponent, out, discovery
|
|
|
2744
2838
|
}
|
|
2745
2839
|
const baseJsonPath = discoveryMap.get(compId)?.jsonPath;
|
|
2746
2840
|
const variantJsonPath = variantEntry.jsonPath;
|
|
2747
|
-
const baseData = baseJsonPath ? JSON.parse(await
|
|
2748
|
-
const variantData = variantJsonPath ? JSON.parse(await
|
|
2841
|
+
const baseData = baseJsonPath ? JSON.parse(await readFile12(baseJsonPath, "utf-8")) : {};
|
|
2842
|
+
const variantData = variantJsonPath ? JSON.parse(await readFile12(variantJsonPath, "utf-8")) : {};
|
|
2749
2843
|
const merged = deepMerge(structuredClone(baseData), variantData);
|
|
2750
2844
|
const src = JSON.stringify(merged, null, 2);
|
|
2751
2845
|
out.set(idx, wrapWithCopyButton(highlight(src, "json"), src));
|
|
@@ -2755,7 +2849,7 @@ async function _resolveFence(info, content, idx, renderComponent, out, discovery
|
|
|
2755
2849
|
out.set(idx, `<p class="doc-error">[src-data: ${escapeHtml(spec)} \u2014 no data file]</p>`);
|
|
2756
2850
|
return;
|
|
2757
2851
|
}
|
|
2758
|
-
const src = await
|
|
2852
|
+
const src = await readFile12(jsonPath, "utf-8");
|
|
2759
2853
|
out.set(idx, wrapWithCopyButton(highlight(src, "json"), src));
|
|
2760
2854
|
}
|
|
2761
2855
|
} catch (e) {
|
|
@@ -2785,7 +2879,7 @@ async function _resolveFence(info, content, idx, renderComponent, out, discovery
|
|
|
2785
2879
|
}
|
|
2786
2880
|
|
|
2787
2881
|
// packages/dev-server/src/css-closure.ts
|
|
2788
|
-
import { readFile as
|
|
2882
|
+
import { readFile as readFile13 } from "node:fs/promises";
|
|
2789
2883
|
import { dirname as dirname5, resolve as resolve7 } from "node:path";
|
|
2790
2884
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
2791
2885
|
import postcss4 from "postcss";
|
|
@@ -2825,7 +2919,7 @@ async function computeCssClosure(componentId, compReg, patternsDir, classOwnerIn
|
|
|
2825
2919
|
const hbsPath = discoveryMap.get(id)?.hbsPath ?? "";
|
|
2826
2920
|
let hbs = "";
|
|
2827
2921
|
try {
|
|
2828
|
-
hbs = hbsPath ? await
|
|
2922
|
+
hbs = hbsPath ? await readFile13(hbsPath, "utf-8") : "";
|
|
2829
2923
|
} catch {
|
|
2830
2924
|
}
|
|
2831
2925
|
const { styleUses } = deriveClassBorrowingFields(hbs, id, classOwnerIndex);
|
|
@@ -2881,76 +2975,6 @@ function linkableClosure(closureIds, perComponentCss) {
|
|
|
2881
2975
|
return closureIds.filter((id) => !!perComponentCss.get(id));
|
|
2882
2976
|
}
|
|
2883
2977
|
|
|
2884
|
-
// packages/dev-server/src/requires.ts
|
|
2885
|
-
import { readFile as readFile13 } from "node:fs/promises";
|
|
2886
|
-
import { join as join15, basename as basename3 } from "node:path";
|
|
2887
|
-
function normalizeScriptId(raw) {
|
|
2888
|
-
let s = raw.trim().replace(/^\[(.+)\]$/, "$1").trim();
|
|
2889
|
-
s = basename3(s);
|
|
2890
|
-
s = s.replace(/\.(ts|js)$/, "");
|
|
2891
|
-
return s;
|
|
2892
|
-
}
|
|
2893
|
-
function parseFrontmatterList(md, key) {
|
|
2894
|
-
const values = [];
|
|
2895
|
-
const re = new RegExp(`^${key}:\\s*(.+)$`, "mg");
|
|
2896
|
-
for (const [, val] of md.matchAll(re)) {
|
|
2897
|
-
values.push(val.trim());
|
|
2898
|
-
}
|
|
2899
|
-
return values;
|
|
2900
|
-
}
|
|
2901
|
-
async function aggregateRequires(componentId, patternsDir, flatNameToPath, discoveryMap, visited = /* @__PURE__ */ new Set()) {
|
|
2902
|
-
if (visited.has(componentId)) return { scripts: [], assets: [] };
|
|
2903
|
-
visited.add(componentId);
|
|
2904
|
-
const entry = discoveryMap.get(componentId);
|
|
2905
|
-
let ownScripts = [];
|
|
2906
|
-
let ownAssets = [];
|
|
2907
|
-
if (entry?.mdPath) {
|
|
2908
|
-
try {
|
|
2909
|
-
const md = await readFile13(entry.mdPath, "utf-8");
|
|
2910
|
-
ownScripts = parseFrontmatterList(md, "requireScript").map(normalizeScriptId);
|
|
2911
|
-
ownAssets = parseFrontmatterList(md, "requireAssets").map((v) => v.trim().replace(/^\[(.+)\]$/, "$1").trim());
|
|
2912
|
-
} catch {
|
|
2913
|
-
}
|
|
2914
|
-
}
|
|
2915
|
-
const allScripts = [...ownScripts];
|
|
2916
|
-
const allAssets = [...ownAssets];
|
|
2917
|
-
const hbsPath = entry?.hbsPath ?? "";
|
|
2918
|
-
let hbs = "";
|
|
2919
|
-
try {
|
|
2920
|
-
hbs = hbsPath ? await readFile13(hbsPath, "utf-8") : "";
|
|
2921
|
-
} catch {
|
|
2922
|
-
}
|
|
2923
|
-
for (const flatName of parsePartialsFromHbs(hbs)) {
|
|
2924
|
-
const childPath = flatNameToPath.get(flatName);
|
|
2925
|
-
if (childPath) {
|
|
2926
|
-
const child = await aggregateRequires(childPath, patternsDir, flatNameToPath, discoveryMap, visited);
|
|
2927
|
-
allScripts.push(...child.scripts);
|
|
2928
|
-
allAssets.push(...child.assets);
|
|
2929
|
-
}
|
|
2930
|
-
}
|
|
2931
|
-
return {
|
|
2932
|
-
scripts: [...new Set(allScripts)],
|
|
2933
|
-
assets: [...new Set(allAssets)]
|
|
2934
|
-
};
|
|
2935
|
-
}
|
|
2936
|
-
async function loadSvgAssets(ids, assetsDir) {
|
|
2937
|
-
const contents = [];
|
|
2938
|
-
for (const id of ids) {
|
|
2939
|
-
for (const candidate of [`${id}.svg`, `images/${id}.svg`]) {
|
|
2940
|
-
try {
|
|
2941
|
-
const raw = await readFile13(join15(assetsDir, candidate), "utf-8");
|
|
2942
|
-
contents.push(hideSvg(raw));
|
|
2943
|
-
break;
|
|
2944
|
-
} catch {
|
|
2945
|
-
}
|
|
2946
|
-
}
|
|
2947
|
-
}
|
|
2948
|
-
return contents;
|
|
2949
|
-
}
|
|
2950
|
-
function hideSvg(svg) {
|
|
2951
|
-
return svg.replace(/<svg(\s|>)/, '<svg$1style="display:none;position:absolute" aria-hidden="true" ');
|
|
2952
|
-
}
|
|
2953
|
-
|
|
2954
2978
|
// packages/dev-server/src/detail.ts
|
|
2955
2979
|
async function buildComponentDetail(componentId, patternsDir, renderFn, tracker, defaultTheme, flatNameToPath, compositionReg, scssGraph, classOwnerIndex, discoveryMap, baseProvenance) {
|
|
2956
2980
|
const parts = componentId.split("/");
|
|
@@ -3075,7 +3099,7 @@ async function buildComponentDetail(componentId, patternsDir, renderFn, tracker,
|
|
|
3075
3099
|
import { join as join16 } from "node:path";
|
|
3076
3100
|
async function buildFolderOverview(folderPath, patternsDir, renderFn, discoveryMap) {
|
|
3077
3101
|
const category = folderPath.split("/")[0];
|
|
3078
|
-
let folderLayout = FULL_CATEGORIES.has(category) ? "full" : "centered";
|
|
3102
|
+
let folderLayout = FULL_CATEGORIES.has(stripOrderPrefixes(category)) ? "full" : "centered";
|
|
3079
3103
|
let doc;
|
|
3080
3104
|
try {
|
|
3081
3105
|
const rawIndex = await readFolderFile(patternsDir, join16(folderPath, "index.md"));
|
|
@@ -3214,10 +3238,10 @@ function normalizeAssetRefs(text, rootNames) {
|
|
|
3214
3238
|
}
|
|
3215
3239
|
|
|
3216
3240
|
// packages/dev-server/src/assets.ts
|
|
3217
|
-
import { existsSync as
|
|
3241
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
3218
3242
|
import { createRequire as createRequire2 } from "node:module";
|
|
3219
3243
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
3220
|
-
function resolveDevUiDist(moduleUrl, exists =
|
|
3244
|
+
function resolveDevUiDist(moduleUrl, exists = existsSync4) {
|
|
3221
3245
|
const packaged = fileURLToPath4(new URL("./dev-ui/", moduleUrl));
|
|
3222
3246
|
if (exists(`${packaged}main.js`)) return packaged;
|
|
3223
3247
|
return fileURLToPath4(new URL("../../../apps/dev-ui/dist/", moduleUrl));
|
|
@@ -3310,7 +3334,12 @@ async function handleRequest(req, res, ctx) {
|
|
|
3310
3334
|
const scriptId = normalizeScriptId(decodeURIComponent(basename4(pathname, ".js")));
|
|
3311
3335
|
try {
|
|
3312
3336
|
if (!state.scriptCache.has(scriptId)) {
|
|
3313
|
-
const entryPoint = scriptsDirs.map((d) => join18(d, `${scriptId}.ts`)).find((f) =>
|
|
3337
|
+
const entryPoint = scriptsDirs.map((d) => join18(d, `${scriptId}.ts`)).find((f) => existsSync5(f));
|
|
3338
|
+
if (entryPoint === void 0) {
|
|
3339
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
3340
|
+
res.end(`No script "${scriptId}": scripts are TypeScript, so ${scriptId}.ts is expected in ` + scriptsDirs.map((d) => relative6(cwd, d) || d).join(" or "));
|
|
3341
|
+
return;
|
|
3342
|
+
}
|
|
3314
3343
|
const js = await compileScriptFile(entryPoint);
|
|
3315
3344
|
state.scriptCache.set(scriptId, js);
|
|
3316
3345
|
}
|
|
@@ -3594,7 +3623,7 @@ function describeBindError(e, port2, role, ports) {
|
|
|
3594
3623
|
}
|
|
3595
3624
|
|
|
3596
3625
|
// packages/dev-server/src/watch.ts
|
|
3597
|
-
import { basename as basename5, extname as extname3, relative as
|
|
3626
|
+
import { basename as basename5, extname as extname3, relative as relative7, resolve as resolve8 } from "node:path";
|
|
3598
3627
|
import chokidar from "chokidar";
|
|
3599
3628
|
function startWatching(ctx) {
|
|
3600
3629
|
const { cfg, state, render, tracker, hotreloader } = ctx;
|
|
@@ -3706,7 +3735,7 @@ function startWatching(ctx) {
|
|
|
3706
3735
|
}
|
|
3707
3736
|
return void 0;
|
|
3708
3737
|
};
|
|
3709
|
-
const rel =
|
|
3738
|
+
const rel = relative7(patternsDir, filePath);
|
|
3710
3739
|
if (event === "change") state.discoveryResult ??= await buildDiscoveryMap(patternRoots);
|
|
3711
3740
|
let owner = ownerIn(state.discoveryResult);
|
|
3712
3741
|
if (event === "change") {
|
|
@@ -3788,21 +3817,21 @@ function startWatching(ctx) {
|
|
|
3788
3817
|
if (ext === ".scss" && !(themesDir && filePath.startsWith(themesDir))) {
|
|
3789
3818
|
await handleComponentScss(filePath);
|
|
3790
3819
|
} else if (ext === ".hbs" && filePath.startsWith(patternsDir)) {
|
|
3791
|
-
await rebuildAndSignalTree(`Pattern added: ${
|
|
3820
|
+
await rebuildAndSignalTree(`Pattern added: ${relative7(patternsDir, filePath)}`);
|
|
3792
3821
|
} else if (ext === ".md" && filePath.startsWith(patternsDir)) {
|
|
3793
3822
|
await handleMarkdown(filePath, "add");
|
|
3794
3823
|
}
|
|
3795
3824
|
});
|
|
3796
3825
|
watcher.on("unlink", async (filePath) => {
|
|
3797
3826
|
if (extname3(filePath) === ".hbs" && filePath.startsWith(patternsDir)) {
|
|
3798
|
-
await rebuildAndSignalTree(`Pattern removed: ${
|
|
3827
|
+
await rebuildAndSignalTree(`Pattern removed: ${relative7(patternsDir, filePath)}`);
|
|
3799
3828
|
} else if (extname3(filePath) === ".md" && filePath.startsWith(patternsDir)) {
|
|
3800
3829
|
await handleMarkdown(filePath, "unlink");
|
|
3801
3830
|
}
|
|
3802
3831
|
});
|
|
3803
3832
|
watcher.on("unlinkDir", async (dirPath) => {
|
|
3804
3833
|
if (dirPath.startsWith(patternsDir) && dirPath !== patternsDir) {
|
|
3805
|
-
await rebuildAndSignalTree(`Pattern dir removed: ${
|
|
3834
|
+
await rebuildAndSignalTree(`Pattern dir removed: ${relative7(patternsDir, dirPath)}`);
|
|
3806
3835
|
}
|
|
3807
3836
|
});
|
|
3808
3837
|
return watcher;
|
|
@@ -3810,7 +3839,7 @@ function startWatching(ctx) {
|
|
|
3810
3839
|
|
|
3811
3840
|
// packages/dev-server/src/export-io.ts
|
|
3812
3841
|
import { readFile as readFile16, writeFile as writeFile4, mkdir as mkdir4 } from "node:fs/promises";
|
|
3813
|
-
import { dirname as dirname6, join as join19, relative as
|
|
3842
|
+
import { dirname as dirname6, join as join19, relative as relative8, resolve as resolve9 } from "node:path";
|
|
3814
3843
|
|
|
3815
3844
|
// packages/dev-server/src/export.ts
|
|
3816
3845
|
var escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -3960,7 +3989,7 @@ async function planExport(config, cwd) {
|
|
|
3960
3989
|
const hbs = await readFile16(entry.hbsPath, "utf-8");
|
|
3961
3990
|
inputs.push({ id, hbs });
|
|
3962
3991
|
hbsById.set(id, hbs);
|
|
3963
|
-
relPathById.set(id,
|
|
3992
|
+
relPathById.set(id, relative8(patternsDir, entry.hbsPath).replace(/\.hbs$/, ""));
|
|
3964
3993
|
if (entry.jsonPath) {
|
|
3965
3994
|
try {
|
|
3966
3995
|
dataJsonById.set(id, await readFile16(entry.jsonPath, "utf-8"));
|
|
@@ -4047,7 +4076,7 @@ async function writeThreadedIncluders(threaded, patternsDir, sink) {
|
|
|
4047
4076
|
const res = rewriteIncludes(src, map);
|
|
4048
4077
|
if (res.rewrites === 0) continue;
|
|
4049
4078
|
rewrites += res.rewrites;
|
|
4050
|
-
const rel =
|
|
4079
|
+
const rel = relative8(patternsDir, hbsPath);
|
|
4051
4080
|
const outPath = join19(sink, rel);
|
|
4052
4081
|
await mkdir4(dirname6(outPath), { recursive: true });
|
|
4053
4082
|
await writeFile4(outPath, res.hbs, "utf-8");
|
|
@@ -4231,6 +4260,7 @@ async function startDevServer(config, cwd, opts = {}) {
|
|
|
4231
4260
|
const styleData = await buildAllStyleData(styleRoots, allComponentIds);
|
|
4232
4261
|
applyStyleData(state, styleData);
|
|
4233
4262
|
surfaceDocumentBase(styleRoots, styleData.baseOutsideList, cwd);
|
|
4263
|
+
await reportUnresolvableScripts(dr.discoveryMap, cfg.scriptsDirs, cfg.globalScripts, cwd);
|
|
4234
4264
|
}
|
|
4235
4265
|
const boot = {
|
|
4236
4266
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -4271,9 +4301,9 @@ async function startDevServer(config, cwd, opts = {}) {
|
|
|
4271
4301
|
|
|
4272
4302
|
// packages/core/src/index.ts
|
|
4273
4303
|
import { build as esbuild } from "esbuild";
|
|
4274
|
-
import { existsSync as
|
|
4304
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
4275
4305
|
import { readFile as readFile17, writeFile as writeFile5, unlink, mkdir as mkdir5 } from "node:fs/promises";
|
|
4276
|
-
import { join as join21, dirname as dirname7, resolve as resolve10, relative as
|
|
4306
|
+
import { join as join21, dirname as dirname7, resolve as resolve10, relative as relative9, isAbsolute } from "node:path";
|
|
4277
4307
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
4278
4308
|
import { createHash as createHash3 } from "node:crypto";
|
|
4279
4309
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
@@ -4316,7 +4346,7 @@ function defaultExportDir(root) {
|
|
|
4316
4346
|
return join21(tmpdir2(), "pattern-dump", key, "export");
|
|
4317
4347
|
}
|
|
4318
4348
|
function assertOutsideRoot(outDir, root) {
|
|
4319
|
-
const rel =
|
|
4349
|
+
const rel = relative9(resolve10(root), resolve10(outDir));
|
|
4320
4350
|
const inside = rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
4321
4351
|
if (inside) {
|
|
4322
4352
|
throw new Error(
|
|
@@ -4387,14 +4417,14 @@ async function runExport(root, configPath, outDir) {
|
|
|
4387
4417
|
}
|
|
4388
4418
|
async function loadConfig(root, configPath) {
|
|
4389
4419
|
if (configPath) {
|
|
4390
|
-
if (!
|
|
4420
|
+
if (!existsSync6(configPath)) {
|
|
4391
4421
|
throw new ConfigError(`--config file not found: ${configPath}`);
|
|
4392
4422
|
}
|
|
4393
4423
|
return validateConfig(await readConfigFile(configPath), configPath);
|
|
4394
4424
|
}
|
|
4395
4425
|
for (const name of ["pattern-dump.config.ts", "pattern-dump.config.json"]) {
|
|
4396
4426
|
const path = join21(root, name);
|
|
4397
|
-
if (
|
|
4427
|
+
if (existsSync6(path)) return validateConfig(await readConfigFile(path), name);
|
|
4398
4428
|
}
|
|
4399
4429
|
throw new ConfigError(
|
|
4400
4430
|
`No pattern-dump.config.ts or pattern-dump.config.json found in ${root} (and no --config given)`
|
|
@@ -4609,14 +4639,14 @@ var USAGE = `Usage: pd <command> [options]
|
|
|
4609
4639
|
help [command] Show this help`;
|
|
4610
4640
|
|
|
4611
4641
|
// packages/cli/src/init/run.ts
|
|
4612
|
-
import { existsSync as
|
|
4642
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
4613
4643
|
import { readFile as readFile19 } from "node:fs/promises";
|
|
4614
|
-
import { basename as basename6, dirname as dirname9, join as join23, relative as
|
|
4644
|
+
import { basename as basename6, dirname as dirname9, join as join23, relative as relative11, resolve as resolve12 } from "node:path";
|
|
4615
4645
|
|
|
4616
4646
|
// packages/cli/package.json
|
|
4617
4647
|
var package_default = {
|
|
4618
4648
|
name: "@pattern-dump/cli",
|
|
4619
|
-
version: "0.1.0-alpha.
|
|
4649
|
+
version: "0.1.0-alpha.3",
|
|
4620
4650
|
private: true,
|
|
4621
4651
|
description: "The pd command and the published pattern-dump package.",
|
|
4622
4652
|
type: "module",
|
|
@@ -4652,14 +4682,14 @@ var PD_VERSION = package_default.version;
|
|
|
4652
4682
|
|
|
4653
4683
|
// packages/cli/src/init/files.ts
|
|
4654
4684
|
import { mkdir as mkdir6, readdir as readdir5, readFile as readFile18, writeFile as writeFile6 } from "node:fs/promises";
|
|
4655
|
-
import { dirname as dirname8, join as join22, relative as
|
|
4685
|
+
import { dirname as dirname8, join as join22, relative as relative10, sep as sep2 } from "node:path";
|
|
4656
4686
|
async function readTemplateDir(dir) {
|
|
4657
4687
|
const out = [];
|
|
4658
4688
|
async function walk(current) {
|
|
4659
4689
|
for (const entry of await readdir5(current, { withFileTypes: true })) {
|
|
4660
4690
|
const full = join22(current, entry.name);
|
|
4661
4691
|
if (entry.isDirectory()) await walk(full);
|
|
4662
|
-
else out.push({ path:
|
|
4692
|
+
else out.push({ path: relative10(dir, full).split(sep2).join("/"), content: await readFile18(full, "utf8") });
|
|
4663
4693
|
}
|
|
4664
4694
|
}
|
|
4665
4695
|
await walk(dir);
|
|
@@ -4759,12 +4789,12 @@ function mergePackageJson(current, answers, packageName) {
|
|
|
4759
4789
|
function dependencySpec(pdSource, cwd) {
|
|
4760
4790
|
if (pdSource === void 0) return `^${PD_VERSION}`;
|
|
4761
4791
|
const asPath = resolve12(cwd, pdSource);
|
|
4762
|
-
if (
|
|
4792
|
+
if (existsSync7(asPath)) return `file:${asPath}`;
|
|
4763
4793
|
return pdSource.startsWith(`${PD_PACKAGE_NAME}@`) ? pdSource.slice(PD_PACKAGE_NAME.length + 1) : pdSource;
|
|
4764
4794
|
}
|
|
4765
4795
|
async function insideGitRepo(target, io) {
|
|
4766
4796
|
let dir = target;
|
|
4767
|
-
while (!
|
|
4797
|
+
while (!existsSync7(dir) && dirname9(dir) !== dir) dir = dirname9(dir);
|
|
4768
4798
|
return await io.run("git", ["rev-parse", "--is-inside-work-tree"], dir) === 0;
|
|
4769
4799
|
}
|
|
4770
4800
|
async function runInit(cmd, io) {
|
|
@@ -4789,7 +4819,7 @@ async function runInit(cmd, io) {
|
|
|
4789
4819
|
}
|
|
4790
4820
|
const pkgPath = join23(target, "package.json");
|
|
4791
4821
|
let packageJson = null;
|
|
4792
|
-
if (
|
|
4822
|
+
if (existsSync7(pkgPath)) {
|
|
4793
4823
|
try {
|
|
4794
4824
|
packageJson = JSON.parse(await readFile19(pkgPath, "utf8"));
|
|
4795
4825
|
} catch (e) {
|
|
@@ -4807,14 +4837,14 @@ async function runInit(cmd, io) {
|
|
|
4807
4837
|
const install = cmd.install ?? (prompt ? await io.confirm("Run npm install", true) : true);
|
|
4808
4838
|
const answers = { name, brand, examples, dependency };
|
|
4809
4839
|
const templates = await readTemplates(io.templatesDir);
|
|
4810
|
-
const result = planInit(templates, answers, { packageJson, exists: (p) =>
|
|
4840
|
+
const result = planInit(templates, answers, { packageJson, exists: (p) => existsSync7(join23(target, p)) }, PD_PACKAGE_NAME);
|
|
4811
4841
|
if (!result.ok) {
|
|
4812
4842
|
io.log(`\u2717 ${result.reason}`);
|
|
4813
4843
|
return 1;
|
|
4814
4844
|
}
|
|
4815
4845
|
const { plan } = result;
|
|
4816
4846
|
await applyPlan(target, plan);
|
|
4817
|
-
const where =
|
|
4847
|
+
const where = relative11(io.cwd, target) || ".";
|
|
4818
4848
|
io.log(`\u2713 ${plan.writes.length} files written to ${where}`);
|
|
4819
4849
|
io.log(`\u2713 package.json ${plan.packageJson.created ? "created" : "updated"} \u2014 ${PD_PACKAGE_NAME} ${answers.dependency}`);
|
|
4820
4850
|
for (const note of plan.packageJson.notes) io.log(` \xB7 ${note}`);
|
|
@@ -4847,7 +4877,7 @@ async function runInit(cmd, io) {
|
|
|
4847
4877
|
}
|
|
4848
4878
|
|
|
4849
4879
|
// packages/cli/src/init/local-build.ts
|
|
4850
|
-
import { existsSync as
|
|
4880
|
+
import { existsSync as existsSync8, statSync } from "node:fs";
|
|
4851
4881
|
import { join as join24 } from "node:path";
|
|
4852
4882
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
4853
4883
|
var BUILT = [
|
|
@@ -4866,9 +4896,9 @@ var mtime = (path) => {
|
|
|
4866
4896
|
};
|
|
4867
4897
|
function detectLocalBuild(moduleUrl, packageName, version) {
|
|
4868
4898
|
const repo = fileURLToPath6(new URL("../../../", moduleUrl)).replace(/[\\/]$/, "");
|
|
4869
|
-
if (!
|
|
4899
|
+
if (!existsSync8(join24(repo, "packages/cli/src/distribution.ts"))) return null;
|
|
4870
4900
|
const tarball = join24(repo, ".pd-pack", `${packageName}-${version}.tgz`);
|
|
4871
|
-
if (!
|
|
4901
|
+
if (!existsSync8(tarball)) return { repo, tarball: null, stale: false };
|
|
4872
4902
|
const newestBuild = Math.max(...BUILT.map((p) => mtime(join24(repo, p))));
|
|
4873
4903
|
return { repo, tarball, stale: newestBuild > mtime(tarball) };
|
|
4874
4904
|
}
|
|
@@ -8,7 +8,8 @@ export type ComponentStatus = "draft" | "stable" | "deprecated";
|
|
|
8
8
|
* in both — the markup directly in <body>, no wrapper — only the frame around it differs:
|
|
9
9
|
* - "centered": the frame is sized to what the content needs (pd-width, measured at the full width
|
|
10
10
|
* available) and to its height (pd-height), and the stage centres it (atoms/molecules/organisms)
|
|
11
|
-
* - "full": the frame fills the stage width AND height, top-aligned (pages/templates
|
|
11
|
+
* - "full": the frame fills the stage width AND height, top-aligned (pages/templates, with or
|
|
12
|
+
* without an ordering prefix: `05-pages` counts)
|
|
12
13
|
* This is the RESOLVED mode (category default ← category index.md frontmatter ← component override),
|
|
13
14
|
* so the shell renders directly without re-deriving precedence.
|
|
14
15
|
*/
|
package/package.json
CHANGED