mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-10-24 12:07:17 +09:00
codex/headers-settings-docs
73
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5e6cb90f7b | Use shared matcher for builder page lookup and centralize path docs | ||
|
|
e3ec50ef5a | fix: preserve saved encoded path rules | ||
|
|
747bcd1832 | docs: clarify headers on exported sites | ||
|
|
662270985c | docs: share one path pattern reference | ||
|
|
d779985e8a | fix: match project rules with published routes | ||
|
|
940ea13e80 | docs: clarify production page route matching | ||
|
|
0d69794c0a | docs: correct page path pattern comparison | ||
|
|
5a56d9cb40 | docs: distinguish project and page path patterns | ||
|
|
f73b5a8dd4 | docs: centralize URL path pattern guidance | ||
|
|
746ea3c97e | docs: improve HTTP response headers guide | ||
|
|
a6a9049399 |
fix: validate published MDX before publish (#6468)
## Related issue Related to #3550. ## Summary - Run the existing published-MDX materializer during pre-publish validation and surface its error diagnostics before starting dynamic or static publishing. - Reuse the dependency walk that builds the publication artifact to limit validation to reachable Content Blocks, including blocks whose asset is missing. - Add actionable fix hints for unavailable MDX assets and invalid HTML nesting. - Show a compact error/warning count in the publish dialog, with a details dialog that has counted Errors and Warnings tabs and hides empty tabs. - Include relevant IDs and navigation links in reports when available, with guidance when they are not; allow users to copy all reports and select the text. - Resolve missing-document IDs against loaded asset metadata and show the filename and Content Assets folder path when available. The page-tree pre-publish audit already checks HTML content models, but it cannot see content generated from MDX assets. This extends preflight to that content using the same materializer and diagnostics as the publish build. It also catches unavailable MDX assets before the publish job starts. ## Plan and status ### Implemented - [x] Reuse existing publish-time MDX discovery and materialization so preflight checks the content that will be published. - [x] Collect every page-tree audit error and warning, not only the first finding for each severity. - [x] Collect every MDX publish error and provide a location and remediation hint. - [x] Collect missing or ambiguous template warnings and content-database omission warnings. - [x] Show a compact error/warning total in the publish dialog. - [x] Add a details dialog with standard panel padding, spaced and separated findings, and counted Errors and Warnings tabs; hide empty tabs. - [x] Copy all reports from the dialog header and allow report text selection. - [x] Include diagnostic codes and relevant instance, asset, document, and resource IDs in reports. - [x] Keep “See issues” visible in the narrow publish panel. - [x] Keep element navigation available from page-tree audit findings and link content findings when the target is available. - [x] Use the same findings UI for dynamic and static publishing. - [x] Block publishing on errors and allow warnings to proceed. - [x] Keep unexpected preflight failures visible to the user. - [x] Show a preflight failure either in the open publish dialog or in a toast when the dialog is closed, avoiding duplicate reports. - [x] Replace opaque “Document … could not be loaded” errors with actionable guidance, including the asset filename and folder path when available. - [x] Load linked document sources during MDX validation and prebuild when they are absent from the compact content artifact. ### Regression checks completed - [x] No-findings validation preserves the normal publish path. - [x] Single and multiple findings show accurate totals and details. - [x] The “See issues” action is visible in the publish panel and opens diagnostics. - [x] “Show element” navigation remains wired to the affected element and closes the publish dialog. - [x] More than five MDX errors and more than ten missing-template warnings remain available in diagnostics. - [x] Mixed MDX errors, audit errors, template warnings, and database warnings are combined and counted. - [x] Errors stop dynamic and static publishing; warnings do not block publishing. - [x] Error-only, warning-only, and mixed states show the right tabs and counts, with empty tabs hidden. - [x] Copy-all includes every error and warning with context, and report text is selectable. - [x] An open dialog receives inline preflight failures without a toast; a closed dialog receives a toast without a duplicate inline report. - [x] Missing-document errors include filename/folder context when available and useful fallback guidance when metadata is unavailable. - [x] Reproduce the linked-author failure with the affected project’s hosted build, then confirm it builds successfully with the fix. ## Verification - `pnpm --filter @webstudio-is/project-build test -- src/runtime/published-mdx.test.ts` (26 tests passed) - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm --filter webstudio typecheck` - Affected project: `webstudio build --template react-router` reproduced the document load error before the fix and completed after it. - `pnpm --filter @webstudio-is/builder test -- app/builder/features/publish/publish-validation-results.test.tsx app/builder/features/publish/content-database-publish-warning.test.tsx app/builder/features/publish/publish-error.test.ts app/services/build-router.server.test.ts` (26 tests passed) - `pnpm --filter @webstudio-is/builder typecheck` - `pnpm exec oxfmt --check` on changed files - `git diff --check` - Reviewed dynamic/static preflight and element-navigation code paths. |
||
|
|
6044792b77 |
docs: Explain Radix force-mount animation requirements (#6471)
## Summary Document the animation constraints around Radix `forceMount`: closed content remains mounted and needs explicit closed-state CSS, while Radix suppresses CSS transitions and animations during height measurement, so the first opening may not animate. Updated Accordion and Collapsible docs, custom prop descriptions, and generated prop metadata so the guidance appears in component discovery. Closes #6197. ## Checks - [x] Accordion and Collapsible documentation updated - [x] Generated prop metadata refreshed - [x] Package typecheck - [x] Targeted Collapsible tests |
||
|
|
8a46350c9a |
fix: Compile MDX Content Blocks in hosted builds (#6455)
Hosted MDX pages can publish successfully and then fail to render because the publish runner skips their source files. Restore source downloads and compilation for MDX Content Blocks, including dynamic article queries and template dependencies. Reuse the existing publication planner and local content compiler. Markdown-only pages keep their bodies on demand; hosted MDX pages download article sources and pay the necessary compilation cost in the runner, not the publish API. Reject missing content databases and MDX materialization errors instead of deploying an incomplete page. Ref #6450 Ref #6454 ## Checklist - [x] Reproduce missing MDX content using the affected deployed build. - [x] Restore hosted MDX compilation without duplicating the static-export compiler. - [x] Add a sync → compile → generated query → React server-render regression with a metadata-only API bundle and a frontmatter-bound Content Block. - [x] Verify new regression checks fail without the required behavior and pass with it. - [x] Reject missing MDX sources and content databases; preserve remote article bodies when no MDX Content Blocks need compilation. - [x] Review documentation impact and update the Content Engine publishing explanation. - [x] Run CLI tests, typecheck, lint, formatting, and package-boundary checks. - [x] Run the full fixture link/sync/build pipeline; no generated changes. - [x] Rebuild the affected project locally and exercise its generated production request handler: HTTP 200 with the article title and body. Asset requests were served from synced local files. The live project was not modified or republished. Its existing title/description bindings still use an array access for a single-result query; that separate project-data issue is not changed here. Agent evaluations were not run. Affected sites need republishing after the updated CLI artifact is deployed. |
||
|
|
9b1100f25b |
fix: Restore hosted Assets queries (#6454)
Hosted Assets queries started returning 502 in 0.301.0 because publish sync omitted their query database. Restore that database for hosted builds while keeping Markdown body-reference queries on demand. Static exports still prepare their database in the build runner. Reject builds with Assets queries but no database before changing generated files, so this failure cannot silently produce another broken deployment or erase the previous generated output. Uses the existing shared query compiler; no MCP-specific logic or API schema changes. Closes #6450 Ref #6427 Replaces #6453 with the same commits on `assets.staging`, which matches the staging deployment branch policy. ## Checklist - [x] Reproduce the reported 502 and verify the fix on project and custom origins. - [x] Preserve static export behavior and on-demand Markdown loading. - [x] Add a regression test for rejecting missing databases; demonstrate failure before the fix and success afterward. - [x] Review documentation impact and update the Content Engine publishing explanation. - [x] Run relevant tests, Builder/CLI typechecks, lint, formatting, and package-boundary checks. - [x] Run the full fixture link, sync, and build pipeline against the patched preview API. Regenerate all eight JSON snapshots with the current formatter; parsed data is unchanged and generated application files are unchanged. Validation: 88 CLI tests, 22 Builder tests, and four no-body-read publication tests pass. Fixture size checks were unavailable without compiled app bundles. Agent evaluations were not run. Existing affected sites need republishing after the fix is deployed. |
||
|
|
d78e770d82 |
perf: Keep article indexing out of publish API requests (#6427)
Ref #6416 The publish workflow was doing too much work in one short-lived API request. This moves content indexing into the build runner and keeps article bodies out of hosted/SSR sync. ## What changed - The build-bundle API can return the lightweight project bundle without preparing a full content index. - The CLI downloads required assets directly from storage and builds the index locally for SSG. Asset downloads remain bounded to 10 concurrent requests. - Hosted/SSR sync skips Markdown and MDX article downloads and does not compile an article index. It still downloads regular assets needed by the build. - Markdown body queries use stored frontmatter and fetch only the requested article at runtime. MDX still needs source downloads and compilation for SSG. - Public MCP and content-engine docs explain the Markdown/MDX tradeoff. This removes article parsing and article-body transfer from the tRPC request. SSG still downloads article sources from storage and compiles MDX in the build runner. Hosted runtime article reads remain on demand. ## Checklist - [x] Keep the tRPC bundle request limited to project metadata and necessary records. - [x] Prepare SSG content indexes in the build runner; keep hosted article bodies out of sync. - [x] Cover no-body query preparation, direct asset reads, and SSG-versus-hosted sync behavior with regression tests. - [x] Update public CLI, MCP, and content-engine guidance. - [x] Regenerate and verify fixtures. - [x] Run workspace tests, typechecks, lint, formatting, package-boundary, generated API/docs, and fixture-size checks. - [ ] Verify the deployed publish flow has comfortable margin below the hosted API timeout. ## Verification - `pnpm -r --workspace-concurrency=1 test`: passed, including all 3,082 Builder tests and 1,150 CLI tests. - `pnpm -r typecheck`, `pnpm lint`, `pnpm check:package-boundaries`, `pnpm check:generated-api`, `pnpm check:generated-docs`, `pnpm check:fixture-sizes`, and `pnpm exec oxfmt --check`: passed. - The new hosted article-download regression test was confirmed to fail with the old behavior and pass after the fix. - A deployed end-to-end publish timing check is still needed, so this PR remains draft. |
||
|
|
a4c3b37fc2 |
fix: Unblock reported MCP workflows and improve issue diagnostics (#6438)
## What this fixes
MCP authors can reuse an existing design token in JSX fragments, create
valid border shorthands with CSS variables, and bypass a font that never
settles during responsive screenshots. Common fixed page titles with
spaced separators are also accepted. Issue reports now include the
project ID and safe, bounded IDs from the failed operation, plus clearer
response and browser-startup diagnostics.
## Scope and tradeoffs
- `token("name")` attaches an existing design token; an unknown name
returns a not-found error. Empty token definitions from Builder/UI
remain definitions and follow the normal conflict rules.
- Border shorthands map a single unresolved `var()` to the remaining
width, style, or color field when the other fields are explicit.
- `waitForFonts: false` skips font readiness but still waits for stable
layout frames. The default remains unchanged.
- Fixed titles such as `Pricing - Plans` stay literal. Addition such as
`first + second` remains an expression. Wrap ambiguous subtraction in
parentheses, for example `(first - second)`. Other ambiguous title forms
may still need an exact report.
- Only recognized operation-level IDs are attached to a public GitHub
issue. Authored values, raw arguments, URLs, and credentials are
excluded. IDs from later successful diagnostic reads are not captured.
- This does not fix the underlying response-transform failure; it
improves future reports for that case.
Closes #6424
Closes #6425
Closes #6434
Closes #6439
Ref #6435
Ref #6430
Ref #6417
## Verification
- [x] Reproduced the privacy, page-expression, empty-token, and
content-mode token-reference regressions with failing tests, then
confirmed the fixes pass. A regression test also covers parenthesized
subtraction.
- [x] Full protocol, template, vision, project-build, and CLI test
suites pass; focused Builder issue-report and fragment tests pass. The
protocol, CLI, and project-build suites were rerun after the CI fix.
- [x] Relevant package typechecks, lint, package-boundary check, fixture
pipeline, generated API check, and generated docs check pass. Fixture
output has no diff.
- [x] Reviewed the authoritative MCP documentation and regenerated the
API metadata and MCP docs.
- [x] CSS parser regressions cover border, each side shorthand, and
unresolved variables in width, style, and color positions; css-data
tests, typecheck, and lint pass.
- [x] Fixed the local evaluation runner to pass the task and Webstudio
MCP tools to Luna/low. Each of the six fixtures passed at least once;
focused MCP/evaluator tests, CLI and project-build typechecks, lint, and
formatting pass.
- [x] The complete Luna/low suite passed all six fixtures in two
consecutive sequential runs. Baselines remain incompatible with this
model/effort override and were not updated.
## Follow-up
- If another fixed-title form still fails, use the new project-level
report context and the exact title shape to narrow the parser case.
|
||
|
|
2c9fd16689 |
feat: configure custom response headers by route (#6429)
## Description Project Settings starts with an empty response-header rule list. Users can add valid HTTP response headers for all paths (`/*`) or an Authentication-style route such as `/private/*`, and remove any configured rule. The Headers and Authentication views share the accessible rule-list form. The header form suggests standard response-header names and common values for the selected header, while accepting custom names and values. `Set-Cookie` is not suggested because a rule can store only one value per header and would replace existing cookies. `X-Powered-By`, `X-Content-Type-Options`, and `Strict-Transport-Security` are dispatcher-owned and cannot be configured. Users may configure `Content-Security-Policy`, `X-Frame-Options`, and `Referrer-Policy`; when absent, the dispatcher supplies their defaults. The SDK validates header names, values, routes, duplicates, and size limits. The CLI emits only configured rules. Customization requires Pro for custom-domain publishing, while unchanged defaults and staging remain available on Free plans. The server checks the saved production snapshot against the project owner's plan. Companion Cloud worker PR: https://github.com/webstudio-is/webstudio-saas/pull/664. Deploy its dispatcher support before exposing these settings in the Builder. Other hosts need an adapter that applies the generated rules; Webstudio Cloud dispatcher defaults do not apply automatically elsewhere. Static exports do not apply headers automatically. ## Validation - SDK, CLI, Builder browser, publish-warning, and production-build tests pass. - Builder, SDK, and CLI typechecks and lint pass. - The companion Cloud worker tests, typecheck, and lint pass. Replaces https://github.com/webstudio-is/webstudio/pull/6428 to use `headers.staging`. Closes https://github.com/webstudio-is/webstudio/issues/4748 |
||
|
|
3d0a0657aa |
feat: Support async resource dependencies (#6030)
## Summary Make `Resource<Document>` the lazy document-resolution abstraction shared by Content Engine graphs, generated sites, and Builder previews. Expressions use one async computation interface: referenced resource documents resolve first, independent requests run concurrently, and unused resources stay unloaded. Ref #6029 Ref #6031 ## Implementation checklist - [x] Define one resource contract for synchronous or asynchronous document resolution. - [x] Resolve explicit roots lazily with memoization, bounded concurrency, cancellation, and structured errors. - [x] Preserve cycle, duplicate, and missing-resource diagnostics. - [x] Extract resource dependencies with the existing expression AST. - [x] Discover consumed resource roots from the current page tree and page metadata. - [x] Generate a lazy request graph for published page data, including independent requests. - [x] Resolve dependency documents before evaluating dependent request expressions. - [x] Integrate dependency-first loading with Builder preview caching and invalidation. - [x] Expose safe Resource bindings in the editor and reject self/indirect cycles. - [x] Adapt REST, GraphQL, Assets, date, and sitemap requests through the same Resource contract. - [x] Cover laziness, chains, shared dependencies, concurrency, invalidation, cancellation, failures, and cycles with fail/pass tests. - [x] Review documentation impact and document dependent Resources in the Data variables guide. - [x] Track collection-item and component-parameter-dependent resources as follow-up #6031. - [x] Regenerate and review affected fixtures. - [x] Resolve action-resource request dependencies when an action is invoked. - [x] Reproduce and fix cached form submissions and multi-root dependency-cycle hangs. - [x] Document uncached form actions and regenerate affected fixtures. - [x] Preserve single and multi-selected content until a cut successfully writes to the clipboard. - [x] Preserve boolean expression values in the search-exclusion checkbox. - [x] Cancel cut deletion if project data changes while preparing or writing the clipboard; cover content/property edits and project switches for single and multi-selection, and document the retry behavior. - [x] Validate pending cuts after the final await, immediately before deletion, and reproduce the queued-update race for single and multi-selection. ## Technical direction The persisted, revisioned `DocumentGraph` remains the Content Engine artifact. `Resource<Document>` is the execution abstraction for obtaining a document; its resolver evaluates only the dependency closure reachable from requested roots. Static and remote documents therefore differ by Resource implementation, not by expression value type. Generated pages always emit a `ResourceRequestGraph`. Each node owns its output name, dependencies, and request factory. Roots come from resource variables actually referenced by the current page's metadata, props, actions, or expression children. Unused and off-page resources remain unresolved. The loader still accepts legacy request maps for compatibility. Builder preview uses the same page-root discovery as published generation. Its existing cache remains the lifecycle boundary: cached dependency documents unlock dependent requests, while invalidation removes downstream requests until their inputs resolve again. The separate canvas frame recomputes its local plan from the synchronized cache so rendered expressions receive those documents. Action requests and their dependencies resolve when a form is submitted. Each submission sends a new action request, bypassing Webstudio's resource cache. Dependency requests still use their configured cache lifetime. ## Review simplifications - Consolidated page resource-root discovery in the SDK and reused it in Builder. - Scoped root and action discovery to the current page tree. - Removed the redundant immediate-resource helper; `Resource.resolve` already accepts `Document | Promise<Document>`. - Moved output names onto graph nodes and removed the duplicate graph-level map. - Removed unused planner output and corrected transitive cycle discovery to include only Resource data sources. - Regenerated fixtures so independent resources also use lazy graph execution. - Reused one abort-aware concurrency limiter for document sessions and Resource resolution. - Collapsed duplicate generator action scans and removed redundant generated-resource bookkeeping. - Unified legacy request maps and request graphs through one resolution path. - Shared the 20-request concurrency limit between SDK, Builder preview, and the server batch boundary. - Preserved dependency failure paths and original causes, including the first cancellation reason. - Removed invalid-request logging that could expose Resource headers or request bodies. - Made editor cycle detection alias-safe by comparing underlying Resource IDs. - Memoized page settings values to prevent repeated async validation renders. ## Verification Latest local verification for `bbca6395e3`: - Both queued-update regression cases failed before the fix and passed afterward. Validation now runs synchronously immediately before deletion, after the final await, in both cut paths. - Passed: 255 copy/paste and command tests, Builder typecheck, lint, package boundaries, formatting, and diff checks. - Reviewed documentation: the existing copy/paste safety description remains accurate. Fixture inputs and outputs are unaffected; no fixture regeneration was needed. Agent evaluations were not run because separate approval is required. - CI for the new commit is pending. Previous local verification for `ffbc75b152`: - Six regression cases failed before the fix and passed afterward: content edits, property edits, and project switches during a pending cut, with both single and multiple selections. - Passed: 253 copy/paste and command tests, Builder typecheck, lint, package boundaries, source formatting, and diff checks. - An unchanged content-block test file initially failed to import in the browser. Its isolated rerun and the full 253-test rerun passed without code changes. - The guard conservatively treats any project-data change as a reason to keep the clipboard copy without deleting content. It shows a retry message. Copy/paste documentation now describes this behavior. - Fixture inputs and outputs are unaffected; fixtures were not regenerated. Agent evaluations were not run because separate approval is required. CI for the new commit is pending. Previous local verification for `3eb580697c`: - Reproduced both regressions with failing tests before fixing them: premature deletion during cut and false search exclusion appearing checked. - Passed: 203 copy/paste and page-settings tests, Builder typecheck, lint, package boundaries, formatting, and diff checks. - Cut coverage includes keyboard and programmatic entry points, single and multiple selections, delayed successful writes, rejected writes, and disabled copying. - Reviewed documentation impact: these fixes restore existing behavior; no documentation update is needed. Only Builder UI and clipboard files changed; fixture inputs and outputs are unaffected, so fixtures were not regenerated for this commit. - CI status for this older commit was recorded as pending at handoff. Agent evaluations were not run; they require separate approval. Previous local verification for `858b348ad`, rebased onto `cf606ca4c`: - Regression tests failed before each fix and passed afterward: repeated submissions in both generated route templates, plus three multi-root/branching cycle cases. - Passed: 590 SDK tests, 1,129 CLI tests, 72 focused Builder tests, SDK/CLI/Builder typechecks, lint, package boundaries, and fixture link/sync/build. - Initial concurrent runs hit timeouts. The complete CLI suite passed with one worker; the focused Builder suites passed without file parallelism. - Documentation and generated fixture changes reviewed. Agent evaluations were not run; they require separate approval. - CI for `858b348ad` passed: Main (including all six E2E shards), Visual Regression, Lint PR, and Check submodules. Earlier verification (before this update): TDD fail/pass evidence includes resolver creation, AST dependency discovery, published graph reachability, dependency-gated request generation, Builder dependency-first planning, Resource editor cycle filtering, page-tree root scoping, off-page action isolation, transitive Resource-only cycle discovery, abort/timeout precedence, server batch limits, and the rebased SSG fixture consuming its lazy Resource. - `pnpm checks` passed after rebasing onto `ce84ddcf12`; it covered workspace tests, typechecks, lint, package boundaries, generated API/docs validation, and fixture link/sync/build. - Earlier focused checks passed: Builder typecheck, 12 page-settings/pages unit tests, lint, formatting, and `git diff --check`. - Local generated-resource E2E passed for HTTP, GraphQL, and current-date resources (3 tests). - The page-actions and Marketplace page-settings persistence E2Es both pass locally. - CI for `6b8b08a70` passed: Main workflow (including all six Builder E2E shards), Visual Regression, Lint PR, and Check submodules. - Agent evaluations were not run because they require separate explicit approval. ## Current behavior and limitations - A failed dependency blocks its dependents and reports the resource path and cause. - One published resolution call is the memoization boundary; Builder maps dependency readiness onto its versioned request-cache lifecycle. - Scoped collection-item and component-parameter resources remain in #6031. - Builder skips cyclic dependency paths without blocking independent resources. |
||
|
|
804cd39bc2 |
fix: Stop slow diagnostics from blocking publishing and clarify publish status (#6416)
Closes #6406 ## What changes Publishing no longer waits for advisory content-database and MDX diagnostics. Those checks run alongside the publish request, so a slow diagnostic does not prevent publishing from starting. Permissions, pending content saves, and blocking project checks still run before publishing. The server continues to enforce publish authorization and build integrity. ### Publish dialog - Add a green **Validate** button beside the blue **Publish** button, with equal widths. - Show waiting states and disable the actions while their work is running. - Let users validate without publishing. Successful validation shows a persistent “Validation passed. Ready to publish.” toast. - Clear the button's **Validated** state when the popover closes. Reopening still reflects an active publish job. - Move **Add new domain**, **Export**, and **Publish settings** into the header's ellipsis menu. - Show yellow progress icons for publishing domains, green checkmarks for completed publishes, red icons for failures, and neutral icons for unpublished domains. Built-in and custom domains share the status mapping. ### CLI and MCP Add `check-publish-readiness` to check the saved project without starting a publish. It checks permissions, rejects empty or unusable domain selections, reuses the existing build-integrity checks, and returns content diagnostics. Broken resource references no longer produce a false `valid: true` result. ### Content checks Run independent collection reads with bounded concurrency instead of processing every collection sequentially. This reduces serial waiting, but does not eliminate the underlying storage reads or content processing. ## Checklist - [x] Keep authorization and blocking project checks in place. - [x] Run advisory content diagnostics alongside publishing. - [x] Add standalone validation, waiting states, and popover-local validation results. - [x] Consolidate secondary actions in the publish menu. - [x] Distinguish pending, completed, failed, and unpublished domain states. - [x] Add CLI/MCP readiness checks using existing integrity and verified-domain logic. - [x] Bound concurrent collection reads. - [x] Add regression tests, including invalid domains, missing resources, status transitions, and popover state. - [x] Demonstrate the latest regression tests failing without the fixes and passing with them. - [x] Review documentation impact: update CLI operation guidance and metadata, and document domain status colors in the publishing guide. - [x] Run focused Builder, CLI, and asset-uploader tests, Builder typechecking, lint, formatting, and the generated-API check. ## Verification and limits The latest UI check passed all 49 publish tests. The preceding readiness fix passed 98 focused Builder tests and 130 CLI tests; collection coverage passed 112 tests. Typechecking, lint, formatting, and generated-API checks passed. The latest fixes do not affect fixture inputs or generated site output. Storybook screenshots and agent evaluations were not run because approval was not given. A live production publish was not performed during the latest verification. Publish can finish before advisory diagnostics do. Returned warnings appear afterward and cannot stop a publish that has already started. Standalone validation still waits for diagnostics, and actual publishing still requires content synchronization, server checks, and build/deployment work. This does not promise that every publishing timeout is eliminated. |
||
|
|
e7181fffdc |
feat: Add GitHub-style Alert component (#6279)
## Summary - Add one official `Alert` component with a content-editable `variant` property for note, tip, important, warning, and caution. - Register Alert in the component catalog with a generated title descendant and Storybook story. - Render GitHub-style alerts in Markdown Embed using the same DOM, class, role, and variant contract. - Materialize connected Content Block MDX alerts as actual Alert instances and serialize content or variant edits back to `> [!TYPE]`. - Document the component and both Markdown workflows. ## Implementation Alert labels and variants live in Content Engine and are shared across the component, Markdown renderer, and MDX adapters. 1. The Alert React component owns the wrapper, generated title, stable classes, `role="note"`, and `data-variant`. 2. Markdown Embed transforms candidate micromark HTML before the existing sanitizer and emits the same markup contract. It remains sanitized HTML rather than a Builder instance tree. 3. Content Engine retains alert metadata on parsed Markdown blockquotes. Project Build maps those nodes to Alert instances, reconciles their authored children, and restores canonical GitHub syntax during MDX serialization. 4. The component registry exports one Alert insertion template with a styleable title descendant. Unsupported, lowercase, misplaced, and malformed markers remain ordinary blockquotes. There are no schema, migration, persisted-data, or sanitizer-policy changes. ## Checklist - [x] Add Alert as an official component with one Variant property. - [x] Support all five GitHub alert types. - [x] Share alert metadata and marker recognition. - [x] Preserve nested Markdown and ordinary blockquote behavior. - [x] Keep URL and HTML sanitization in the existing security boundary. - [x] Add shared, title, and type-specific Markdown Embed descendants. - [x] Materialize Content Block alerts as Alert instances. - [x] Preserve alert content and variant changes through MDX serialization. - [x] Regenerate component props and Storybook artifacts from source. - [x] Review documentation impact and update Alert, Markdown Embed, Content Block, and navigation docs. - [x] Verify fixture impact; no fixture inputs or generated fixture outputs are changed. ## Verification - [x] New tests demonstrated failure before implementation and pass afterward. - [x] `pnpm --filter @webstudio-is/content-engine test` — 417 passed. - [x] `pnpm --filter @webstudio-is/project-build test` — 2,282 passed. - [x] `pnpm --filter @webstudio-is/sdk-components-react test` — 144 passed, 1 skipped. - [x] SDK component registry tests. - [x] Relevant package typechecks, declaration builds, and production builds. - [x] Root lint, formatting, package-boundary, generated-doc, and diff checks. - [x] GitHub Actions main, E2E, lint, submodule, deployment, and approved visual-regression checks. ## Known limitations Alert identifiers must be uppercase and appear at the start of the blockquote's first paragraph, matching the documented syntax. Markdown Embed emits the component's markup contract but cannot create Builder instances inside sanitized HTML. Closes #6278 |
||
|
|
ea17eaa3c4 |
docs: explain the complete Content Engine workflow (#6403)
## What changed - Add the complete Content Engine video tutorial to the main guide. - Explain the launch benefits before the step-by-step setup: file-based content, visual MDX editing, designed templates, collection entry forms, and MCP automation. - Document collection entry creation and editing in Content mode. - Explain content collection folders in the Assets guide. - Document that shared Slots cannot be used inside Content Block Templates. - Add missing links between Content Engine and Content Block documentation. ## Release documentation audit Reviewed the shipped MDX-backed Content Block, MDX template, structured collection entry, collection authoring, query diagnostic, publication warning, and asset-path changes. The detailed feature docs already cover their implementation-specific behavior. This PR fills the remaining discovery and workflow gaps across the main Content Engine, Assets, Modes, and Content Block pages. ## Todo - [x] Add the launch video to the Content Engine guide. - [x] Update the main launch value proposition and supported scale. - [x] Document collection workflows in Assets and Content mode. - [x] Document the shared-Slot limitation for Content Block Templates. - [x] Review documentation impact and navigation. - [x] Verify generated documentation remains clean. - [x] Verify changed relative links resolve. ## Verification - Content Engine documentation tests: 2 passed - Generated Content Engine and MCP documentation checks: passed - Documentation TypeScript check: passed - Relative link check: passed - Git diff whitespace check: passed The repository formatter excludes these GitBook Markdown files, so the pre-commit formatting task had no eligible targets. No fixture inputs or generated fixture outputs are affected. |
||
|
|
f23007457d |
fix(content-engine): normalize asset path filters (#6389)
## Description Fixes Assets path filters so authors can use visible folder and file names while canonical stored paths remain URL-encoded. - normalizes path filter operands segment by segment without double encoding - preserves already encoded filters and literal string matching behavior - covers equality, inequality, membership, contains, starts-with, and ends-with operators with spaces and URL-significant characters - verifies local/Preview database execution and published runtime return the same result - documents visible path input in the generated Content Engine reference Closes #6388 ## Steps for reproduction 1. Create an Assets folder named `Tutorial posts`. 2. Add an MDX file inside it. 3. Create an Assets system resource with `path starts with "Tutorial posts/"`. 4. Preview the query and expect the MDX file to match. 5. Change the value to `Tutorial%20posts/` and expect the same result for backward compatibility. ## Regression proof Before the implementation, the focused reproduction failed because the matcher returned no items: expected `["alpha"]`, received `[]`. With the fix, the expanded path-operator regression suite passes. ## Verification - [x] Content Engine test suite: 47 files, 577 tests passed - [x] Content Engine typecheck - [x] CLI typecheck - [x] Repository lint with warnings denied - [x] Formatting check for every changed source/test file - [x] Content Engine documentation test - [x] Content Engine and MCP documentation generation is idempotent - [x] Webstudio Features fixture generation is idempotent and typechecks - [x] No agent evaluations were run ## Documentation impact Updated the authoritative CLI Content Engine reference source and regenerated the Builder Content Engine and MCP documentation. The new guidance tells users to enter visible path names and notes that existing encoded filters remain supported. ## Code Review - [ ] hi @kof, I need you to do - conceptual review (architecture, feature-correctness) - detailed review (read every line) - test it on preview ## Before requesting a review - [x] made a self-review - [x] added inline comments where behavior is not obvious ## Before merging - [ ] tested on preview environment (preview dev login: 0000) - [ ] updated test cases document (not needed; automated regression and authoritative user docs were updated) - [x] added tests - [x] no new environment variables |
||
|
|
5d34b77fac |
feat: Improve collection entry authoring (#6361)
Collection authors and editors get clearer field help, direct entry navigation, and actionable validation instead of warnings that point at the wrong place. Closes #6360 ## Implementation - [x] Keep resettable help open after a click while the label remains hovered - [x] Stop repeating the property label inside resettable help - [x] Store JSON Schema field descriptions and show them in entry forms - [x] Add an optional dynamic collection entry page for explicit canvas navigation - [x] Rename entry file actions to **Edit file** - [x] Add **Open on canvas** to entry menus and Entry settings - [x] Put the entry filename in the Entry settings title - [x] Make collection validation banners explain the problem and open the first affected entry - [x] Remove false output-only `UNOBSERVED_FIELD` warnings while keeping filter and sort diagnostics - [x] Encourage useful field descriptions in general MCP collection guidance - [x] Update Content Engine documentation - [x] Confirm no database migration is required - [x] Regenerate the affected asset-query runtime fixture - [ ] Visually review the affected Storybook states in light and dark themes - [ ] Run the complete local agent evaluation suite - [x] Run broader package and Builder checks - [x] Complete final diff review ## Technical notes - `entryPageId` lives in `collection.json` under `x-webstudio`; no database schema changes are needed. - Entry creation still leaves the current canvas unchanged. Canvas navigation only happens after the user selects **Open on canvas**. - An entry page must contain exactly one URL parameter. The entry filename supplies that parameter, so the page can identify the selected entry. - Output projection fields are schemaless and may be produced after reference resolution, so catalog absence is no longer reported there. Filter and sort fields still report catalog diagnostics. - The structured-query runtime change affects the generated `webstudio-features` fixture, which is regenerated in this PR. ## Verification - 561 Content Engine tests - 2,413 Project Build tests - 253 Design System tests - 1,794 Builder tests - 67 focused Builder regression tests after the final navigation change - 11 ResettableLabel browser tests - 128 focused MCP tests - Builder, Content Engine, Design System, and Project Build typechecks - Repository lint and package-boundary checks - Generated documentation checks - Full workspace fixture build with `pnpm -r fixtures:build` - Formatting and diff checks - New regression tests were demonstrated failing before their fixes and passing afterward ## Documentation impact - [x] Updated the Content Engine guide for field descriptions, dynamic entry pages, actionable validation, **Edit file**, and **Open on canvas** - [x] Updated MCP guidance so collection fields include editor-facing descriptions |
||
|
|
e69a3d2f8e |
feat: Create structured MDX entries from collection folders (#6317)
## Paragraph editing follow-up — |
||
|
|
722b3af113 |
feat: Copy links to instances from the context menu (#6342)
Right-click an instance in the Navigator and choose **Copy link to
instance** to share its full Builder URL. Opening it restores the page
and the same instance occurrence, including descendants of shared Slots.
The shared menu also exposes the action on the canvas.
Copying and opening a link use the same existing
`getDeepLinkedInstanceSelection` function, moved unchanged from
`use-switch-page.ts` into `shared/instance-utils/link.ts`, alongside URL
creation and the existing instance URL parser. It validates the instance
path and page access. The context menu and pre-publish “Show element”
links both call `getInstanceLink(instanceSelector)`. It lives in
`shared/instance-utils/link.ts` and owns validation and the complete URL
setup: project, page, full selector, origin, share token, editor mode,
and safe mode, using the existing `builderUrl`. There is no separate
link-permission implementation.
The link keeps the current share access and editor mode, clears
unrelated scroll anchors, and shows clipboard success or failure. Body
is supported; Global Root and multiple selections are unavailable.
Instance-only navigation now preserves loaded Builder data: the route
comparison recognizes the `instance` parameter as well as the older
`instanceId`. A functional regression test confirms that changing the
target does not change the data URL comparison, while changing share
access does.
MCP guidance explains how to extract the target ID from the link for
`inspect-instance`, verify the project and shared Slot context, and
avoid guessing when an instance no longer exists. This does not add a
URL-taking MCP endpoint.
1. [x] Add the menu action and reuse complete instance-link construction
with pre-publish links.
2. [x] Share existing instance-link validation between copying and
opening links.
3. [x] Update the Navigator and MCP guidance; regenerate CLI
documentation.
4. [x] Extend the existing functional test to round-trip a shared Slot
URL, including share access and editor mode. Verify it fails without the
instance parameter and passes after restoration.
5. [x] Remove the React/clipboard test harness and duplicate
permission-test matrix. Confirm no fixture inputs or outputs are
affected.
Validation: 28 focused Builder tests, Builder typecheck, repository
lint, and `git diff --check` pass on this revision. The earlier CLI
documentation checks passed and their inputs are unchanged. An earlier
GPT-5.4 mini subagent at low reasoning passed a focused native MCP test
against commit
|
||
|
|
05706b5425 |
feat: Make Content Block templates the MDX authoring interface (#6307)
Closes #6306 ## Outcome Content Block templates are now the public component model for MDX authoring. - Standard Markdown resolves through matching Content Block templates. - PascalCase JSX resolves to a named template first, then to a registered component. - Adding or changing a template immediately affects matching MDX, including content authored before that template existed. - Every supported standard MDX element is present in new Content Blocks by default. - Template `name` is a stable PascalCase JSX identifier. `label` remains optional display text only. - Lowercase JSX represents native HTML and SVG without exposing `ws.element` in authored syntax. - Unknown, ambiguous, and unsafe JSX stays in source, produces a source-ranged Builder diagnostic, and is omitted from published output. - Frontmatter images preserve exact `$ref` values and use the Asset description for `alt` text. - Keyboard and mouse insertion from the slash menu remove the trigger slash and preserve the selected template. ## Public MDX contract - Markdown is canonical for standard prose. - Lowercase JSX creates native elements: `<section><p>Text</p></section>`. - PascalCase JSX uses templates and registered components: `<PromotionCard />`, `<Heading tag="h1">Title</Heading>`, and `<YouTube src="https://youtu.be/KI5JHpzBK1s" />`. - Component-name collisions use stable qualified identifiers such as `Checkbox` and `RadixCheckbox`. - A self-closing template keeps its designed default subtree. An explicitly paired empty template clears it. - Static quoted values and bare booleans are supported. - Imports, exports, expressions, spreads, functions, executable JavaScript, unsafe attributes, `<$.*>`, and authored `<ws.element>` are rejected. - `ws` remains only for compiler primitives with no React component. ## Implementation - [x] Add stable, unique template names and keep them separate from labels. - [x] Parse and validate Markdown and JSX through their ASTs with precise source ranges. - [x] Share component identity between template JSX, Content MDX, Builder materialization, reload, copy, and publication. - [x] Resolve templates live after add, edit, rename, reorder, removal, undo/redo, collaboration updates, and reload. - [x] Preserve authored props, children, Asset references, template defaults, and the exact slash-menu template choice. - [x] Make one typed MDX semantic inventory drive default templates and slash-menu eligibility. - [x] Move component-dependent template assembly into the component registry. - [x] Replace production `$`, `animation`, and `radix` JSX namespaces with direct component imports. - [x] Keep only explicit compiler primitives in `ws` template JSX. - [x] Migrate repository templates, fixtures, stories, examples, MCP guidance, CLI guidance, and generated outputs. - [x] Add Builder unit and Playwright coverage for authoring, diagnostics, insertion, synchronization, reload, and publication. - [x] Review and update the authoritative Content Block and generated MCP documentation. ## Compatibility - Persisted project data continues to use namespaced component IDs and `ws:element` for generic HTML elements. No project-data migration is required. - Legacy `<ws.element ws:tag="…">`, `<ws.element ws:name="…">`, `<$.*>`, `<animation.*>`, and `<radix.*>` input remains readable during the compatibility window. - Current serializers and repository-owned sources emit only canonical Markdown, lowercase intrinsic JSX, or PascalCase identifiers. - Untouched user MDX is not rewritten automatically. Legacy syntax is canonicalized when its owning source is edited. - Deferred follow-up: remove legacy namespace readers and proxy support only after the canonical writer is deployed and existing projects are backfilled. This is intentionally outside this PR. ## Verification - [x] CI package tests, typechecks, lint, package boundaries, generated assets, migrations, and size checks pass. - [x] All six Builder E2E shards pass. - [x] Fixture checks pass on Ubuntu and Windows. - [x] Targeted local Content Engine, Template, SDK, registry, Project Build, migration, Builder, component, CLI, and Playwright tests pass. - [x] Runtime contracts, CLI docs, and MCP docs were regenerated from their owning sources. - [x] Local fixture generation completed without an unexpected fixture diff. - [x] Documentation impact reviewed and included in this PR. - [x] Review and approve the intentional List visual snapshot change. - [x] Run the complete agent evaluation suite after explicit approval. - [x] Run the network fixture link/sync pipeline against the matching PR deployment after explicit permission. ## Known visual change The generated List story now targets its actual default `ul` element instead of `ol`, so the default list styling appears in the visual snapshot. The visual change was reviewed and the approved visual check passes. |
||
|
|
2e39477303 |
feat: Expose Force Mount for Collapsible Content (#6338)
## Problem Closed Collapsible Content is removed from the HTML, and the Builder does not expose Radix’s Force Mount option. ## Solution - Expose **Force Mount** as a boolean on Collapsible Content. - Enable it for newly inserted Collapsible templates. - Keep closed force-mounted content visually collapsed with template styles. - Preserve the existing Radix default for existing instances that do not set the prop. - Add regression coverage for the template default and generated Builder metadata. ## Checklist - [x] Expose the Force Mount control - [x] Keep new Collapsible content mounted while closed - [x] Preserve existing-instance behavior - [x] Regenerate Collapsible prop metadata from source - [x] Add regression coverage - [x] Review documentation impact and update the Collapsible guide - [x] Verify fixture inputs and outputs are not affected ## Verification - [x] `pnpm --filter @webstudio-is/sdk-components-react-radix test` — 20 tests passed - [x] `pnpm --filter @webstudio-is/sdk-components-react-radix typecheck` - [x] `pnpm --filter @webstudio-is/sdk-components-react-radix build` - [x] Targeted Oxlint and formatting checks - [x] `git diff --check` ## Known limitations Storybook visual verification was not run because it requires separate approval. Closes #6337 |
||
|
|
55920c57c4 |
fix: Show all Markdown and Assets query diagnostics (#6308)
Ref #6305 ## Outcome Show actionable Markdown, MDX, and Assets query problems in the editor, query Diagnostics, API, and MCP. The current implementation substantially improves source diagnostics, query error aggregation, query scoping, exact paths, MCP feedback, and loading states. The exhaustive audit below also records what is not complete yet. ## Completion rule An error state is complete only when all applicable checks pass: - [x] The editor uses the production validator and shows every issue for the open file. - [x] Query execution uses the same validation and returns every issue for every file that matches the query, not only the returned page. - [ ] MCP can reproduce the state through a real tool call and returns the same code, severity, message, file, and location. - [x] Diagnostics shows fatal errors and nonfatal warnings in the correct place. - [x] Exact file is always present; line and column are present whenever the parser can determine them. - [x] Multiple issues in the same file, multiple files, and multiple validation phases are returned together. - [ ] A regression test proves failure without the behavior and success with it. ## Cross-surface contract ### Required validator parity - [x] Editor, query execution, and MCP file operations invoke the same exported production file-validation pipeline for byte decoding, source/frontmatter, Markdown/MDX, Content Block semantics, and references. Copied schemas, adapter-only checks, or reimplementations do not count as parity. - [x] Query builder, query execution, `validate-asset-query`, and `preview-asset-query` invoke the same exported structural and catalog-aware semantic query validator with the same project snapshot and context. - [x] Every surface preserves the same complete, deterministically ordered diagnostic array: severity, code, message, phase/scope, asset ID, file path, line/column/range, query path, and fatal-versus-warning/result behavior. UI, API, and MCP serializers must not drop or remap fields. - [ ] A table-driven contract suite calls the real editor, query, API, and MCP entry points—including MCP upload, update, download, validate, and preview—and compares full normalized arrays for multiple errors, multiple warnings, multiple files, and pre-pagination matches. - [x] Markdown and MDX source syntax/frontmatter use validateTextAssetSource in editor, query compilation, and MCP file tools. - [x] Query request execution and MCP local parsing use assetQueryRequest. - [x] Fatal query setup errors retain all detected semantic errors and accompanying warnings. - [x] Nonfatal query warnings retain a stable code and exact query path. - [x] Source diagnostics retain severity, phase, code, asset ID, path, and available source position. - [x] Query Diagnostics excludes diagnostics produced only by unrelated published queries. - [x] Query, Preview, and Diagnostics tabs show loading states. - [x] Authenticated diagnostics can show a sanitized internal message; public/pre-auth errors remain redacted. - [x] Share byte-level UTF-8 validation instead of decoding separately in query and MCP. - [x] Make the query editor and MCP call one literal shared query-validation function before execution. - [x] Share cross-file reference validation across editor, query, and MCP file operations. - [x] Share contextual Content Block/template validation across all applicable surfaces. - [x] Preserve an invalid stored query in the editor and explain it instead of replacing it with defaults. - [x] Define and enforce whether “matches the query” includes every pre-pagination match; current source validation follows returned/paginated IDs. - [x] Continue through source, reference, and runtime phases where safe so one phase does not hide later issues. - [x] Map every user-triggerable graph/storage/runtime failure to a structured public error instead of INTERNAL_ERROR. - [ ] Label candidate-file warnings separately from returned-file diagnostics. ## File transport and encoding - [x] Empty Markdown and MDX are accepted. - [x] UTF-8 BOM and CRLF are accepted. - [x] Whole Markdown/MDX file over 1 MiB is detected. - [x] Missing or unavailable selected content is reported. - [x] Invalid UTF-8 frontmatter returns the same structured diagnostic in query and MCP. - [x] Invalid UTF-8 body returns the same structured diagnostic in query and MCP. - [x] MCP download must use fatal UTF-8 decoding rather than replacement characters. - [x] Validate bytes before committing an upload, or return the committed Asset ID and explicit cleanup state when post-commit feedback fails. - [x] Reject filename/format mismatches instead of allowing either hint to bypass Markdown/MDX validation. - [x] Storage status, missing body, invalid metadata, revision mismatch, format mismatch, short read, and excess read each return structured file context. - [x] Content changing during validation has a clear retryable conflict diagnostic. ## Frontmatter - [x] No frontmatter. - [x] Empty frontmatter. - [x] Opening delimiter without a closing delimiter. - [x] Frontmatter over 64 KiB. - [x] Invalid YAML grammar. - [x] Multiple YAML parser errors. - [x] Duplicate keys. - [x] YAML aliases. - [x] Unsupported YAML tags. - [x] Scalar or array root instead of an object. - [x] Non-JSON values, NaN, Infinity, and unsafe integers. - [x] Nesting deeper than 8. - [x] More than 256 fields/array entries. - [x] One string over 16 KiB. - [x] Normalized indexed properties over 64 KiB. - [x] Frontmatter warnings remain nonfatal and visible. - [x] Collect all post-parse normalization/limit errors; this phase currently stops at the first. - [ ] Prove every state above through real MCP upload, update, download, query, and Diagnostics paths. ## Markdown body - [x] Treat ordinary CommonMark/GFM as permissive; malformed-looking Markdown and raw HTML are not automatically syntax errors. - [x] Preserve and validate the body when frontmatter is invalid. - [x] Detect the 1 MiB body/file limit. - [x] Handle body extraction and bounded excerpts. - [x] Return a shared structured invalid-UTF-8 body error from every byte-reading surface. - [ ] Distinguish author errors from internal excerpt-limit/configuration errors. - [ ] Prove body-size and decoding states through real MCP and Diagnostics. ## MDX grammar and safety - [x] Malformed MDX/JSX grammar. - [x] Imports. - [x] Exports. - [x] Executable flow expressions. - [x] Executable text expressions. - [x] JSX expression attributes. - [x] JSX spread attributes. - [x] Arbitrary components. - [x] HTML-looking JSX outside ws.element. - [x] Unsupported/raw MDX node types. - [x] Duplicate attributes and normalized alias collisions. - [x] Event-handler attributes. - [x] srcdoc, srcset, and dangerouslySetInnerHTML. - [x] Unsafe URL protocols in link/source/action-like props. - [x] Forbidden tags: base, link, meta, noscript, script, style, template, title. - [x] Conflicting, empty, or non-static ws:name and ws:tag. - [x] More than 20,000 nodes. - [x] Nesting deeper than 100. - [x] More than 4,000 props. - [x] Multiple recoverable unsafe-mdx warnings are collected. - [ ] Collect multiple fatal grammar/structural errors when parser recovery can do so; unrecoverable parsing currently stops at the first fatal error. - [x] Preserve sibling expression warnings when unsupported JSX is also present; {first()}, <Card />, {second()} currently reports only the Card warning. - [ ] Prove every state above through real MCP and Diagnostics, not only validator unit tests. ## Content Block semantics - [x] Unresolved template warning exists. - [x] Unknown template prop warning exists. - [x] Incompatible template prop warning exists. - [x] Design-only template prop warning exists. - [x] Stale template prop warning exists. - [x] Invalid materialized HTML content model error exists. - [x] Run these checks for an MDX file even when no active editor Content Block root has materialized it. - [x] Run applicable semantic checks in query Diagnostics. - [x] Run applicable semantic checks for MCP upload as well as contextual update/download. - [x] Return all Content Block frontmatter diagnostics; one path still throws only diagnostics[0]. - [ ] Add real MCP and UI coverage for every semantic state. ## Cross-file references - [x] Non-string $ref marker. - [x] Invalid reference URL. - [x] Invalid fragment encoding. - [x] Invalid fragment. - [x] Invalid JSON Pointer. - [x] Missing referenced document. - [x] Missing referenced JSON path. - [x] Missing referenced local Asset warning. - [x] Unsupported target representation. - [x] Reference cycle. - [x] Duplicate document ID or URL. - [x] Missing graph source or target. - [x] Root not found. - [x] Duplicate/unused/unresolved reference. - [x] Invalid resolved value. - [x] Content identity conflict. - [x] Target revision mismatch. - [x] Representation selector required/invalid. - [ ] Diagnose {$ref: value, extraKey: value} as an invalid marker or explicitly document it as ordinary data. - [x] Collect all bad references and targets instead of stopping at the first graph failure. - [x] Validate references from the editor and MCP file tools, not only query compilation. - [x] Map graph compilation/resolution, Markdown-document, and JSON-document errors to exact structured Diagnostics rows. - [x] Prevent an unrelated file's graph error or duplicate canonical URL from blocking an exact-file query. - [ ] Prove missing targets, cycles, bad representations, and bad JSON paths through real MCP. ## Query request and structure - [x] Invalid JSON, invalid request UTF-8, empty/non-object request, and request over 512 KiB. - [x] Missing query and unknown request/query keys. - [x] Invalid result mode. - [x] Malformed where/all/any/filter shape. - [x] More than 32 filters or children. - [x] Filter nesting deeper than 8. - [x] Empty field path or segment. - [x] Field path deeper than 9. - [x] Bare properties path. - [x] Unknown or nested standard field. - [x] Missing or unknown operator. - [x] Non-JSON operator value. - [x] Invalid in value or more than 1,000 in values. - [x] Non-boolean exists/isEmpty value. - [x] More than 8 sort entries. - [x] Invalid sort field or direction. - [x] first/last without a sort. - [x] Invalid output mode or includeMetadata. - [x] Duplicate output fields or more than 256 fields. - [x] No selected output. - [x] Negative, fractional, or over-1,000 limit. - [x] Negative, fractional, or over-1,000 offset. - [x] Invalid content mode. - [x] Invalid full/markdown-body-ref maxBytes outside 1..1 MiB. - [x] Invalid range offset/length or range over 256 KiB. - [x] Empty or over-255-character index revision. - [x] Multiple simultaneous schema issues retain exact query paths. - [x] Make content option objects strict; unknown keys are currently stripped. - [x] Show an invalid persisted resource body rather than silently loading the default query. - [x] Aggregate unknown-key errors with every other structural issue; MCP currently stops at the first unsupported key. - [x] Add field-value type validation, for example reject size gt "large" and id contains {}. - [x] Warn about unobserved dynamic fields selected only as output. - [ ] Prove the full structural matrix through the MCP server/API end to end; the current broad matrix tests the local adapter. ## Query semantic states - [x] INCOMPATIBLE_OPERATOR is fatal for standard fields. - [x] UNOBSERVED_FIELD is a nonfatal warning. - [x] INCOMPATIBLE_OBSERVED_TYPES is a nonfatal warning. - [x] STRUCTURED_SORT_ORDER is a nonfatal warning. - [x] Every incompatible standard-field operator is collected. - [x] Fatal semantic errors retain nonfatal warnings. - [x] Successful warnings appear with exact query paths. - [ ] Reproduce every catalog-dependent semantic state through real MCP. - [x] Test repeated warnings at distinct query paths without accidental deduplication. ## Query execution and hydration - [x] Stale index revision. - [x] result one matching multiple files, including matchedCount. - [x] Candidate document limit of 1,000. - [x] Result payload limit of 16 MiB. - [x] Hydrated file count limit of 20. - [x] Per-file hydration limit of 1 MiB. - [x] Total hydration limit of 2 MiB. - [x] Range limit of 256 KiB. - [x] Binary content requested as text. - [x] Invalid UTF-8 during hydration. - [x] Missing, stale, or conflicting content identity. - [x] Canonical metadata/byte-count mismatch. - [x] Storage returning more bytes than requested. - [x] Missing content reader. - [x] Selected content not returned. - [x] Runtime Asset URL unavailable. - [x] Document graph document-count/per-file/total limits. - [x] Classify candidate-document and result-byte limits as CONTENT_LIMIT_EXCEEDED instead of INVALID_REQUEST. - [x] Give unavailable URL, missing reader/content, storage, selection, and assembly failures stable codes and exact asset/file details instead of INTERNAL_ERROR. - [x] Never silently turn an exact-file unavailable-content failure into an empty successful result. - [x] Add direct regression tests for duplicate identity, excess bytes, and canonical byte mismatch. - [ ] Reproduce every runtime/hydration state through real MCP. ## Scoping and aggregation - [x] Errors and warnings from multiple loaded result files are returned together. - [x] Nonfatal errors do not suppress successful query results. - [x] Unrelated published-query diagnostics do not replace current-query diagnostics. - [x] File path and available line/column are shown. - [x] Exact nested query paths are shown. - [x] Validate and report every pre-pagination matching file if that is the product definition. - [ ] Explain candidate metadata warnings when invalid metadata prevents deciding whether a file matches. - [ ] Stop including METADATA_PREPARATION_FAILED globally unless the UI labels its candidate scope. - [x] Aggregate reference errors instead of stopping at the first. - [x] Aggregate across validation phases where safe. - [x] Add a matrix for same-file multiple errors, multiple files, outside-page errors, filter-only candidate files, and unrelated queries. ## Transport, authorization, cancellation, and internal failures - [x] UNAUTHORIZED and FORBIDDEN. - [x] REQUEST_CANCELLED in query HTTP paths. - [x] Sanitized authenticated internal message. - [x] Generic unauthenticated/public internal message. - [x] Preserve structured causes for document-load HTTP status/body/metadata failures. - [x] Preserve structured causes for object-storage read failures. - [x] Preserve structured causes for graph selection/assembly failures. - [ ] Test MCP/API cancellation directly. - [ ] Reproduce authorization, cancellation, storage, and sanitized-internal states through real MCP where safe. ## MCP reproduction - [x] Real MCP reproduction: multiple Markdown YAML errors. - [x] Real MCP reproduction: multiple simultaneous structural query errors. - [x] MCP update returns Markdown and MDX source diagnostics. - [x] MCP upload returns Markdown and MDX source diagnostics. - [x] MCP download returns Markdown and MDX source diagnostics. - [x] Temporary remote fixtures are removed after reproduction. - [ ] Real MCP reproduction for every frontmatter code. - [ ] Real MCP reproduction for every MDX fatal/warning class. - [ ] Real MCP reproduction for every Content Block semantic diagnostic. - [ ] Real MCP reproduction for every reference/graph error. - [ ] Real MCP reproduction for every semantic query warning/error. - [ ] Real MCP reproduction for every hydration/runtime/limit error. - [ ] Real MCP reproduction for auth, cancellation, storage, and internal errors where safe. - [ ] A durable table-driven test proves code/severity/message/path parity between editor, query, Diagnostics, and MCP. - [x] Preserve stable top-level error identity and structured details through MCP instead of flattening known errors to MCP_TOOL_FAILED. - [x] Prove failed post-commit MCP feedback reports whether a mutation committed and returns enough identity for cleanup. ## Real MCP recheck and follow-up fixes (2026-09-03) Ran the branch CLI against the PR preview backend. The first run exposed that the saved CLI origin pointed to a different backend, so those results were discarded. Every MCP result below came from the PR preview. All temporary remote and local fixtures were removed afterward. The failures found in that run were then fixed and covered by regression tests. - [x] Exact broken Markdown query returns FRONTMATTER_INVALID with severity, filename, message, line, and column. - [x] Exact MDX query returns unsafe-mdx with severity, filename, message, line, and column. - [x] A no-extension query returns warnings from both matching Markdown and MDX files. - [x] A Markdown-only query excludes the unrelated MDX warning. - [x] Two fatal MDX files inside the returned page are both reported; matching warnings remain attached. - [x] Structural query validation returns three independent errors with exact paths in one call. - [x] Semantic query validation returns three fatal operator errors and two warnings with exact paths in one call. - [x] MCP upload, update, download, and exact-file query return multiple source diagnostics for the same MDX source. - [x] Query preview reports a missing Asset reference as ASSET_NOT_FOUND with the source file and reference. - [x] All temporary MCP fixtures were deleted and the saved CLI connection was restored. - [x] Fixed after recheck: validate every matching file before pagination, including broken files outside the returned page. - [x] Fixed after recheck: unrelated graph failures no longer block an exact-file query. - [x] Fixed after recheck: update, download, editor, and query paths use shared reference validation. - [x] Fixed after recheck: graph failures map to structured diagnostics with the exact file. - [x] Fixed after recheck: shared fatal UTF-8 validation runs before upload writes and preserves structured error identity. - [x] Fixed after recheck: MCP rejects filename/format mismatches. - [x] Fixed after recheck: MDX validation keeps sibling and nested warnings around unsupported components. - [x] Fixed after recheck: MCP preserves stable top-level error codes and structured details. - [x] Fixed after recheck: query and MCP serializers preserve full normalized diagnostic fields. - [x] Fixed after recheck: unknown keys are aggregated with all other structural query errors. - [x] Fixed after recheck: shared query validation covers literal types, output-only fields, and strict content options. - [x] Fixed after recheck: unavailable selected content returns an exact-file diagnostic instead of a silent empty result. ## Tests and delivery - [x] Full Builder suite: 2,707 tests. - [x] Content Engine suite: 445 tests. - [x] Asset uploader suite: 211 tests. - [x] Project runtime/MCP targeted suite: 128 tests. - [x] CLI/MCP suite: 1,051 tests. - [x] Relevant package typechecks, lint, generated docs, and diff checks. - [x] Documentation impact reviewed and generated Content Engine/MCP reference updated. - [x] Add the missing cross-surface error matrix described above. - [ ] Demonstrate red/green behavior for every new matrix case. - [ ] Run the complete agent evaluation suite after explicit approval. - [ ] Re-run all checks after the remaining checklist is implemented. ## Compatibility and risk Normal query result and expression-binding shapes remain unchanged. Diagnostics add optional fields. Existing public/pre-auth error redaction remains intact. The remaining unchecked items are broader exhaustive real-MCP coverage, parser-recovery limits, candidate-warning labeling, cancellation coverage, and agent evaluations. |
||
|
|
0ffdf36665 |
fix: Explain dynamic Content Block asset sources (#6333)
## Summary Content Block source operations now explain how to resolve a dynamic Assets resource for one rendered occurrence. A caller can keep the persisted expression, supply the concrete resource result through `variables`, and receive safe structured diagnostics when the expression does not resolve to a non-empty MDX Asset id. The operation still does not load page routes or resource results itself. That work remains in the rendering or caller context. ## Checklist - [x] Reproduce the unresolved result-one Assets resource expression - [x] Preserve the dynamic source expression while validating a concrete Asset id - [x] Return the evaluated value shape without exposing supplied values - [x] Reuse the shared Content Block source resolver - [x] Describe `renderScope` and `variables` in the operation schema - [x] Add a result-one Assets resource example - [x] Verify connection keeps the dynamic expression after resolving the supplied result - [x] Add regression coverage for structured unresolved-source diagnostics - [x] Regenerate runtime contracts and CLI documentation - [x] Review fixture impact: fixture inputs and outputs are not affected - [x] Review documentation impact: MCP and CLI guidance are updated ## Verification - New diagnostic regression failed against the old generic error and passed with this fix - Project Build: 88 files, 2,284 tests passed - Project Build typecheck - CLI typecheck - Generated documentation and contract checks - Formatting and lint with warnings denied - Full CLI suite from the implementation review: 66 files, 1,038 tests passed Agent evaluations were not run because they require separate explicit approval. Closes #6330 |
||
|
|
2e4efb52f9 |
docs: update Link target values (#6326)
## Summary Update the Link documentation to match the current code. The Builder uses `_self`, `_blank`, `_parent`, and `_top` as the Link `target` values. The old docs described these as `Self`, `Blank`, `Parent`, and `Top`, which could make setting a new-tab link confusing. ## Changes - Document the four current target values. - Explain that `_blank` opens a link in a new tab or window. - Remove the outdated Target screenshot. - Checked the rest of `docs/` for the same outdated target names; no other related occurrences were found. ## Verification - `git diff --check` passed. - Confirmed the values in `packages/sdk-components-react/src/__generated__/link.props.ts` and `packages/sdk-components-react/src/create-link.tsx`. - Checked that the docs file and navigation file exist. - `pnpm exec oxfmt --check docs/university/core-components/link.md` did not run because the Markdown file is excluded by the formatter configuration. ## Checklist - [x] Review the current Builder implementation. - [x] Review the authoritative docs page. - [x] Check for similar outdated documentation. - [x] Review documentation impact: this PR updates the affected page; no other docs need changes. - [ ] Merge the pull request. |
||
|
|
75840a119c |
fix: Start previews and diagnose runtime failures (#6321)
## Summary Preview startup now binds loopback directly instead of scanning network interfaces first. MCP no longer exposes or accepts a fixed preview host or port: the CLI asks the operating system for an available loopback port and returns the resulting URL. The CLI also returns safe, structured diagnostics when the runtime blocks preview networking or Chromium IPC, when generated IDs collide, and when a listening preview fails its HTTP readiness probe. Preview startup retries only a genuine automatic-port race; HTTP and connection failures return immediately instead of repeating the full startup timeout five times. ## Issue checklist - [x] #6318 — reproduced the `uv_interface_addresses` failure, replaced interface discovery with a direct TCP bind, and added a regression test for the exact failure. - [x] #6319 — reproduced Chromium aborting before DevTools startup when the managed runtime blocks browser IPC/socket operations. The host restriction cannot be bypassed by the CLI, but future reports now include a safe `browser_ipc_permission_denied` issue without raw stderr, paths, or tokens. - [x] #6320 — ran four reported insert variants sequentially across two pages; all generated unique IDs. Future collision errors now include the affected namespace and insertion stage without exposing the generated ID. - [x] #6324 — reproduced the generic readiness timeout with a real generated preview whose root probe returned HTTP 500 after the server printed its Local URL. The MCP contract and documentation also allowed agents to force a busy port; network binding is now runner-owned. - [x] #6325 — confirmed the responsive screenshot uses the same readiness path. Future reports distinguish HTTP, refused-connection, timeout, and permission failures, non-port failures are no longer retried, and screenshots cannot request a fixed preview port. - [x] Documentation impact reviewed. Updated MCP examples and vision guidance to omit runner-owned host and port fields. ## Technical notes - Removes the CLI's direct `get-port` dependency. That package calls `os.networkInterfaces()` even when a host is supplied. - Binds `{ host: "127.0.0.1", port: 0 }`, reads the assigned TCP port, then closes the temporary server. - Removes `host` and `port` from MCP preview and screenshot input schemas and rejects those fields at runtime. - Returns the selected preview URL from `preview.start`; managed screenshots reuse that active target. - Returns `PREVIEW_NETWORK_RESTRICTED` with a stable `network_permission_denied` issue when the OS rejects loopback binding. - Reads at most the last 4 KB of Chromium startup stderr, maps only the reproduced IPC/socket denial to a safe diagnostic, and discards the buffer after startup. - Preserves browser startup issues through CLI browser fallback aggregation and the MCP screenshot error boundary. - Reports generated record collisions with `generated_id_conflict`, the namespace constraint, and the fragment insertion stage. - Preserves structured readiness diagnostics when preview output is appended. - Reports HTTP 5xx and local connection failures without exposing raw fetch errors. - Retries with a newly allocated port only for `EADDRINUSE` / `PREVIEW_PORT_IN_USE`. ## Verification - [x] New regression tests were shown to fail before implementation and pass afterward. - [x] Reproduced the old generic timeout through the real preview controller; after the fix, the same path returned `PREVIEW_HTTP_ERROR` with `http_status:500`. - [x] Verified MCP advertised and accepted fixed host/port fields before the change, then rejected both fields after the change. - [x] Preview readiness/controller tests: 2 files, 29 tests passed. - [x] Vision tests: 13 files, 81 tests passed. - [x] Project-build tests: 88 files, 2,282 tests passed. - [x] CLI tests: 66 files, 1,038 tests passed. - [x] Vision, project-build, and CLI typechecks passed. - [x] Lint passed with warnings denied. - [x] Package-boundary and MCP documentation checks passed. - [x] Fixture impact reviewed; no fixture inputs or generated fixture outputs are affected. Generated documentation was updated; the generated runtime operation contract did not change. Agent evaluations were not run because they require separate approval. Closes #6318 Ref #6319 Ref #6320 Ref #6324 Ref #6325 |
||
|
|
7ff42abfb5 |
docs: Simplify MCP setup (#6311)
## Summary - Add a short introduction with the only setup step: install the Codex desktop app or Claude Desktop and ask it to install Webstudio CLI and use MCP. - Keep the existing generated reference below a divider. - Remove documentation wording assertions across generators, CLI manuals and help, MCP guidance, tool descriptions, and operation docs. - Retain structured and executable coverage for command catalogs, schemas, examples, runtime behavior, errors, and UI contracts. ## Implementation The introduction lives in the MCP page template, and the generated GitBook page is committed with it. Documentation prose is now free to change without breaking tests; tests continue to cover machine-readable contracts and observable behavior. ## Checklist - [x] Add the concise introduction to the MCP template. - [x] Regenerate the authoritative `docs/` page. - [x] Audit the repository for documentation prose assertions. - [x] Remove prose-only generator, manual, help, guidance, schema-description, and operation-description assertions. - [x] Preserve structured and executable contract coverage. - [x] Review documentation impact: the existing MCP page is updated; navigation and other documentation are unaffected. - [x] Run targeted tests, typechecks, formatting, and lint checks. ## Verification - CLI: 121 tests passed across the affected suites (119 in the sandboxed run; 2 link tests passed separately with config-directory access). - Project build: 513 tests passed. - Protocol: 23 tests passed. - Content engine reference: 1 test passed. - `pnpm docs:mcp:typecheck` - Typechecks for `webstudio`, `@webstudio-is/project-build`, and `@webstudio-is/protocol` - `oxlint --deny-warnings` on all changed TypeScript files - `oxfmt` and `git diff --check` ## Compatibility and limitations Documentation and test-only changes. No runtime behavior, schemas, fixture inputs or outputs, or external integrations are affected. |
||
|
|
4a10645cb8 |
docs: Explain Builder themes and CSS warnings (#6298)
## Summary - Document the shared System, Light, and Dark interface-theme preference in the Dashboard and Builder guides. - Distinguish the Webstudio interface theme from the authored site's color scheme. - Explain experimental, nonstandard, and obsolete CSS property warnings in the Advanced Style panel. - Add focused, matching light- and dark-theme screenshots of the released Dashboard controls. ## Implementation The Dashboard guide owns the screenshot and complete theme explanation. The Builder anatomy guide documents the Builder menu path and links to that canonical section. The screenshot pair was captured from the released interface, cropped to the smallest useful region, and excludes account identity. ## Checklist - [x] Document the Dashboard theme path and available preferences. - [x] Document the Builder theme path and canvas-theme boundary. - [x] Explain CSS property status warnings and MDN compatibility details. - [x] Capture and visually review matching light/dark screenshots. - [x] Review documentation impact and update all affected authoritative `docs/` pages. - [x] Verify internal anchors, asset references, image formats, and the final diff. ## Verification - `git diff --check` — passed. - Screenshot assets — verified as 366×100 PNG files with equivalent UI state and no account identity. - Referenced files and `#interface-theme` / `#example-dark-mode` anchors — verified. - Repository formatter — not applicable; `oxfmt` excludes these documentation targets. - Tests — not run; documentation and screenshot assets only. - Fixture inputs and generated outputs — unaffected. ## Known limitations None. Closes #6297 |
||
|
|
9ec4c820e1 |
fix: Use writable npm cache for previews (#6272)
## Summary - Use a writable `.webstudio/preview/.npm-cache` for npm preview installs when `npm_config_cache` is not explicitly configured. - Preserve explicit npm cache settings and pnpm behavior. - Document a safe recovery path that requires no cache deletion. This removes preview startup failures caused by an unwritable default npm cache. Initial dependency installation and its network/download cost still remain when preview dependencies are not already installed. ## Technical choices - Keep the cache beside the isolated generated preview because that directory is already writable and reused across regenerations. - Let an explicit `npm_config_cache` continue to take precedence. - Do not retry arbitrary install failures or classify package-manager prose. ## Todo - [x] Reproduce npm dependency installation against an unwritable cache before changing code. - [x] Reproduce #6274 at the same dependency-install stage used by session-backed screenshots. - [x] Demonstrate the regression assertion failing before the fix and passing afterward. - [x] Use the preview-local cache only for npm without an explicit cache. - [x] Preserve explicit npm cache configuration and pnpm behavior. - [x] Verify the real dependency installer against an unwritable project npm cache. - [x] Verify session-backed screenshot flow proceeds from successful preview preparation to browser capture. - [x] Review documentation impact and update the CLI manual plus generated MCP documentation. - [x] Review fixture impact; no project fixture inputs or outputs are affected. - [x] Review the final diff for correctness, duplication, and unnecessary complexity. ## Verification - Actual npm install reproduced #6269 and #6274 with `EPERM` against an unwritable cache. - Real preview dependency installation passed after the fix while project npm configuration still pointed at that cache. - Fail-before/pass-after regression demonstrated. - `pnpm --filter webstudio test` — 65 files, 1,044 tests passed. - `pnpm --filter webstudio typecheck` - `pnpm lint` - `pnpm check:generated-docs` - Formatting and diff checks passed. - GitHub CI after rebasing onto current `main` — 30 checks passed, 7 skipped, no failures. - Agent evaluations were not run because they require separate explicit approval. Closes #6269 Closes #6274 |
||
|
|
1b48716ff4 |
docs: Document MDX-backed Content Blocks (#6273)
## Summary - Document how people create, connect, edit, validate, and publish MDX-backed Content Blocks. - Document the complete MCP workflow, including scoped expression sources, frontmatter updates, diagnostics, conflicts, and disconnect behavior. - Add two focused screenshots for the human workflow. - Fix issues found by a low-reasoning MCP agent while executing every documented workflow. Ref #6182 ## Implementation notes - Connection confirmation uses the public `confirmReplacement` field because `confirm` is reserved as a hidden transport field. - MCP edits frontmatter with `update-content-block-frontmatter`; materialized MDX elements are not persistent targets for generic instance mutation tools. - Reload now intentionally discards a conflicted local source and accepts the Asset's latest storage revision before an edit is reapplied. - Generated MCP documentation and runtime contracts are updated from their source files. ## Checklist - [x] Document the human MDX Content Block workflow. - [x] Document MCP discovery, connection, editing, diagnostics, frontmatter, dynamic sources, conflicts, and disconnection. - [x] Add only screenshots that clarify otherwise hard-to-describe UI steps. - [x] Test every documented MDX capability through the local MCP CLI with a low-reasoning agent. - [x] Reproduce and fix the replacement-confirmation schema mismatch. - [x] Reproduce and fix persistent-session conflict reload and reapply. - [x] Add regression tests that failed before each product fix and pass afterward. - [x] Regenerate runtime contracts and generated MCP documentation. - [x] Review authoritative `docs/` content and update affected pages. - [x] Run affected tests, typechecks, formatting, and diff checks. ## Verification - Project Build: 208 affected tests passed. - Content Engine Asset session: 8 tests passed. - CLI documentation tests: 14 tests passed. - MCP docs generator: 3 tests passed. - Content Engine, Project Build, CLI, and MCP docs typechecks passed. - `pnpm oxfmt --check` passed. - `git diff --check` passed. - Low-reasoning MCP evaluation passed all documented workflows, including a real two-client revision conflict, reload, reapply, and final saved inspection. |
||
|
|
f6c524572d |
feat: add Builder dark theme and rebuild colors
## Summary
Rebuilds Webstudio’s color system, migrates the entire Builder to it,
and introduces a complete dark theme.
A small set of theme colors and contrast controls now drives the
interface through relative CSS colors:
```text
Theme colors and contrast
↓
Light/dark derivation bounds
↓
Derived color families
↓
Reusable semantic colors
↓
Component composition
↓
Builder interface
```
CSS is the runtime source of truth. Light and dark modes share the same
theme inputs, so changing a theme color automatically updates its
surfaces, content, borders, states, and component presentation. The
refactor turns dark mode into a first-class Builder theme rather than a
separately maintained palette.
This is an atomic migration. Legacy color names and compatibility
aliases will not remain after all consumers have moved.
## Scope
- The color source, derivation model, semantic vocabulary, validation,
typing, and Storybook overview.
- Every design-system component.
- Builder, dashboard, authentication, shared UI, Query Builder, stories,
and tests that consume the legacy color scale.
- Removal of the legacy Stitches color scale after its final consumer is
migrated.
- A complete dark theme across application UI while keeping authored
canvas content independent.
- Complete light and dark visual verification.
- Unified browser-test infrastructure: Vitest Browser Mode for Design
System browser contracts and standard Playwright Test for all Builder
E2E workflows.
Literal colors remain only where color is the actual content or belongs
to a deliberately separate system, such as user-authored values,
external previews, brand artwork, data visualization, functional canvas
overlays, and source assets. Every remaining exception must have an
explicit owner.
## Architecture decisions
- Theme authors control six color families and three bounded contrast
controls.
- Relative CSS colors derive the rest of the system.
- Dark mode changes derivation bounds instead of maintaining a second
independent palette.
- Components consume a small reusable semantic vocabulary.
- Component states and exceptional presentation are composed inside
components.
- Builder-specific categorical meaning uses focused composite recipes,
not intent semantics or a larger global vocabulary.
- TypeScript validates public semantic CSS-variable names but does not
generate runtime colors.
- No token-manager dependency, compatibility aliases, or
component-specific public color tokens.
- A new semantic or theme variable is added only when existing semantics
and local composition cannot represent a reusable cross-feature
decision.
## Todo
### Color-system foundation
- [x] Establish direct CSS as the runtime source of truth.
- [x] Define bounded theme colors and contrast controls.
- [x] Derive light and dark modes from the same theme inputs.
- [x] Reduce the semantic inventory to reusable decisions and explicit
accessibility pairs.
- [x] Generate only TypeScript names for public semantic CSS variables.
- [x] Validate layers, references, cycles, consumption, naming,
generated types, and browser-computed contrast.
- [x] Add the Storybook color-system overview and theme controls.
- [x] Document the architecture and its relationship to the public Craft
specification.
### Design-system migration
- [x] Replace every active legacy color consumer in design-system
components and Storybook chrome.
- [x] Compose component states locally without component-specific public
tokens.
- [x] Preserve intentional preview and sample-content colors.
- [x] Add complete positive, negative, warning, informative, and accent
accessibility pairings.
- [x] Validate light and dark scheme-bound references independently.
- [x] Verify the design-system package with typecheck, lint, formatting,
Storybook, and 222 tests.
### Inventory and contract
- [x] Inventory all 319 legacy references across 107 Builder, Query
Builder, story, test, and design-system files.
- [x] Classify every reference as a direct semantic replacement, local
composite recipe, documented literal exception, or removable code.
- [x] Record the intentional authored-content, external-preview,
functional-preview, data-visualization, brand, and source-asset
exceptions.
- [x] Treat the public semantic vocabulary as closed by default and
justify any proposed addition by cross-feature reuse and accessibility
need.
- [x] Keep Builder code limited to typed public variables accepted by
`cssVar()`.
### Theme infrastructure
- [x] Add `system` (default), `light`, and `dark` application
preferences.
- [x] Persist the preference in existing client settings and resolve
`system` through `matchMedia`.
- [x] Apply the resolved scheme before paint and respond to
operating-system changes.
- [x] Expose the persisted theme control under **View → Color scheme**.
- [x] Keep authored canvas documents independent from the application
theme.
- [x] Ensure portals, overlays, embedded surfaces, and third-party
controls receive the correct interface scheme.
### Generic interface migration
- [x] Migrate shared dialogs, project settings, notifications, controls,
and Query Builder.
- [x] Migrate dashboard, authentication, publishing, and shared
application UI.
- [x] Migrate the Builder loading state, topbar, sidebars, navigator,
workspace, footer, settings, pages, alerts, and menus.
- [x] Replace fixed interface literals alongside their owning surfaces.
- [x] Remove the old scrollbar variable and hardcoded loading color.
### Style panel and style-source recipes
- [x] Migrate ordinary style-panel inputs, labels, layouts, spacing,
alignment, menus, property states, and value editors.
- [x] Model style-source provenance, kind, interaction, and error as
separate axes.
- [x] Compose categorical style-source colors from neutral and
accent-relative colors.
- [x] Use negative semantics only for actual errors, not overwritten
provenance.
- [x] Reuse one feature-owned recipe across style-source controls,
badges, menus, and values without adding global tokens.
### Canvas and editors
- [x] Migrate canvas selection, reusable outlines, grid guides, resize
handles, labels, badges, and overlays.
- [x] Keep collaborator colors as data visualization while guaranteeing
readable labels.
- [x] Prevent Builder theme values from leaking into authored content.
- [x] Migrate editor surfaces, selections, autocomplete, lint states,
and tooltips.
- [x] Derive syntax visualization from neutral and accent-relative
colors; reserve intent colors for diagnostics.
### Explicit color domains
- [x] Isolate external search and social previews from the application
scheme.
- [x] Preserve user-authored CSS values, functional color previews, and
checkerboards.
- [x] Review brand surfaces independently in both schemes.
- [x] Document every retained literal in the exception ledger.
### Stories, tests, and legacy removal
- [x] Migrate all affected Builder stories and tests.
- [x] Replace the design-system test that intentionally references the
legacy scale.
- [x] Add theme-preference and scheme-resolution behavior tests.
- [x] Remove the legacy `design-tokens.color` registry.
- [x] Remove the Stitches `colors` scale and `rawTheme.colors`.
- [x] Remove color-name conversion code that exists only for the legacy
scale.
- [x] Add a focused repository check that rejects legacy references.
- [x] Confirm no compatibility mappings or deprecated aliases remain.
### Browser-test infrastructure
- [x] Run pure Design System tests in Node and browser-dependent tests
in Vitest Browser Mode with Playwright Chromium.
- [x] Migrate all 79 Builder E2E workflows from the custom harness to
standard Playwright Test.
- [x] Replace filename-based shard discovery with standard Playwright
sharding.
- [x] Preserve clean-backend shard retries and upload Playwright failure
artifacts in CI.
- [x] Remove the custom runner, registry, and timeout infrastructure.
### Verification and documentation
- [x] Compare light-mode visual regressions directly with `main`; review
every difference rather than accepting snapshots wholesale.
- [x] Add representative dark coverage for dashboard, Builder shell,
style panel, dialogs, editors, canvas tools, and status states.
- [x] Test default and extreme custom-theme presets.
- [x] Verify semantic and categorical-recipe contrast.
- [x] Test first paint, persistence, system changes, portals, and canvas
isolation.
- [x] Run affected tests, typechecks, lint, formatting, and Storybook
checks.
- [x] Review fixture impact; no fixture inputs or generated outputs are
affected.
- [x] Review authoritative `docs/` content and update it where needed.
- [x] Review the final diff and make this checklist reflect delivered
scope.
## Current verification
- Design-system typecheck and generated-type freshness: passed.
- Design-system tests: 222 passed, including the full theme-parameter
contrast sweep and browser component coverage.
- Builder typecheck and production build: passed.
- Theme preference and scheme-resolution tests: 10 passed.
- Scoped Oxlint, formatting, and diff checks: passed.
- Design-system Storybook build and representative light/dark visual
review: passed.
- Builder E2E: 80/80 Playwright entries passed (setup plus 79
workflows).
Ref #3818
Closes #6267
|
||
|
|
f9681dc30f |
feat: MDX-backed Content Blocks (#6234)
## Summary Supersede #6182 with a clean implementation of MDX-backed Content Blocks on top of the unchanged `main` Content Block editing model. A connected `.mdx` Asset changes where authored children are loaded and saved; it must not change how Content mode inserts, edits, selects, moves, copies, or deletes instances. The previous implementation remains available in `agent/mdx-content-block-6124` and `agent/mdx-content-block-6124-review`. Reuse its independently tested parsers, converters, schemas, Asset repository, template resolution, publication, MCP, and UI work where those pieces fit the corrected architecture. Do not port its per-operation storage routing, projected editing stores, MDX undo/history, or atomic multi-root machinery. Ref #6124 Ref #6182 Closes #6261 ## Locked behavior - `.md` keeps its existing Markdown behavior; `.mdx` enables MDX. - Standard Markdown structures are stored as Markdown. JSX is used only for structures Markdown cannot represent losslessly. - Generic elements use `<ws.element ws:tag="…">`; template instances use `<ws.element ws:name="…">`. - Invalid, unsafe, or unsupported MDX never prevents editing the file or publishing the project. Builder and publication use the same recovery result: recoverable nodes are skipped with source-located warnings, while an unrecoverable document renders no authored file content in either environment. - Connecting a source never serializes existing Content Block children into the file. **Connect** removes ordinary persisted children, preserves Templates, sets `src`, and uses file content. - Disconnecting resets `src`, discards derived instances, leaves the Content Block empty, and never changes the Asset. - While connected, normal Content Block mutations update in-memory instances synchronously. Asset persistence happens afterward and never blocks rendering. - Genuine external revision conflicts use the standard reload-required flow. Rapid local edits are ordered/coalesced and must never conflict with each other. - Repeated scopes use Content Block ID plus Collection item identity. - Multiple Content Blocks may intentionally share one MDX Asset. They share one revisioned document session and edits propagate to every connected occurrence. - Missing templates show warnings/placeholders only in Builder and are skipped on published sites. ## Reuse strategy - [x] Audit all 62 original implementation commits and 5 later review/fix commits - [x] Reuse the shared Content Engine Markdown/MDX AST, parser, serializer, diagnostics, reference discovery, and tests - [x] Reuse SDK source schemas, instance-name utilities, unique template naming, and source-integrity validation - [x] Reuse template resolution/materialization and authored-tree conversion after removing storage-operation coupling - [x] Reuse revisioned Asset content repository, authorization, limits, and browser/server transport - [x] Reuse publication, document-graph, CLI, MCP, source-control UI, frontmatter UI, and E2E work where contracts remain valid - [x] Reuse tests as behavioral specifications; rewrite tests that assert the rejected projection/routing architecture - [x] Do not port per-operation MDX routing, alternate projected mutation stores, semantic reconciliation after each command, MDX Builder history/undo, atomic multi-file rollback, or canvas loading/saving UI ## Old-branch porting map — do not rewrite Before implementing any checklist batch, inspect the named implementation and tests on `agent/mdx-content-block-6124-review`. Move the implementation and its tests first; change only the boundary that conflicts with the rebuilt architecture. Do not create a second implementation under a new name. When a test encodes the rejected projected-store architecture, retain its behavioral assertion and replace only its setup. ### Already ported - `parseMarkdownAst`, `createMdxDocumentFromMarkdown`, `parseMdxDocument`, `serializeMdxDocument`, `preferMarkdownSyntax`, `discoverMdxBodyAssetReferences`, `discoverMdxAssetReferences`, and `previewMarkdownToMdxConversion` - Asset-reference, byte-stream, document-graph, Markdown, and MDX helpers included in commit `76bc388ba9` - Tests: the corresponding `packages/content-engine/src/**/*.test.ts` files already on this branch ### Port with their existing tests | Area | Functions to move or adapt | Tests to move with them | | --- | --- | --- | | Source contract and integrity | `parseContentBlockSourceProp`, `getContentBlockSource`, `isEqualContentBlockSource`, `formatContentBlockSourceIntegrityIssue`, `getContentBlockSourceIntegrityIssues`, `allocateUniqueContentBlockTemplateName` | `packages/sdk/src/content-block.test.ts`, `packages/sdk/src/schema/content-block.test.ts` | | Existing instance/name utilities | `findChildReferenceIndex`, `findParentInstanceReference`, `getInstanceName` | `packages/sdk/src/instances-utils.test.tsx` | | Template naming in mutations | `assignUniqueBlockTemplateNamesMutable`, `findBlockTemplateNameCollision`, `getSourceBackedBlockTemplateContext`, `getBlockTemplateNameConfirmation`, `getBlockTemplateInsertionIndex` | `packages/project-build/src/runtime/block.test.ts` | | Content-mode property permissions | `getContentModePropEligibility`; preserve its distinction between editable, design-only, incompatible, and unknown props | `packages/project-build/src/runtime/content-mode-permissions.test.ts` | | Template resolution | `resolveMdxTemplates` | `packages/project-build/src/runtime/mdx-template-resolution.test.ts` | | Template materialization | `createMdxScopeIdGenerator`, `materializeMdxTemplates` | `packages/project-build/src/runtime/mdx-materialization.test.ts` | | MDX → instances and instances → MDX | `isMaterializedMdxAuthoredContentRoot`, `preserveMdxAuthoredContentIds`, `materializeMdxAuthoredContent`, `reconcileMdxAuthoredContent`, `omitTransientEmptyParagraphs`, `serializeMdxTemplateInsertion` | `packages/project-build/src/runtime/mdx-authored-content.test.ts`; retain the pure serialization cases from `mdx-storage-adapter.test.ts` | | Revisioned Asset I/O | `createAssetContentRevision`, `readAssetContentBytes`, the package-owned `createHttpAssetContentRepository`, the thin Builder `createBuilderHttpAssetContentRepository`, `createAssetContentBridge`, `initAssetContentBridge`, `getAssetContentBridge`; keep one repository implementation rather than copying the old Builder duplicate | `packages/asset-uploader/src/content-repository.test.ts`, `apps/builder/app/builder/shared/assets/mdx-content-repository.test.ts`, `apps/builder/app/shared/asset-content-bridge.client.test.ts` | | Source lifecycle planning | `createContentBlockBodyRemoval`, `prepareContentBlockConnect`, `prepareContentBlockDisconnect`, `prepareContentBlockSwitch`, `ContentBlockSourceRevisionConflictError` | `packages/project-build/src/runtime/content-block-source-lifecycle.test.ts` | | Per-Asset revision/session behavior | `getContentBlockSessionSource`, `isContentBlockSessionSourceCommitted`; reuse the loading, authorization, revision, queue, conflict, retry, cancellation, and source-replacement internals of `createMdxAssetEditingSession`, but key the rebuilt session by Asset rather than Content Block/render root | Port the applicable cases from `packages/project-build/src/runtime/mdx-asset-session.test.ts`; replace root-projection setup with in-memory snapshot setup | | Template migrations | `validateMdxTemplateMigrationConfirmation`, `planMdxTemplateMigration` | `packages/project-build/src/runtime/mdx-template-migration.test.ts` | | Publication | `createPublishedMdxMaterializationCache`, `materializePublishedMdx`, `getPublishedMdxContentDatabaseMaxBytes`, `getDynamicPublishedMdxSourceBlockIds`, `hasDynamicPublishedMdxSources`, `createPublishedBuildContentCompilationPlan`, `resolvePublishedMdxDependencyClosure`, `resolvePublishedMdxAssetCandidates` | `packages/project-build/src/runtime/published-mdx.test.ts`, `packages/project-build/src/content-database.test.ts` | | Build/import integrity | `assertContentBlockSourceIntegrity` and the Content Block cases in `getBuildIntegrityIssues`/`formatBuildIntegrityIssue` | `packages/project-build/src/build-integrity.test.ts` | | MDX paste/MCP insertion | `insertMdxText` and its input/result schemas; retain parsing, confirmation, template-resolution, and insertion-index logic, then invoke the normal mutation path | `packages/project-build/src/runtime/mdx-paste.test.ts` | | Builder source control | `createContentBlockSourceController`, `createBuilderContentBlockSourceController` and the existing source-control components | `content-block-source-controller.test.ts`, `content-block-source.test.tsx` | | Diagnostics | `formatContentBlockDiagnostic`, `deduplicateContentBlockDiagnostics`, `takeNewContentBlockDiagnostics` | Port only their focused cases from `apps/builder/app/shared/content-block-content.test.ts` | ### Explicitly do not port - `projectContentStorageChanges`, `createContentStorageProjection`, `createContentStorageSelectorProjection`, `executeContentStorageMutation`, `executeContentStorageTextReplacement`, `executeContentStoragePropMutation`, and `executeContentStorageStructuralMutation` - `applyMdxContentStorageChanges` and `prepareMdxContentStorageWrites`; replace them with one post-mutation snapshot serializer built from the reusable pure `reconcileMdxAuthoredContent` converter - `createContentBlockApplicationOperations` and the persistence-plan wrappers that route individual editing commands - Builder `$runtime*` projected stores, materialized mutation functions, alternate selector/tree helpers, pending projected-change state, and MDX-specific mutation sequences from `content-block-content.ts` - Canvas loading/saving/open-file presentation state, MDX history/undo, and atomic rollback machinery ## Implementation checklist ### 1. Preserve the `main` editing architecture - [x] Keep normal synchronous insert, text, Enter, slash menu, property, delete, move, wrap, copy/paste, selection, and focus mutations unchanged - [x] Materialize connected content through the same runtime instance interfaces used by ordinary Content Blocks - [x] Keep connected authored children in memory and exclude them from persisted build data - [x] Route persistence only after a synchronous mutation has updated the canvas - [x] Never wait for Asset loading, conversion, or saving before rendering an interaction - [x] Add no MDX-specific implementation to individual editing commands ### 2. Shared Markdown and MDX conversion - [x] Parse Markdown and the Markdown portion of MDX through one shared AST and plugin configuration - [x] Implement one shared MDX-to-instances converter and one shared instances-to-MDX converter - [x] Serialize headings, paragraphs, links, images, lists, tables, task lists, blockquotes, thematic breaks, code, emphasis, strong, strikethrough, and other supported GFM structures as Markdown - [x] Serialize only non-lossless/custom structures as Webstudio JSX - [x] Preserve nested Markdown in MDX elements, frontmatter, comments, tight/loose list semantics, code whitespace, reference links, and Asset references - [x] Omit transient empty draft paragraphs instead of emitting `<ws.element ws:tag="p" />` - [x] Preserve unsupported source text and authored metadata whenever it cannot be converted safely - [x] Add deterministic round-trip and canonical-output coverage for every supported Markdown structure ### 3. Invalid and unsafe MDX - [x] Preserve file source exactly; never silently repair or rewrite invalid source - [x] Ignore imports, exports, expressions, executable JavaScript, invalid properties, and other unsupported nodes when they can be isolated - [x] Continue rendering valid siblings and report every skipped subtree once with filename, line, and column - [x] Use the same recovery pipeline in Builder and publication so both render the same authored result for the current file revision - [x] When structural syntax prevents recovery, render no authored file content in Builder or publication instead of retaining a stale materialization - [x] Skip an unrecoverable Content Block on published sites and continue the build with a warning - [x] Keep invalid and unsafe files editable and reconnectable - [x] Enforce UTF-8, byte-size, depth, node-count, property-count, and generated-output limits with source-located diagnostics where possible ### 4. File formats and Asset creation - [x] Keep `.md` parsing and raw-HTML behavior unchanged - [x] Support creating, opening, editing, deleting, and recreating `.mdx` files through the normal text-file UI - [x] Open `.mdx` in the same editor experience as `.md` - [x] Always create an independent empty MDX Asset even when identical empty files exist - [x] Allow renaming `.md` to `.mdx` without converting or rewriting its contents; after rename, handle invalid contents through the normal MDX diagnostics and recovery pipeline - [x] Update an already-open MDX editor immediately after canvas persistence - [x] Bound read/write buffering and verify the returned Asset identity and revision ### 5. Source contracts and lifecycle - [x] Support direct Asset bindings and dynamic expression bindings - [x] Keep source mutation controls available only in Design mode; show the connected filename and **Open** action read-only in Content mode - [x] Reject duplicate source props, unsupported prop types, missing Assets, non-MDX Assets, and unauthorized Assets - [x] Analyze selected file diagnostics before confirmation without modifying the block or file; MDX syntax diagnostics do not block connection - [x] For a non-empty block, show **Abort** and **Connect** and explain that ordinary children will be replaced - [x] On connect, remove every non-template child, preserve Templates, set `src`, and materialize file content - [x] Replace disconnect handoff with normal `src` reset; discard derived content and leave the block empty - [x] Remove disconnect confirmation and conversion; resetting a repeated binding leaves every occurrence empty - [x] Switching sources validates/loads the target before replacing the usable binding and leaves both files unchanged - [x] Revalidate Asset revision and project version when confirmation is submitted - [x] Make repeated connect/disconnect operations idempotent - [x] Prevent disposed, stale, or out-of-order loads from replacing the newest source - [x] Keep loading, saving, conflict, empty-file, and open-file actions off canvas ### 6. Asynchronous persistence and conflicts - [x] Snapshot the current in-memory authored root after normal mutations - [x] Serialize/coalesce rapid edits per resolved Asset and always prepare against the latest local snapshot - [x] Allow independent Assets to save concurrently without scope leakage - [x] Use one revisioned document session and one ordered save queue per Asset, even when multiple Content Blocks or render scopes reference it - [x] After a shared Asset changes, rematerialize every connected occurrence without persisting their generated instances to project data - [x] Pin the resolved Asset and exact loaded revision for each write - [x] Recheck authorization immediately before storage - [x] Ensure local queued edits never produce stale-revision conflicts with each other - [x] On a genuine external revision conflict, preserve local content, stop writes, and enter the standard reload-required state - [x] Keep failed non-conflicting writes retryable without discarding local content - [x] Finish already accepted persistence writes after a Content Block unmounts or switches source - [x] Cancel obsolete loads, materializations, and UI updates after unmount, reload, or source switch - [x] Dispose project-scoped roots, queues, parse caches, failure state, generations, and session subscriptions when the Asset session is replaced - [x] Invalidate Asset resources and synchronize open file editors after successful writes - [x] Keep multi-root persistence ordered, serial, and non-atomic; report partial completion without rollback - [x] Do not add Asset-history undo/redo; native text-editor undo remains local to the open editor ### 7. Content mode parity - [x] Empty connected blocks remain selectable and expose the normal Content-mode `+` affordance - [x] First insertion renders immediately - [x] Enter creates and focuses the next paragraph immediately - [x] Slash commands work in newly created empty paragraphs - [x] Deleting one selected instance deletes exactly that instance - [x] Mouse and keyboard moves use the same operation and permissions - [x] Preserve sibling reorder, nested reparenting, and moves between editable Content Blocks where `main` permits them - [x] Preserve content-editable props such as Link `href` - [x] Preserve copy, paste, cut, multi-cut, wrapping, unwrapping, grid insertion, selection, Navigator order, and canvas order - [x] Cover mutation routing centrally, retain the full unconnected Builder suite, and exercise representative connected interactions in real Builder E2E ### 8. Template names and permissions - [x] Resolve only exact user-facing names from the direct flat Templates list - [x] Enforce unique names within each Templates list - [x] Reject duplicate names during rename with inline validation - [x] Allocate unique names during insert, paste, duplicate, move, wrap, and unwrap - [x] Apply valid template properties using the same permissions as Content mode - [x] Preserve and warn about ignored design-only, invalid, or stale properties - [x] Preserve template shell provenance without serializing expanded template internals - [x] Generate deterministic materialized IDs from source identity, render scope, and authored usage path so focus/selection survives saves - [x] Warn before renaming or deleting referenced templates; files remain unchanged - [x] Provide shared AST-based rename/remove migration operations for MCP-assisted multi-file cleanup ### 9. Scope, frontmatter, and diagnostics - [x] Scope materialized content by Content Block ID plus exact Collection-item/render context - [x] Prevent repeated instances and dynamic candidates from leaking generated IDs, template resolution, or diagnostics across scopes while sharing the underlying Asset source and revision where applicable - [x] Remove frontmatter editing from Settings; edit the exact YAML through the MDX Asset file editor - [x] Preserve the exact frontmatter source byte-for-byte during canvas body saves - [x] Route canvas body changes and complete-file editor saves through one revisioned per-Asset coordinator - [x] Show a source warning indicator in Settings and precise source-located diagnostics in the Asset editor - [x] Deduplicate repeated diagnostics without losing distinct locations - [x] Keep unresolved-template placeholders selectable and accessible only in Builder ### 10. Asset references, transfer, and integrity - [x] Discover and rewrite Asset references in frontmatter, Markdown links/images, and MDX properties - [x] Preserve Asset references while editing unrelated content - [x] Include referenced Asset and template revisions in dependency/cache identity - [x] Route referenced Assets through published URL rewriting - [x] Validate Content Block source integrity during project import, fragment/page transfer, copy/paste, build integrity, and pre-publish audit - [x] Allow multiple Content Blocks and dynamic render scopes to reference the same MDX Asset without treating the connection as an integrity error - [x] Preserve Templates when copying a connected Content Block - [x] Preserve direct and dynamic Content Block source bindings when copying or pasting within the same project - [x] When copying only one rendered Collection item, resolve that item’s current MDX Asset and replace the copied Content Block’s dynamic source with a direct binding to that same Asset - [x] When copying an entire Collection, preserve the Collection, its instances, and its dynamic source bindings - [x] Preserve the complete MDX source and frontmatter by reference; copying a connected block must not rewrite the shared file - [x] During cross-project transfer, copy every discoverable distinct bound MDX Asset and rewrite transferred bindings to the destination Assets - [x] If some cross-project dynamic candidates cannot be discovered or copied, continue with successful copies, preserve what can be represented safely, and warn about skipped candidates - [x] Revalidate source revisions and the destination project before applying a cross-project transfer - [x] If cross-project Asset creation or project insertion fails, leave the source project unchanged and clean up any newly reserved destination Asset - [x] Use the same transfer operation through Builder and MCP ### 11. Dynamic sources and publication - [x] Resolve dynamic bindings once per render/save scope - [x] Require finite, discoverable candidate sets for publication and load no unrelated MDX - [x] Warn and skip unbounded, missing, unreadable, malformed, or unsafe sources without failing the complete build - [x] Materialize only rendered Content Blocks; ignore Templates definitions and `src` on non-Content-Block instances - [x] Skip unresolved template subtrees while keeping valid siblings - [x] Include selected template styles, fonts, resources, unresolved names, and referenced Asset revisions in generated dependency output - [x] Keep draft-only MDX Assets out of publication retention ### 12. Builder, MCP, CLI, and shared operations - [x] Use the same converters, source lifecycle, revision checks, persistence service, diagnostics, and template migrations in Builder and MCP - [x] Keep frontmatter editing file-based; retain whole-frontmatter runtime operations only where compatibility requires them - [x] Avoid Builder-only or MCP-only mutation/conversion implementations - [x] Regenerate runtime/API contracts from their source definitions - [x] Update CLI Content Engine reference and generated MCP documentation ### 13. Verification and delivery - [x] Add regression tests that reproduce failures from the previous implementation, including double deletion and blocked rendering - [x] Cover two Content Blocks sharing one Asset: edits from either block serialize once, update both canvases, preserve scope-specific Templates, and cannot overwrite a newer local snapshot - [x] Verify new tests fail against the broken implementation and pass with the corrected behavior - [x] Run SDK, Content Engine, Asset Uploader, Project Build, Builder, React SDK, CLI, Protocol, and HTTP Client affected suites and typechecks - [x] Run real Builder E2E for source lifecycle, live file refresh, empty insertion, Enter/slash focus, Link props, delete, keyboard reorder, switching, disconnect, conflicts, unresolved templates, dynamic sources, and repeated scopes - [x] Regenerate shared project fixture bundles and verify a second generation leaves the tree clean - [x] Run lint, package boundaries, `pnpm oxfmt --check`, and `git diff --check` - [x] Review and update authoritative `docs/` content and navigation - [ ] Run the complete agent evaluation suite — not run because it requires separate explicit approval ### 14. Content-mode parity and disconnect handoff - [x] Allow keyboard reordering in Content mode through the normal move command while keeping the editable Content Block boundary - [x] Let already accepted Asset writes drain independently before resetting the source; disconnect does not load, flush, or convert the file - [x] Remove MDX-to-instance copying from disconnect - [x] Reset `src`, remove the derived tree, and leave the ordinary Content Block empty - [x] Preserve automatic text-editor focus after inserting editable content from the template menu - [x] Remove Builder frontmatter-save UI and report complete-file save failures through the Asset editor - [x] Add regression coverage for keyboard movement, disconnect teardown, source switching, insertion focus, and paragraph deletion focus restoration - [x] Run the complete six-scenario MDX Content Block Builder E2E suite ### 15. Final architecture review fixes - [x] Keep one canonical ordered pending document per Asset so shared Content Block occurrences cannot conflict with one another - [x] Merge ordered local edits from different occurrences while preserving text changes, insertions, deletions, and sibling reordering; keep external revisions on the strict reload-required path - [x] Centralize typed render-scope parsing, repeated-occurrence detection, scoped variable lookup, and dynamic Asset resolution across Canvas, Settings, source lifecycle, and copy/paste - [x] Capture the owning Asset session when a save is accepted so normal unmount/source-switch teardown cannot redirect or lose it - [x] Dispose project-owned roots, queues, caches, generations, failure state, and subscriptions when replacing the project Asset session - [x] Add regression coverage for same-Asset edits from two occurrences, same-node last-write ordering, structural reorder, insertion preservation, scoped source resolution, and project cleanup - [x] Re-run affected full unit suites, typechecks, production build, static checks, and all six MDX Content Block Builder E2E scenarios ### 16. Final persistence and transfer hardening - [x] Drain every accepted per-Asset edit before project-session teardown while retaining the owning authorization context - [x] Drain canvas serialization queues and revisioned Asset writes before pre-publish audit and publication - [x] Block publication on a queued serialization failure or Asset revision conflict - [x] Copy actual Asset bytes during cross-project paste, preserve MDX reference names, rewrite direct and Collection-backed Asset IDs, and clean up newly created Assets when insertion fails - [x] Include every resolved dynamic MDX source when copying an entire Collection and warn while preserving successful copies when individual Assets cannot be transferred - [x] Keep MDX editor save failures visible with retry and route conflicts through the standard reload-required flow - [x] Give keyboard nested reparenting the same editable Content Block boundary used by pointer movement - [x] Add regression coverage and rerun the complete Content Engine and Builder unit suites plus type, lint, formatting, package-boundary, and diff checks ## Current rebuild status - The connected Content Block now owns one complete MDX document: frontmatter feeds designed-shell bindings and the explicit Body outlet owns the authored MDX body. - Builder and published output resolve the same frontmatter document graph, including nested document references and Asset references. - Direct frontmatter text/property edits use the existing ordered per-Asset session; referenced-document values remain file-owned. - Repeated Collection occurrences keep isolated runtime shell/Body identities and occurrence-specific document values. - The local blog article layout has been upgraded to the document/Body model and its bindings validate cleanly. - Full affected package suites and typechecks pass; every new regression was demonstrated fail/pass. - `pnpm lint`, package boundaries, `pnpm oxfmt --check`, generated API/docs checks, fixture builds, and `git diff --check` pass. - Full fixture synchronization is blocked by the development API rejecting this local CLI version before fixture generation; existing fixture bundles build successfully. - Complete agent evaluations remain pending explicit approval. ### 17. Treat Content Block source as a property - [x] Declare Content Block `src` in component metadata as a Design-mode initial property labeled **Source** - [x] Add the short property description: “Create an .mdx file in Assets, then select or bind it here.” - [x] Accept only a direct Asset or an expression resolving to an Asset ID; reject URL/string sources, missing Assets, and non-MDX Assets - [x] Extract and reuse the Image-style Asset picker and binding presentation without duplicating source-control UI - [x] Render Source through the normal properties section and remove the separate source-section placement and special `src` filtering - [x] Route Source changes through Content Block connect, switch, and disconnect lifecycle operations instead of generic prop updates - [x] Keep connect confirmation, Open, diagnostics, and persistence state attached to Source; remove frontmatter and disconnect UI - [x] Add regression coverage for direct Assets, dynamic Asset bindings, invalid resolved values, lifecycle operations, and Design/Content mode visibility - [x] Re-review authoritative `docs/` content for the Source-property UI change and update it if required ### 18. Source property UX - [x] Show one full-width bindable Connect .mdx file button while disconnected - [x] Show equal-width filename and Open buttons while connected - [x] Switch files from the filename button through the source lifecycle - [x] Override PropertyLabel reset and Alt-click with the disconnect lifecycle - [x] Preserve confirmation, pending, failure, repeated-scope, and dynamic-source behavior - [x] Add regression coverage for connect, switch, binding, reset, and disconnect - [x] Update Content Block documentation - [x] Run affected tests, typecheck, lint, formatting, package boundaries, and diff checks ### 19. Reduced file-owned frontmatter follow-up This checklist supersedes the earlier structured-frontmatter and disconnect-copy behavior. Frontmatter remains file-owned and is edited only in the MDX Asset editor. #### A. Remove structured frontmatter UI - [x] Remove the JSON frontmatter editor and unused Builder controller/state - [x] Keep source mutation Design-mode-only; show connected Source read-only in Content mode and allow authorized editors to open the complete file - [x] Retain runtime frontmatter APIs only where compatibility requires them #### B. Preserve source and separate validation - [x] Preserve the exact frontmatter envelope during every canvas body save without parsing/stringifying YAML - [x] Preserve comments, ordering, quoting, whitespace, BOM, newline style, delimiters, and invalid but closed YAML - [x] Keep the existing unsupported-node/property MDX recovery; do not add an ad hoc partial parser - [x] Parse body and frontmatter independently so either valid half remains usable - [x] Keep bounded Asset-query frontmatter extraction unchanged - [x] Treat structurally malformed MDX as having no safe body tree #### C. Share Asset state with the raw editor - [x] Route canvas and complete-file changes through one ordered, non-blocking per-Asset coordinator - [x] Update canvas and clean raw editors immediately from shared in-memory source - [x] Reject stale dirty-editor saves, preserve unsaved text, and require reload; never force-overwrite - [x] Drain accepted writes after source replacement/disconnect and report background failures globally - [x] Dispose sessions only after they have no consumers and no queued work #### D. Connect, replace, and disconnect - [x] Load and diagnose before connect; block only unreadable/unauthorized/non-MDX Assets - [x] Show **Abort / Connect** for non-empty blocks, including diagnostics and the recoverable-content warning - [x] Set `src` and delete persisted children through one runtime mutation - [x] Switch to a loaded source without waiting for the previous Asset's network save - [x] Remove disconnect confirmation and conversion - [x] Reset `src` immediately, discard the derived tree, leave the block empty, and preserve the Asset - [x] Resetting a bound source leaves every repeated occurrence empty #### E. Dynamic and shared sources - [x] Keep one source/revision state per Asset and a separate derived instances tree per occurrence - [x] Resolve Templates independently per Content Block and preserve Builder-only missing-template placeholders - [x] Resolve bound `src` from the selected Collection occurrence - [x] Make **Open** use the occurrence's resolved Asset; update the filename and disable Open when unresolved - [x] Add direct/bound tests including Collection item A opening `a.mdx` and item B opening `b.mdx` #### F. Diagnostics, MCP, and publication - [x] Show an accessible warning icon beside Source with the first diagnostic, line/column, and remaining count - [x] Show precise YAML/MDX diagnostics in the Asset editor without repetitive canvas/toast UI - [x] Reuse parser/diagnostic/revision contracts in Builder, build, publication, and MCP - [x] Keep MCP frontmatter editing file-based and return structured diagnostics for complete-source writes - [x] Emit build warnings; published sites skip invalid/unsupported content without diagnostic UI #### G. Verification and documentation - [x] Add fail/pass regressions for source preservation, independent validation, stale raw saves, lifecycle, dynamic Open, shared Assets, and cleanup - [x] Run affected tests, typechecks, lint, formatting, package boundaries, fixtures, and diff checks - [x] Open Markdown and MDX editors at twice the default dialog size with the right-side preview visible initially - [x] Document canvas body editing, file-owned frontmatter, Content-mode Asset access, and cloning an MDX Asset for a new post - [x] Perform a final correctness, data-loss, DRY, simplification, accessibility, and performance review - [x] Keep this checklist synchronized with implementation status ### 20. Content-mode component properties - [x] Show a connected Content Block Source read-only in Content mode with an active **Open** action - [x] Keep source switching, binding, reset, and disconnect available only in Design mode - [x] Expose HTML Embed code and preserve Code Text's code-editor metadata on authored Text Content - [x] Audit every registered component and expose authored payload while keeping design, structure, and behavior controls in Design mode - [x] Keep media dimensions and Code Text theme Design-only while preserving adapter-owned intrinsic Image metadata during MDX round trips - [x] Add exact component-permission and regression coverage - [x] Update authoritative component documentation - [x] Run affected full suites, typechecks, formatting, lint, package boundaries, and generated contract/documentation checks ### 21. Designed document shell and Body outlet - [x] Add one structural **Content Block Body** outlet and keep legacy Content Blocks without it compatible - [x] Materialize and persist only `document.body` children through the Body outlet while preserving the surrounding designed shell and Templates - [x] Expose the connected document frontmatter through a Content Block `document` parameter for shell text and property bindings - [x] Write direct frontmatter-bound text and properties back through the same ordered per-Asset session without blocking canvas mutations - [x] Resolve document `$ref` dependencies and Asset references consistently in Builder and published output - [x] Keep referenced-document values read-only on canvas and direct editors to the referenced file - [x] Isolate repeated Collection occurrences while retaining occurrence-specific source, frontmatter, shell, and Body content - [x] Render the same designed shell, frontmatter values, and Body substitution in generated/published output - [x] Upgrade the local blog article layout to bind title, excerpt, dates, author data, and images from frontmatter and render MDX through Body - [x] Add fail/pass regressions for nested Body discovery, lifecycle, permissions, repeated values, document references, and generated shell rendering - [x] Update authoritative Content Block documentation - [x] Run affected tests and typechecks, formatting, lint, package boundaries, generated API/docs checks, and fixture builds ### 22. Final nested references and frontmatter editing - [x] Keep direct frontmatter-bound text and property controls editable in Content mode without exposing or replacing their bindings - [x] Keep referenced-document values read-only and preserve legacy instance-property name normalization - [x] Render direct frontmatter text bindings through the plain-text editing path - [x] Resolve nested legacy and structured Asset references from referenced Markdown/MDX frontmatter - [x] Preserve missing Asset references, emit structured `ASSET_NOT_FOUND` diagnostics, and keep them out of the document graph - [x] Add fail/pass regressions for the real Settings control and root/nested missing Asset-reference cases - [x] Fix exact Content Block selection after the Body node appears in Navigator - [x] Run full affected suites/typechecks, all six MDX Content Block E2E scenarios, deterministic fixture builds, generated checks, lint, formatting, package boundaries, and diff checks ### Before merge - [x] Resolve #6261: Nested Asset references in referenced Markdown frontmatter work consistently in Assets queries, previews, publication, and static export ### 23. Explicit writable expression bindings - [x] Add an explicit `readwrite` mode to expression bindings; existing expressions remain read-only by default - [x] Accept `readwrite` only for direct static member paths and centralize their parsing and validation - [x] Require the expression root to provide a writable data source; initially support the connected Content Block document frontmatter - [x] Update Content Block permissions, canvas text editing, and property controls to require a valid writable binding - [x] Persist direct frontmatter edits through the existing ordered per-Asset session - [x] Create new direct frontmatter bindings with `readwrite` mode and migrate existing compatible bindings - [x] Preserve writable mode through schemas, serialization, loading, copy/paste, transfer, and export - [x] Add fail/pass regressions for valid paths, derived expressions, unsupported sources, permissions, persistence, and compatibility - [x] Review authoritative `docs/` content and update it if the persisted binding contract affects user-facing documentation - [x] Reject unsafe frontmatter paths and reject `readwrite` bindings outside a connected Content Block document - [x] Preserve expression binding mode through the public HTTP client and document the MCP authoring contract - [x] Limit frontmatter value write-back to Content mode so Design mode retains normal binding replacement/reset behavior - [x] Keep bindings inside Templates and across nested Content Block ownership boundaries read-only - [x] Upgrade compatible legacy bindings even when the Content Block is disconnected during migration - [x] Run affected tests, typechecks, formatting, lint, package boundaries, fixture checks, and `git diff --check` Verification: full SDK (567), Project Build (2,277), and Builder (2,695) suites pass, along with affected Expression, Migration, Template, HTTP Client, and MCP suites; typechecks, lint, formatting, package boundaries, and diff checks pass. Generated contracts are refreshed. Fixture synchronization remains blocked before generation because the development API rejects this local CLI version as incompatible. The checked-in bundles pass the current Protocol suite and every fixture build with the current bundle version. |
||
|
|
7e7c14868a |
fix: Preserve read-only guides and publish targets (#6266)
## Summary - Route explicit read-only `meta.guide` requests to focused discovery tools and exclude mutations, side-effecting session tools, broad design context, and visual verification. - Require explicit task scope, specialized workflow, authored-fragment routing, and design-system reuse instead of inferring behavior from brief prose. - Persist the requested staging or production target in new SaaS deployment records. - Return the same target from publish list and job status, with backward-compatible inference for historical records. ## Todo - [x] Reproduce the read-only custom-code audit misrouting from #6262. - [x] Add failing regressions and implement strict read-only routing. - [x] Remove behavior-affecting prose inference from CLI/MCP guide routing. - [x] Reproduce the single-domain production target mismatch from #6263. - [x] Add create-to-list/status regressions and persist the explicit target. - [x] Cover historical deployment records that predate the stored target. - [x] Verify production create → list → get-job through the staging deployment. - [x] Regenerate and verify project fixtures against the changed bundle contract. - [x] Review documentation impact and update the generated MCP manual. - [x] Review the complete diff for correctness, compatibility, duplication, and unnecessary complexity. ## Verification - Real staging publish for #6263 — passed; create, list, and get-job consistently reported `production` for a one-domain publish. The supplied project has no custom domains, so the custom-domain variant was not available. The job remained `pending` during this check. - Real local CLI/MCP verification for #6262 — passed; no mutation or side-effecting tools leaked. - `pnpm --filter @webstudio-is/protocol test -- src/fixtures.test.ts` — 17 passed - `pnpm -r fixtures:build` — passed for all eight fixtures - `pnpm --filter @webstudio-is/project-build test` — 2,134 passed - `pnpm --filter webstudio test` — 1,037 passed; the one payload-size regression was fixed and its targeted test passed - `pnpm --filter @webstudio-is/domain test` — 24 passed - `pnpm --filter @webstudio-is/sdk test` — 519 passed - Builder API router test — 30 passed - Relevant package typechecks — passed - `pnpm lint` - `pnpm check:package-boundaries` - `pnpm check:generated-api` - `pnpm check:generated-docs` - Regression tests were demonstrated failing against the previous behavior and passing with the fixes. - Agent evaluations were not run because they require separate explicit approval. Closes #6262 Closes #6263 |
||
|
|
cbe4950cd0 |
fix: Use available package manager for previews (#6251)
## Summary - Use the npm or pnpm launcher that started Webstudio for preview dependency installation, builds, and server startup. - Use pnpm-compatible isolated-install flags and report the selected package-manager path on failure. - Preserve the existing installed-dependency reuse path before package-manager resolution. ## Technical choices - Read the standard `npm_execpath` metadata already supplied by npm and pnpm; users do not need to configure another environment variable. - Run JavaScript launchers such as `pnpm.cjs` with the selected Node runtime, supporting bundled Node distributions without adjacent npm. - Keep the existing npx-to-npm mapping and fallback behavior unchanged. - Distinguish numeric package-manager exit codes from process-launch errors such as `ENOENT`. ## Todo - [x] Reproduce the bundled Node + pnpm + missing adjacent npm failure. - [x] Add fail-before/pass-after coverage for dependency installation, production build, and preview startup. - [x] Reuse the detected pnpm launcher. - [x] Preserve installed-dependency reuse. - [x] Include the selected launcher path in installation failures. - [x] Report package-manager exits and process-launch errors accurately. - [x] Review documentation impact and update the CLI manual plus generated MCP documentation. - [x] Review fixture impact; no fixture inputs or outputs are affected. ## Verification - Focused install diagnostic regression suite — 28 tests passed. - `pnpm --filter webstudio typecheck` - `pnpm lint` - `pnpm --filter webstudio test` — 1,029 of 1,030 tests passed; an existing process-supervisor cleanup test hit a transient `ENOENT`, then passed 4/4 when rerun in isolation. - Generated documentation checks passed. - Real pnpm JavaScript launcher invocation with isolated preview install flags. - Agent evaluations were not run because they require separate approval. Closes #6250 |
||
|
|
981f45fd0d |
docs: Optimize documentation image sizes (#6253)
## Summary Replace ten oversized PNG screenshots in the product documentation with high-quality WebP assets and update their references. The affected assets shrink from 27,813,051 bytes to 2,822,010 bytes (90% smaller) while retaining their original pixel dimensions. ## Technical choices - Encoded screenshots as WebP at quality 88 with sharp YUV conversion. - Kept original dimensions to preserve UI text legibility and zoom detail. - Left animated GIFs unchanged: GIF-native optimization, palette reduction, and resizing tests increased their file sizes, so changing them would add cost or reduce clarity. - Kept documentation content, navigation, and public page paths unchanged. ## Checklist 1. [x] Audit raster assets in `docs/.gitbook/assets`. 2. [x] Optimize referenced PNG assets above 1 MB where conversion materially reduces size. 3. [x] Update every affected documentation reference. 4. [x] Verify replacement dimensions and image decoding. 5. [x] Verify visual quality (SSIM 0.961–0.997 plus manual spot checks). 6. [x] Verify new references resolve and removed filenames are no longer referenced. 7. [x] Review documentation impact; this PR changes documentation assets and their direct references only. 8. [x] Verify no fixture inputs or generated fixture outputs are affected. ## Verification - `git diff --check` - Reference checks for all ten added and removed filenames - Pixel-dimension comparison for all ten replacements - FFmpeg SSIM comparison for all ten replacements - Manual visual review of representative full-resolution screenshots The repository formatter excludes these documentation files, so it reported no matching targets. Agent evaluations were not run because this is a documentation-asset-only change. Closes #6252 |
||
|
|
471f504087 |
feat: Select unused assets before deleting (#6245)
Closes #6243 ## Summary - Add checked-by-default controls for every asset in the **Delete unused assets** dialog. - Add a footer **Select all** control that reflects the complete selection and toggles all assets. - Delete only selected assets that remain unused and disable deletion when the selection is empty. - Keep the Assets documentation aligned with the selective deletion workflow. ## Implementation The dialog owns a set of selected asset IDs initialized from the unused-assets result. Individual checkboxes update that set, while **Select all** replaces it with either every currently unused ID or an empty set. Asset usage inputs remain subscribed while the dialog is open. The deletion payload is intersected with the current unused-assets list, and this cleanup path does not force deletion. If an asset becomes referenced before the mutation executes, the runtime rejects its deletion instead of removing a now-used asset. ## Todo - [x] Add per-asset selection controls. - [x] Add and position the **Select all** footer control. - [x] Limit deletion to selected asset IDs that remain unused. - [x] Protect against assets becoming referenced while the dialog is open. - [x] Add regression tests for individual selection, select-all behavior, empty-selection protection, selective deletion, and live usage changes. - [x] Review documentation impact and update the Assets guides. - [x] Verify formatting, lint, types, and Asset Manager/assets tests. ## Verification - `pnpm --filter @webstudio-is/builder exec vitest run app/builder/shared/asset-manager app/builder/shared/assets` — 26 files, 221 tests passed. - `pnpm --filter @webstudio-is/builder typecheck` — passed. - `pnpm exec oxlint --deny-warnings apps/builder/app/builder/shared/assets/delete-assets.ts apps/builder/app/builder/shared/asset-manager/delete-unused-assets.tsx apps/builder/app/builder/shared/asset-manager/delete-unused-assets.test.tsx` — passed. - `pnpm exec oxfmt --check apps/builder/app/builder/shared/assets/delete-assets.ts apps/builder/app/builder/shared/asset-manager/delete-unused-assets.tsx apps/builder/app/builder/shared/asset-manager/delete-unused-assets.test.tsx` — passed. - Both regression tests were confirmed failing before their respective implementations and passing afterward. ## Compatibility and follow-ups No data migrations, public API changes, fixture changes, or known follow-ups. |
||
|
|
db2175f333 |
fix: transfer pasted assets across deployments (#6228)
Closes #6227 ## What changed Cross-deployment copy/paste now transfers referenced assets into the destination project before inserting instances, pages, templates, or folders. - Add optional source deployment metadata to the existing v0.1 clipboard formats. - Keep old v0.1 payloads readable and keep new payloads readable by older builders, which ignore the additive field. - Reuse the existing asset upload-by-URL flow for images, fonts, videos, and files. - Preserve source video dimensions through the existing upload route. - Replace source asset IDs and font-family references with destination values before runtime insertion. - Include and remap page social images and marketplace thumbnails. - Reject current clipboard payloads whose page metadata references omitted assets. - Leave the public `pageTransfer.insert` runtime input unchanged. - Abort insertion with a paste error when an asset cannot be imported. No clipboard version increase, custom network fetcher, address blocklist, rollback framework, or global paste wrapper is introduced. If a multi-asset import partially uploads before a later upload fails, the completed uploads may remain unused. ## Checklist - [x] Rebased onto `main` - [x] Preserve the existing v0.1 clipboard format - [x] Transfer and remap instance assets - [x] Transfer and remap page, template, and folder assets - [x] Preserve video metadata - [x] Keep runtime page-transfer API compatible - [x] Add regression coverage - [x] Review documentation impact and update page-copy documentation - [x] Run Builder tests and typecheck - [x] Run project-build tests and typecheck - [x] Run lint, package-boundary, and generated-API checks ## Verification - Builder full suite: 219 files, 2,552 tests passed - Project-build full suite: 78 files, 2,129 tests passed - Final affected suite: 84 tests passed - New regressions were confirmed failing before the fixes and passing afterward - Builder and project-build typechecks passed - `pnpm lint` passed - `pnpm check:package-boundaries` passed - `pnpm check:generated-api` passed - Fixture inputs and generated fixture bundles are unaffected |
||
|
|
9e504037fb |
fix: improve MCP reliability across project workflows (#6222)
## Summary Fixes the reproducible MCP, preview, redirect, audit, mutation, and asset-upload failures from the latest issue batch. Historical and non-reproducible reports were investigated without speculative fixes. Visual verification is now opt-in unless the user explicitly requests it. ## Issue checklist - [x] #6207 — report tested recovery when an explicitly selected browser fails to start. - [x] #6208 — accept generic and registered buttons as valid label targets without requiring a separate form label. - [x] #6209 — reject unknown style coordinates such as `breakpointId` and document the supported `breakpoint` field. - [x] #6210 — traced Node 18 access to CLI 0.293.0 predating the launcher guard; closed as already fixed by #6201. - [x] #6211 — verified the supported launcher blocks the reported Node 18 crypto path; closed as already fixed by #6201. - [x] #6212 — give sequential responsive captures the sum of their per-capture timeout budgets. - [x] #6213 — keep preview install, build, and server subprocesses on the parent CLI Node runtime. - [x] #6214 — add safe confirmation and diagnostics for ambiguous mutation responses; this does not claim to remove upstream latency. - [x] #6215 — confirmed as the same historical Node 18 release path as #6210; closed as already fixed by #6201. - [x] #6216 — verified malformed input returns structured errors on current main; closed as not reproducible and improved future failure diagnostics. - [x] #6217 — add transaction-id confirmation for large fragment mutations after ambiguous 5xx responses; this does not make the operation asynchronous. - [x] #6218 — verified the existing DevTools reconnect fix from #6205; closed as already fixed. - [x] #6219 — preserve the incoming pathname and query when a redirect target supplies only a hash. - [x] #6220 — return ordered `uploaded`, `failed`, and `ambiguous` results so partial asset successes are not lost or retried unsafely. - [x] #6221 — verified parser recovery without a Node crash; closed as not reproducible and improved future JSX failure diagnostics. - [x] #6223 — verified browser-session reuse, reconnect, and cleanup; closed as already fixed by #6205 after the reported CLI version. - [x] #6224 — expose both text-asset sources and encode the exactly-one requirement in the standard MCP schema. - [x] #6225 — could not reproduce the project-specific upstream timeout; closed with safe confirmation coverage and improved structured diagnostics, without claiming a latency fix. - [x] #6226 — could not reproduce the project-specific upstream timeout; closed with safe confirmation coverage for insert-fragment, without adding a speculative fragment-specific fix. - [x] #6229 — reproduced the reported two-process sequence with the current local CLI and a real browser; both captures passed, so the 0.293.0 report was closed without a speculative fix. - [x] Require explicit user consent before preview, screenshots, diffs, OCR, or rendered visual audits unless visual verification was requested. ## Technical notes - Ambiguous mutation responses are confirmed only with the same idempotent transaction id. If confirmation is also ambiguous, the session reports `AMBIGUOUS_COMMIT`, refreshes state, and never replays a fresh mutation. - CLI error mapping retains the original remote error as a non-enumerable cause, so JSON gateway status reaches the ambiguity classifier without exposing raw remote context in serialized diagnostics. - Forced asset uploads are not automatically retried after an unknown/network/5xx outcome. Batch results retain the original input index, including duplicate filenames. - Stable issue codes and constraints are retained for diagnostics. Arbitrary validation paths, messages, argument values, project content, and raw contextual data are excluded. - The MCP handshake remains the source of tool input schemas; goal-specific guides avoid duplicating those contracts and reduce model-context cost. - `update-asset-content` now exposes `path` and `content` with a machine-readable `oneOf` constraint, matching the runtime rule that exactly one source is required. - Redirect targets with their own pathname or query still replace those request components. - Generated runtime contracts, CLI documentation, product documentation, and deployment fixtures were regenerated from their sources. ## Verification - [x] Three independent review/test agents exercised visual consent and preview behavior; mutation, asset, and privacy behavior; and accessibility, styles, and redirects. - [x] `pnpm checks` passed after the final transport follow-up: all workspace tests and typechecks, lint with warnings denied, package boundaries, generated API contracts, generated docs and documentation checks, and the complete fixture link/sync/build pipeline. - [x] Changed-package suites passed, including Project Build (2,125 tests), HTTP client (42 tests), CLI, Protocol, and Builder. - [x] Complete `pnpm evaluations` run on the preceding implementation commit: all five real-world fixtures and every behavioral check passed. Four baseline comparisons passed; one font-assets sample exceeded only its model-output token allowance, and its isolated rerun passed. Evaluations were not rerun after the final transport and schema follow-ups because fresh approval is required. - [x] Design evaluation MCP response bytes improved from the 39.8 KB baseline to 37.6 KB after removing duplicated guide contracts. - [x] Documentation impact reviewed; generated MCP docs and multi-file upload guidance are updated. ## Related issues Closes #6207 Closes #6208 Closes #6209 Ref #6210 Ref #6211 Closes #6212 Closes #6213 Ref #6214 Ref #6215 Ref #6216 Ref #6217 Ref #6218 Closes #6219 Closes #6220 Ref #6221 Ref #6223 Closes #6224 Ref #6225 Ref #6226 Ref #6229 |
||
|
|
626b5e741b |
fix: Reduce discovery for authored fragments (#6203)
Ref #6177 Ref #6154 ## Outcome Bounded authored-fragment requests no longer receive broad design/authentication context bundles, registry discovery, or design-token operations through generic keyword matching. The initial ProjectSession synchronization is unchanged. Focused target reads, missing nested schemas, and expression guidance can still add calls when the requested fragment requires them. ## Root cause `meta.guide` treated the generic word `design` as visual intent and allowed workflow-specific context bundle tools to enter ordinary keyword-ranked recommendations. An authored component insertion could therefore be classified as visual work and receive `inspect-design-context` even without a supplied visual reference or a request to reuse the project design system. ## Implementation - Give specialized goal guides stable IDs and return structured routing metadata with the matched workflow and broad context tools. - Keep `inspect-auth-context` and `inspect-design-context` exclusive to their specialized workflows. - Treat Figma, screenshots, supplied designs, and explicit design-system references as visual intent without treating every use of `design` as visual work. - Suppress component/template registry discovery for explicit `insert-fragment` or authored-fragment requests. - Suppress design-token operations for those requests unless the brief explicitly asks for design-system or token reuse. - Preserve the existing design-input workflow for Figma, screenshots, and supplied designs. ## Todo - [x] Add a regression test for the reported authored timer/component workflow. - [x] Demonstrate that the regression test fails before the routing fix and passes afterward. - [x] Preserve explicit design-input discovery and verification behavior. - [x] Add machine-readable workflow routing metadata. - [x] Review documentation impact and update the authoritative MCP manual plus generated GitBook output. - [x] Review fixture impact; no fixture inputs or generated fixture bundles are affected. - [ ] Run the complete local agent evaluation suite. It was not run because repository policy requires separate explicit approval and approval was not provided. ## Verification - Project-session MCP tests: 117 passed. - Project-build and CLI typechecks passed. - Targeted oxlint passed. - Documentation generator tests and documentation typecheck passed. - MCP documentation and CLI generated docs were regenerated twice with stable hashes. - `git diff --check` passed. ## Tradeoffs and limitations - Brief classification remains deterministic intent matching; clients still decide which recommended tools they actually call. - The change prevents broad context tools from being recommended generically but does not enforce a universal discovery-call limit. - A fragment that genuinely needs existing tokens, unfamiliar expressions, or unknown target structure can still require focused discovery. - No schema migration, project-data migration, or fixture regeneration is required. |
||
|
|
b2d62b2e49 |
fix: Restore scoped descendant selectors (#6195)
## Summary Restore custom state selectors that target descendants of the selected instance, including `:hover .button` and `:hover > .icon`. The CSS engine already generated these selectors correctly. #5886 unintentionally rejected them while hardening MCP style inputs against selectors that can escape instance scope. ## Technical choices - Parse exactly one selector with `css-tree`. - Require the selector to begin with a pseudo-class, pseudo-element, or attribute state anchored to the selected instance. - Allow only descendant and direct-child combinators after that anchor. - Continue rejecting selector lists, unanchored type/class/ID selectors, sibling combinators, unknown pseudo-selectors, and pseudo-elements used as ancestors. - Document CSS variables as the preferred parent-child interaction pattern; use descendant selectors when selector-based targeting is specifically required. ## Todo - [x] Restore scoped descendant and direct-child selectors. - [x] Preserve instance-scope protections. - [x] Cover real authoring inputs and generated CSS. - [x] Demonstrate new tests fail without the restored behavior and scope guards. - [x] Verify the reported workflow through the local CLI/MCP and generated preview. - [x] Review documentation impact and update the authoritative Builder docs. - [x] Verify generated API contracts remain current. ## Verification - `pnpm --filter @webstudio-is/css-data test` — 4,623 passed, 1 skipped - `pnpm --filter @webstudio-is/css-data typecheck` - `pnpm --filter @webstudio-is/project-build exec vitest run src/runtime/styles.test.ts src/runtime/audit.test.ts` — 198 passed - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm lint` - `pnpm check:generated-api` - Documentation targets and anchors verified - Local MCP disposable-fixture workflow: - Discovered `insert-fragment` and `update-styles` through MCP metadata. - Inserted a card with a descendant `<button class="button">`. - Dry-run and committed `state: ":hover .button"`; `get-styles` returned the persisted state. - MCP preview generated `.chjrfuf:hover .button` while the card used the `chjrfuf` instance class, proving the selector remained instance-anchored. - Preview screenshot completed and returned HTTP 200. - Agent evaluations were not run because the suite has no custom-selector coverage ## Known limitation Sibling combinators remain unsupported because they can select elements outside the selected instance. Selector lists remain unsupported because later list entries can escape the generated instance prefix. Closes #6175 |
||
|
|
2df130171f |
feat: Resolve asset references as structured metadata (#6184)
## Summary - add exact `$ref` asset values that resolve to Asset Manager metadata - keep plain local asset paths returning URL strings for backward compatibility - derive reference metadata from the canonical asset object so newly added asset fields flow through automatically - let Assets query output fields select only the metadata returned, including nested arrays - carry the same resolved shape through preview, generated preview, published runtime, and static export - document the syntax and accessible image binding in Content Engine and MCP docs ## Design The source document declares only the relationship: ```yaml featureImage: $ref: ./assets/hero.png ``` The Assets query controls projection with fields such as `properties.featureImage.src` and `properties.featureImage.description`. Selecting `properties.featureImage` returns the canonical Asset Manager asset metadata together with the resolved `src`. The Content Engine runtime contract accepts the canonical asset object instead of maintaining a second metadata field list; `url` becomes `src`, and internal `contentRef` is not exposed. Plain strings retain their existing URL-string result. Existing document `$ref` behavior is preserved by resolving structured asset metadata only when the target is a known non-document asset. ## Verification - [x] Content Engine full test suite: 298 tests - [x] SDK full test suite: 517 tests - [x] Asset repository tests: 39 tests - [x] CLI prebuild tests: 58 tests - [x] Content Engine, SDK, Asset Uploader, CLI, and Project Build typechecks - [x] Repository lint - [x] Content Engine and MCP documentation generation and tests - [x] Generated API check - [x] Local fixture build and generated fixture update - [x] New behavior tests demonstrated fail before/pass after the implementation - [ ] Complete fixture sync (development API currently rejects this branch's newer CLI protocol; local fixture build passes) - [ ] Agent evaluations (not run; require explicit approval) ## Checklist - [x] Local structured references return field-selected metadata - [x] Newly added canonical asset fields flow through without a Content Engine whitelist change - [x] Plain-path queries remain backward compatible - [x] Nested object and array projection - [x] External URL strings remain usable - [x] Missing or null descriptions allow `??` fallback to the title - [x] Expanded metadata counts toward query result-size limits - [x] Documentation impact reviewed and Content Engine and MCP docs updated - [ ] Missing asset targets return a non-failing unresolved value and dedicated diagnostic - [ ] Apply the resource and Image binding changes to the separate Webstudio blog project ## Known limitation A `$ref` whose asset target no longer exists is not yet converted into an unresolved asset value with a dedicated diagnostic. This PR intentionally does not claim that acceptance criterion yet. Ref #6179 |
||
|
|
5a57234c75 |
revert: Store Content Block content in MDX assets
Revert the accidental merge of #6125 so the implementation can continue in draft PR #6181. |
||
|
|
5ec3547d36 |
fix: Support JSON content files in Builder (#6168)
## Summary - make the complete asset filename editable in Asset settings - convert existing editable text assets when their extension changes while preserving the asset ID - accept every JSON root type and normalize JSON-compatible syntax into formatted strict JSON - expose the same optional extension change through MCP/API `update-asset-content` - initialize new JSON files and empty text-to-JSON conversions with a valid empty object - distinguish browser URL imports from JSON file uploads so JSON objects with a root `url` field remain file content - update the Assets and Content Engine documentation ## Root cause Asset settings rendered the extension as a fixed suffix outside the name input. The metadata rename mutation could only change the display basename, while content revisions always inherited the current storage extension. As a result, changing `.md` to `.json` was impossible in the UI and unavailable through the shared MCP/API revision command. Asset settings now edits the complete filename. Ordinary renames keep using the metadata mutation. A text-extension change loads the current content, validates it for the target format, and writes a new immutable revision through the existing conflict-safe content endpoint. The existing Acorn-backed `parseJsonExpression` utility accepts JSON-compatible syntax without evaluating code and serializes it as strict JSON. Objects, arrays, strings, numbers, booleans, and `null` are all accepted. ## Checklist - [x] Create JSON files by entering a `.json` filename - [x] Edit the complete filename in Asset settings - [x] Convert editable text-file extensions while preserving the asset ID - [x] Expose extension conversion through `update-asset-content` - [x] Create JSON files and convert empty text files with a valid empty object - [x] Normalize safe JSON-compatible syntax to strict JSON - [x] Accept objects, arrays, and scalar JSON roots - [x] Reject executable or incomplete content - [x] Preserve browser-uploaded JSON object shapes - [x] Review and update authoritative Builder documentation - [x] Add focused UI, revision, HTTP-client, CLI/MCP, protocol, and upload regression tests - [x] Run affected typechecks, lint, documentation checks, and the Builder production build - [ ] Manually verify create, edit, rename `.md` to `.json`, reload persistence, and Content Engine query in a browser - [ ] Run the complete local agent evaluation suite if approved ## Verification - 217 focused tests passed across Builder, asset revisions, HTTP client, CLI/MCP, and protocol - Builder, asset-uploader, HTTP-client, protocol, CLI, and project-build typechecks passed - Builder production build passed - MCP and Content Engine documentation checks passed - `oxlint` on changed TypeScript files passed - `git diff --check` passed - Regression tests were demonstrated failing before the implementation and passing afterward A disposable E2E database and PostgREST stack bootstrapped successfully in the earlier real-path test, but UI automation remained blocked because no controllable browser was available. Fixture inputs and generated fixture outputs are not affected. Agent evaluations were not run because approval is required and was not requested. Closes #6167 |
||
|
|
81d5148046 |
fix: canonicalize trailing-slash page URLs (#6173)
## Outcome Canonical page URLs now omit a trailing slash in Webstudio Cloud sites and exported JavaScript applications. A request such as `/about/?campaign=launch` receives a permanent `301` redirect to `/about?campaign=launch`, preventing both URL variants from serving identical page content. The behavior is implemented once in the generated root redirect handler, so it covers fixed and dynamic application routes without generating an extra route per page. Exact project redirects remain authoritative. Protocol-relative-looking paths such as `//example.com/` are left untouched so canonicalization cannot become an external redirect. Static exports cannot redirect requests themselves. Their URL behavior remains host-specific and is documented for Cloudflare Pages, Netlify, Vercel, and other static hosts. ## Implementation - Add one shared pathname normalizer in the SDK. - Apply canonicalization after exact authored redirect matching in both generated application runtimes. - Ignore repeated leading slashes before constructing a redirect location. - Extend redirect-loop detection to model the implicit canonical redirect. - Regenerate the affected fixture applications from their templates. - Document application canonicalization and host-specific static export behavior. ## Todo 1. [x] Add central trailing-slash canonicalization. 2. [x] Preserve query strings, encoded path segments, and the root path. 3. [x] Cover concrete dynamic URLs without per-route generation. 4. [x] Preserve explicit project redirect precedence. 5. [x] Detect redirect loops that pass through canonicalization. 6. [x] Prevent protocol-relative external redirects. 7. [x] Regenerate and review fixture output. 8. [x] Review documentation impact; document application and SSG behavior. 9. [x] Run targeted and repository-level verification. ## Verification - SDK tests: 548 passed - SDK typecheck: passed - Project Build tests: 2,379 passed - Project Build typecheck: passed - CLI tests: 997 passed; two tests timed out only while three package suites ran concurrently, then both affected files passed in isolation (6/6) - Redirect regression suite after security follow-up: 302 passed - CLI typecheck: passed - `pnpm lint`: passed - `pnpm check:package-boundaries`: passed - `pnpm fixtures`: passed - Documentation internal anchors and Markdown whitespace: checked - New regression tests were confirmed failing before their implementations and passing afterward - Agent evaluations were not run because they require separate explicit approval Closes #6172 Closes https://github.com/webstudio-is/webstudio/issues/4327 |
||
|
|
86b6310fff | feat: Store Content Block content in MDX assets |