Skip to content

Commit ea052dc

Browse files
committed
-
1 parent 79d9131 commit ea052dc

File tree

3 files changed

+85
-58
lines changed

3 files changed

+85
-58
lines changed

inputfiles/removedComments.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[
2+
"DOMHighResTimeStamp",
3+
"PublicKeyCredentialCreationOptions",
4+
"PublicKeyCredentialRequestOptions",
5+
"MediaTrackConstraints",
6+
"MediaTrackSupportedConstraints",
7+
"MediaTrackSettings",
8+
"RequestInit"
9+
]

src/build.ts

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ async function emitDom() {
9595
const addedItems = await readInputJSON("addedTypes.jsonc");
9696
const comments = await readInputJSON("comments.json");
9797
const deprecatedInfo = await readInputJSON("deprecatedMessage.json");
98-
const documentationFromMDN = await generateDescriptions();
98+
const removedComments = await readInputJSON("removedComments.json");
99+
const documentationFromMDN = await generateDescriptions(removedComments);
99100
const removedItems = await readInputJSON("removedTypes.jsonc");
100101

101102
async function readInputJSON(filename: string) {
@@ -129,15 +130,17 @@ async function emitDom() {
129130

130131
function mergeApiDescriptions(
131132
idl: Browser.WebIdl,
132-
descriptions: Record<string, any>,
133+
descriptions: { interfaces: { interface: Record<string, any> } },
133134
) {
134135
const namespaces = arrayToMap(
135136
idl.namespaces!,
136137
(i) => i.name,
137138
(i) => i,
138139
);
139140

140-
for (const [key, descObject] of Object.entries(descriptions)) {
141+
for (const [key, descObject] of Object.entries(
142+
descriptions.interfaces.interface,
143+
)) {
141144
const target = idl.interfaces?.interface?.[key] || namespaces[key];
142145

143146
if (!target) continue;
@@ -146,30 +149,8 @@ async function emitDom() {
146149
if (descObject.__comment) {
147150
target.comment = descObject.__comment;
148151
}
149-
150-
const { properties, methods } = idl.interfaces?.interface?.[key] || {};
151-
152-
const propertyItems = properties?.property
153-
? Object.values(properties.property)
154-
: [];
155-
const methodItems = methods?.method ? Object.values(methods.method) : [];
156-
157-
// Add comments to properties
158-
for (const prop of propertyItems) {
159-
const propDesc = descObject[prop.name];
160-
if (propDesc?.__comment) {
161-
prop.comment = propDesc.__comment;
162-
}
163-
}
164-
165-
// Add comments to methods
166-
for (const method of methodItems) {
167-
const methodDesc = descObject[method.name];
168-
if (methodDesc?.__comment) {
169-
method.comment = methodDesc.__comment;
170-
}
171-
}
172152
}
153+
idl = merge(idl, descriptions);
173154

174155
return idl;
175156
}

src/build/mdn-comments.ts

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import fs from "fs/promises";
2-
32
const basePath = new URL(
43
"../../inputfiles/mdn/files/en-us/web/api/",
54
import.meta.url,
@@ -52,33 +51,48 @@ function extractSummary(markdown: string): string {
5251

5352
async function walkDirectory(dir: URL): Promise<URL[]> {
5453
const entries = await fs.readdir(dir, { withFileTypes: true });
54+
const parentDirName = dir.pathname.split("/").filter(Boolean).slice(-1)[0];
5555
let results: URL[] = [];
5656

5757
for (const entry of entries) {
58-
const fullPath = new URL(`${entry.name}/`, dir);
59-
const fullFile = new URL(entry.name, dir);
60-
6158
if (entry.isDirectory()) {
62-
results = results.concat(await walkDirectory(fullPath));
59+
if (entry.name === parentDirName) continue;
60+
const subDir = new URL(`${entry.name}/`, dir);
61+
results = results.concat(await walkDirectory(subDir));
6362
} else if (entry.isFile() && entry.name === "index.md") {
64-
results.push(fullFile);
63+
results.push(new URL(entry.name, dir));
6564
}
6665
}
6766

6867
return results;
6968
}
7069

70+
const types: Record<string, string> = {
71+
property: "properties",
72+
method: "methods",
73+
};
74+
75+
function generateTypes(content: string): string[] | undefined {
76+
const pageType = content.match(/page-type:\s*["']?([^"'\n]+)["']?/);
77+
if (!pageType) throw new Error("pageType not found");
78+
79+
const type = pageType[1].split("-").pop()!;
80+
const plural = types[type];
81+
if (!plural) return;
82+
83+
return [plural, type];
84+
}
85+
7186
function generateSlug(content: string): string[] {
72-
const match = content.match(/slug:\s*["']?([^"'\n]+)["']?/)!;
87+
const match = content.match(/slug:\s*["']?([^"'\n]+)["']?/);
88+
if (!match) throw new Error("Slug not found");
89+
7390
const url = match[1].split(":").pop()!;
74-
const parts = url.split("/").slice(2); // remove first 2 segments
75-
return parts;
91+
const parts = url.split("/").slice(2); // skip `/en-US/web/api/...`
92+
return parts; // Keep only top-level and method
7693
}
7794

78-
function ensureLeaf(
79-
obj: Record<string, any>,
80-
keys: string[],
81-
): Record<string, any> {
95+
function ensureLeaf(obj: Record<string, any>, keys: string[]) {
8296
let leaf = obj;
8397
for (const key of keys) {
8498
leaf[key] ??= {};
@@ -87,7 +101,29 @@ function ensureLeaf(
87101
return leaf;
88102
}
89103

90-
export async function generateDescriptions(): Promise<Record<string, any>> {
104+
function insertComment(
105+
root: Record<string, any>,
106+
slug: string[],
107+
summary: string,
108+
types?: string[],
109+
) {
110+
if (slug.length === 1 || !types) {
111+
const iface = ensureLeaf(root, slug);
112+
iface.__comment = summary;
113+
} else {
114+
const [ifaceName, memberName] = slug;
115+
const iface = ensureLeaf(root, [ifaceName, ...types]);
116+
117+
const mainComment = root[ifaceName]?.__comment;
118+
if (mainComment !== summary) {
119+
iface[memberName] = { comment: summary };
120+
}
121+
}
122+
}
123+
124+
export async function generateDescriptions(removedComments: string[]): Promise<{
125+
interfaces: { interface: Record<string, any> };
126+
}> {
91127
const stats = await fs.stat(basePath);
92128
if (!stats.isDirectory()) {
93129
throw new Error(
@@ -99,23 +135,24 @@ export async function generateDescriptions(): Promise<Record<string, any>> {
99135
try {
100136
const indexPaths = await walkDirectory(basePath);
101137

102-
const promises = indexPaths.map(async (fileURL) => {
103-
try {
104-
const content = await fs.readFile(fileURL, "utf-8");
105-
const slug = generateSlug(content);
106-
const summary = extractSummary(content);
107-
const leaf = ensureLeaf(results, slug);
108-
leaf.__comment = summary;
109-
} catch (error) {
110-
console.warn(`Skipping ${fileURL.href}: ${error}`);
111-
}
112-
});
113-
114-
// Wait for all file processing to finish
115-
await Promise.all(promises);
116-
} catch (error) {
117-
console.error("Error generating API descriptions:", error);
138+
await Promise.all(
139+
indexPaths.map(async (fileURL) => {
140+
try {
141+
const content = await fs.readFile(fileURL, "utf-8");
142+
const slug = generateSlug(content);
143+
const types = generateTypes(content);
144+
145+
if (removedComments.includes(slug[0])) return;
146+
147+
const summary = extractSummary(content);
148+
insertComment(results, slug, summary, types);
149+
} catch (error) {
150+
console.error("Error generating API descriptions:", error);
151+
}
152+
}),
153+
);
154+
} catch (err) {
155+
console.error("Error generating API descriptions:", err);
118156
}
119-
120-
return results;
157+
return { interfaces: { interface: results } };
121158
}

0 commit comments

Comments
 (0)