From 8c5143653ccc826baf4a23c3da9c9e0dac7ecdba Mon Sep 17 00:00:00 2001 From: contribuewwt <38278035+undefinedDarkness@users.noreply.github.com> Date: Tue, 4 May 2021 12:47:16 +0530 Subject: [PATCH] gen-docs.js ~ widget argument type support (#148) * Clumsy typescript / deno rewrite * Requested Changes --- gen-docs.js | 92 --------------------------------- gen-docs.ts | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 92 deletions(-) delete mode 100644 gen-docs.js create mode 100644 gen-docs.ts diff --git a/gen-docs.js b/gen-docs.js deleted file mode 100644 index 36b7f71..0000000 --- a/gen-docs.js +++ /dev/null @@ -1,92 +0,0 @@ -const fs = require("fs"); -fs.readFile(process.argv[process.argv.length - 1], "utf8", (err, data) => { - if (err) { - return console.log(err); - } else { - const vars = parseVars(data); - printDocs(vars, parseDocs(data)); - } -}); - -function parseVars(code) { - const VAR_PATTERN = /^.*\/\/+ *@var +(.*?) +- +(.*)$/; - const vars = {}; - for (let line of code.split("\n")) { - const match = line.match(VAR_PATTERN); - if (match && match.length == 3) { - const name = match[1]; - const value = match[2]; - vars[name] = value; - } - } - return vars; -} - -function parseDocs(code) { - const NEW_WIDGET_PATTERN = /^.*\/\/+ *@widget +(!?)(.*?)(?: +extends +(.*))?$/; - const DESC_PATTERN = /^.*\/\/+ *@desc +(.*)$/; - const PROP_PATTERN = /^.*\/\/+ *@prop +(.*?) +- +(.*)$/; - - const widgets = {}; - let currentWidget = ""; - for (let line of code.split("\n")) { - const newWidgetMatch = line.match(NEW_WIDGET_PATTERN); - if (newWidgetMatch && newWidgetMatch.length >= 3) { - const name = newWidgetMatch[2]; - /** @type string[] */ - const exts = newWidgetMatch[3] - ? newWidgetMatch[3].split(/, */) - : []; - currentWidget = name; - widgets[currentWidget] = { - name, - exts, - props: [], - isVisible: newWidgetMatch[1] !== "!", - }; - continue; - } - - const descMatch = line.match(DESC_PATTERN); - if (descMatch && descMatch.length == 2) { - widgets[currentWidget].desc = descMatch[1]; - continue; - } - - const propMatch = line.match(PROP_PATTERN); - if (propMatch && propMatch.length == 3) { - widgets[currentWidget].props.push({ - name: propMatch[1], - desc: propMatch[2], - }); - } - } - return widgets; -} - -function printDocs(vars, docs) { - let output = Object.values(docs) - .filter((x) => x.isVisible) - .map((x) => { - x.props = [ - ...x.props, - ...x.exts.map((w) => docs[w]).flatMap((w) => w.props), - ]; - return x; - }) - .map((x) => printWidget(x)) - .map((x) => x.replace(/\$\w+/g, (x) => vars[x.replace("$", "")])) - .join("\n\n"); - console.log(output); -} - -function printWidget(widget) { - return ` -## \`${widget.name}\` ${widget.desc ? `\n${widget.desc}` : ""} - -**Properties** -${widget.props.map((prop) => `- **\`${prop.name}\`**: ${prop.desc}`).join("\n")} -`; -} - -// vim:ft=javascript diff --git a/gen-docs.ts b/gen-docs.ts new file mode 100644 index 0000000..17cf195 --- /dev/null +++ b/gen-docs.ts @@ -0,0 +1,144 @@ +interface WidgetData { + name: string; + desc: string; + type: string; // this should be an enum.. maybe +} + +interface Widget { + name: string; + exts: string[]; + desc: string; + props: WidgetData[]; + isVisible: boolean; +} + +function parseVars(code: string): Record { + const VAR_PATTERN = /^.*\/\/+ *@var +(.*?) +- +(.*)$/; + const vars: Record = {}; + + for (const line of code.split("\n")) { + + const match = line.match(VAR_PATTERN); + if (match && match.length == 3) { + const name = match[1]; + const value = match[2]; + vars[name] = value; + } + } + return vars; +} + +function replaceTypeNames(type: string) { + + switch (type) { + case "f64": + case "f32": + return "float" + case "i32": + case "i64": + return "int" + default: + return type + } + +} + +function parseDocs(code: string) { + const NEW_WIDGET_PATTERN = /^.*\/\/+ *@widget +(!?)(.*?)(?: +extends +(.*))?$/; + const DESC_PATTERN = /^.*\/\/+ *@desc +(.*)$/; + const PROP_PATTERN = /^.*\/\/+ *@prop +(.*?) +- +(.*)$/; + const ARG_TYPE_PATTERN = /(\w+):\s+as_(\w+)/g; + + const widgets: Record = {}; + const lines = code.split("\n") + + let currentWidget = ""; + + for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) { + + const line = lines[lineIndex] + const newWidgetMatch = NEW_WIDGET_PATTERN.exec(line); + + if (newWidgetMatch && newWidgetMatch.length >= 3) { + const name = newWidgetMatch[2]; + /** @type string[] */ + const exts = newWidgetMatch[3] + ? newWidgetMatch[3].split(/, */) + : []; + currentWidget = name; + widgets[currentWidget] = { + name, + exts, + desc: "", + props: [], + isVisible: newWidgetMatch[1] !== "!", + }; + continue; + } + + const descMatch = line.match(DESC_PATTERN); + if (descMatch && descMatch.length == 2) { + widgets[currentWidget].desc = descMatch[1]; + continue; + } + + const propMatch = line.match(PROP_PATTERN); + if (propMatch && propMatch.length == 3) { + let no = lineIndex + 1 + + while (/\s*\/\//.test(lines[no])) { + no += 1 + } // continue till you find the line with actual code + + const matches = [...lines[no].matchAll(ARG_TYPE_PATTERN)].map(z => { z.shift(); return z }).flat() // try to use the iterator directly + + const possibleMatch = matches.findIndex(x => x == propMatch[1].replaceAll("-", "_")) + if (possibleMatch == -1) { + console.log(`Failed to find a match for "${propMatch[1].replace("-", "_")}" ~ ${JSON.stringify(matches, null, 2)} ~ ${lines[no]}`) + } + const type = replaceTypeNames(matches[possibleMatch + 1]) + + widgets[currentWidget].props.push({ + name: propMatch[1], + desc: propMatch[2], + type: type ?? "no-type-found" + }); + } + } + return widgets; +} + +function printDocs(vars: Record, docs: Record) { + const output = Object.values(docs) + .filter((x) => x.isVisible) + .map((x) => { + x.props = [ + ...x.props, + ...x.exts.map((w) => docs[w]).flatMap((w) => w.props), + ]; + return x; + }) + .map((x) => printWidget(x)) + .map((x) => x.replace(/\$\w+/g, (x) => vars[x.replace("$", "")])) + .join("\n\n"); + console.log(output); +} + +function printWidget(widget: Widget) { + return ` +## \`${widget.name}\` ${widget.desc ? `\n${widget.desc}` : ""} + +**Properties** +${widget.props.map((prop) => `- **\`${prop.name}\`**: *\`${prop.type}\`* ${prop.desc}`).join("\n")} +`; +} + +// Deno args start from actual args +// Redirect stderr to ignore deno checking messages so: +// deno run --allow-read gen-docs.ts ./src/widgets/widget_definitions.ts 2> /dev/null +Deno.readTextFile(Deno.args[0]).then(data => { + const vars = parseVars(data); + printDocs(vars, parseDocs(data)); +}).catch(err => { + return console.error(err); +})