Skip to content

Commit 85d307f

Browse files
committed
add script to add appEvent documentation to source code
1 parent 9bc1460 commit 85d307f

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import "dotenv/config";
2+
import path from "path";
3+
import fs from "fs";
4+
5+
const discourseDir = process.env.DISCOURSE_CORE;
6+
7+
function updateFileWithAppEventDocs(filePath, appEventsDetails) {
8+
const fileContent = fs.readFileSync(filePath, "utf8");
9+
const lines = fileContent.split("\n");
10+
// appEventsDetails has to be sorted in descending order of line number
11+
// so as to maintain line numbers while inserting comments
12+
// NOTE: this does result in app_events_details.json going out of date in terms of lineNumbers
13+
appEventsDetails.sort((a, b) => b.lineNumber - a.lineNumber);
14+
appEventsDetails.forEach((details) => {
15+
const { lineNumber } = details;
16+
// lines is 0-indexed while lineNumber refers to file line number which is 1-indexed
17+
const startPos = lineNumber - 1;
18+
const indentation = lines[startPos].length - lines[startPos].trimStart().length;
19+
const docString = createDocumentation(details, indentation); // TODO: this should be a separate script
20+
lines.splice(startPos, 0, docString);
21+
});
22+
23+
fs.writeFileSync(filePath, lines.join('\n'), 'utf8');
24+
}
25+
26+
function createDocumentation(details, indentation=0) {
27+
const { eventId, args, comments } = details;
28+
if (!eventId && !comments && args.length === 0) { return null; }
29+
30+
const createArgDoc = (arg) => {
31+
const argTemplate = (argName, argType, argDesc) => {
32+
const templatedDesc = argDesc ? ` - ${argDesc}` : "";
33+
return ` * @arg {${argType}} ${argName}${templatedDesc}`;
34+
};
35+
36+
if (arg.argType === 'object') {
37+
const objectArgName = `objectArg${arg.argPosition}`;
38+
const initialObjDoc = ` * @arg {object} ${objectArgName}`;
39+
return [
40+
initialObjDoc,
41+
...arg.argValue
42+
.map((nestedArg) => argTemplate(`${objectArgName}.${nestedArg.key}`, nestedArg.valueType, nestedArg.description))
43+
.map((part) => `${' '.repeat(indentation)}${part}`)
44+
].join('\n');
45+
}
46+
47+
return argTemplate(arg.argValue, arg.argType, arg.description);
48+
};
49+
50+
const argsStrings = args
51+
.sort((a, b) => a.argPosition - b.argPosition)
52+
.map((arg) => createArgDoc(arg));
53+
54+
return [
55+
`/**`,
56+
` * ${eventId} appEvent`,
57+
` *`,
58+
` * @event ${eventId}`,
59+
...argsStrings,
60+
` */`
61+
].map((part) => `${' '.repeat(indentation)}${part}`)
62+
.join('\n');
63+
}
64+
65+
66+
(async () => {
67+
if (process.argv.length != 2) {
68+
console.log(
69+
"Usage: node add_app_events_docs_to_discourse.mjs, Remember to define DISCOURSE_CORE in an .env file"
70+
);
71+
process.exit(1);
72+
}
73+
74+
75+
const appEventsDetailsFilePath = path.join(
76+
".",
77+
"lib",
78+
"app_events_docs_generator",
79+
"app_events",
80+
"app_events_details.json"
81+
);
82+
83+
const appEventsDetails = JSON.parse(
84+
fs.readFileSync(appEventsDetailsFilePath, "utf8")
85+
);
86+
87+
// Group appEventsDetails by filePath, so that each file is only updated once
88+
const groupedByFilePath = appEventsDetails.reduce((result, detail) => {
89+
result[detail.filePath] ||= [];
90+
result[detail.filePath].push(detail);
91+
return result;
92+
}, {});
93+
94+
Object.keys(groupedByFilePath).forEach((filePath) => {
95+
updateFileWithAppEventDocs(
96+
path.join(discourseDir, filePath),
97+
groupedByFilePath[filePath]
98+
);
99+
});
100+
})();

0 commit comments

Comments
 (0)