@port60/template-kit 0.21.0 → 1.0.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/README.md +42 -3
- package/bin/cli.mjs +10 -0
- package/package.json +4 -2
- package/src/commands/content.mjs +4 -3
- package/src/commands/create.mjs +11 -3
- package/src/commands/dev.mjs +9 -3
- package/src/commands/model.mjs +3 -3
- package/src/commands/packageCmd.mjs +1 -1
- package/src/commands/publish.mjs +1 -1
- package/src/commands/refresh.mjs +8 -3
- package/src/commands/release.mjs +22 -0
- package/src/commands/setupPreviews.mjs +19 -0
- package/src/commands/validate.mjs +1 -1
- package/src/lib/agentsMd.mjs +108 -162
- package/src/lib/designer-bridge.js +26 -0
- package/src/lib/designerPalette.mjs +62 -0
- package/src/lib/galleryPosters.mjs +105 -0
- package/src/lib/previewOptions.mjs +1 -1
- package/src/lib/releaseBundle.mjs +141 -0
- package/src/vendor/contract/v2/behaviours.json +346 -0
- package/src/vendor/contract/v2/content-bounds.json +117 -0
- package/src/vendor/contract/v2/content-model.json +766 -0
- package/src/vendor/contract/v2/context.json +1569 -0
- package/src/vendor/contract/v2/dialect.json +105 -0
- package/src/vendor/contract/v2/fonts.json +910 -0
- package/src/vendor/contract/v2/imagery.json +32 -0
- package/src/vendor/contract/v2/islands.json +263 -0
- package/src/vendor/contract/v2/layout.json +28 -0
- package/src/vendor/contract/v2/manifest.schema.json +388 -0
- package/src/vendor/contract/v2/sections.json +947 -0
- package/src/vendor/contract/v2/site.schema.json +1353 -0
- package/src/vendor/contract/v2/tokens.json +101 -0
- package/src/vendor/contract/v2.lock.json +6931 -0
- package/src/vendor/engine/content-footprint.mjs +76 -1
- package/src/vendor/engine/majors.mjs +42 -0
- package/src/vendor/validator/gift-aid-logo.svg +6 -0
- package/src/vendor/validator/model-reference-v2.mjs +95 -0
- package/src/vendor/validator/platform-base.css +310 -0
- package/src/vendor/validator/preview-v1.mjs +691 -0
- package/src/vendor/validator/preview-v2.mjs +654 -0
- package/src/vendor/validator/preview.mjs +8 -688
- package/src/vendor/validator/site-context-v2.mjs +113 -0
- package/src/vendor/validator/validate-v1.mjs +666 -0
- package/src/vendor/validator/validate-v2.mjs +642 -0
- package/src/vendor/validator/validate.mjs +21 -663
- package/starter/assets/theme.css +3 -0
- package/starter/layout.liquid +15 -18
- package/starter/manifest.json +5 -4
- package/starter/preview/config.json +4 -0
- package/starter/preview/media/README.md +9 -0
- package/starter/sections/campaigns.liquid +5 -4
- package/starter/sections/homeHero.liquid +25 -21
- package/starter/sections/values.liquid +1 -1
package/README.md
CHANGED
|
@@ -33,6 +33,8 @@ newer contract asks of you.
|
|
|
33
33
|
| `dev [dir]` | Live preview over the contract's sample fixtures; validation re-runs on save. |
|
|
34
34
|
| `validate [dir] [--json]` | The exact checks the platform runs at upload. `--json` emits `{ok, errors, warnings, provenSupports}`. |
|
|
35
35
|
| `package [dir]` | Validate, then build the contract-shaped zip the studio accepts as-is. |
|
|
36
|
+
| `release [dir]` | Build separate runtime and independent designer-preview folders for a trusted store release. Does not upload. |
|
|
37
|
+
| `setup-previews [--with-deps]` | Install the pinned headless browser for automatic gallery images. Add `--with-deps` in Linux CI. |
|
|
36
38
|
| `model [--json]` | The content model, in hand; `--json` for agents. |
|
|
37
39
|
| `content [dir]` | Eject the model's data as your editable copy; render it with `dev --content`. |
|
|
38
40
|
| `upgrade [dir]` | Latest kit + contract for an existing template; re-briefs and re-validates. |
|
|
@@ -48,9 +50,46 @@ See the [AI quickstart](https://developers.port60.com/guides/ai-quickstart/).
|
|
|
48
50
|
|
|
49
51
|
## The contract
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
Kit 1.0.0 authors **port60-liquid@2**, content model **2.0**, using the contract under
|
|
54
|
+
`src/vendor/contract/v2`. Collection envelopes, independent header/footer navigation,
|
|
55
|
+
resolved actions and page-scoped sections are explicit. V1 sources need a deliberate migration,
|
|
56
|
+
not a manifest-only relabel. Historical v1 contracts remain frozen for existing platform pins.
|
|
57
|
+
|
|
58
|
+
## Designer previews
|
|
59
|
+
|
|
60
|
+
The scaffold creates `preview/config.json` and `preview/media/`. Optional `content` points to
|
|
61
|
+
fictional v2 sample JSON relative to `preview/`; omission uses contract fixtures. `focus` is
|
|
62
|
+
`none`, `donate` or `volunteer`. Use approved local JPEG, PNG or WebP images via
|
|
63
|
+
`p60preview:filename.jpg` and retain provenance with the source. Never use selecting-tenant data.
|
|
64
|
+
|
|
65
|
+
`npm run release` writes `dist/release/NAME/VERSION/`: lightweight `template/` files, separate
|
|
66
|
+
`preview/` HTML/media/metadata, and a `release.json` completion record. Every Look is generated
|
|
67
|
+
from actual Liquid/CSS with matching palettes. Existing output is refused. Limits are 24 Looks,
|
|
68
|
+
2 MiB per image/page and 24 MiB per release. Demo forms, navigation and transactions are inactive.
|
|
69
|
+
|
|
70
|
+
The first-party publisher uploads completion last. The catalogue supplies matching preview
|
|
71
|
+
metadata to tenant-admin; charity-site reads only runtime files. Previews are not bundled into
|
|
72
|
+
admin and do not become tenant content. Preview-only changes also need a new template version.
|
|
73
|
+
The Studio ZIP `package`/`publish` path remains separate and runtime-only.
|
|
74
|
+
|
|
75
|
+
Before your first release build, run `npm run preview:setup` in a new scaffold, or
|
|
76
|
+
`p60-template-kit setup-previews` in an existing project. Repeat after upgrading the kit.
|
|
77
|
+
The release builder automatically captures each Look from the actual template at 1440x900
|
|
78
|
+
and writes a 960x600 WebP to `preview/gallery/`, capped at 160 KiB. No separate screenshot
|
|
79
|
+
authoring or upload is needed. The gallery uses these images; opening a design loads its HTML.
|
|
80
|
+
The pinned browser is a build dependency only, never part of the live website.
|
|
81
|
+
|
|
82
|
+
Linux capture requires a working Chromium sandbox. Ubuntu 24.04 hosted CI installs the
|
|
83
|
+
repository's browser-path-scoped AppArmor profile to allow its user namespaces.
|
|
84
|
+
No `--no-sandbox` or global AppArmor disablement is used. On another Linux
|
|
85
|
+
host, configure an administrator-approved sandbox according to
|
|
86
|
+
[Chromium's guidance](https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md).
|
|
87
|
+
Browser installation alone does not change the host's security policy.
|
|
88
|
+
|
|
89
|
+
Only packaged preview assets and fonts.bunny.net are accessible during capture. Failed required
|
|
90
|
+
imagery or Latin fonts stop generation. Arabic-specific poster font fidelity is deferred;
|
|
91
|
+
full previews and live-site typography are unchanged. Preserve the same kit/browser/OS for
|
|
92
|
+
immutable upload retries; output changes need a new version, not an overwrite.
|
|
54
93
|
|
|
55
94
|
Full documentation: [developers.port60.com](https://developers.port60.com)
|
|
56
95
|
|
package/bin/cli.mjs
CHANGED
|
@@ -12,6 +12,8 @@ import { upgrade } from '../src/commands/upgrade.mjs';
|
|
|
12
12
|
import { refresh } from '../src/commands/refresh.mjs';
|
|
13
13
|
import { login, logout, whoami } from '../src/commands/auth.mjs';
|
|
14
14
|
import { publish } from '../src/commands/publish.mjs';
|
|
15
|
+
import { releaseCmd } from '../src/commands/release.mjs';
|
|
16
|
+
import { setupPreviews } from '../src/commands/setupPreviews.mjs';
|
|
15
17
|
|
|
16
18
|
function parseArgs(argv) {
|
|
17
19
|
const args = { _: [] };
|
|
@@ -37,6 +39,12 @@ const [command, ...rest] = process.argv.slice(2);
|
|
|
37
39
|
const args = parseArgs(rest);
|
|
38
40
|
|
|
39
41
|
switch (command) {
|
|
42
|
+
case 'setup-previews':
|
|
43
|
+
setupPreviews(args);
|
|
44
|
+
break;
|
|
45
|
+
case 'release':
|
|
46
|
+
await releaseCmd(args);
|
|
47
|
+
break;
|
|
40
48
|
case 'create':
|
|
41
49
|
create(args);
|
|
42
50
|
break;
|
|
@@ -85,6 +93,8 @@ usage:
|
|
|
85
93
|
p60-template-kit content [dir] [--out file] eject the model's data as your editable copy
|
|
86
94
|
p60-template-kit validate [dir] [--json] the platform's exact conformance checks
|
|
87
95
|
p60-template-kit package [dir] validate + build the uploadable zip
|
|
96
|
+
p60-template-kit release [dir] build separate template/ and preview/ store bundles
|
|
97
|
+
p60-template-kit setup-previews [--with-deps] install the release builder's headless browser
|
|
88
98
|
p60-template-kit upgrade [dir] move an existing template to the latest kit
|
|
89
99
|
and contract, re-brief, re-validate
|
|
90
100
|
p60-template-kit login sign in from the terminal (the browser does the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@port60/template-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Build Port60 site templates locally: scaffold, live-preview, validate against the platform contract, and package for studio upload. AI-agent ready: every scaffold ships AGENTS.md and validate emits machine-readable JSON.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,8 +16,10 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"ajv": "^8.20.0",
|
|
19
|
+
"jsdom": "29.1.1",
|
|
19
20
|
"liquidjs": "^10.27.2",
|
|
20
|
-
"lucide-static": "^1.41.0"
|
|
21
|
+
"lucide-static": "^1.41.0",
|
|
22
|
+
"playwright": "1.63.0"
|
|
21
23
|
},
|
|
22
24
|
"license": "MIT",
|
|
23
25
|
"repository": {
|
package/src/commands/content.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import { buildSiteFixture, composePage, validatePreviewContent } from '../vendor/validator/site-context.mjs';
|
|
3
|
+
import { buildSiteFixture, composePage, validatePreviewContent } from '../vendor/validator/site-context-v2.mjs';
|
|
4
4
|
import { loadArtifactDir } from '../lib/artifactFiles.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -34,9 +34,10 @@ export function content(args) {
|
|
|
34
34
|
}
|
|
35
35
|
const data = {
|
|
36
36
|
brand: site.brand,
|
|
37
|
-
nav:
|
|
37
|
+
nav: site.nav,
|
|
38
|
+
actions: site.actions,
|
|
38
39
|
...(manifest ? { pages: { home: composePage(manifest, 'home'), about: composePage(manifest, 'about') } } : {}),
|
|
39
|
-
...
|
|
40
|
+
...site.content
|
|
40
41
|
};
|
|
41
42
|
const problems = validatePreviewContent(data);
|
|
42
43
|
if (problems.length > 0) {
|
package/src/commands/create.mjs
CHANGED
|
@@ -19,7 +19,7 @@ export function create(args) {
|
|
|
19
19
|
const name = (args.name ?? basename(target)).toLowerCase();
|
|
20
20
|
if (!NAME_PATTERN.test(name)) {
|
|
21
21
|
console.error(`✗ '${name}' is not a valid template name (lowercase letters, digits, hyphens, `
|
|
22
|
-
+ '3
|
|
22
|
+
+ '3 to 50 chars, starting with a letter). Pass --name.');
|
|
23
23
|
process.exit(1);
|
|
24
24
|
}
|
|
25
25
|
if (existsSync(join(target, 'manifest.json'))) {
|
|
@@ -50,7 +50,9 @@ export function create(args) {
|
|
|
50
50
|
dev: 'p60-template-kit dev .',
|
|
51
51
|
validate: 'p60-template-kit validate .',
|
|
52
52
|
'validate:json': 'p60-template-kit validate . --json',
|
|
53
|
-
package: 'p60-template-kit package .'
|
|
53
|
+
package: 'p60-template-kit package .',
|
|
54
|
+
release: 'p60-template-kit release .',
|
|
55
|
+
'preview:setup': 'p60-template-kit setup-previews'
|
|
54
56
|
},
|
|
55
57
|
devDependencies: {
|
|
56
58
|
'@port60/template-kit': `^${KIT_PACKAGE.version}`
|
|
@@ -58,11 +60,17 @@ export function create(args) {
|
|
|
58
60
|
}, null, 2) + '\n');
|
|
59
61
|
writeFileSync(join(target, 'README.md'), `# ${label}
|
|
60
62
|
|
|
61
|
-
A Port60 site template
|
|
63
|
+
A Port60 site template using \`port60-liquid@2\`, content model \`2.0\` and kit \`1.0.0\`.
|
|
64
|
+
Existing v1 platform pins keep historical support; this kit accepts v2 authoring only.
|
|
65
|
+
Start with \`npm install\`, then:
|
|
62
66
|
|
|
63
67
|
- \`npm run dev\`, live preview at http://localhost:4400
|
|
64
68
|
- \`npm run validate\`, conformance against the platform contract
|
|
65
69
|
- \`npm run package\`, the uploadable zip in \`dist/\` (recreated on every run)
|
|
70
|
+
- \`npm run release\`, separate runtime and designer-preview folders in \`dist/release/\`
|
|
71
|
+
- \`npm run preview:setup\`, install the pinned browser before your first release build
|
|
72
|
+
- \`preview/config.json\` selects author sample content and widget state; put optional
|
|
73
|
+
author images in \`preview/media/\` and reference them as \`p60preview:filename.jpg\`.
|
|
66
74
|
|
|
67
75
|
**Working with an AI agent?** Point it at this directory, \`AGENTS.md\` (and \`CLAUDE.md\`)
|
|
68
76
|
brief it on the contract, the rules and the validate loop.
|
package/src/commands/dev.mjs
CHANGED
|
@@ -3,9 +3,9 @@ import { watch, readFileSync, existsSync } from 'node:fs';
|
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
4
|
import { surfaceFor, knobOverridesFromQuery, previewAssetPath, previewAssetType } from '../lib/previewOptions.mjs';
|
|
5
5
|
import { renderStudioPreview } from '../vendor/validator/preview.mjs';
|
|
6
|
-
import { validateArtifact } from '../vendor/validator/validate.mjs';
|
|
7
|
-
import { applyPreviewContent, buildSiteFixture, validatePreviewContent } from '../vendor/validator/site-context.mjs';
|
|
8
|
-
import { renderModelReferenceHtml } from '../vendor/validator/model-reference.mjs';
|
|
6
|
+
import { validateNewArtifact as validateArtifact } from '../vendor/validator/validate.mjs';
|
|
7
|
+
import { applyPreviewContent, buildSiteFixture, validatePreviewContent } from '../vendor/validator/site-context-v2.mjs';
|
|
8
|
+
import { renderModelReferenceHtml } from '../vendor/validator/model-reference-v2.mjs';
|
|
9
9
|
import { loadArtifactDir } from '../lib/artifactFiles.mjs';
|
|
10
10
|
import { join } from 'node:path';
|
|
11
11
|
|
|
@@ -80,6 +80,12 @@ function imageOriginsOf(json) {
|
|
|
80
80
|
*/
|
|
81
81
|
export async function dev(args) {
|
|
82
82
|
const dir = resolve(args._[0] ?? '.');
|
|
83
|
+
const initialManifest = JSON.parse(loadArtifactDir(dir)['manifest.json'] ?? '{}');
|
|
84
|
+
if (initialManifest.format !== 'port60-liquid@2') {
|
|
85
|
+
console.error('✗ Kit 1.0.0 requires port60-liquid@2. Existing v1 pins remain supported by the platform, not by the new authoring kit.');
|
|
86
|
+
process.exitCode = 1;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
83
89
|
const port = Number(args.port ?? 4400);
|
|
84
90
|
// The dev-richer half of the imagery split: point P60_FIXTURE_IMAGES at the platform's fixture
|
|
85
91
|
// imagery base and the preview loads photographic fixtures from that ONE origin instead of the
|
package/src/commands/model.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { contentModel } from '../vendor/engine/content-footprint.mjs';
|
|
1
|
+
import { contentModelV2 as contentModel } from '../vendor/engine/content-footprint.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* `model [--json]`, the content model, in hand. Prints every `site.content.*` collection with
|
|
@@ -15,7 +15,7 @@ export function model(args) {
|
|
|
15
15
|
console.log('site also carries: ' + contentModel.siblings.keys.map((k) => `site.${k}`).join(', '));
|
|
16
16
|
console.log('');
|
|
17
17
|
for (const [name, collection] of Object.entries(contentModel.collections)) {
|
|
18
|
-
const more = collection.
|
|
18
|
+
const more = collection.shape === 'envelope' ? ' · {label, href, items, pagination}' : ' · array';
|
|
19
19
|
console.log(`site.content.${name} (bounded at ${collection.cap}${more}, since ${collection.since})`);
|
|
20
20
|
for (const [field, spec] of Object.entries(collection.item)) {
|
|
21
21
|
const notes = [
|
|
@@ -27,7 +27,7 @@ export function model(args) {
|
|
|
27
27
|
}
|
|
28
28
|
console.log('');
|
|
29
29
|
}
|
|
30
|
-
console.log('Rules: collections are bounded (link onward via
|
|
30
|
+
console.log('Rules: collections are bounded (link onward via href and pagination); enums are open (branch and');
|
|
31
31
|
console.log('fall back); nullable fields need a branch; the model only grows. Your footprint and');
|
|
32
32
|
console.log('minimum model version are computed at publish, you never declare them. Live examples:');
|
|
33
33
|
console.log('the /model page on your dev preview.');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { resolve, join } from 'node:path';
|
|
3
|
-
import { validateArtifact } from '../vendor/validator/validate.mjs';
|
|
3
|
+
import { validateNewArtifact as validateArtifact } from '../vendor/validator/validate.mjs';
|
|
4
4
|
import { loadArtifactDir, skippedNotice } from '../lib/artifactFiles.mjs';
|
|
5
5
|
import { buildZip } from '../lib/zip.mjs';
|
|
6
6
|
|
package/src/commands/publish.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
|
-
import { validateArtifact } from '../vendor/validator/validate.mjs';
|
|
2
|
+
import { validateNewArtifact as validateArtifact } from '../vendor/validator/validate.mjs';
|
|
3
3
|
import { loadArtifactDir, skippedNotice } from '../lib/artifactFiles.mjs';
|
|
4
4
|
import { buildZip } from '../lib/zip.mjs';
|
|
5
5
|
import { accessToken, api, apiBase, loadCredentials, requireCredentials } from '../lib/auth.mjs';
|
package/src/commands/refresh.mjs
CHANGED
|
@@ -2,9 +2,9 @@ import { readFileSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { resolve, join } from 'node:path';
|
|
3
3
|
import { agentsMd } from '../lib/agentsMd.mjs';
|
|
4
4
|
import { loadArtifactDir } from '../lib/artifactFiles.mjs';
|
|
5
|
-
import { validateArtifact } from '../vendor/validator/validate.mjs';
|
|
6
|
-
import { contentModel } from '../vendor/engine/content-footprint.mjs';
|
|
7
|
-
import dialect from '../vendor/contract/
|
|
5
|
+
import { validateNewArtifact as validateArtifact } from '../vendor/validator/validate.mjs';
|
|
6
|
+
import { contentModelV2 as contentModel } from '../vendor/engine/content-footprint.mjs';
|
|
7
|
+
import dialect from '../vendor/contract/v2/dialect.json' with { type: 'json' };
|
|
8
8
|
|
|
9
9
|
const KIT_PACKAGE = JSON.parse(
|
|
10
10
|
readFileSync(resolve(import.meta.dirname, '../../package.json'), 'utf8')
|
|
@@ -25,6 +25,11 @@ export async function refresh(args) {
|
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
const manifest = JSON.parse(files['manifest.json']);
|
|
28
|
+
if (manifest.format !== dialect.format) {
|
|
29
|
+
console.error(`✗ Kit ${KIT_PACKAGE.version} requires ${dialect.format}. Migrate the template before refreshing its instructions. No files changed.`);
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
28
33
|
|
|
29
34
|
const briefing = agentsMd(manifest.name);
|
|
30
35
|
writeFileSync(join(dir, 'AGENTS.md'), briefing);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync, existsSync, lstatSync } from 'node:fs';
|
|
2
|
+
import { resolve, join, dirname } from 'node:path';
|
|
3
|
+
import { buildReleaseBundle } from '../lib/releaseBundle.mjs';
|
|
4
|
+
|
|
5
|
+
export async function releaseCmd(args) {
|
|
6
|
+
const root = resolve(args._[0] ?? '.');
|
|
7
|
+
const bundle = await buildReleaseBundle(root);
|
|
8
|
+
const output = join(root, 'dist', 'release', bundle.manifest.name, bundle.manifest.version);
|
|
9
|
+
// Never follow a linked build destination or silently mix two builds of an immutable release.
|
|
10
|
+
for (const dir of [join(root, 'dist'), join(root, 'dist', 'release'), join(root, 'dist', 'release', bundle.manifest.name), output]) {
|
|
11
|
+
if (existsSync(dir) && lstatSync(dir).isSymbolicLink()) throw new Error('Linked release destination refused');
|
|
12
|
+
}
|
|
13
|
+
if (existsSync(output)) throw new Error(`Release output already exists: ${output}. Review/remove that generated directory or bump the version before rebuilding.`);
|
|
14
|
+
for (const [path, file] of Object.entries(bundle.files)) {
|
|
15
|
+
const destination = join(output, path);
|
|
16
|
+
mkdirSync(dirname(destination), { recursive: true });
|
|
17
|
+
writeFileSync(destination, file.bytes, { flag: 'wx' });
|
|
18
|
+
}
|
|
19
|
+
console.log(`Validated release: ${output}`);
|
|
20
|
+
console.log('template/ is runtime only; preview/ is the independent designer gallery. Publish release.json last.');
|
|
21
|
+
console.log('Studio package/publish still accepts the runtime ZIP; store release publication uses the first-party pipeline.');
|
|
22
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
|
|
5
|
+
export function previewSetupCommand(args = {}) {
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
// Playwright exports its manifest, not a ./cli module. Use its declared binary so
|
|
8
|
+
// this resolves the kit's pinned installation even inside another npm project.
|
|
9
|
+
const manifestPath = require.resolve('playwright/package.json');
|
|
10
|
+
const command = [resolve(dirname(manifestPath), require(manifestPath).bin.playwright), 'install', 'chromium', '--only-shell'];
|
|
11
|
+
if (args['with-deps']) command.push('--with-deps');
|
|
12
|
+
return command;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function setupPreviews(args) {
|
|
16
|
+
const result = spawnSync(process.execPath, previewSetupCommand(args), { stdio: 'inherit' });
|
|
17
|
+
if (result.error) throw result.error;
|
|
18
|
+
process.exitCode = result.status ?? 1;
|
|
19
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
|
-
import { validateArtifact } from '../vendor/validator/validate.mjs';
|
|
2
|
+
import { validateNewArtifact as validateArtifact } from '../vendor/validator/validate.mjs';
|
|
3
3
|
import { loadArtifactDir } from '../lib/artifactFiles.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|