@lovo/matter-cli 1.0.0 → 2.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/CHANGELOG.md +2 -0
- package/README.md +3 -3
- package/dist/harness/index.tsx +7 -0
- package/dist/index.js +4 -4
- package/dist/poster/e2e.test.js +18 -1
- package/dist/poster/e2e.test.js.map +1 -1
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -100,13 +100,13 @@ pnpm exec playwright install chromium
|
|
|
100
100
|
|
|
101
101
|
```bash
|
|
102
102
|
# Default — writes ./public/hero.jpg (JPEG q80)
|
|
103
|
-
npx matter-cli poster --
|
|
103
|
+
npx matter-cli poster --source ./src/components/matter/hero.tsx --output ./public/hero.jpg
|
|
104
104
|
|
|
105
105
|
# Posterized shader — PNG compresses smaller
|
|
106
|
-
npx matter-cli poster --
|
|
106
|
+
npx matter-cli poster --source ./gradient.tsx --output ./public/gradient.png --format png
|
|
107
107
|
|
|
108
108
|
# Higher quality JPEG
|
|
109
|
-
npx matter-cli poster --
|
|
109
|
+
npx matter-cli poster --source ./aurora.tsx --output ./public/aurora.jpg --quality 92
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
Wire it up:
|
package/dist/harness/index.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
|
|
3
|
+
import { setReducedMotionPolicy } from '@lovo/matter';
|
|
3
4
|
import { createRoot } from 'react-dom/client';
|
|
4
5
|
|
|
5
6
|
import { installFrameReadyWatcher } from './frameReady.js';
|
|
@@ -36,6 +37,12 @@ if (!rootEl) throw new Error('matter poster: #root missing from harness HTML');
|
|
|
36
37
|
|
|
37
38
|
const root = createRoot(rootEl);
|
|
38
39
|
|
|
40
|
+
// Pin the animation clock so the poster captures a deterministic t=0 frame,
|
|
41
|
+
// matching what users see at mount (ShaderScene also resets to t=0 at first
|
|
42
|
+
// paint). 'paused' sets the reduced-motion time scale to 0, so elapsedTime
|
|
43
|
+
// stays 0 regardless of how many settle frames elapse before the screenshot.
|
|
44
|
+
setReducedMotionPolicy('paused');
|
|
45
|
+
|
|
39
46
|
root.render(<Component />);
|
|
40
47
|
|
|
41
48
|
installFrameReadyWatcher();
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ function fail(caughtError) {
|
|
|
9
9
|
process.exit(1);
|
|
10
10
|
}
|
|
11
11
|
var program = new Command();
|
|
12
|
-
program.name("matter-cli").description("CLI for Matter \u2014 copy-paste components from the registry into your project").version("
|
|
12
|
+
program.name("matter-cli").description("CLI for Matter \u2014 copy-paste components from the registry into your project").version("2.0.0");
|
|
13
13
|
program.command("init").description("one-time project setup \u2014 writes matter.config.json").option("--force", "overwrite an existing matter.config.json").action(async (opts) => {
|
|
14
14
|
try {
|
|
15
15
|
const { runInit } = await import("./init-NB5EOU5H.js");
|
|
@@ -21,7 +21,7 @@ program.command("init").description("one-time project setup \u2014 writes matter
|
|
|
21
21
|
program.command("list").description("show available components in the registry").option("--registry <url>", "override the registryUrl from matter.config.json").option("--reference <ref>", "tag, branch, or commit (defaults to the CLI version)").action(async (opts) => {
|
|
22
22
|
try {
|
|
23
23
|
const { runList } = await import("./list-L725RQM3.js");
|
|
24
|
-
await runList({ registry: opts.registry, ref: opts.reference, cliVersion: "
|
|
24
|
+
await runList({ registry: opts.registry, ref: opts.reference, cliVersion: "2.0.0" });
|
|
25
25
|
} catch (caughtError) {
|
|
26
26
|
fail(caughtError);
|
|
27
27
|
}
|
|
@@ -34,7 +34,7 @@ program.command("add").description("copy one or more components from the registr
|
|
|
34
34
|
registry: opts.registry,
|
|
35
35
|
ref: opts.reference,
|
|
36
36
|
force: opts.force,
|
|
37
|
-
cliVersion: "
|
|
37
|
+
cliVersion: "2.0.0"
|
|
38
38
|
});
|
|
39
39
|
} catch (caughtError) {
|
|
40
40
|
fail(caughtError);
|
|
@@ -49,7 +49,7 @@ program.command("update").description("re-fetch a previously-added component (or
|
|
|
49
49
|
registry: opts.registry,
|
|
50
50
|
ref: opts.reference,
|
|
51
51
|
force: opts.force,
|
|
52
|
-
cliVersion: "
|
|
52
|
+
cliVersion: "2.0.0"
|
|
53
53
|
});
|
|
54
54
|
} catch (caughtError) {
|
|
55
55
|
fail(caughtError);
|
package/dist/poster/e2e.test.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import "../chunk-D4HDZEJT.js";
|
|
18
18
|
|
|
19
19
|
// src/poster/e2e.test.ts
|
|
20
|
-
import { mkdtemp, rm, stat } from "fs/promises";
|
|
20
|
+
import { mkdtemp, readFile, rm, stat } from "fs/promises";
|
|
21
21
|
import { tmpdir } from "os";
|
|
22
22
|
import { join } from "path";
|
|
23
23
|
var E2E_ENABLED = process.env.MATTER_E2E === "1";
|
|
@@ -100,5 +100,22 @@ describe.skipIf(!E2E_ENABLED)("runPoster \u2014 E2E (MATTER_E2E=1)", () => {
|
|
|
100
100
|
}
|
|
101
101
|
}, 3e4);
|
|
102
102
|
}
|
|
103
|
+
it("captures a deterministic t=0 frame across runs", async () => {
|
|
104
|
+
const outA = join(outDir, "determinism-a.png");
|
|
105
|
+
const outB = join(outDir, "determinism-b.png");
|
|
106
|
+
const base = {
|
|
107
|
+
from: join(FIXTURES, "gradient-plus-grain.tsx"),
|
|
108
|
+
type: "png",
|
|
109
|
+
exportName: "default",
|
|
110
|
+
timeSeconds: 0,
|
|
111
|
+
width: 320,
|
|
112
|
+
height: 240,
|
|
113
|
+
deviceScaleFactor: 1
|
|
114
|
+
};
|
|
115
|
+
await runPoster({ ...base, out: outA }, { cwd: process.cwd(), log: vi.fn() });
|
|
116
|
+
await runPoster({ ...base, out: outB }, { cwd: process.cwd(), log: vi.fn() });
|
|
117
|
+
const [bytesA, bytesB] = await Promise.all([readFile(outA), readFile(outB)]);
|
|
118
|
+
globalExpect(Buffer.compare(bytesA, bytesB)).toBe(0);
|
|
119
|
+
}, 6e4);
|
|
103
120
|
});
|
|
104
121
|
//# sourceMappingURL=e2e.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/poster/e2e.test.ts"],"sourcesContent":["import { mkdtemp, rm, stat } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';\n\nimport { runPoster } from '../commands/poster.js';\n\nconst E2E_ENABLED = process.env.MATTER_E2E === '1';\n\nconst FIXTURES = new URL('../test-fixtures/posters/', import.meta.url).pathname;\n\nconst cases = [\n {\n name: 'single-linear-gradient',\n file: 'single-linear-gradient.tsx',\n type: 'png',\n extra: {},\n },\n {\n name: 'gradient-plus-grain',\n file: 'gradient-plus-grain.tsx',\n type: 'png',\n extra: {},\n },\n {\n name: 'aurora-with-time',\n file: 'aurora-with-time.tsx',\n type: 'png',\n extra: { timeSeconds: 2 },\n },\n {\n name: 'named-export',\n file: 'named-export.tsx',\n type: 'png',\n extra: { exportName: 'NamedExport' },\n },\n // Exercises the default JPEG path and verifies the magic-byte header.\n {\n name: 'jpeg-default',\n file: 'single-linear-gradient.tsx',\n type: 'jpg',\n extra: {},\n },\n] as const;\n\ndescribe.skipIf(!E2E_ENABLED)('runPoster — E2E (MATTER_E2E=1)', () => {\n let outDir: string;\n\n beforeEach(async () => {\n outDir = await mkdtemp(join(tmpdir(), 'matter-poster-e2e-'));\n });\n\n afterEach(async () => {\n await rm(outDir, { recursive: true, force: true });\n });\n\n for (const c of cases) {\n it(`produces a ${c.type.toUpperCase()} for ${c.name}`, async () => {\n const out = join(outDir, `${c.name}.${c.type === 'jpg' ? 'jpg' : 'png'}`);\n\n await runPoster(\n {\n from: join(FIXTURES, c.file),\n out,\n type: c.type,\n exportName: 'default',\n timeSeconds: 0,\n width: 800,\n height: 600,\n deviceScaleFactor: 1,\n ...c.extra,\n },\n { cwd: process.cwd(), log: vi.fn() },\n );\n const s = await stat(out);\n\n expect(s.size).toBeGreaterThan(1024); // > 1 KB\n expect(s.size).toBeLessThan(5 * 1024 * 1024); // < 5 MB\n\n const { open } = await import('node:fs/promises');\n const fh = await open(out, 'r');\n\n try {\n const head = Buffer.alloc(4);\n\n await fh.read(head, 0, 4, 0);\n if (c.type === 'png') {\n expect(head[0]).toBe(0x89);\n expect(head[1]).toBe(0x50);\n } else {\n expect(head[0]).toBe(0xff);\n expect(head[1]).toBe(0xd8);\n }\n } finally {\n await fh.close();\n }\n }, 30_000);\n }\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS,IAAI,YAAY;
|
|
1
|
+
{"version":3,"sources":["../../src/poster/e2e.test.ts"],"sourcesContent":["import { mkdtemp, readFile, rm, stat } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';\n\nimport { runPoster } from '../commands/poster.js';\n\nconst E2E_ENABLED = process.env.MATTER_E2E === '1';\n\nconst FIXTURES = new URL('../test-fixtures/posters/', import.meta.url).pathname;\n\nconst cases = [\n {\n name: 'single-linear-gradient',\n file: 'single-linear-gradient.tsx',\n type: 'png',\n extra: {},\n },\n {\n name: 'gradient-plus-grain',\n file: 'gradient-plus-grain.tsx',\n type: 'png',\n extra: {},\n },\n {\n name: 'aurora-with-time',\n file: 'aurora-with-time.tsx',\n type: 'png',\n extra: { timeSeconds: 2 },\n },\n {\n name: 'named-export',\n file: 'named-export.tsx',\n type: 'png',\n extra: { exportName: 'NamedExport' },\n },\n // Exercises the default JPEG path and verifies the magic-byte header.\n {\n name: 'jpeg-default',\n file: 'single-linear-gradient.tsx',\n type: 'jpg',\n extra: {},\n },\n] as const;\n\ndescribe.skipIf(!E2E_ENABLED)('runPoster — E2E (MATTER_E2E=1)', () => {\n let outDir: string;\n\n beforeEach(async () => {\n outDir = await mkdtemp(join(tmpdir(), 'matter-poster-e2e-'));\n });\n\n afterEach(async () => {\n await rm(outDir, { recursive: true, force: true });\n });\n\n for (const c of cases) {\n it(`produces a ${c.type.toUpperCase()} for ${c.name}`, async () => {\n const out = join(outDir, `${c.name}.${c.type === 'jpg' ? 'jpg' : 'png'}`);\n\n await runPoster(\n {\n from: join(FIXTURES, c.file),\n out,\n type: c.type,\n exportName: 'default',\n timeSeconds: 0,\n width: 800,\n height: 600,\n deviceScaleFactor: 1,\n ...c.extra,\n },\n { cwd: process.cwd(), log: vi.fn() },\n );\n const s = await stat(out);\n\n expect(s.size).toBeGreaterThan(1024); // > 1 KB\n expect(s.size).toBeLessThan(5 * 1024 * 1024); // < 5 MB\n\n const { open } = await import('node:fs/promises');\n const fh = await open(out, 'r');\n\n try {\n const head = Buffer.alloc(4);\n\n await fh.read(head, 0, 4, 0);\n if (c.type === 'png') {\n expect(head[0]).toBe(0x89);\n expect(head[1]).toBe(0x50);\n } else {\n expect(head[0]).toBe(0xff);\n expect(head[1]).toBe(0xd8);\n }\n } finally {\n await fh.close();\n }\n }, 30_000);\n }\n\n it('captures a deterministic t=0 frame across runs', async () => {\n const outA = join(outDir, 'determinism-a.png');\n const outB = join(outDir, 'determinism-b.png');\n const base = {\n from: join(FIXTURES, 'gradient-plus-grain.tsx'),\n type: 'png' as const,\n exportName: 'default',\n timeSeconds: 0,\n width: 320,\n height: 240,\n deviceScaleFactor: 1,\n };\n\n await runPoster({ ...base, out: outA }, { cwd: process.cwd(), log: vi.fn() });\n await runPoster({ ...base, out: outB }, { cwd: process.cwd(), log: vi.fn() });\n\n const [bytesA, bytesB] = await Promise.all([readFile(outA), readFile(outB)]);\n\n // Determinism regression guard: the grain overlay animates with elapsedTime,\n // so if the harness ever stopped pinning the clock (paused -> scale 0), a run\n // that rode a different warmup time could shift the grain and diverge. This\n // asserts two runs stay byte-identical; it does not by itself prove the\n // paused clock is load-bearing (warmup may coincide), only that determinism\n // holds.\n expect(Buffer.compare(bytesA, bytesB)).toBe(0);\n }, 60_000);\n});\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lovo/matter-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "CLI for Matter — copy-paste components from the registry into your project.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -48,9 +48,10 @@
|
|
|
48
48
|
"typescript": "^5.6.0",
|
|
49
49
|
"vite": "^8.0.14",
|
|
50
50
|
"vitest": "^4.1.7",
|
|
51
|
-
"@lovo/matter
|
|
51
|
+
"@lovo/matter": "2.0.0",
|
|
52
|
+
"@matter/registry": "0.0.0",
|
|
52
53
|
"@matter/tsconfig": "0.0.0",
|
|
53
|
-
"@matter
|
|
54
|
+
"@lovo/matter-react": "2.0.0"
|
|
54
55
|
},
|
|
55
56
|
"peerDependencies": {
|
|
56
57
|
"playwright": "*"
|