@agent-scope/cli 1.0.2 → 1.1.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/dist/cli.js +159 -21
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +134 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +134 -2
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { loadTrace, generateTest, getBrowserEntryScript } from '@agent-scope/pla
|
|
|
6
6
|
import { chromium } from 'playwright';
|
|
7
7
|
import { safeRender, ALL_CONTEXT_IDS, contextAxis, stressAxis, ALL_STRESS_IDS, RenderMatrix, SatoriRenderer, BrowserPool } from '@agent-scope/render';
|
|
8
8
|
import * as esbuild from 'esbuild';
|
|
9
|
+
import { createRequire } from 'module';
|
|
9
10
|
|
|
10
11
|
// src/manifest-commands.ts
|
|
11
12
|
|
|
@@ -315,7 +316,7 @@ function writeReportToFile(report, outputPath, pretty) {
|
|
|
315
316
|
const json = pretty ? JSON.stringify(report, null, 2) : JSON.stringify(report);
|
|
316
317
|
writeFileSync(outputPath, json, "utf-8");
|
|
317
318
|
}
|
|
318
|
-
async function buildComponentHarness(filePath, componentName, props, viewportWidth) {
|
|
319
|
+
async function buildComponentHarness(filePath, componentName, props, viewportWidth, projectCss) {
|
|
319
320
|
const bundledScript = await bundleComponentToIIFE(filePath, componentName, props);
|
|
320
321
|
return wrapInHtml(bundledScript, viewportWidth);
|
|
321
322
|
}
|
|
@@ -403,7 +404,8 @@ ${msg}`);
|
|
|
403
404
|
}
|
|
404
405
|
return outputFile.text;
|
|
405
406
|
}
|
|
406
|
-
function wrapInHtml(bundledScript, viewportWidth) {
|
|
407
|
+
function wrapInHtml(bundledScript, viewportWidth, projectCss) {
|
|
408
|
+
const projectStyleBlock = "";
|
|
407
409
|
return `<!DOCTYPE html>
|
|
408
410
|
<html lang="en">
|
|
409
411
|
<head>
|
|
@@ -414,6 +416,7 @@ function wrapInHtml(bundledScript, viewportWidth) {
|
|
|
414
416
|
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, sans-serif; }
|
|
415
417
|
#scope-root { display: inline-block; min-width: 1px; min-height: 1px; }
|
|
416
418
|
</style>
|
|
419
|
+
${projectStyleBlock}
|
|
417
420
|
</head>
|
|
418
421
|
<body>
|
|
419
422
|
<div id="scope-root" data-reactscope-root></div>
|
|
@@ -581,6 +584,121 @@ function csvEscape(value) {
|
|
|
581
584
|
}
|
|
582
585
|
return value;
|
|
583
586
|
}
|
|
587
|
+
var CONFIG_FILENAMES = [
|
|
588
|
+
".reactscope/config.json",
|
|
589
|
+
".reactscope/config.js",
|
|
590
|
+
".reactscope/config.mjs"
|
|
591
|
+
];
|
|
592
|
+
var STYLE_ENTRY_CANDIDATES = [
|
|
593
|
+
"src/index.css",
|
|
594
|
+
"src/globals.css",
|
|
595
|
+
"app/globals.css",
|
|
596
|
+
"app/index.css",
|
|
597
|
+
"styles/index.css",
|
|
598
|
+
"index.css"
|
|
599
|
+
];
|
|
600
|
+
var TAILWIND_IMPORT = /@import\s+["']tailwindcss["']\s*;?/;
|
|
601
|
+
var compilerCache = null;
|
|
602
|
+
function getCachedBuild(cwd) {
|
|
603
|
+
if (compilerCache !== null && resolve(compilerCache.cwd) === resolve(cwd)) {
|
|
604
|
+
return compilerCache.build;
|
|
605
|
+
}
|
|
606
|
+
return null;
|
|
607
|
+
}
|
|
608
|
+
function findStylesEntry(cwd) {
|
|
609
|
+
for (const name of CONFIG_FILENAMES) {
|
|
610
|
+
const p = resolve(cwd, name);
|
|
611
|
+
if (!existsSync(p)) continue;
|
|
612
|
+
try {
|
|
613
|
+
if (name.endsWith(".json")) {
|
|
614
|
+
const raw = readFileSync(p, "utf-8");
|
|
615
|
+
const data = JSON.parse(raw);
|
|
616
|
+
const scope = data.scope;
|
|
617
|
+
const entry = scope?.stylesEntry ?? data.stylesEntry;
|
|
618
|
+
if (typeof entry === "string") {
|
|
619
|
+
const full = resolve(cwd, entry);
|
|
620
|
+
if (existsSync(full)) return full;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
} catch {
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
const pkgPath = resolve(cwd, "package.json");
|
|
627
|
+
if (existsSync(pkgPath)) {
|
|
628
|
+
try {
|
|
629
|
+
const raw = readFileSync(pkgPath, "utf-8");
|
|
630
|
+
const pkg = JSON.parse(raw);
|
|
631
|
+
const entry = pkg.scope?.stylesEntry;
|
|
632
|
+
if (typeof entry === "string") {
|
|
633
|
+
const full = resolve(cwd, entry);
|
|
634
|
+
if (existsSync(full)) return full;
|
|
635
|
+
}
|
|
636
|
+
} catch {
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
for (const candidate of STYLE_ENTRY_CANDIDATES) {
|
|
640
|
+
const full = resolve(cwd, candidate);
|
|
641
|
+
if (existsSync(full)) {
|
|
642
|
+
try {
|
|
643
|
+
const content = readFileSync(full, "utf-8");
|
|
644
|
+
if (TAILWIND_IMPORT.test(content)) return full;
|
|
645
|
+
} catch {
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return null;
|
|
650
|
+
}
|
|
651
|
+
async function getTailwindCompiler(cwd) {
|
|
652
|
+
const cached = getCachedBuild(cwd);
|
|
653
|
+
if (cached !== null) return cached;
|
|
654
|
+
const entryPath = findStylesEntry(cwd);
|
|
655
|
+
if (entryPath === null) return null;
|
|
656
|
+
let compile;
|
|
657
|
+
try {
|
|
658
|
+
const require2 = createRequire(resolve(cwd, "package.json"));
|
|
659
|
+
const tailwind = require2("tailwindcss");
|
|
660
|
+
const fn = tailwind.compile;
|
|
661
|
+
if (typeof fn !== "function") return null;
|
|
662
|
+
compile = fn;
|
|
663
|
+
} catch {
|
|
664
|
+
return null;
|
|
665
|
+
}
|
|
666
|
+
const entryContent = readFileSync(entryPath, "utf-8");
|
|
667
|
+
const loadStylesheet = async (id, base) => {
|
|
668
|
+
if (id === "tailwindcss") {
|
|
669
|
+
const nodeModules = resolve(cwd, "node_modules");
|
|
670
|
+
const tailwindCssPath = resolve(nodeModules, "tailwindcss", "index.css");
|
|
671
|
+
if (!existsSync(tailwindCssPath)) {
|
|
672
|
+
throw new Error(
|
|
673
|
+
`Tailwind v4: tailwindcss package not found at ${tailwindCssPath}. Install with: npm install tailwindcss`
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
const content = readFileSync(tailwindCssPath, "utf-8");
|
|
677
|
+
return { path: "virtual:tailwindcss/index.css", base, content };
|
|
678
|
+
}
|
|
679
|
+
const full = resolve(base, id);
|
|
680
|
+
if (existsSync(full)) {
|
|
681
|
+
const content = readFileSync(full, "utf-8");
|
|
682
|
+
return { path: full, base: resolve(full, ".."), content };
|
|
683
|
+
}
|
|
684
|
+
throw new Error(`Tailwind v4: could not load stylesheet: ${id} (base: ${base})`);
|
|
685
|
+
};
|
|
686
|
+
const result = await compile(entryContent, {
|
|
687
|
+
base: cwd,
|
|
688
|
+
from: entryPath,
|
|
689
|
+
loadStylesheet
|
|
690
|
+
});
|
|
691
|
+
const build2 = result.build.bind(result);
|
|
692
|
+
compilerCache = { cwd, build: build2 };
|
|
693
|
+
return build2;
|
|
694
|
+
}
|
|
695
|
+
async function getCompiledCssForClasses(cwd, classes) {
|
|
696
|
+
const build2 = await getTailwindCompiler(cwd);
|
|
697
|
+
if (build2 === null) return null;
|
|
698
|
+
const deduped = [...new Set(classes)].filter(Boolean);
|
|
699
|
+
if (deduped.length === 0) return null;
|
|
700
|
+
return build2(deduped);
|
|
701
|
+
}
|
|
584
702
|
|
|
585
703
|
// src/render-commands.ts
|
|
586
704
|
var MANIFEST_PATH2 = ".reactscope/manifest.json";
|
|
@@ -635,6 +753,20 @@ function buildRenderer(filePath, componentName, viewportWidth, viewportHeight) {
|
|
|
635
753
|
if (renderError !== null) {
|
|
636
754
|
throw new Error(`Component render error: ${renderError}`);
|
|
637
755
|
}
|
|
756
|
+
const rootDir = process.cwd();
|
|
757
|
+
const classes = await page.evaluate(() => {
|
|
758
|
+
const set = /* @__PURE__ */ new Set();
|
|
759
|
+
document.querySelectorAll("[class]").forEach((el) => {
|
|
760
|
+
for (const c of el.className.split(/\s+/)) {
|
|
761
|
+
if (c) set.add(c);
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
return [...set];
|
|
765
|
+
});
|
|
766
|
+
const projectCss = await getCompiledCssForClasses(rootDir, classes);
|
|
767
|
+
if (projectCss != null && projectCss.length > 0) {
|
|
768
|
+
await page.addStyleTag({ content: projectCss });
|
|
769
|
+
}
|
|
638
770
|
const renderTimeMs = performance.now() - startMs;
|
|
639
771
|
const rootLocator = page.locator("[data-reactscope-root]");
|
|
640
772
|
const boundingBox = await rootLocator.boundingBox();
|