Skip to content

Commit 08966e4

Browse files
committed
fix(docs): resolve API anchor ID collisions by appending kind suffix
1 parent fe45eb6 commit 08966e4

File tree

5 files changed

+65
-36
lines changed

5 files changed

+65
-36
lines changed

packages/docs/src/routes/api/index.tsx

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { $, component$, useOn, useSignal, useStore, useTask$, isBrowser } from '@builder.io/qwik';
22
import { Link } from '@builder.io/qwik-city';
3-
43
import { toSnakeCase } from '../../utils/utils';
54

65
// TODO: load the content of these files using fs instead of importing them
@@ -140,32 +139,45 @@ export const ApiMemberWrapper = component$(({ id, data, filters }: any) => {
140139
});
141140

142141

143-
export const ApiMemberList = component$(({ id, data, filters }: any) => (
144-
<ul class="grid sm:grid-cols-2 lg:grid-cols-3 pb-5">
145-
{data.members.map((member: any) => {
146-
const kind = toSnakeCase(member.kind);
147-
148-
if (!member.name) {
149-
return;
150-
}
151-
152-
const name = member.name.toLowerCase()
153-
.replace(/[^a-zA-Z0-9]/g, '')
154-
.replace(/ /g, '-');
155-
156-
157-
return (
158-
<li
159-
key={`${id}-member-${member.id}-${kind}`}
160-
data-kind={kind}
161-
data-kind-label={kind.substring(0, 1).toUpperCase()}
162-
class={`api-item list-none text-xs ${
163-
(kind in filters && !filters[kind] && 'hidden') || ''
164-
}`}
165-
>
166-
<Link href={`${data.id}#${name}`}>{member.name}</Link>
167-
</li>
168-
);
169-
})}
170-
</ul>
171-
));
142+
export const ApiMemberList = component$(({ id, data, filters }: any) => {
143+
const nameCounts = data.members.reduce((acc: Record<string, number>, m: any) => {
144+
if (m.name) {
145+
const normalizedName = m.name.toLowerCase();
146+
acc[normalizedName] = (acc[normalizedName] || 0) + 1;
147+
}
148+
return acc;
149+
}, {});
150+
return (
151+
<ul class="grid sm:grid-cols-2 lg:grid-cols-3 pb-5">
152+
{data.members.map((member: any) => {
153+
const kind = toSnakeCase(member.kind);
154+
155+
if (!member.name) {
156+
return;
157+
}
158+
159+
const name = member.name.toLowerCase()
160+
.replace(/[$]/g, '_')
161+
.replace(/[^a-zA-Z0-9_]/g, '')
162+
.replace(/ /g, '-');
163+
164+
const anchorId = nameCounts[member.name.toLowerCase()] > 1
165+
? `${name}-${kind}`
166+
: name;
167+
168+
return (
169+
<li
170+
key={`${id}-member-${member.id}-${kind}`}
171+
data-kind={kind}
172+
data-kind-label={kind.substring(0, 1).toUpperCase()}
173+
class={`api-item list-none text-xs ${
174+
(kind in filters && !filters[kind] && 'hidden') || ''
175+
}`}
176+
>
177+
<Link href={`${data.id}#${anchorId}`}>{member.name}</Link>
178+
</li>
179+
);
180+
})}
181+
</ul>
182+
);
183+
});

packages/docs/src/routes/api/qwik-city-vite-azure-swa/index.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ title: \@builder.io/qwik-city/vite/azure-swa API Reference
44

55
# [API](/api) &rsaquo; @builder.io/qwik-city/vite/azure-swa
66

7-
## azureSwaAdapter
7+
<h2 id="azureswaadapter">azureSwaAdapter</h2>
88

99
```typescript
1010
export declare function azureSwaAdapter(opts?: AzureSwaAdapterOptions): any;
@@ -44,7 +44,7 @@ any
4444

4545
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-city/src/adapters/azure-swa/vite/index.ts)
4646

47-
## AzureSwaAdapterOptions
47+
<h2 id="azureswaadapteroptions">AzureSwaAdapterOptions</h2>
4848

4949
```typescript
5050
export interface AzureSwaAdapterOptions extends ServerAdapterOptions

packages/docs/src/routes/api/qwik-city-vite-static/index.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ title: \@builder.io/qwik-city/vite/static API Reference
44

55
# [API](/api) &rsaquo; @builder.io/qwik-city/vite/static
66

7-
## staticAdapter
7+
<h2 id="staticadapter">staticAdapter</h2>
88

99
```typescript
1010
export declare function staticAdapter(opts: StaticGenerateAdapterOptions): any;
@@ -42,7 +42,7 @@ any
4242

4343
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-city/src/adapters/static/vite/index.ts)
4444

45-
## StaticGenerateAdapterOptions
45+
<h2 id="staticgenerateadapteroptions">StaticGenerateAdapterOptions</h2>
4646

4747
```typescript
4848
export interface StaticGenerateAdapterOptions extends Omit<StaticGenerateRenderOptions, 'outDir'>

scripts/api-docs.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { execa } from 'execa';
22
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
33
import { join } from 'node:path';
44
import { format } from 'prettier';
5-
import { type BuildConfig } from './util.ts';
5+
import { type BuildConfig, toSnakeCase } from './util.ts';
66

77
export async function generateQwikApiMarkdownDocs(config: BuildConfig, apiJsonInputDir: string) {
88
await generateApiMarkdownPackageDocs(config, apiJsonInputDir, ['qwik']);
@@ -198,6 +198,12 @@ async function createApiData(
198198
async function createApiMarkdown(a: ApiData) {
199199
let md: string[] = [];
200200

201+
const memberNameCounts = a.members.reduce((acc: Record<string, number>, m) => {
202+
const normalizedName = m.name.toLowerCase();
203+
acc[normalizedName] = (acc[normalizedName] || 0) + 1;
204+
return acc;
205+
}, {});
206+
201207
md.push(`---`);
202208
md.push(`title: \\${a.package} API Reference`);
203209
md.push(`---`);
@@ -207,7 +213,11 @@ async function createApiMarkdown(a: ApiData) {
207213

208214
for (const m of a.members) {
209215
// const title = `${toSnakeCase(m.kind)} - ${m.name.replace(/"/g, '')}`;
210-
md.push(`## ${m.name}`);
216+
const kind = toSnakeCase(m.kind);
217+
const isDuplicateName = memberNameCounts[m.name.toLowerCase()] > 1;
218+
const anchorId = isDuplicateName ? `${m.id}-${kind}` : m.id;
219+
220+
md.push(`<h2 id="${anchorId}">${m.name}</h2>`);
211221
md.push(``);
212222

213223
// sanitize / adjust output

scripts/util.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,3 +366,10 @@ export async function getQwikVersion(config: BuildConfig) {
366366
const qwikPkgJson = await readPackageJson(qwikDir);
367367
return qwikPkgJson.version;
368368
}
369+
370+
// pascal to snake case
371+
export const toSnakeCase = (str: string) =>
372+
str
373+
.split(/\.?(?=[A-Z])/)
374+
.join('-')
375+
.toLowerCase();

0 commit comments

Comments
 (0)