Repository navigation
Harden the compiler and checker, speed up scoping, and fix Cloudflare base-path staging - #102
collin-thomas wants to merge 36 commits into
Conversation
…es only that preview’s theme, and saves to theme-demo. Outside the preview, it still uses the site-wide theme setting. Updated the theme-toggle.html:23, styles.css:106, theme-toggle.md:18, and examples.spec.ts:29.
…pilation, CSS scoping, JS/TypeScript scoping, directive execution (build, routes, server, stream), static checking (--check), and dist/ artifact emission.
Here is a summary of the bugs discovered, fixed, and covered with tests:
1. CSS & JS Whole-Identifier Scoping (No Substring Clobbering)
CSS Scoping (styles.ts): prefixKeyframes, scopeCssCustomProperties, scopeLayerNames, scopeViewTransitionNames, and scopeAnchorNames previously looped over declared names sequentially (forEach), which allowed a later or shorter declared name (such as b or --a) to match inside an earlier generated name (all minified hashes begin with b...) or as a prefix of a longer name (--a-b), corrupting the emitted CSS. All five passes now rewrite whole identifiers in a single pass with shieldCssStrings protection, and shieldCssStrings now uses createContentShield so nested shielding is re-entrant.
JS DOM Selector Scoping (javascript.ts): prefixElementAttribute previously iterated uniqueAttributesToReplace.forEach(...) sequentially over each <script> block, allowing a short class/id/name token (such as b) to corrupt an earlier minified token (b0123...) in className =, setAttribute("class", ...), getElementsByClassName(...), and classList.*. It now rewrites tokens in a single lookup pass per AST/call pattern and also supports space-separated multi-class strings in getElementsByClassName("a b").
2. Raw-Text, Comment, and Attribute Boundary Hardening
Slot & Prop Injection (components.ts):
injectProps, injectPropAttributes, parseNamedSlots, and replaceDefaultSlots now shield/mask HTML comments and <script>/<style>/<textarea> bodies so example markers in comments or code strings are never mutated.
parseNamedSlots now supports single-quoted data-bascik-slot='name' and closing tags with trailing whitespace (</div >).
mergeAttributesOntoRoot now matches class= and style= with a leading whitespace boundary so data-class="..." or data-style="..." on a component's root element is never corrupted.
Element & ID Class Injection (styles.ts, javascript.ts):
addElementClassesInHtml, addIdClassesInHtml, and replaceSafeAttr now shield HTML comments and <style>/<textarea> raw text so commented-out markup or <textarea> values are not mutated.
<meta> tag shielding in prefixElementAttribute is now quote-aware (> inside content="a > b") and uses createContentShield.
Page Head <style> Minification & Unresolved Tag Scan (processing.ts):
Page-level <style> minification under minify.css: true previously replaced the tag with <style>${minifiedCss}</style>, dropping media="..." or other attributes on the <style> tag. It now preserves the original opening and closing tags.
The unresolved component warning scan now uses maskRawTextContent so > inside a quoted attribute on <script>/<style>/<textarea> does not terminate raw-text stripping early.
Script Type & External src Detection (script-types.ts, typescript.ts, processing.ts, javascript.ts, script-source-lines.ts):
getScriptType, withoutTypeAttribute, and src= checks now match whole attribute names (data-type and data-src are no longer mistaken for type and src), and transformTypeScriptScriptTags / minifyScriptTagsInHtml ignore <script> tags inside HTML comments and <textarea>.
3. Directive Conflicts, CSP Hashes, Sitemap, and --check
Directive Conflict Parity (build-scripts.ts, routes.ts): Added data-bascik-build + data-bascik-stream and data-bascik-routes + data-bascik-stream conflict guards at build time (matching server-scripts.ts and check.ts), and updated executeRoutesScript to use findComponentRoot and quote-aware getHtmlAttributeValue.
CSP Hashes (csp-hashes.ts): computePageCspHashes now blanks HTML comments, <textarea>/<title>/<noscript>/<xmp>, and <script> bodies (before scanning <style>) so <script> or <style> text inside comments or JS strings is never hashed into csp-hashes.json.
Sitemap Exclusion (sitemap.ts): isPageExcludedFromSitemap now strips comments and raw-text elements before checking for <meta name="bascik-sitemap" content="exclude">, uses quote-aware <meta> matching, and falls back to checking the emitted dist/ HTML for dynamically generated route pages ([slug].html).
bascik --check (check.ts, compatibility-checker.ts):
extractOpenTagData and maskPreservedSubtrees now use quote-aware open-tag matching.
Component structure order and compatibility checks now ignore comments and raw-text/code blocks, skip Node directive scripts when checking browser JS rules, and strip comments before matching CSS/JS compatibility regexes.
…workspace have now been run and verified.
1. Fixed Failing E2E Test (dynamic-dom.test.ts)
Cause: dynamic-dom.test.ts previously had an outdated assertion expecting li.setAttribute("class", "item unscoped-item") to leave "item unscoped-item" untouched because the old single-token setAttribute("class", ...) regex failed to match space-separated multi-class strings (even though the JS-only class discovery pass in javascript.ts already split setAttribute("class", "x y") on whitespace).
Resolution: Updated dynamic-dom.test.ts and compatibility.md to reflect that setAttribute("class", "item unscoped-item") scopes known component classes (item
→
→ bascik__dynamic-dom__item) while preserving unknown global classes (unscoped-item), matching el.className = ... and getElementsByClassName(...).
2. New E2E Coverage Added for Compiler & Scoping Fixes
scoping-boundary.test.ts & scoping-boundary.html & scoping-boundary-test.html:
Verifies <textarea> raw text containing <button id="boundary-btn" class="boundary-box" data-bascik-prop-sample="x"> is never mutated by element/ID/class/prop passes.
Verifies short and prefix-overlapping class names (.a, .b, .a-b) and CSS custom properties (--v, --v-long) scope cleanly without clobbering, and document.getElementsByClassName("a b") matches multi-class elements across instances.
Verifies <script data-src="/lazy-chunk.js"> is recognized as an inline script (not skipped as external src).
Verifies root attribute inheritance (class="passed-root-class" style="outline-width: 2px;") preserves data-class and data-style on the component root.
typescript-strip.test.ts & ts-strip-test.html:
Verifies <script data-type="custom-meta" data-src="/lazy.js" type="text/typescript"> strips TypeScript and type="text/typescript" while preserving data-type and data-src in the emitted HTML across all server modes.
slots-test.html (slots.test.ts):
Verifies single-quoted data-bascik-slot='footer' and closing tags with trailing whitespace (</div >) are extracted and slotted in browser E2E runs.
Eliminated Per-Instance scopedCssCache Misses on ID-Bearing Components (javascript.ts)
Before: scopedCssCache included JSON.stringify(component.scopedIdNames) in its cache key. Because scopedIdNames holds per-instance IDs (bascik__comp__<instanceId>__btn), every component template containing an id="..." attribute missed scopedCssCache on every single instance and re-ran all 10 CSS regex/shielding passes from scratch.
Now: rewriteIdReferencesInCss (for url(#id) SVG/CSS fragment references) runs on component.cssFileContent before the cache lookup when url( is present, and scopedIdKey is removed from the cache key. Components with ordinary HTML IDs and #id CSS selectors now hit scopedCssCache across all instances while components with url(#id) CSS fragments still get per-instance CSS.
Consolidated addElementClassesInHtml into a Single Pass (styles.ts)
Before: Looped over elementsConvertedClasses and ran result = result.replace(new RegExp('<' + element + ...), ...) once per styled element tag (e.g., 10 full HTML scans for a component styling 10 HTML elements).
Now: Compiles a single combined alternation regex (<(p|h1|h2|div|...)(?![\w.:-])...>) and injects the corresponding bascik__<scope>__el__<tag> class in one pass over the shielded HTML.
Fast-Path Early Returns Across CSS & HTML Scoping Passes (styles.ts, javascript.ts, id-references.ts, components.ts, processing.ts)
styles.ts: Added cheap substring guards before calling shieldCssStrings() / maskCssSyntax() in getKeyframeNames (@Keyframes), removeIdSelectors ([id), convertCssIdSelectorsToClasses (#), scopeViewTransitionNames (view-transition-name), scopeCounterStyleNames (@counter-style), scopeAnchorNames (anchor-name / @position-try), and scopeInlineStyleTags (<style).
javascript.ts: Skips the entire "id" or "name" prefixElementAttribute pass (avoiding comment shielding, <style>/<textarea> shielding, and tag scanning) when the component template contains no id= or name= attribute and no data-bascik-preserve directive. Also skips quote-range scanning in replaceSafeAttr for tags without =, and skips rewriteIdReferencesInStyleTags when no <style is present.
id-references.ts: Added QUICK_ID_REF_RE and usemap guards in rewriteIdReferencesInHtml and rewriteUsemapReferencesInHtml so tags and templates without ID-reference attributes skip shielding and per-attribute regex replacements.
components.ts & processing.ts: injectProps returns immediately when props is empty and the template has no data-bascik-prop- markers. recursivelyTranspile skips the while (childSearchFrom < slotTemplate.length) nested-component slot-protection scan when neither the component template nor usage innerContent contains data-bascik-slot.
Deduplicated Component Script Dependency Scanning per Page (processing.ts)
Before: transpilePage looped over allUsedComponents (every component instance on the page) and called collectAllScriptDeps on each one—re-scanning the same component's raw source 50+ times on pages with repeated components.
Now: Deduplicates by comp.name (seenDepComponents) so collectAllScriptDeps runs at most once per unique component used on a page.
Scoped Cache Invalidation in watchSourceCycles & Package Resolution Memoization (watch-source.ts, package-identity.ts, build-scripts.ts)
watch-source.ts: Direct page .html edits in exec.watch mode now call clearBuildScriptCaches(path) for the edited page instead of wiping all build-script caches and componentListCache globally on every edit.
package-identity.ts: Memoizes resolved external package specifiers (resolvedSpecMemo) so import.meta.resolve + realpath is not repeated for every build script tag across every page, while still reading entry and package.json files so live package edits invalidate cache keys accurately.
Regression & Parity Tests Added
pipeline-efficiency.test.ts:
Verifies scopedCssCache hits on repeated instances of ID-bearing components while preserving per-instance CSS when url(#id) fragments are used.
Verifies byte-for-byte parity of single-pass addElementClassesInHtml + addIdClassesInHtml across comments, scripts, textareas, and existing attributes.
Verifies rewriteIdReferencesInHtml across all single-ID, ID-list, fragment (href, xlink:href), SVG presentation (fill, stroke, filter, clip-path, mask, marker-*), and inline style attributes.
Verifies full CSS scoping parity (@layer, @Property, @counter-style, @container, @position-try, ::view-transition-*, @Keyframes, #id, element selectors, and code preservation) with minify.identifiers both false and true.
Property-based fast-check suite verifying deterministic cold-vs-warm cache output across nested and sibling component trees.
watch-source.integration.test.ts:
Added tests verifying that direct page HTML edits keep componentListCache and unrelated build-script memos warm, while component edits invalidate componentListCache and clear per-path build-script caches.
…tage microbenchmarks, a dedicated pipeline-heavy site, the create-bascik starter site, and the full 100-page docs site (both build and live dev-edit timelines). All full-site comparisons were run using yarn workspace @bascik/bascik profile:compare and profile:compiler on isolated tmp fixtures with alternating round order (baseline -> candidate on odd rounds, candidate -> baseline on even rounds) and verified byteIdentical: true across every emitted HTML file. 1. Pipeline Stage Microbenchmarks (Direct Head-to-Head) Comparing the pre-optimization compiler snapshot (f8eabb2) against the optimized compiler in the same Node process across 5 interleaved rounds: Pipeline Stage / Workload Before After Speedup rewriteIdReferencesInHtml (IDs present, 0 ID-ref attrs) 2,115.8 ms 85.4 ms -96.0% (24.77x faster) computePackageIdentity ("marked", 1,000 calls) 1,242.9 ms 117.1 ms -90.6% (10.62x faster) rewriteIdReferencesInHtml (mixed tags + aria-*/href) 2,307.7 ms 225.6 ms -90.2% (10.23x faster) recursivelyTranspile (40 ID-bearing components w/ dynamic data-bascik-attr-*) 7,222.7 ms 3,788.0 ms -47.6% (1.91x faster) recursivelyTranspile (30 nested no-slot components) 405.1 ms 369.8 ms -8.7% (1.10x faster) addElementClassesInHtml (11 element rules, 5x template) 424.5 ms 397.2 ms -6.4% (1.07x faster) 2. Dedicated Pipeline-Heavy Site (perf-site) Workload: 25 pages, 10 components with id attributes, element CSS selectors, #id CSS selectors, aria-labelledby/href="#..." references, data-bascik-attr-* + data-bascik-prop-* bindings (1,000 total component instances across the build), and a data-bascik-build script importing marked on every page (n = 5 paired rounds, byteIdentical: true). Metric (Median of 5 Rounds) Before After Improvement Warm Build readyMs (full CLI wall time) 1,124.5 ms 672.8 ms -40.2% (1.67x faster) Warm Build batchMs (page compilation batch) 1,080.0 ms 634.0 ms -41.3% (1.70x faster) Warm Build sum(workMs) (synchronous JS work) 847.0 ms 589.0 ms -30.5% (1.44x faster) Warm Build CPU time (user + system) 1,283.5 ms 892.2 ms -30.5% (-391 ms CPU) Cold Build readyMs (including child script spawns) 1,136.8 ms 940.0 ms -17.3% (1.21x faster) Cold Build batchMs 1,090.0 ms 901.0 ms -17.3% (1.21x faster) Why this site sees the largest end-to-end gain: Every component instance has dynamic attribute bindings (data-bascik-attr-*) and id attributes. Previously, scopedCssCache missed on every single instance (1,000 CSS pipeline runs per build) because scopedIdNames was baked into the cache key, and computePackageIdentity("marked") re-resolved and re-tokenized marked's entry bundle 25 times per build. Now scopedCssCache hits across all instances after the first per component (10 misses, 990 hits), and computePackageIdentity memoizes specifier resolution and AST specifier extraction. 3. create-bascik Starter Site (starter-site) Workload: Freshly scaffolded starter app (2 pages, 3 components, n = 5 paired rounds, byteIdentical: true). Metric (Median of 5 Rounds) Before After Improvement Cold Build batchMs 96.0 ms 85.0 ms -11.5% Cold Build sum(workMs) 32.2 ms 23.8 ms -26.1% (1.35x faster) Warm Build batchMs 52.0 ms 49.0 ms -5.8% Warm Build sum(workMs) 31.0 ms 26.7 ms -13.9% (1.16x faster) 4. Repository docs Site (100 pages, workers: true) Workload: All 100 docs pages, 689 data-bascik-build scripts, 6 exec scripts, 8 worker threads (n = 3 paired rounds, byteIdentical: true). Metric (Median of 3 Rounds) Before After Improvement Warm Build readyMs 4,225.5 ms 3,716.7 ms -12.0% (-509 ms) Warm Build batchMs 3,910.0 ms 3,470.0 ms -11.3% (-440 ms) Warm Build sum(workMs) (across all 100 pages) 14,605.0 ms 13,147.0 ms -10.0% (-1,458 ms) Cold Build sum(workMs) 12,715.0 ms 11,646.0 ms -8.4% (-1,069 ms) Cold Build CPU time (main process) 21,610.4 ms 19,823.9 ms -8.3% (-1,786 ms) Dev Mode: Single Page Edit (src/pages/index.html) 452.8 ms (3,155 readFiles) 422.8 ms (3,059 readFiles) -6.6% wall time, ~96 fewer component file reads per edit Additional Refinements Landed During Benchmarking While running the profiler harness, we also identified and landed five additional hot-path improvements: package-identity.ts: Memoized collectPackageSpecifiers(entry) by entry file content (entrySpecifiersMemo) in computePackageIdentity so large external package entrypoints (like marked) are not re-tokenized by the JS scanner on every build script cache check (10.6x speedup on computePackageIdentity). javascript.ts: Cached the extracted set of CSS class names per stylesheet in cssDeclaredClassesCache, checked tagMatch.includes("${attrName}=") in replaceSafeAttr, and added a fast path in namespaceScriptTags when no <script tag is present. styles.ts: Added a /class=/i fast path in injectClassIntoTag so elements without an existing class attribute skip the character-by-character quote scanner. shielding.ts: Added tag-presence checks in shieldElementContents and maskElementContents before compiling and running per-tag regexes, and a data-bascik-preserve fast path in stripPreserveDirectives. compiler-timeline.ts: Updated the repository docs fixture setup to copy sibling examples and skills directories referenced by bascik.config.ts.
…nd documented across the docs site, Copilot instructions, and profiler agent definition so any future contributor or agent can run the exact same three-tier comparison in one command. What Was Added & Updated Built-in Pipeline Benchmark Fixture (--fixture pipeline in bench) profile-fixture.ts: Added createPipelineBenchmarkFixture(), which generates the 25-page, 10-component, 1,000-instance synthetic benchmark project (exercising id scoping, element and #id CSS rules, aria-* and href="#..." ID reference rewriting, dynamic data-bascik-attr-* and data-bascik-prop-* bindings, and external package build scripts). compiler-compare.ts: Added --fixture pipeline support so you no longer have to hand-roll a temporary project to benchmark compiler changes: compiler-timeline.test.ts & README.md: Added unit tests and CLI documentation for --fixture pipeline. New Dedicated Internals Docs Page (/internals/benchmarking) benchmarking.md & benchmarking.html: Created the new Benchmarking & Profiling page covering: Throughput microbenchmarks (yarn pkg:bench) Private report directory isolation rules (0700 outside the repo) Step-by-step git worktree snapshot setup (avoiding git stash) Paired compiler comparisons (profile:compare) for the built-in --fixture pipeline, the create-bascik starter site, and the full docs site, including byteIdentical: true verification and how to read comparison.json Compiler timelines and live dev-edit (--edits) profiling (profile:compiler) Runtime workload captures (profile:workload) nav.ts, internals.md, and testing.md: Linked /internals/benchmarking in the Internals navigation, overview list, and the Testing Internals page. Copilot Instructions & Profiler Agent Updates copilot-instructions.md: Added the Repeatable Benchmarking & Compiler Comparisons (bench) section detailing the git worktree baseline rule, same-path paired build requirement for HTML byte parity, the three-tier benchmark matrix (--fixture pipeline, starter-site, docs), microbenchmarks, and tmp cleanup. bascik-profiler.agent.md: Updated the Bascik Performance & Profiling agent with the profile:compare and profile:compiler commands and the 5-step worktree comparison workflow.
…compatibility rule contract tests
Deploying bascik with
|
| Latest commit: |
58e66de
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://3bcf405f.bascik.pages.dev |
| Branch Preview URL: | https://pre-release-102.bascik.pages.dev |
…oted directive syntax
…nd CSS/JS scoping symmetry
…l 7 migration site torture tests
…ev rebuilds, align create-bascik LSP version pin, and consume dev E2E fixture reloads
…SP hashes, empty-valued preserve, and --fix/--check parity - csp-hashes: find scripts and styles with the WHATWG tokenizer so <!--, <textarea>, or <title> inside a script body no longer corrupts or drops hashes (strict CSP blocked valid scripts) - html-patterns: add hasHtmlAttribute and isPageAwareBuildOpenTag; data-bascik-build="pages" or "page-x" and attribute-like text in quoted values no longer defer a script - shielding: data-bascik-preserve="" (the bare form DOM serializers write) preserves id, name, and class like the bare directive - lsp/extension: quote-aware form attribute reader; unquoted external action URLs are recognized and empty preserve satisfies the name check; parity guard - check: new unknown-directive-value warning; --fix edits only usages --check reports (not comments, scripts, or textarea text) - js-document-class-query: cover compound/backtick selectors and getElementsByClassName(...)[0]/.item(0); skip selectors anchored on a scoped #id - cli: document --lint, --fix, and --only in help with a drift test; docs and skills updated
…ty, and file URLs with a trailing slash - adapter-cloudflare: stage public files below a non-root base (public/docs/...), keeping _worker.js and _routes.json at the public root. Every static page and asset under base: "/docs/" was a 404 on Pages and Workers while bascik --server served it - adapter-cloudflare: route the aliases of a static 404.html through the Worker and answer them with status 404, matching the Node server instead of the asset layer's 200 - server: a non-HTML extension path ending in / (/style.css/) is no longer served as the file; it falls through to page lookup and 404s like static hosts and the asset layer - workerd parity tests for both variants under a non-root base, plus the 404 page at its own URL; docs for base staging, 404 routing, and static alias redirects
…se metadata timing
…d it now passes 3 out of 3 runs. Before the change it failed every run. The test now holds every page except the slowest to median * 5, so a growing queue-wait staircase still fails it. The slowest page, which pays the one-time cold cost, is held to max(median * 10, 150) ms. The sum-versus-wall-time assertion is unchanged.
…set Fingerprinting. It covers: What Bascik does: it emits the hashes but doesn't set a policy. The recipe: a short post exec script that hashes each page's inline scripts and inserts a <meta http-equiv> policy. Meta tag limits: it can't carry frame-ancestors, sandbox or report-uri. Third-party scripts and 'unsafe-eval': when they're needed. Styles: why inline style="" attributes are harder. Checking it: how to see violations. It mentions that a post script can't read csp-hashes.json. It never mentions Cloudflare's 100-rule limit. The reason a <meta> tag works is simply that it needs no host configuration. Other docs changes: Deployment overview: the per-page _headers example is gone. It now has a short paragraph linking to the how-to. FAQ and Lighthouse Best Practices: they link to the how-to. Asset Fingerprinting: its sentence pointing at the removed example is reworded. Testing the script. I ran the exact script from the page against a copy of the built docs. Four pages loaded in a browser with no CSP violations. An injected script was blocked, which shows the check can fail.
feat(logging): add option to pin server URL in interactive terminal test(worker-pool): add tests for task settlement and worker behavior fix(worker-pool): prevent overwriting tasks for busy workers feat(transpile): improve build completion messages with color docs: update skill documentation for clarity and accuracy chore: add pinServerUrl to known defaults in config chore: update yarn.lock for dependency management
…5 s default to 30 s. Run on their own, all 7 cases pass and the typecheck is clean. The full yarn pkg:integration run, which is where the timeouts happened, is still going in the background, so I haven't confirmed the fix there yet. The change is in archetype-torture.integration.test.ts, on the it.each named "builds and passes --check on real example site from migration-tutorials-oct052026". Each case runs git archive, a full --build and a --check as separate processes. When the whole suite runs at once, that adds up to more than 5 s. 30 s matches the other tests in that file that start processes or a browser. I also added a comment saying why the timeout is longer.
- Introduced a new CI job for running unit tests on Windows. - Implemented `runNpm` and `npmInvocation` functions to handle npm commands across platforms. - Updated documentation to clarify Windows support and symlink behavior.
- Removed the `pinServerUrl` option from the logging configuration and related code. - Introduced `--no-pin` flag to disable pinning the server address in the terminal. - Updated documentation to reflect changes in logging options and added descriptions for new flags. - Enhanced CLI tests to validate behavior of `--quiet` and `--no-pin` flags. - Refactored logging functions to utilize a centralized logging level management system. - Ensured backward compatibility by providing informative error messages for deprecated configurations.
…and create examples/package.json
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical compiler and Cloudflare regressions, plus moderate checking, caching, URL-rewriting, and routing issues, block approval.
8 open findings
Keep Cloudflare control files at the public root · New Normalize empty script types as absent · New Preserve original script bodies during transformation · New Detect unscoped compound attribute selectors · New Close HTML attribute ranges on matching quotes only · New Detect unscoped compound attribute selectors · New Invalidate dependencies after pre-exec producers run · New Require positive confirmation before skipping project checks · New
What changed in this PR
Pre-launch hardening of Bascik’s compiler, checking tools, development pipeline, and Cloudflare deployment support.
Changes:
- Refines scoping, HTML/script parsing, directives, caching, and worker scheduling.
- Unifies checker and editor diagnostics and updates Cloudflare base-path staging.
- Expands regression tests, benchmarks, documentation, scaffolding, and CI.
| File | Review summary |
|---|---|
skills/bascik/scripts/verify.mjs |
Avoids duplicate linting. Moderate, line 79: older releases can silently skip installed language-server checks; require positive confirmation of integrated checks. |
skills/bascik-testing/SKILL.md |
Documents unified checking. |
skills/bascik-scripts/SKILL.md |
Clarifies page-aware directive values. |
skills/bascik-components/SKILL.md |
Updates verification guidance. |
skills/bascik-compatibility/SKILL.md |
Documents scoping exceptions and warnings. |
pkg/test-coverage.json |
Refreshes unit coverage. |
pkg/src/transpile.ts |
Colors summaries and pins server URLs. |
pkg/src/lib/worker-pool.ts |
Updates worker environments and dispatch tracking. |
pkg/src/lib/worker-pool.test.ts |
Tests worker environments and scheduling. |
pkg/src/lib/worker-pool.real.integration.test.ts |
Tests real-worker task settlement. |
pkg/src/lib/watch-source.ts |
Targets cache invalidation. Moderate, line 55: pre-exec producers can leave cached dependency bytes stale; fully invalidate when a matching pre entry ran. |
pkg/src/lib/typescript.ts |
Revises script scanning. Critical, line 269: masking alters markup-like literals inside executable scripts and can hide subsequent scripts; compile original, contextually located bodies. |
pkg/src/lib/typescript.test.ts |
Tests script attributes and raw-text handling. |
pkg/src/lib/shielding.test.ts |
Tests empty preserve directives. |
pkg/src/lib/server.ts |
Updates access logs and rejects slash-suffixed asset paths. |
pkg/src/lib/server-assets-suite.test.ts |
Tests trailing-slash asset requests. |
pkg/src/lib/script-types.ts |
Shares attribute parsing. Critical, line 12: empty script types no longer count as JavaScript, bypassing IIFE wrapping and risking repeated global declarations. |
pkg/src/lib/script-source-lines.ts |
Distinguishes source attributes from metadata. |
pkg/src/lib/routes.ts |
Validates stream conflicts and component roots. |
pkg/src/lib/routes-io.test.ts |
Tests routes/stream conflicts. |
pkg/src/lib/package-identity.ts |
Memoizes package resolution and dependency scanning. |
pkg/src/lib/ownership.test.ts |
Limits permission tests to supported environments. |
pkg/src/lib/output-scope.ts |
Handles unquoted class values near closing slashes. |
pkg/src/lib/output-scope.test.ts |
Tests unquoted class scoping. |
pkg/src/lib/log.ts |
Adds level-aware progress logging. |
pkg/src/lib/log.test.ts |
Tests progress filtering. |
pkg/src/lib/log-level.ts |
Centralizes logging levels. |
pkg/src/lib/id-references.test.ts |
Tests spaced and unquoted attributes. |
pkg/src/lib/html-patterns.ts |
Adds attribute and page-awareness helpers. |
pkg/src/lib/html-patterns.test.ts |
Tests directive attribute boundaries. |
pkg/src/lib/file-system.ts |
Colors asset-operation logs. |
pkg/src/lib/exec.ts |
Filters and colors exec progress. |
pkg/src/lib/exec.test.ts |
Tests quiet exec logging. |
pkg/src/lib/environment.ts |
Propagates URL-pinning overrides. |
pkg/src/lib/environment.test.ts |
Tests quiet and pinning flags. |
pkg/src/lib/dev-boot-transpile-timing.integration.test.ts |
Allows one bounded cold-page timing outlier. |
pkg/src/lib/css-minifier.ts |
Preserves empty custom-property whitespace. |
pkg/src/lib/css-minifier.test.ts |
Tests whitespace-sensitive CSS. |
pkg/src/lib/csp-hashes.test.ts |
Expands tokenizer-sensitive hashing cases. |
pkg/src/lib/config.ts |
Shares logging levels and colors warnings. |
pkg/src/lib/config-validation.ts |
Explains removed pinning configuration. |
pkg/src/lib/config-validation.test.ts |
Tests pinning migration guidance. |
pkg/src/lib/compiler-timeline.test.ts |
Tests benchmark fixture arguments. |
pkg/src/lib/compatibility-rules.json |
Updates scoping diagnostics. Moderate, line 14: unanchored compound attribute selectors escape reporting; fix the canonical rule and regenerate both copies. Moderate, line 23: sibling combinators incorrectly receive the safe descendant exception. |
pkg/src/lib/build-scripts.ts |
Validates stream conflicts and clears package memos. |
pkg/src/lib/build-scripts.test.ts |
Tests build/stream conflicts. |
pkg/src/lib/base-path.ts |
Revises URL rewriting. Moderate, line 169: treating backslashes as HTML quote escapes can hide following URL attributes and leave their base prefix unapplied. |
pkg/src/lib/base-path.test.ts |
Tests quoted and unquoted URL rewriting. |
pkg/src/index.ts |
Handles integrated checking and fix failures. |
pkg/src/index.test.ts |
Tests checker results and missing-server errors. |
pkg/package.json |
Updates release and optional language-server peer. |
pkg/e2e/tests/typescript-strip.test.ts |
Tests metadata-preserving TypeScript output. |
pkg/e2e/tests/scoping-boundary.test.ts |
Tests raw text, overlapping names, and root attributes. |
pkg/e2e/tests/dynamic-dom.test.ts |
Updates multi-class scoping expectations. |
pkg/e2e/tests/dev-server-reload.test.ts |
Waits for fixture-restoration reloads. |
pkg/e2e/src/pages/slots-test.html |
Exercises single-quoted slots. |
pkg/e2e/src/pages/scoping-boundary-test.html |
Exercises root attribute merging. |
pkg/e2e/src/components/ts-strip-test/ts-strip-test.html |
Adds script metadata fixtures. |
pkg/e2e/src/components/scoping-boundary/scoping-boundary.html |
Expands scoping boundary fixtures. |
pkg/e2e-test-coverage.json |
Refreshes E2E coverage. |
pkg/bench/README.md |
Documents pipeline benchmark fixtures. |
pkg/bench/compiler-timeline.ts |
Copies additional documentation dependencies. |
package.json |
Adds documentation build measurement. |
lsp/test-coverage.json |
Refreshes language-server coverage. |
lsp/src/start.ts |
Shares server startup. |
lsp/src/rules.ts |
Adds positioned, comment-aware compatibility matching. |
lsp/src/project.ts |
Adds API-root and project-path helpers. |
lsp/src/index.ts |
Exports checker and directive rules. |
lsp/src/ignore-comments.ts |
Accepts spaced suppression lists. |
lsp/src/ignore-comments.test.ts |
Tests spaced suppression lists. |
lsp/src/component-metadata.ts |
Recognizes unquoted bindings and slots. |
lsp/src/component-metadata.test.ts |
Tests unquoted metadata inference. |
lsp/src/compatibility-rules.json |
Updates editor diagnostics. Moderate, line 14: unanchored compound attribute selectors escape editor and per-file checks; regenerate from the corrected canonical rule. Moderate, line 23: sibling combinators incorrectly receive the safe descendant exception. |
lsp/src/bin.ts |
Uses shared startup. |
lsp/src/api-rules.ts |
Assigns diagnostic rule IDs. |
lsp/package.json |
Updates release and checker exports. |
extensions/vscode-bascik/test-coverage.json |
Refreshes thin-client coverage. |
extensions/vscode-bascik/src/test/lsp-parity.test.ts |
Removes duplicate-analysis parity tests. |
extensions/vscode-bascik/src/rules.ts |
Removes extension-owned rules. |
extensions/vscode-bascik/src/ignore-comments.ts |
Removes duplicate suppression parsing. |
extensions/vscode-bascik/src/ignore-comments.test.ts |
Removes duplicate parser tests. |
extensions/vscode-bascik/src/config.ts |
Removes extension-owned analysis configuration. |
extensions/vscode-bascik/src/config.test.ts |
Removes duplicate configuration tests. |
extensions/vscode-bascik/src/client-options.ts |
Defines document selection and server location. |
extensions/vscode-bascik/README.md |
Explains shared-server testing. |
extensions/vscode-bascik/package.json |
Updates release and bundling dependencies. |
extensions/vscode-bascik/build.mjs |
Bundles client and language server. |
extensions/vscode-bascik/.vscodeignore |
Excludes build-only files. |
examples/starter-site/package.json |
Updates compiler dependency. |
examples/package.json |
Establishes ES-module scope. |
examples/components/theme-toggle/theme-toggle.html |
Isolates preview themes and storage. |
docs/test-coverage.json |
Refreshes documentation coverage. |
docs/src/pages/internals/benchmarking.html |
Adds benchmarking page shell. |
docs/src/pages/how-to/content-security-policy.html |
Adds CSP page shell. |
docs/src/pages/development-server.html |
Includes build-breakdown content. |
docs/src/lib/pages-headers.ts |
Adds site-wide security headers. |
docs/src/lib/pages-headers.test.ts |
Tests security-header generation. |
docs/src/lib/nav.ts |
Registers benchmarking and CSP pages. |
docs/src/lib/csp-meta.test.ts |
Tests script hashes and policy injection. |
docs/src/css/styles.css |
Adds light-preview styling. |
docs/src/components/test-comp/test-comp.html |
Suppresses an intentional class-query warning. |
docs/src/components/docs-sidebar/docs-sidebar.html |
Suppresses intentional document-wide lookups. |
docs/src/components/docs-search/docs-search-dom.js |
Declares intentional lookup exceptions. |
docs/src/components/docs-nav/docs-nav.html |
Declares intentional document-wide lookups. |
docs/src/components/docs-footer/docs-footer.html |
Suppresses an intentional attribute lookup. |
docs/src/components/component-demo/component-demo.html |
Annotates intentional element-selector usage. |
docs/src/components/code-block/code-block.css |
Sets code tab width. |
docs/src/components/build-breakdown/build-breakdown.html |
Renders measured build breakdowns. |
docs/scripts/generate-csp-meta.ts |
Injects policies into emitted HTML. |
docs/scripts/generate-compatibility-rules.ts |
Stops generating extension-owned rules. |
docs/scripts/generate-compatibility-rules.test.ts |
Checks compiler/server rule parity. |
docs/scripts/capture-kit/project.ts |
Removes an unused linter executable export. |
docs/e2e/examples.spec.ts |
Tests preview-only theme changes. |
docs/e2e/csp.spec.ts |
Tests browser CSP enforcement. |
docs/content/why-bascik.md |
Updates terminal recording descriptions. |
docs/content/tools/vscode-extension.md |
Explains shared analysis and diagnostic scope. |
docs/content/testing/linting.md |
Documents unified command-line checks. |
docs/content/scoped-javascript.md |
Removes example-comment emoji. |
docs/content/preserve.md |
Documents empty preserve values. |
docs/content/lighthouse/best-practices.md |
Links the CSP recipe. |
docs/content/internals/transpilation-pipeline.md |
Clarifies development compilation order. |
docs/content/internals/testing.md |
Links benchmarking guidance. |
docs/content/internals/scoping-system.md |
Uses instance-safe ID lookup examples. |
docs/content/internals/create-app.md |
Updates scaffold checking guidance. |
docs/content/internals.md |
Adds benchmarking navigation. |
docs/content/how-to/page-aware-scripts.md |
Clarifies exact directive values. |
docs/content/how-to/asset-fingerprinting.md |
Removes an obsolete CSP reference. |
docs/content/getting-started.md |
Updates scaffold verification guidance. |
docs/content/exec-scripts.md |
Clarifies post-phase metadata availability. |
docs/content/example-components/theme-toggle.md |
Explains preview isolation. |
docs/content/deployment/index.md |
Replaces an outdated CSP recipe. |
docs/content/deployment/cloudflare.md |
Documents base staging and alias behavior. |
docs/content/configuration.md |
Documents quiet logging and URL pinning. |
docs/content/components.md |
Explains shared structural checks. |
docs/bascik.config.ts |
Configures timing inputs, cache exclusions, and CSP generation. |
create/test-coverage.json |
Refreshes scaffold coverage. |
create/src/scaffold.ts |
Updates dependencies and unified checking. |
create/src/scaffold.test.ts |
Checks generated commands and version alignment. |
create/src/npm.ts |
Adds Windows-compatible npm execution. |
create/src/npm.test.ts |
Tests npm invocation and failures. |
create/src/index.ts |
Uses the npm execution helper. |
create/package.json |
Updates scaffold release. |
create/assets/skills/bascik-testing/SKILL.md |
Synchronizes testing guidance. |
create/assets/skills/bascik-scripts/SKILL.md |
Synchronizes directive guidance. |
create/assets/skills/bascik-components/SKILL.md |
Synchronizes checker guidance. |
create/assets/skills/bascik-compatibility/SKILL.md |
Synchronizes compatibility guidance. |
adapters/cloudflare/test-coverage.json |
Refreshes adapter coverage. |
adapters/cloudflare/src/serverless-build.integration.test.ts |
Tests base-prefixed asset staging. |
adapters/cloudflare/src/runtime.ts |
Handles static 404 aliases. Moderate, line 298: non-HEAD methods become GET, bypassing the required 405 response and method guard. |
adapters/cloudflare/src/build.ts |
Stages base-prefixed assets. Critical, line 215: authored _headers and _redirects move below the base and become ineffective; retain them at the asset root. |
adapters/cloudflare/src/adapter.test.ts |
Tests staging across deployment variants. |
adapters/cloudflare/package.json |
Updates adapter release and compiler peer. |
.semgrepignore |
Removes obsolete extension exclusions. |
.github/workflows/ci.yml |
Installs Chromium and adds Windows unit tests. |
.github/scripts/publish-vsce.sh |
Explains bundled runtime dependencies. |
.github/agents/bascik-profiler.agent.md |
Documents paired benchmark workflow. |
.gitattributes |
Standardizes cross-platform line endings. |
🧠 Review effort: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| for (const rel of graph.publicFiles) { | ||
| const from = join(distDir, rel); | ||
| const to = join(publicDir, rel); | ||
| const to = join(assetRoot, rel); |
There was a problem hiding this comment.
Kept _headers and _redirects at public/ while prefixing ordinary assets, with coverage for both Cloudflare variants. Fixed in 58e66de7.
| const scannable = html | ||
| .replace(/<!--[\s\S]*?(?:-->|$)/g, (comment) => " ".repeat(comment.length)) | ||
| .replace( | ||
| /<(textarea|title|noscript|xmp)\b((?:[^>"']|"[^"]*"|'[^']*')*)>([\s\S]*?)(<\/\1(?:[\t\n\f\r /][^>]*)?>)/gi, | ||
| (_match, tag: string, attrs: string, inner: string, close: string) => |
There was a problem hiding this comment.
Replaced global comment masking with contextual scanning and pass original script-body slices to the compiler; added comment-like script-body regressions. Fixed in 58e66de7.
| "id": "css-attribute-selector", | ||
| "kind": "css", | ||
| "pattern": "(^|,)\\s*\\[(?!id\\b)[A-Za-z0-9_-]+(?:\\s*(?:[~|^$*]?=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\]\"'\\s]+))?)?\\]", | ||
| "pattern": "(^|,)\\s*\\[(?!id\\b)[A-Za-z0-9_-]+(?:\\s*(?:[~|^$*]?=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\]\"'\\s]+))?)?\\](?=\\s*[,{])", |
There was a problem hiding this comment.
Expanded the canonical rule for unanchored compound attribute selectors while preserving the scoped-descendant exception, then regenerated both copies. Fixed in 58e66de7.
| "id": "css-attribute-selector", | ||
| "kind": "css", | ||
| "pattern": "(^|,)\\s*\\[(?!id\\b)[A-Za-z0-9_-]+(?:\\s*(?:[~|^$*]?=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\]\"'\\s]+))?)?\\]", | ||
| "pattern": "(^|,)\\s*\\[(?!id\\b)[A-Za-z0-9_-]+(?:\\s*(?:[~|^$*]?=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\]\"'\\s]+))?)?\\](?=\\s*[,{])", |
There was a problem hiding this comment.
Updated the canonical rule to detect unanchored compound attribute selectors, retained the scoped-descendant exception, and regenerated both package copies. Fixed in 58e66de7.
| @@ -51,10 +51,32 @@ export const watchSourceCycles = async ( | |||
| const pages = new Set<string>(); | |||
| let all = false; | |||
| let staticAssetsInvalidated = false; | |||
| let shouldInvalidateComponents = false; | |||
| let shouldClearAllBuildCaches = false; | |||
There was a problem hiding this comment.
Matching pre producers now trigger full build-script cache invalidation before recompilation. Added a regression test; fixed in 58e66de7.
| const lintTargets = [undefined, ...external]; | ||
| // bascik --check already ran the per-file checks over this project, so running the linter on it again would print | ||
| // every finding twice. It says so when it had to skip them, and only then does the linter stand in for it. | ||
| const perFileSkipped = /per-file checks skipped/.test(checked.output ?? ''); |
There was a problem hiding this comment.
The standalone project lint now skips only when output positively confirms integrated per-file checks completed; added coverage for old output without that confirmation. Fixed in 58e66de7.
Co-authored-by: collin-thomas <2100124+collin-thomas@users.noreply.github.com>
|
issue with cicd, closing to see if it resolves. |


Summary
Pre-launch hardening. A compiler audit fixes scoping, raw-text, and directive edge cases, the scoping pipeline gets faster with identical output, the checker and language server catch more problems, and the Cloudflare adapter now serves sites deployed under a non-root base path.
Compiler fixes
prefixKeyframes,scopeCssCustomProperties,scopeLayerNames,scopeViewTransitionNames, andscopeAnchorNamesrewrote names one declaration at a time, so a short name such asbor--acould match inside a generated name or a longer name (--a-b). Each pass now rewrites whole identifiers in one step. The JS side (prefixElementAttribute) does the same and handles multi-class strings such asgetElementsByClassName("a b")andsetAttribute("class", "a b").<script>,<style>, and<textarea>bodies. Slots accept single quotes and</div >.data-classanddata-styleon a component root are no longer mistaken forclassandstyle.<style>minification keepsmediaand other attributes.data-typeanddata-srcare no longer read astypeandsrc, and script tags inside comments or<textarea>are skipped.data-bascik-buildwithdata-bascik-stream(androuteswithstream) now conflict at build time, matching the server and--check.data-bascik-preserve=""preservesid,name, andclasslike the bare directive.<!--,<textarea>, or<title>inside a script body no longer drops or corrupts hashes. Sitemap exclusion ignores<meta>text inside comments and raw text and falls back to emitted HTML for dynamic routes.data-bascik-buildvalues (pages,page-x) no longer defer a script because of attribute-like text inside quoted values.Checker and language server
bascik --checkis quote-aware, ignores comments and raw text, and skips Node directive scripts when checking browser JS rules. Newunknown-directive-valuewarning.--fixedits only what--checkreports.js-document-class-querywarning fordocument.querySelector('.class'), which is document-wide underdeduplicateCss. It covers compound and backtick selectors andgetElementsByClassName(...)[0], and skips selectors anchored on a scoped#id.--lintalias is removed.--checkis the one command.Performance
Output is byte-identical to before on every fixture compared.
scopedCssCacheno longer keys on per-instance scoped IDs unless the CSS hasurl(#id)references, so components with ordinary IDs hit the cache across instances.addElementClassesInHtmlmakes one pass instead of one per styled tag.@keyframes,[id,#,<style, ID-reference attributes, props, slots).collectAllScriptDepsruns once per component per page. Package specifier resolution and entry scanning are memoized inpackage-identity.ts.--fixture pipelineoption in the bench harness generates a 25-page, 1,000-instance benchmark site, and a new/internals/benchmarkingpage documents the paired baseline and candidate workflow.dev-boot-transpile-timing.integration.test.tsassumed every page costs about the median. After the cache fix one cold page carries the one-time cost, so the test now holds the slowest page tomax(median * 10, 150)ms and every other page tomedian * 5.Cloudflare adapter
public/docs/...) while_worker.jsand_routes.jsonstay at the public root. Previously every static page and asset underbase: "/docs/"was a 404 on Pages and Workers.404.htmlgo through the Worker and answer with status 404, matching the Node server./(for example/style.css/) is no longer served as the file. It falls through to page lookup and 404s, like static hosts.1.0.0-rc.6, with peer dependency@bascik/bascikat^1.0.0-rc.7.Tests, docs, and CI
cross-platform-crlfandscoping-differentialtests.:is()exception, post-phase metadata timing, base-path staging, 404 routing, and static alias redirects. The docs_headersfile gains a security headers rule (frame-ancestors 'none',X-Frame-Options,nosniff, referrer policy).