@kudzujs/core 0.16.26 → 0.16.28
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 +21 -1
- package/framework/build.mjs +35 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Kudzu compiles ordinary React-shaped TypeScript and TSX into complete static HTM
|
|
|
14
14
|
|
|
15
15
|
> Experimental `0.16.x`: the compiler API and supported TSX surface may change.
|
|
16
16
|
|
|
17
|
-
**Current release: [0.16.
|
|
17
|
+
**Current release: [0.16.28](https://github.com/kudzujs/kudzu/releases/tag/v0.16.28).** Write reusable components, native event handlers, and pure collection expressions; Kudzu specializes supported source into static content and direct browser updates.
|
|
18
18
|
|
|
19
19
|
- [Documentation](https://kudzujs.cloud/docs)
|
|
20
20
|
- [Installation guide](https://kudzujs.cloud/docs#install)
|
|
@@ -130,6 +130,26 @@ A static sibling outside an enhanced-navigation group ships no JavaScript merely
|
|
|
130
130
|
because another page is interactive. Shared layout effects or explicit navigation
|
|
131
131
|
groups have their own lifetime; native anchors remain the default.
|
|
132
132
|
|
|
133
|
+
## Verify
|
|
134
|
+
|
|
135
|
+
A successful build validates supported source and emits deployable outputs; it
|
|
136
|
+
does not verify browser behavior or accessibility. Check visible DOM and relevant
|
|
137
|
+
interactions, labels, status updates, keyboard focus, and responsive layouts in a
|
|
138
|
+
browser as needed. Binding comments and inert templates mean raw HTML string
|
|
139
|
+
matches or tag stripping are not reliable checks of rendered text.
|
|
140
|
+
|
|
141
|
+
Normal builds also scan generated route HTML after `afterBuild`, reporting counts
|
|
142
|
+
with/without script or modulepreload text markers and unreadable files, with up to
|
|
143
|
+
five paths per category (long paths are truncated). This is a literal text scan,
|
|
144
|
+
not proof of script freedom: comments and inert content can match, inline event
|
|
145
|
+
attributes are not checked, and extra public HTML files are outside the route
|
|
146
|
+
inventory. Quiet and JSON builds omit this summary.
|
|
147
|
+
|
|
148
|
+
Keep checks bounded and report concise counts and failing paths rather than
|
|
149
|
+
repeatedly dumping minified artifacts. A missing tool or truncated response is
|
|
150
|
+
not a pass. After source changes, rerun affected checks. Optional compiler/artifact
|
|
151
|
+
reports and their limits are documented under [Build output](https://kudzujs.cloud/docs#build).
|
|
152
|
+
|
|
133
153
|
## How It Works
|
|
134
154
|
|
|
135
155
|
```text
|
package/framework/build.mjs
CHANGED
|
@@ -59,12 +59,16 @@ export async function buildWithSession(project, { changedFiles, quiet = false, m
|
|
|
59
59
|
try {
|
|
60
60
|
await recoverOutput(outputDirectory, backupOutput)
|
|
61
61
|
await rm(stagedOutput, { recursive: true, force: true })
|
|
62
|
-
const { result, pageCount, behaviorCount, cache, inspectionData, explanation } = await buildInto(project, stagedOutput, { changedFiles, minify, quiet, retainCache, explanationRoute })
|
|
62
|
+
const { result, pageCount, behaviorCount, cache, inspectionData, explanation, htmlSummary } = await buildInto(project, stagedOutput, { changedFiles, minify, quiet, retainCache, explanationRoute })
|
|
63
63
|
const promoteStarted = project.timings ? performance.now() : 0
|
|
64
64
|
await promoteOutput(stagedOutput, outputDirectory, backupOutput)
|
|
65
65
|
addTiming(project.timings, "writeMs", promoteStarted)
|
|
66
66
|
project.buildCache = retainCache ? cache : undefined
|
|
67
|
-
if (!quiet)
|
|
67
|
+
if (!quiet) {
|
|
68
|
+
console.log(`Built ${pageCount} page(s), ${behaviorCount} interactive page(s) into dist/`)
|
|
69
|
+
console.log(htmlSummary)
|
|
70
|
+
console.log("Browser behavior and accessibility need verification: https://kudzujs.cloud/docs#build")
|
|
71
|
+
}
|
|
68
72
|
return explanationRoute ? explanation : inspection ? createInspectionReport(inspectionData) : result
|
|
69
73
|
} catch (error) {
|
|
70
74
|
const normalized = normalizeDiagnosticError(error, root)
|
|
@@ -550,6 +554,34 @@ async function buildInto(project, outputDirectory, { changedFiles, minify, quiet
|
|
|
550
554
|
if (typeof config.afterBuild !== "function") throw new Error("kudzu.config afterBuild must be a function")
|
|
551
555
|
await config.afterBuild({ root, outDir: outputDirectory, sourceDir: sourceDirectory, base, routes: plans.map(plan => plan.route), plans, rewrites: sortedRewrites, artifacts })
|
|
552
556
|
}
|
|
557
|
+
let htmlSummary
|
|
558
|
+
if (!quiet) {
|
|
559
|
+
const counts = { "With markers": 0, Unreadable: 0 }
|
|
560
|
+
const samples = { "With markers": [], Unreadable: [] }
|
|
561
|
+
// Scan final route files, not compiler closure metadata or a previous build's scratch report.
|
|
562
|
+
const outputs = routeRecords.map(record => record.output).sort()
|
|
563
|
+
for (let offset = 0; offset < outputs.length; offset += 64) {
|
|
564
|
+
const batch = outputs.slice(offset, offset + 64)
|
|
565
|
+
const categories = await Promise.all(batch.map(async output => {
|
|
566
|
+
try {
|
|
567
|
+
const html = await readFile(join(outputDirectory, output, "index.html"), "utf8")
|
|
568
|
+
if (/<script(?=[\s/>])|<link(?=[\s/>])[^>]*\bmodulepreload\b/i.test(html)) return "With markers"
|
|
569
|
+
} catch {
|
|
570
|
+
return "Unreadable"
|
|
571
|
+
}
|
|
572
|
+
}))
|
|
573
|
+
for (const [index, category] of categories.entries()) {
|
|
574
|
+
if (!category) continue
|
|
575
|
+
counts[category]++
|
|
576
|
+
if (samples[category].length < 5) {
|
|
577
|
+
const path = join("dist", batch[index], "index.html").replaceAll(sep, "/")
|
|
578
|
+
samples[category].push(JSON.stringify(path.length > 240 ? `${path.slice(0, 240)}...` : path))
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
htmlSummary = `Route HTML scan: ${routeRecords.length - counts["With markers"] - counts.Unreadable} without script/modulepreload text markers, ${counts["With markers"]} with markers, ${counts.Unreadable} unreadable.`
|
|
583
|
+
for (const category of Object.keys(counts)) if (counts[category]) htmlSummary += `\n ${category}: ${samples[category].join(", ")}${counts[category] > 5 ? ` (+${counts[category] - 5} more)` : ""}`
|
|
584
|
+
}
|
|
553
585
|
addTiming(project.timings, "writeMs", writeStarted)
|
|
554
586
|
|
|
555
587
|
let explanation
|
|
@@ -567,6 +599,7 @@ async function buildInto(project, outputDirectory, { changedFiles, minify, quiet
|
|
|
567
599
|
result: { sourceResults, incremental },
|
|
568
600
|
inspectionData: { sourceFiles: sourceFiles.map(file => relative(root, file).replaceAll(sep, "/")), sourceResults, compatibility, artifacts },
|
|
569
601
|
explanation,
|
|
602
|
+
htmlSummary,
|
|
570
603
|
pageCount: routeRecords.length,
|
|
571
604
|
behaviorCount,
|
|
572
605
|
cache: { pageRenders, pageSources, placeholders, sourceResults: sourceResultsByFile }
|