Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 28 additions & 0 deletions .github/skills/xplat-docs-api-links/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,13 @@ Each JSON file is a TypeDoc reflection tree. Top-level `children` contains all e
| `member` | no | Property or method name for the anchor. |
| `prefixed` | no | Default `true` — adds `Igr`/`Igx`/`Igc`/`Igb` automatically. Set `false` when `type` contains `{ComponentName}` or the name is already fully-qualified. **Always `false` for excel types.** |
| `suffix` | no | Default `true` — appends `Component` suffix for Angular DV packages. Set `false` for utility classes (FilteringOperand, SortingStrategy, SummaryOperand, all excel types). |
| `exclude` | no | Comma-separated platform list (`"Angular"`, `"Blazor"`, etc.). On listed platforms the symbol renders as inline code (backticks) instead of a link. Use when the type/member genuinely **does not exist** on those platforms. **Preferred over wrapping a single `<ApiLink/>` in a `<PlatformBlock for="...">`** for the sole purpose of platform-omission. |
| `excludeSuffixFor` | no | Comma-separated platform list. On listed platforms the package `classSuffix` (e.g. `Component`) is **not** appended, overriding the per-package default. Use when the same type is a plain class on some platforms (e.g. `IgxChartSelection`) but a `Component`-suffixed class on others. **Generates a real link — combine with `exclude` if the type is also absent on other platforms.** |
| `excludePrefixFor` | no | Comma-separated platform list. On listed platforms the platform prefix (`Igr`/`Igx`/`Igc`/`Igb`) is **not** prepended. Use when a type has no prefix on certain platforms. **Generates a real link — combine with `exclude` if needed.** |
| `label` | no | Override display text. |

> **Critical rule:** NEVER replace an existing `<ApiLink/>` with backtick text. If a URL is broken on certain platforms, add `exclude="Platform"` to the tag. Only backtick text is acceptable when the type has no TypeDoc page on *any* platform AND has never been an ApiLink in the content history. When in doubt, keep the ApiLink — the broken link will be caught by `check-api-links.mjs` and fixed via `apply-excludes.mjs`.

### Platform prefix mapping

| Platform | Prefix | Example (type="Column") |
Expand Down Expand Up @@ -253,6 +258,29 @@ Angular's `grids` package appends `Component` to all **UI component** class name
<ApiLink pkg="grids" type="StringFilteringOperand" suffix={false} />
```

### Use `excludeSuffixFor=` when only some platforms use the suffix

When the suffix causes a 404 on **specific platforms only** (not globally), use `excludeSuffixFor` to remove it just for those platforms while keeping the link alive:

```mdx
<!-- ChartSelection has no "Component" suffix on Angular DV packages -->
<ApiLink pkg="charts-core" type="ChartSelection" excludeSuffixFor="Angular" />
```

The `check-mdx-links.mjs` script automatically suggests this fix when it detects a broken link that resolves correctly after stripping the suffix — look for `→ FIX: excludeSuffixFor="..."` in the output.

Similarly, `excludePrefixFor` removes the platform prefix (`Igr`/`Igx`/`Igc`/`Igb`) for the listed platforms only:

```mdx
<ApiLink pkg="core" type="SomeType" excludePrefixFor="Blazor" />
```

> **Decision guide**:
> - Symbol **doesn't exist** on a platform → `exclude="Platform"`
> - Symbol exists but URL has wrong suffix on those platforms → `excludeSuffixFor="Platform"`
> - Symbol exists but URL has wrong prefix on those platforms → `excludePrefixFor="Platform"`
> - `suffix={false}` / `prefixed={false}` → removes suffix/prefix globally (all platforms)

### Classes that NEED `suffix={false}`

- All `*FilteringOperand` classes: `BooleanFilteringOperand`, `NumberFilteringOperand`, `StringFilteringOperand`, `DateFilteringOperand`, `DateTimeFilteringOperand`, `TimeFilteringOperand`
Expand Down
223 changes: 223 additions & 0 deletions .github/skills/xplat-docs-api-map-sync/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
---
name: xplat-docs-api-map-sync
description: "Reference guide for synchronizing the xplat docs ApiLink references with the upstream igniteui-xplat-docs apiMap data. Covers running scripts/resolve-api-links.mjs to inject ApiLink tags from `IgxFoo.bar`-style backtick references in MDX, syncing docConfig.json with the sibling igniteui-xplat-docs repo, generating per-platform broken-link reports via scripts/check-api-links.mjs, and applying exclude= props to broken ApiLink tags via scripts/apply-excludes.mjs. Use when bumping API package versions, after merging vNext content, or when ApiLink coverage drifts from upstream."
user-invocable: true
---

# AI Agent Guide — Syncing xplat-docs ApiLink Coverage

## Context

This Astro xplat docs project mirrors the legacy gulp-based `igniteui-xplat-docs` pipeline. The legacy pipeline used **apiMap JSON** files (one per platform) and **docConfig.json** to:

1. Convert backtick-prefixed type/member references (`` `IgxGrid.sort` ``) into resolved API URLs.
2. Resolve the right per-platform package version, prefix, suffix, and base URL.

Here those responsibilities are split across:

| Responsibility | Implementation |
|---|---|
| `apiMap` lookup of valid types / members | Per-platform JSON files in sibling `igniteui-xplat-docs/apiMap/{Angular,React,Blazor,WebComponents}/*.apiMap.json` |
| `docConfig` (package versions, prefixes, base URLs) | `docs/xplat/docConfig.json` |
| Backtick → `<ApiLink/>` conversion | `docs/xplat/scripts/resolve-api-links.mjs` (or workspace-level equivalent) |
| Verifying generated URLs against staging | `scripts/check-api-links.mjs` |
| Auto-applying `exclude=` for broken URLs | `scripts/apply-excludes.mjs` |
| Migrating `<PlatformBlock for="..."><ApiLink/></PlatformBlock>` to `exclude=` | `scripts/migrate-platformblock-to-exclude.mjs` |

---

## Sibling Repository Layout

The `igniteui-xplat-docs` repo is at <https://github.com/IgniteUI/igniteui-xplat-docs>.

```
igniteui-xplat-docs/
apiMap/
Angular/*.apiMap.json
React/*.apiMap.json
Blazor/*.apiMap.json
WebComponents/*.apiMap.json
docConfig.json
gulpfile.js ← legacy reference; do not run
```

The `astro-components` repo is also a sibling (checked out next to `docs-template`) and is symlinked into `node_modules/igniteui-astro-components` via the workspace config in `docs-template/package.json`. The `<ApiLink/>` Astro component lives there at `src/components/mdx/ApiLink/ApiLink.astro`.

---

## Workflow 0 — Applying Fixes from an Existing mdx-link-report

When `mdx-link-report-{angular,react,wc,blazor}.md` files already exist at the repo root (generated by a previous `check-mdx-links` run), apply all suggested fixes in one step:

```bash
# Preview what will change (no writes)
node scripts/apply-mdx-report-fixes.mjs --dry-run

# Apply all fixes across all four platform reports
node scripts/apply-mdx-report-fixes.mjs
```

The script reads every `mdx-link-report-*.md` it finds, parses each broken-URL entry's **FIX** line, and merges the appropriate prop (`excludeSuffixFor`, `excludePrefixFor`, or `exclude`) onto the matching `<ApiLink>` tag in the xplat source file. Angular report paths are automatically remapped to their canonical `docs/xplat/src/content/` source (except `grids/` and `changelog/` which Angular owns directly).

After applying, re-run the check to confirm the broken count drops to 0:

```bash
npm run check-mdx-links:report:angular
npm run check-mdx-links:report:react
npm run check-mdx-links:report:wc
npm run check-mdx-links:report:blazor
```

---

## Workflow 1 — After Bumping a Platform Version

When a platform's API package version changes (e.g. Angular 21.1 → 21.2) some symbols may be renamed, removed, or relocated. Walk through:

```bash
# 1. Sync docConfig.json with upstream (manual diff)
# Compare docs/xplat/docConfig.json with sibling igniteui-xplat-docs/docConfig.json.
# Apply any version, base-URL, or package-key changes; preserve local-only fields
# (e.g. codeSandboxButtonInject).

# 2. Generate per-platform broken-link reports against staging
node scripts/check-api-links.mjs --platform=angular
node scripts/check-api-links.mjs --platform=react
node scripts/check-api-links.mjs --platform=wc
node scripts/check-api-links.mjs --platform=blazor
# → produces api-link-report-{angular,react,wc,blazor}.md at repo root.

# 3. Auto-apply exclude= to ApiLink tags whose URLs are broken
node scripts/apply-excludes.mjs --dry-run # preview
node scripts/apply-excludes.mjs # apply

# 4. Re-run reports — broken count should now be near 0
node scripts/check-api-links.mjs --platform=angular
# (and the other three)
```

## Workflow 2 — After Importing New Content from vNext

**Critical rule: never demote an existing `<ApiLink/>` to backtick text.** If a URL is broken on some platforms, add `exclude="Platform"` — never remove the link. Backtick text is only acceptable when the type has no TypeDoc page on *any* platform and was never an ApiLink in the upstream content.

**Correct pipeline order** — must run in this sequence:

```bash
# 1. Strip Igr/Igx/Igc/Igb prefixes from backtick-wrapped prose refs.
# (Xplat content is platform-agnostic. `IgrToolbar` → `Toolbar`)
# Script skips code fences, JSX tags, and PlatformBlock-wrapped content
# (e.g. <PlatformBlock for="React">`IgrFoo`</PlatformBlock> is intentional).
node scripts/fix-igr-backtick-prefix.mjs

# 2. Convert bare backtick refs (`Toolbar`, `DataChart`, etc.) into <ApiLink/>
# using the sibling igniteui-xplat-docs/apiMap JSON files.
# Reads mentionedTypes: frontmatter to scope the lookup per file.
cd docs/xplat && node scripts/resolve-api-links.mjs

# 3. Fix <ApiLink> attributes: strip CLR arity suffixes, add prefixed={false}
# for enums, reclassify class → interface for known mis-classified types.
# Does NOT demote ApiLinks to backtick text.
node scripts/fix-api-link-attrs.mjs

# 4. Migrate any <PlatformBlock for="..."><ApiLink/></PlatformBlock> wrappers
# that exist purely for platform-omission into exclude= props.
cd /c/Repos/docs/docs-template && node scripts/migrate-platformblock-to-exclude.mjs

# 5. Run Workflow 1 (steps 2-4) to verify and auto-fix broken URLs.
```

**Angular content syncs automatically** — after fixing xplat, run:
```bash
cd docs/xplat && node scripts/generate.mjs --platform=Angular --lang=en
cd /c/Repos/docs/docs-template && node docs/angular/scripts/sync-generated.mjs --lang=en
# repeat for --lang=jp, --lang=kr if needed
```

---

## Script Reference

### `scripts/check-api-links.mjs`

Walks `docs/xplat/src/content/**/*.mdx`, extracts every `<ApiLink/>` tag, computes the staging URL per platform, and HEAD-checks each URL.

- Honors enclosing `<PlatformBlock for="...">` (stack-based intersection) so a tag wrapped for one platform is checked only on that platform.
- Honors `exclude="..."` on the tag itself — listed platforms are dropped from the check set.
- Output:
- Console summary (OK / Not found / HTTP / Total broken).
- `api-link-report-<platform>.md` with details on every broken URL and the MDX files it appears in.

CLI:
```
node scripts/check-api-links.mjs --platform=angular|react|wc|blazor
```

### `scripts/apply-excludes.mjs`

Reads all four `api-link-report-*.md` files, builds a per-file map of broken URLs → platforms, then walks each file's `<ApiLink/>` tags and merges `exclude="..."` for any matching tag. Idempotent.

Matching algorithm:
- Strip platform prefix (`Igr/Igx/Igc/Igb`) from URL type names.
- Generate two key variants per URL — with and without `Component/Module/Directive/Element` suffix — to match Angular tags written either with or without the suffix.
- Lowercase member fragments so Blazor's PascalCased `#Condition` matches a tag's `member="condition"`.
- On tag side, key is `(stripPrefix(type) | lowercased member | kind || 'class')`.

CLI:
```
node scripts/apply-excludes.mjs --dry-run
node scripts/apply-excludes.mjs
```

### `scripts/migrate-platformblock-to-exclude.mjs`

Finds the anti-pattern:

```mdx
<PlatformBlock for="A,B,C">
<ApiLink ... />
</PlatformBlock>
```

When `for=` lists exactly N-1 of the 4 platforms, rewrites to:

```mdx
<ApiLink ... exclude="MissingPlatform" />
```

Skips tags that already have an `exclude=` attribute.

### `scripts/resolve-api-links.mjs` (or workspace equivalent)

Walks MDX content and converts backtick-only API references like `` `IgxGrid.sort` `` into `<ApiLink/>` tags by looking up the type and member in the sibling `igniteui-xplat-docs/apiMap/*.json` files.

---

## docConfig.json Sync Checklist

When syncing `docs/xplat/docConfig.json` with the upstream `igniteui-xplat-docs/docConfig.json`:

- Pull in any new platform version numbers (`apiPackages[platform][packageId].version`).
- Pull in any new packageId entries (e.g. new component packages added upstream).
- Preserve **local-only** fields the Astro project uses but the legacy pipeline does not — e.g. `codeSandboxButtonInject`.
- Leave `prefix`, `classSuffix`, and `apiUrl` alone unless explicitly changed upstream — only Angular has a non-empty `classSuffix` ("Component") for chart/gauge/map/excel/spreadsheet packages.

---

## Common Pitfalls

| Pitfall | Symptom | Fix |
|---|---|---|
| Forgot to re-run `check-api-links` after `apply-excludes` | Same broken count reported | Re-run check after apply; report is regenerated. |
| Member casing mismatch (Blazor PascalCase vs MDX lowercase) | Blazor 0 tags updated even though report shows breaks | `apply-excludes.mjs` already handles this via lowercase key. If you customize, preserve the lowercase logic. |
| Angular `Component` suffix only on certain packages | Some Angular URLs still broken after apply | Verify `apply-excludes.mjs` `baseVariants()` adds both with-suffix and without-suffix variants. |
| `replace_string_in_file` silently failing on `apply-excludes.mjs` | Edits report success but file unchanged | Use a Node-based file patcher: `readFileSync` + `.replace()` + `writeFileSync`. Always grep to verify. |
| Running resolve-api-links BEFORE fix-igr-backtick-prefix | Backtick refs with `Igr` prefix can't be resolved; new backtick `Toolbar` refs created after fix-igr go unconverted | Always run fix-igr **first**, then resolve-api-links, then fix-api-link-attrs. |
| Adding types to a NONEXISTENT_TYPES demotion list in fix-api-link-attrs | ApiLinks removed from content; replaced with `IgrFoo` backtick text | **Never demote ApiLinks.** `fix-api-link-attrs.mjs` has NO demotion logic. Handle broken URLs with `exclude=` via `apply-excludes.mjs`. |
| fix-igr-backtick-prefix stripping Igr prefix inside PlatformBlock | `<PlatformBlock for="React">`IgrFoo`</PlatformBlock>` → `Foo` (wrong) | The script already skips lines containing `<PlatformBlock`. Do not remove that guard. |

---

## Related Skills

- [`xplat-docs-api-links`](../xplat-docs-api-links/SKILL.md) — ApiLink prop reference
- [`xplat-docs-platform-block`](../xplat-docs-platform-block/SKILL.md) — PlatformBlock and ApiLink `exclude=` semantics
61 changes: 61 additions & 0 deletions .github/skills/xplat-docs-platform-block/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,67 @@ Typical full-coverage pattern:
| `src/components/mdx/PlatformBlock.astro` | PlatformBlock component — renders content conditionally per platform |
| `src/lib/platform-context.ts` | Platform detection and config (used by ApiLink; same platforms) |

## ApiLink `exclude` prop — preferred for pure exclusion

**Do NOT** use a `<PlatformBlock for="...">` whose only purpose is to **omit** an `<ApiLink/>` for a subset of platforms. Use the `exclude="..."` prop on `<ApiLink/>` instead.

The `exclude` prop accepts a comma-separated list of platform names (same casing as `for`). On the listed platforms, the link renders as **inline code (backticks)** instead of a hyperlink — preserving the symbol name in prose without producing a broken URL.

### Anti-pattern (DO NOT DO THIS)

```mdx
<!-- Wrong: PlatformBlock used purely to hide ApiLink from one platform -->
<PlatformBlock for="Angular, React, WebComponents">
<ApiLink pkg="grids" type="MyType" member="someMember" />
</PlatformBlock>
```

### Correct pattern

```mdx
<ApiLink pkg="grids" type="MyType" member="someMember" exclude="Blazor" />
```

This renders a normal link on Angular/React/WebComponents and renders `MyType.someMember` in backticks on Blazor. No PlatformBlock needed.

### When to use which

| Situation | Use |
|---|---|
| The same `<ApiLink/>` references something missing on N platforms (broken URL) | `exclude="P1,P2"` on the ApiLink |
| Different platforms need genuinely **different** ApiLinks (different `type`, `kind`, `member`, etc.) | One `<PlatformBlock>` per variant (each containing its own `<ApiLink/>`) |
| Surrounding **prose or code** also differs per platform | `<PlatformBlock>` (regular usage) |

### Migration script

`scripts/migrate-platformblock-to-exclude.mjs` automatically rewrites the anti-pattern (a `<PlatformBlock for="...">` containing only a single `<ApiLink/>` whose `for=` covers exactly N-1 of the 4 platforms) into `<ApiLink ... exclude="MissingPlatform" />`.

### Report-driven exclusion

`scripts/apply-excludes.mjs` reads `api-link-report-{angular,react,wc,blazor}.md` (produced by `scripts/check-api-links.mjs`) and adds `exclude="..."` to every ApiLink whose generated URL is broken on a given platform. Run after every API package version bump:

```bash
# 1. Generate per-platform reports
node scripts/check-api-links.mjs --platform=angular
node scripts/check-api-links.mjs --platform=react
node scripts/check-api-links.mjs --platform=wc
node scripts/check-api-links.mjs --platform=blazor

# 2. Auto-apply exclude= to broken-link tags (idempotent)
node scripts/apply-excludes.mjs --dry-run # preview
node scripts/apply-excludes.mjs # apply

# 3. Re-run reports to verify near-zero broken count
```

The script:
- Strips `Igx/Igr/Igc/Igb` prefix from URL type names.
- Strips `Component/Module/Directive/Element` suffix (Angular adds these to certain class names).
- Lowercases member fragments (Blazor PascalCases members in URLs).
- Merges with any existing `exclude=` attribute (preserves manually-added platforms).

---

## Related Skills

- [`xplat-docs-api-links`](../xplat-docs-api-links/SKILL.md) — ApiLink usage guide
4 changes: 2 additions & 2 deletions api-link-report-angular.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# API Link Check Report

_Generated: 2026-05-19 18:51:16 UTC_
_Generated: 2026-05-22 09:54:39 UTC_

## Summary

| | |
|---|---|
| ✅ OK | 1483 |
| ✅ OK | 2084 |
| ❌ Not found (type/member missing) | 0 |
| ❌ HTTP error | 0 |
| ❌ **Total broken** | **0** |
4 changes: 2 additions & 2 deletions api-link-report-blazor.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# API Link Check Report

_Generated: 2026-05-19 17:55:20 UTC_
_Generated: 2026-05-22 09:58:46 UTC_

## Summary

| | |
|---|---|
| ✅ OK | 1054 |
| ✅ OK | 1785 |
| ❌ Not found (type/member missing) | 0 |
| ❌ HTTP error | 0 |
| ❌ **Total broken** | **0** |
4 changes: 2 additions & 2 deletions api-link-report-react.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# API Link Check Report

_Generated: 2026-05-19 17:53:29 UTC_
_Generated: 2026-05-22 09:55:43 UTC_

## Summary

| | |
|---|---|
| ✅ OK | 1106 |
| ✅ OK | 1812 |
| ❌ Not found (type/member missing) | 0 |
| ❌ HTTP error | 0 |
| ❌ **Total broken** | **0** |
4 changes: 2 additions & 2 deletions api-link-report-wc.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# API Link Check Report

_Generated: 2026-05-19 17:54:07 UTC_
_Generated: 2026-05-22 09:56:43 UTC_

## Summary

| | |
|---|---|
| ✅ OK | 1128 |
| ✅ OK | 1752 |
| ❌ Not found (type/member missing) | 0 |
| ❌ HTTP error | 0 |
| ❌ **Total broken** | **0** |
Loading
Loading