Skip to content

Commit ab91814

Browse files
committed
Fix dead anchor links
1 parent 700e55b commit ab91814

4 files changed

Lines changed: 99 additions & 16 deletions

File tree

docs/llms-full.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2447,9 +2447,9 @@ base64-encoded XDR string.
24472447
transactions onto your account! Doing so will invalidate this pre-compiled
24482448
transaction!
24492449
- Send this XDR string to your other parties. They can use the instructions
2450-
for [getKeypairSignature](#getKeypairSignature) to sign the transaction.
2450+
for [`getKeypairSignature`](#transactiongetkeypairsignaturekeypair) to sign the transaction.
24512451
- They should send you back their `publicKey` and the `signature` string
2452-
from [getKeypairSignature](#getKeypairSignature), both of which you pass to
2452+
from [`getKeypairSignature`](#transactiongetkeypairsignaturekeypair), both of which you pass to
24532453
this function.
24542454

24552455
```ts
@@ -2467,7 +2467,7 @@ addSignature(publicKey: string = "", signature: string = ""): void;
24672467

24682468
Signs a transaction with the given `Keypair`. Useful if someone sends
24692469
you a transaction XDR for you to sign and return (see
2470-
[addSignature](#addSignature) for more information).
2470+
[`addSignature`](#transactionaddsignaturepublickey-signature) for more information).
24712471

24722472
When you get a transaction XDR to sign....
24732473
- Instantiate a `Transaction` object with the XDR
@@ -5035,9 +5035,9 @@ base64-encoded XDR string.
50355035
transactions onto your account! Doing so will invalidate this pre-compiled
50365036
transaction!
50375037
- Send this XDR string to your other parties. They can use the instructions
5038-
for [getKeypairSignature](#getKeypairSignature) to sign the transaction.
5038+
for [`getKeypairSignature`](#transactiongetkeypairsignaturekeypair) to sign the transaction.
50395039
- They should send you back their `publicKey` and the `signature` string
5040-
from [getKeypairSignature](#getKeypairSignature), both of which you pass to
5040+
from [`getKeypairSignature`](#transactiongetkeypairsignaturekeypair), both of which you pass to
50415041
this function.
50425042

50435043
```ts
@@ -5078,7 +5078,7 @@ getClaimableBalanceId(opIndex: number): string;
50785078

50795079
Signs a transaction with the given `Keypair`. Useful if someone sends
50805080
you a transaction XDR for you to sign and return (see
5081-
[addSignature](#addSignature) for more information).
5081+
[`addSignature`](#transactionaddsignaturepublickey-signature) for more information).
50825082

50835083
When you get a transaction XDR to sign....
50845084
- Instantiate a `Transaction` object with the XDR

docs/reference/core-transactions.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,9 +327,9 @@ base64-encoded XDR string.
327327
transactions onto your account! Doing so will invalidate this pre-compiled
328328
transaction!
329329
- Send this XDR string to your other parties. They can use the instructions
330-
for [getKeypairSignature](#getKeypairSignature) to sign the transaction.
330+
for [`getKeypairSignature`](#transactiongetkeypairsignaturekeypair) to sign the transaction.
331331
- They should send you back their `publicKey` and the `signature` string
332-
from [getKeypairSignature](#getKeypairSignature), both of which you pass to
332+
from [`getKeypairSignature`](#transactiongetkeypairsignaturekeypair), both of which you pass to
333333
this function.
334334

335335
```ts
@@ -347,7 +347,7 @@ addSignature(publicKey: string = "", signature: string = ""): void;
347347

348348
Signs a transaction with the given `Keypair`. Useful if someone sends
349349
you a transaction XDR for you to sign and return (see
350-
[addSignature](#addSignature) for more information).
350+
[`addSignature`](#transactionaddsignaturepublickey-signature) for more information).
351351

352352
When you get a transaction XDR to sign....
353353
- Instantiate a `Transaction` object with the XDR
@@ -2915,9 +2915,9 @@ base64-encoded XDR string.
29152915
transactions onto your account! Doing so will invalidate this pre-compiled
29162916
transaction!
29172917
- Send this XDR string to your other parties. They can use the instructions
2918-
for [getKeypairSignature](#getKeypairSignature) to sign the transaction.
2918+
for [`getKeypairSignature`](#transactiongetkeypairsignaturekeypair) to sign the transaction.
29192919
- They should send you back their `publicKey` and the `signature` string
2920-
from [getKeypairSignature](#getKeypairSignature), both of which you pass to
2920+
from [`getKeypairSignature`](#transactiongetkeypairsignaturekeypair), both of which you pass to
29212921
this function.
29222922

29232923
```ts
@@ -2958,7 +2958,7 @@ getClaimableBalanceId(opIndex: number): string;
29582958

29592959
Signs a transaction with the given `Keypair`. Useful if someone sends
29602960
you a transaction XDR for you to sign and return (see
2961-
[addSignature](#addSignature) for more information).
2961+
[`addSignature`](#transactionaddsignaturepublickey-signature) for more information).
29622962

29632963
When you get a transaction XDR to sign....
29642964
- Instantiate a `Transaction` object with the XDR

scripts/build-docs.ts

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,80 @@ function slugifyHeading(text: string): string {
758758
.replace(/[^a-z0-9-]/g, "");
759759
}
760760

761+
interface RenderedFile {
762+
slug: string;
763+
content: string;
764+
}
765+
766+
// Post-render guard: every intra-page (`#anchor`) and cross-file
767+
// (`./slug.md#anchor`) markdown link must point at a heading that
768+
// actually exists. Heading ids are derived with `slugifyHeading`, so
769+
// they match the ids Starlight emits. This catches stale or mistyped
770+
// anchors — e.g. JSDoc links written against an older anchor scheme —
771+
// before they ship as dead links. Fails the build on any miss,
772+
// consistent with the unmapped-symbol gate in `main()`. External
773+
// (`http(s):`/`mailto:`) links and non-`.md` relative paths are out of
774+
// scope and skipped.
775+
function validateAnchors(files: RenderedFile[]): void {
776+
// Strip fenced code blocks first: a ```ts``` declaration is not a
777+
// heading, and signatures must never be scanned for links.
778+
const stripFences = (content: string): string =>
779+
content.replace(/```[\s\S]*?```/g, "");
780+
781+
const anchorsBySlug = new Map<string, Set<string>>();
782+
for (const { slug, content } of files) {
783+
const ids = new Set<string>();
784+
for (const m of stripFences(content).matchAll(/^#{1,6}\s+(.+?)\s*$/gm)) {
785+
ids.add(slugifyHeading(m[1]));
786+
}
787+
anchorsBySlug.set(slug, ids);
788+
}
789+
790+
const problems: string[] = [];
791+
for (const { slug, content } of files) {
792+
for (const m of stripFences(content).matchAll(/\[[^\]]*\]\(([^)]+)\)/g)) {
793+
const url = m[1].trim();
794+
if (/^(https?:|mailto:)/.test(url)) continue;
795+
796+
if (url.startsWith("#")) {
797+
const anchor = url.slice(1);
798+
if (anchorsBySlug.get(slug)?.has(anchor) !== true) {
799+
problems.push(
800+
`${slug}.md: ${m[0]} → no heading with id "#${anchor}" on this page`,
801+
);
802+
}
803+
continue;
804+
}
805+
806+
const cross = url.match(/^\.?\/?([\w-]+)\.md(?:#(.+))?$/);
807+
if (cross !== null) {
808+
const targetSlug = cross[1];
809+
const targetAnchor = cross[2];
810+
const targetIds = anchorsBySlug.get(targetSlug);
811+
if (targetIds === undefined) {
812+
problems.push(
813+
`${slug}.md: ${m[0]} → links to unknown file "${targetSlug}.md"`,
814+
);
815+
} else if (targetAnchor !== undefined && !targetIds.has(targetAnchor)) {
816+
problems.push(
817+
`${slug}.md: ${m[0]} → no heading with id "#${targetAnchor}" in ${targetSlug}.md`,
818+
);
819+
}
820+
}
821+
}
822+
}
823+
824+
if (problems.length > 0) {
825+
console.error(
826+
`[error] ${problems.length} dead anchor link(s) in generated reference docs:`,
827+
);
828+
for (const p of problems) {
829+
console.error(` [dead-anchor] ${p}`);
830+
}
831+
process.exit(1);
832+
}
833+
}
834+
761835
interface ResolvedLink {
762836
bucket: BucketName;
763837
slug: string;
@@ -1254,6 +1328,7 @@ function main(): void {
12541328
currentLinkResolver = buildLinkResolver(collected);
12551329

12561330
mkdirSync(OUTPUT_DIR, { recursive: true });
1331+
const rendered: RenderedFile[] = [];
12571332
let totalSymbols = 0;
12581333
for (const [bucket, slug] of Object.entries(BUCKET_TO_SLUG) as [
12591334
BucketName,
@@ -1264,10 +1339,18 @@ function main(): void {
12641339
throw new Error(`Internal: bucket "${bucket}" not pre-populated`);
12651340
}
12661341
const content = renderFile(bucket, list, DOCS_SOURCE_REF);
1267-
writeFileSync(join(OUTPUT_DIR, `${slug}.md`), content, "utf8");
1342+
rendered.push({ slug, content });
12681343
console.log(` ${slug}.md: ${list.length} symbol(s)`);
12691344
totalSymbols += list.length;
12701345
}
1346+
1347+
// Guard before writing: a dead intra-page or cross-file anchor must
1348+
// fail the build rather than ship (mirrors the unmapped-symbol gate
1349+
// above). Only write once every link is known to resolve.
1350+
validateAnchors(rendered);
1351+
for (const { slug, content } of rendered) {
1352+
writeFileSync(join(OUTPUT_DIR, `${slug}.md`), content, "utf8");
1353+
}
12711354
currentLinkResolver = undefined;
12721355
currentRenderBucket = undefined;
12731356
console.log(

src/base/transaction_base.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export class TransactionBase<
106106
/**
107107
* Signs a transaction with the given {@link Keypair}. Useful if someone sends
108108
* you a transaction XDR for you to sign and return (see
109-
* [addSignature](#addSignature) for more information).
109+
* `{@link Transaction.addSignature | addSignature}` for more information).
110110
*
111111
* When you get a transaction XDR to sign....
112112
* - Instantiate a `Transaction` object with the XDR
@@ -145,9 +145,9 @@ export class TransactionBase<
145145
* transactions onto your account! Doing so will invalidate this pre-compiled
146146
* transaction!
147147
* - Send this XDR string to your other parties. They can use the instructions
148-
* for [getKeypairSignature](#getKeypairSignature) to sign the transaction.
148+
* for `{@link Transaction.getKeypairSignature | getKeypairSignature}` to sign the transaction.
149149
* - They should send you back their `publicKey` and the `signature` string
150-
* from [getKeypairSignature](#getKeypairSignature), both of which you pass to
150+
* from `{@link Transaction.getKeypairSignature | getKeypairSignature}`, both of which you pass to
151151
* this function.
152152
*
153153
* @param publicKey - the public key of the signer

0 commit comments

Comments
 (0)