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