feat(*): stop copying files to the angular tree during the xplat->angular build - #547
feat(*): stop copying files to the angular tree during the xplat->angular build#547ChronosSF wants to merge 7 commits into
Conversation
There was a problem hiding this comment.
🔵 Needs a closer look
Critical cleanup-safety and generated-content validation issues remain unresolved.
Pull request overview
Replaces copied xplat Angular content with precedence-aware content-root overlays.
Changes:
- Adds multi-root content loading and resolution.
- Updates Angular generation, validation, and cleanup workflows.
- Removes obsolete synchronized content infrastructure.
File summaries
| File | Description |
|---|---|
src/sidebar.ts |
Resolves TOC entries across roots. |
src/plugins/remark-md-links.ts |
Computes links relative to each file’s root. |
src/llms.ts |
Resolves metadata using root precedence. |
src/lib/doc-roots.ts |
Adds shared root-resolution utilities. |
src/integration.ts |
Configures overlays and multi-root processing. |
src/content-helper.ts |
Implements the Astro overlay loader. |
scripts/check-relative-links.mjs |
Checks links across overlaid roots. |
scripts/check-mdx-links.mjs |
Scans generated Angular API links. |
README.md |
Documents the overlay workflow. |
package.json |
Updates link-check generation commands. |
docs/angular/src/content/jp/.gitignore |
Removes obsolete generated-file ignores. |
docs/angular/src/content/en/components/geo-map-binding-data-overview.mdx |
Removes a shadowed Angular topic. |
docs/angular/src/content/en/.gitignore |
Removes obsolete generated-file ignores. |
docs/angular/src/content.config.ts |
Loads generated xplat content as an overlay. |
docs/angular/scripts/sync-generated.mjs |
Removes the former copy script. |
docs/angular/scripts/clean-synced.mjs |
Adds cleanup for legacy copied files. |
docs/angular/package.json |
Replaces synchronization with generation commands. |
docs/angular/astro.config.ts |
Registers the xplat overlay root. |
API-LINK-WORKFLOW.md |
Updates API-link workflow instructions. |
.github/workflows/check-relative-links.yml |
Generates xplat output before CI checks. |
.github/CONTRIBUTING.md |
Documents overlay precedence and ownership. |
Review details
Suppressed comments (2)
src/content-helper.ts:159
- Deleting a winning overlay entry removes the only stored value for this id, but the lower-precedence copy was previously discarded by
set. Astro's glob loader handlesunlinkonly in the watcher registered for that root, so the unchanged lower file is not reloaded and the fallback page disappears until restart. Preserve shadowed entries or explicitly reconcile lower roots when the winner is deleted.
delete: (id: string) => {
if (takenByOther(id)) return;
claimed.delete(id);
return store.delete(id);
src/content-helper.ts:152
- Blocking
setis too late to make a shadowed page “ignored.” Aftergetreturnsundefined, Astro's glob loader still reads, parses, validates, and renders the lower-precedence file before callingset; invalid frontmatter or MDX in a stale Angular copy can therefore fail the build even though that page will never be stored. Filter shadowed paths before invoking the lower loader, or use a loader that can skip them before parsing.
get: (id: string) => (takenByOther(id) ? undefined : store.get(id)),
set: (entry: { id: string }) => {
if (takenByHigher(entry.id)) return false;
- Files reviewed: 21/21 changed files
- Comments generated: 11
- Review effort level: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🟡 Changes recommended
The critical overlay watcher issue can remove routes until a full reload or restart.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (1)
src/lib/doc-roots.ts:22
- This ordering note contradicts the implementation below:
overlayLoaderiterates roots in the supplied order and blocks writes from lower-precedence roots; it never reverses the list. Keeping the comment as written makes future callers likely to reverse roots incorrectly.
* The one place that reverses the list is the content loader, where the *last*
* loader to write a given id is the one that wins.
- Files reviewed: 22/22 changed files
- Comments generated: 1
- Review effort level: Balanced
There was a problem hiding this comment.
🔵 Needs a closer look
Unresolved CI coverage and documentation issues remain in this cross-cutting multi-root change.
Review details
Suppressed comments (1)
API-LINK-WORKFLOW.md:150
- The command table above still says the Angular checker runs “after xplat Angular sync,” even though this section now documents generation plus an in-place overlay and the sync scripts are removed. Update that table entry to describe scanning the authored and generated roots so this workflow does not give conflicting guidance.
npm run xplat:generate --prefix docs/angular
npm run xplat:generate:jp --prefix docs/angular
scan docs/angular/src/content and docs/xplat/generated/Angular
- Files reviewed: 22/22 changed files
- Comments generated: 1
- Review effort level: Balanced
Adds vitest (root devDependency) plus 361 unit tests covering the multi-root overlay code (doc-roots, the content-helper glob/overlay loader driven through a fake Astro loader context, and the Angular content-root helpers), the sidebar and llms.txt builders, the HTML-to-Markdown converter, the five remark/rehype plugins, and the platform registries. Astro-dependent entry points (integration.ts, content.config.ts, routes, middleware) and the CLI scripts are deliberately left for later, as are .astro components and any e2e site build. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds vitest (root devDependency) plus 361 unit tests covering the multi-root overlay code (doc-roots, the content-helper glob/overlay loader driven through a fake Astro loader context, and the Angular content-root helpers), the sidebar and llms.txt builders, the HTML-to-Markdown converter, the five remark/rehype plugins, and the platform registries. Astro-dependent entry points (integration.ts, content.config.ts, routes, middleware) and the CLI scripts are deliberately left for later, as are .astro components and any e2e site build. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
|
@viktorkombov , thanks for checking the PR. I think both issues can be logged separately. Please, do that and we can merge this. |
Done. I have logged a separate issue - #553. |

The Angular site no longer copies anything.
xplat:generatewritesdocs/xplat/generated/Angular/{lang}/components/, and the site reads it in place as a second content root overlaid on its own — xplat winning every slug collision, as you specified.Core mechanism — doc-roots.ts (new) establishes one convention: roots are ordered highest-precedence-first everywhere. content-helper.ts runs one glob loader per root behind a per-root store facade — necessary because Astro's glob loader snapshots store.keys() and deletes everything it didn't touch, so two naive loaders would wipe each other. The facade also hides shadowed entries so Astro's duplicate-slug warning never fires on a deliberate override.
remark-md-links.ts now computes each page's slug against its own root rather than a single DOCS_SOURCE_PATH. That's what keeps the 45 cross-tree links working: both roots share a slug namespace, so ../grid/grid.mdx from a generated topic still yields /grid/grid even though that file doesn't exist in the generated tree.
DOCS_SOURCE_PATH keeps its old meaning (the site's own root) so environment.json lookups and the dev proxy are untouched; the new DOCS_SOURCE_PATHS carries the ordered list.