Skip to content

Preserve Markdown route fidelity - #4119

Open
thodges-gh wants to merge 5 commits into
mainfrom
docs/markdown-fidelity
Open

Preserve Markdown route fidelity#4119
thodges-gh wants to merge 5 commits into
mainfrom
docs/markdown-fidelity

Conversation

@thodges-gh

Copy link
Copy Markdown
Contributor

Description

Some public documentation pages are also served as Markdown (.md) for tools and agents. The conversion could silently remove text, links, code, or other useful content when the source MDX used a component that the converter did not handle.

This PR fixes known content losses in the production converter. It adds Markdown output for PageTabs, Tabs, TabsContent, PackageManagerTabs, Fragment, Accordion, Address, Callout, reusable callout selectors, SchemaFieldsTable, and static language branches. For example, the CRE CLI installation pages now keep the operating-system heading and ordered macOS / Linux and Windows links. The Data Feeds contract registry now keeps each contract address as a normal Markdown link.

This PR does not fix every existing Markdown loss. The full documentation set still has known missing, unsupported, unverifiable, and degraded findings.

npm run check:markdown-fidelity is both a regression check and an inventory of the remaining work. It compares source MDX with output from the same MarkdownArtifact builder used by the public .md route. The normal site build can succeed even when Markdown content disappears, so this separate check is needed. Focused --path runs fail on non-exempt losses. The full run compares its findings with a checked-in baseline, which allows existing problems to be fixed one at a time but fails when a new finding is added. The command makes no model or network calls, needs no credentials, and adds no dependency.

Verification

Some problematic example pages before/after.

Before:

# Installing the CRE CLI
Source: https://docs.chain.link/cre/getting-started/cli-installation
Last Updated: 2025-11-04

> For the complete documentation index, see [llms.txt](/llms.txt).

These guides explain how to install the Chainlink Developer Platform CLI (also referred to as the CRE CLI).%

After:

# Installing the CRE CLI
Source: https://docs.chain.link/cre/getting-started/cli-installation
Last Updated: 2025-11-04

> For the complete documentation index, see [llms.txt](/llms.txt).

These guides explain how to install the Chainlink Developer Platform CLI (also referred to as the CRE CLI).

## Select your operating system

- [macOS / Linux](/cre/getting-started/cli-installation/macos-linux)

- [Windows](/cre/getting-started/cli-installation/windows)%

Before:

# Flags Contract Registry
Source: https://docs.chain.link/data-feeds/contract-registry

> For the complete documentation index, see [llms.txt](/llms.txt).

The Chainlink Flags Contract Registry provides a reliable, onchain source of truth for all active Chainlink price feed proxy contracts across supported networks. It serves as a central reference point for identifying which data feeds are **owned and operated by Chainlink**, verifying the authenticity of the feeds your applications rely on.

A proxy address that returns `true` when checked against this registry indicates two things:

1. The data feed is officially owned and operated by Chainlink
2. The feed is currently active

Inactive feeds are removed from the registry to ensure accuracy. The list is actively maintained as new feeds are deployed, making it a trusted resource for keeping up with the evolving state of Chainlink's oracle infrastructure.

## Querying Flags Onchain

To check if a proxy address is flagged (owned by Chainlink and active) in your Solidity code, you can call the `getFlag` function on the `Flags` contract deployed on the corresponding network:

```solidity
interface IFlags {
    function getFlag(address) external view returns (bool);
}

contract Example {
    IFlags public flags;

    // Initialize with the correct Flags contract address for your network
    constructor(address flagsContractAddress) {
        flags = IFlags(flagsContractAddress);
    }

    function isOfficialChainlinkFeed(address proxy) public view returns (bool) {
        return flags.getFlag(proxy);
    }
}
```

## Flags Contract Addresses

> **NOTE: This list isn't exhaustive**
>
> Not every chain where Chainlink Data Feeds are live has a Flags contract. If your chain is missing from the table
> below, reach out to [chainlink\_data\_feeds@smartcontract.com](mailto:chainlink_data_feeds@smartcontract.com) to confirm
> feed status.

Below is a list of all available Flags contracts on the supported networks:

|                                                                                                          | Chain               | ChainFlag Contract Address                                                                                                                              |
| -------------------------------------------------------------------------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <img src="/assets/chains/arbitrum.svg" style="height: 24px; width: auto; vertical-align: middle;" />     | Arbitrum            | <Address contractUrl="https://arbiscan.io/address/0x20551B03c092D998b1410c47BD54004D7C3106D0" eventName="docs_product_interaction" />                   |
| <img src="/assets/chains/avalanche.svg" style="height: 24px; width: auto; vertical-align: middle;" />    | Avalanche           | <Address contractUrl="https://snowtrace.io/address/0x71c5CC2aEB9Fa812CA360E9bAC7108FC23312cdd" eventName="docs_product_interaction" />                  |
| <img src="/assets/chains/base.svg" style="height: 24px; width: auto; vertical-align: middle;" />         | Base                | <Address contractUrl="https://basescan.org/address/0x71c5CC2aEB9Fa812CA360E9bAC7108FC23312cdd" eventName="docs_product_interaction" />                  |
| <img src="/assets/chains/bob.svg" style="height: 24px; width: auto; vertical-align: middle;" />          | Bob                 | <Address contractUrl="https://explorer.gobob.xyz/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e" eventName="docs_product_interaction" />            |
| <img src="/assets/chains/bnb-chain.svg" style="height: 24px; width: auto; vertical-align: middle;" />    | BNB Chain (BSC)     | <Address contractUrl="https://bscscan.com/address/0x141f4278A5D71070Dc09CA276b72809b80F20eF0" eventName="docs_product_interaction" />                   |
| <img src="/assets/chains/celo.svg" style="height: 24px; width: auto; vertical-align: middle;" />         | Celo                | <Address contractUrl="https://celo.blockscout.com/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e" eventName="docs_product_interaction" />           |
| <img src="/assets/chains/ethereum.svg" style="height: 24px; width: auto; vertical-align: middle;" />     | Ethereum            | <Address contractUrl="https://etherscan.io/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e" eventName="docs_product_interaction" />                  |
| <img src="/assets/chains/gnosis-chain.svg" style="height: 24px; width: auto; vertical-align: middle;" /> | Gnosis Chain (xDai) | <Address contractUrl="https://gnosisscan.io/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e" eventName="docs_product_interaction" />                 |
| <img src="/assets/chains/ink.svg" style="height: 24px; width: auto; vertical-align: middle;" />          | Ink                 | <Address contractUrl="https://explorer.inkonchain.com/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e" eventName="docs_product_interaction" />       |
| <img src="/assets/chains/linea.svg" style="height: 24px; width: auto; vertical-align: middle;" />        | Linea               | <Address contractUrl="https://lineascan.build/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e" eventName="docs_product_interaction" />               |
| <img src="/assets/chains/mantle.svg" style="height: 24px; width: auto; vertical-align: middle;" />       | Mantle              | <Address contractUrl="https://mantlescan.xyz/address/0x141f4278A5D71070Dc09CA276b72809b80F20eF0" eventName="docs_product_interaction" />                |
| <img src="/assets/chains/monad.svg" style="height: 24px; width: auto; vertical-align: middle;" />        | Monad               | <Address contractUrl="https://monadvision.com/address/0x2C4936af7C8867e62DAF9874519239dBE6b6DfFD" eventName="docs_product_interaction" />               |
| <img src="/assets/chains/optimism.svg" style="height: 24px; width: auto; vertical-align: middle;" />     | Optimism            | <Address contractUrl="https://optimistic.etherscan.io/address/0x71c5CC2aEB9Fa812CA360E9bAC7108FC23312cdd" eventName="docs_product_interaction" />       |
| <img src="/assets/chains/polygon.svg" style="height: 24px; width: auto; vertical-align: middle;" />      | Polygon             | <Address contractUrl="https://polygonscan.com/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e" eventName="docs_product_interaction" />               |
| <img src="/assets/chains/robinhood.svg" style="height: 24px; width: auto; vertical-align: middle;" />    | Robinhood           | <Address contractUrl="https://robinhoodchain.blockscout.com/address/0xbb601D8e5e568e6464D6D34feE489AA61b8d035A" eventName="docs_product_interaction" /> |
| <img src="/assets/chains/scroll.svg" style="height: 24px; width: auto; vertical-align: middle;" />       | Scroll              | <Address contractUrl="https://scrollscan.com/address/0x141f4278A5D71070Dc09CA276b72809b80F20eF0" eventName="docs_product_interaction" />                |
| <img src="/assets/chains/soneium.svg" style="height: 24px; width: auto; vertical-align: middle;" />      | Soneium             | <Address contractUrl="https://soneium.blockscout.com/address/0x3DE960FE090BFec72F585347fa0a27CF96a83b36" eventName="docs_product_interaction" />        |
| <img src="/assets/chains/sonic.svg" style="height: 24px; width: auto; vertical-align: middle;" />        | Sonic               | <Address contractUrl="https://sonicscan.org/address/0x141f4278A5D71070Dc09CA276b72809b80F20eF0" eventName="docs_product_interaction" />                 |
| <img src="/assets/chains/tempo.svg" style="height: 24px; width: auto; vertical-align: middle;" />        | Tempo               | <Address contractUrl="https://explore.tempo.xyz/address/0xae22AF6B02A4E7CCc535D1670442B29a3ef69a88" eventName="docs_product_interaction" />             |
| <img src="/assets/chains/unichain.svg" style="height: 24px; width: auto; vertical-align: middle;" />     | UniChain            | <Address contractUrl="https://uniscan.xyz/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e" eventName="docs_product_interaction" />                   |
| <img src="/assets/chains/zksync.svg" style="height: 24px; width: auto; vertical-align: middle;" />       | zkSync              | <Address contractUrl="https://explorer.zksync.io/address/0xC370405879C1ab0470604679E3275a02bCb89C91" eventName="docs_product_interaction" />            |

After:

# Installing the CRE CLI
Source: https://docs.chain.link/cre/getting-started/cli-installation
Last Updated: 2025-11-04

> For the complete documentation index, see [llms.txt](/llms.txt).

These guides explain how to install the Chainlink Developer Platform CLI (also referred to as the CRE CLI).

## Select your operating system

- [macOS / Linux](/cre/getting-started/cli-installation/macos-linux)

- [Windows](/cre/getting-started/cli-installation/windows)%                                                        ~/Projects/chainlink/documentation   main ± 

 ~/Projects/chainlink/documentation   main ± 

 ~/Projects/chainlink/documentation   main ± 
 ~/Projects/chainlink/documentation   main ±  curl --fail --silent \
  http://localhost:4321/data-feeds/contract-registry.md
# Flags Contract Registry
Source: https://docs.chain.link/data-feeds/contract-registry

> For the complete documentation index, see [llms.txt](/llms.txt).

The Chainlink Flags Contract Registry provides a reliable, onchain source of truth for all active Chainlink price feed proxy contracts across supported networks. It serves as a central reference point for identifying which data feeds are **owned and operated by Chainlink**, verifying the authenticity of the feeds your applications rely on.

A proxy address that returns `true` when checked against this registry indicates two things:

1. The data feed is officially owned and operated by Chainlink
2. The feed is currently active

Inactive feeds are removed from the registry to ensure accuracy. The list is actively maintained as new feeds are deployed, making it a trusted resource for keeping up with the evolving state of Chainlink's oracle infrastructure.

## Querying Flags Onchain

To check if a proxy address is flagged (owned by Chainlink and active) in your Solidity code, you can call the `getFlag` function on the `Flags` contract deployed on the corresponding network:

```solidity
interface IFlags {
    function getFlag(address) external view returns (bool);
}

contract Example {
    IFlags public flags;

    // Initialize with the correct Flags contract address for your network
    constructor(address flagsContractAddress) {
        flags = IFlags(flagsContractAddress);
    }

    function isOfficialChainlinkFeed(address proxy) public view returns (bool) {
        return flags.getFlag(proxy);
    }
}
```

## Flags Contract Addresses

> **NOTE: This list isn't exhaustive**
>
> Not every chain where Chainlink Data Feeds are live has a Flags contract. If your chain is missing from the table
> below, reach out to [chainlink\_data\_feeds@smartcontract.com](mailto:chainlink_data_feeds@smartcontract.com) to confirm
> feed status.

Below is a list of all available Flags contracts on the supported networks:

|   | Chain               | ChainFlag Contract Address                                                                                                             |
| - | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|   | Arbitrum            | [0x20551B03c092D998b1410c47BD54004D7C3106D0](https://arbiscan.io/address/0x20551B03c092D998b1410c47BD54004D7C3106D0)                   |
|   | Avalanche           | [0x71c5CC2aEB9Fa812CA360E9bAC7108FC23312cdd](https://snowtrace.io/address/0x71c5CC2aEB9Fa812CA360E9bAC7108FC23312cdd)                  |
|   | Base                | [0x71c5CC2aEB9Fa812CA360E9bAC7108FC23312cdd](https://basescan.org/address/0x71c5CC2aEB9Fa812CA360E9bAC7108FC23312cdd)                  |
|   | Bob                 | [0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e](https://explorer.gobob.xyz/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e)            |
|   | BNB Chain (BSC)     | [0x141f4278A5D71070Dc09CA276b72809b80F20eF0](https://bscscan.com/address/0x141f4278A5D71070Dc09CA276b72809b80F20eF0)                   |
|   | Celo                | [0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e](https://celo.blockscout.com/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e)           |
|   | Ethereum            | [0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e](https://etherscan.io/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e)                  |
|   | Gnosis Chain (xDai) | [0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e](https://gnosisscan.io/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e)                 |
|   | Ink                 | [0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e](https://explorer.inkonchain.com/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e)       |
|   | Linea               | [0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e](https://lineascan.build/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e)               |
|   | Mantle              | [0x141f4278A5D71070Dc09CA276b72809b80F20eF0](https://mantlescan.xyz/address/0x141f4278A5D71070Dc09CA276b72809b80F20eF0)                |
|   | Monad               | [0x2C4936af7C8867e62DAF9874519239dBE6b6DfFD](https://monadvision.com/address/0x2C4936af7C8867e62DAF9874519239dBE6b6DfFD)               |
|   | Optimism            | [0x71c5CC2aEB9Fa812CA360E9bAC7108FC23312cdd](https://optimistic.etherscan.io/address/0x71c5CC2aEB9Fa812CA360E9bAC7108FC23312cdd)       |
|   | Polygon             | [0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e](https://polygonscan.com/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e)               |
|   | Robinhood           | [0xbb601D8e5e568e6464D6D34feE489AA61b8d035A](https://robinhoodchain.blockscout.com/address/0xbb601D8e5e568e6464D6D34feE489AA61b8d035A) |
|   | Scroll              | [0x141f4278A5D71070Dc09CA276b72809b80F20eF0](https://scrollscan.com/address/0x141f4278A5D71070Dc09CA276b72809b80F20eF0)                |
|   | Soneium             | [0x3DE960FE090BFec72F585347fa0a27CF96a83b36](https://soneium.blockscout.com/address/0x3DE960FE090BFec72F585347fa0a27CF96a83b36)        |
|   | Sonic               | [0x141f4278A5D71070Dc09CA276b72809b80F20eF0](https://sonicscan.org/address/0x141f4278A5D71070Dc09CA276b72809b80F20eF0)                 |
|   | Tempo               | [0xae22AF6B02A4E7CCc535D1670442B29a3ef69a88](https://explore.tempo.xyz/address/0xae22AF6B02A4E7CCc535D1670442B29a3ef69a88)             |
|   | UniChain            | [0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e](https://uniscan.xyz/address/0xaB93491064aEE774BE4b8a1cFFe4421F5B124F4e)                   |
|   | zkSync              | [0xC370405879C1ab0470604679E3275a02bCb89C91](https://explorer.zksync.io/address/0xC370405879C1ab0470604679E3275a02bCb89C91)            |%

Additional checks, run:

npm run check:markdown-fidelity

Report is saved in reports/markdown-fidelity-report.json. Use the following command to show only problems:

jq '.findings[]
  | select(.status != "present")
  | {
      status,
      sourcePath,
      sourceLine,
      name,
      reason,
      expected,
      servedLine,
      servedText
    }' reports/markdown-fidelity-report.json

What the statuses mean

  • missing: Source content was not found in the generated Markdown. Fix this first.
  • unsupported: The checker found an MDX component it does not know how to inspect.
  • unverifiable: The content depends on dynamic MDX or HTML. This is not proof of data loss.
  • degraded: The route used fallback or replacement output instead of the normal converter.
  • present: The source content was found.

Make the shared MarkdownArtifact builder the only generator for the .md
route and project supported MDX components and language branches into
Markdown. Add a zero-network fidelity checker that compares raw source
facts and blocks non-exempt losses.
@thodges-gh
thodges-gh requested review from a team as code owners August 28, 2026 20:49
@vercel

vercel Bot commented Aug 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
documentation Ready Ready Preview Aug 28, 2026 10:27pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

👋 thodges-gh, thanks for creating this pull request!

To help reviewers, please consider creating future PRs as drafts first. This allows you to self-review and make any final changes before notifying the team.

Once you're ready, you can mark it as "Ready for review" to request feedback. Thanks!

@thodges-gh

Copy link
Copy Markdown
Contributor Author

Replaces #4110

Comment thread src/lib/markdown/buildMarkdownArtifact.ts Fixed
Replace quantified slash-trimming regexes with a linear index scan and
cover long leading and trailing slash runs.
Route Aside conversion through the existing MDX AST handler and add
regression coverage for long repeated input.
Route ClickToZoom conversion through the existing MDX AST handler and simplify
fallback component stripping to one linear regular expression. Add regression
coverage for repeated input and fallback output.
Comment thread src/lib/markdown/buildMarkdownArtifact.ts Fixed
Replace fallback tag, static import, selector, frontmatter, and highlighter
regular expressions with bounded string scanners. Add repeated malformed-input
coverage for each scanner.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants