You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
230 lines
5.9 KiB
230 lines
5.9 KiB
const fs = require("fs");
|
|
const path = require("path");
|
|
|
|
// Extract emmy lua classes from a file
|
|
// "---@class Bastion" -> "Bastion"
|
|
function extractClasses(file) {
|
|
const classes = [];
|
|
const lines = file.split("\n");
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const line = lines[i];
|
|
if (line.startsWith("---@class ")) {
|
|
const className = line.replace("---@class ", "");
|
|
classes.push(className);
|
|
}
|
|
}
|
|
return classes;
|
|
}
|
|
|
|
// console.log(
|
|
// extractClasses(fs.readFileSync(path.join(__dirname, "Bastion.lua"), "utf8"))
|
|
// );
|
|
|
|
// Extract emmy lua functions from a file
|
|
/*
|
|
"---@param name string" -> "name", "string"
|
|
"---@param name2 string|nil" -> "name2", "string|nil"
|
|
"---@return string" -> "string"
|
|
"function Bastion:Test(name, name2)" -> "Bastion", "Test"
|
|
|
|
Every function documentation starts with a ---@param line or a ---@return line and ends with a function line, we should ignore any
|
|
other lines in between these lines
|
|
|
|
return {
|
|
name: "Bastion",
|
|
function: "Test",
|
|
params: [
|
|
{
|
|
name: "name",
|
|
type: "string"
|
|
},
|
|
{
|
|
name: "name2",
|
|
type: "string|nil"
|
|
},
|
|
],
|
|
returns: [
|
|
{
|
|
type: "string"
|
|
}
|
|
]
|
|
}
|
|
*/
|
|
function extractFunctions(file) {
|
|
const functions = [];
|
|
const lines = file.split("\n");
|
|
|
|
let params = [];
|
|
let returns = [];
|
|
let description = "";
|
|
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const line = lines[i];
|
|
|
|
if (line.startsWith("---@param ")) {
|
|
const paramLine = line.replace("---@param ", "");
|
|
|
|
// get the name (everything before the first space) and the types (everything after the first space allowing for spaces in the types)
|
|
const name = paramLine.split(" ")[0];
|
|
const type = paramLine.replace(name + " ", "");
|
|
|
|
params.push({
|
|
name,
|
|
type,
|
|
});
|
|
} else if (line.startsWith("---@return ")) {
|
|
const returnLine = line.replace("---@return ", "");
|
|
const type = returnLine;
|
|
returns.push({
|
|
type,
|
|
});
|
|
} else if (line.startsWith("---") && !line.startsWith("---@")) {
|
|
// This is a description line
|
|
description += line.replace("---", "") + "\n";
|
|
} else if (line.startsWith("function ")) {
|
|
// We have reached the end of the function documentation, now we can extract the function name and class name
|
|
|
|
if (params.length === 0 && returns.length === 0) {
|
|
// There is no documentation for this function
|
|
continue;
|
|
}
|
|
|
|
const functionLine = line.replace("function ", "");
|
|
const [className, functionName] = functionLine.split(":");
|
|
functions.push({
|
|
className: className,
|
|
function: functionName,
|
|
params,
|
|
returns,
|
|
description: description,
|
|
});
|
|
|
|
// Reset the params and returns array
|
|
params = [];
|
|
returns = [];
|
|
description = "";
|
|
}
|
|
}
|
|
return functions;
|
|
}
|
|
|
|
let globalFunctions = [];
|
|
|
|
// dump a file to markdown
|
|
function Dump(filePath) {
|
|
const fileName = path.basename(filePath);
|
|
|
|
const functions = extractFunctions(fs.readFileSync(filePath, "utf8"));
|
|
globalFunctions = [...globalFunctions, ...functions];
|
|
|
|
const classes = extractClasses(fs.readFileSync(filePath, "utf8")).map(
|
|
(className) => {
|
|
return {
|
|
name: className,
|
|
functions: functions.filter((func) => func.className === className),
|
|
};
|
|
}
|
|
);
|
|
|
|
// console.log(classes);
|
|
|
|
// write the data to disk as a markdown file
|
|
const markdown = classes
|
|
.map((classData) => {
|
|
const classMarkdown = `# ${classData.name}
|
|
|
|
|
|
${classData.functions
|
|
.map((func) => {
|
|
return `## ${func.className}:${func.function}
|
|
|
|
${func.description}
|
|
|
|
${func.params.length > 0 ? "### Parameters" : ""}
|
|
${func.params
|
|
.map((param) => {
|
|
return `\`${param.name} (${param.type})\``;
|
|
})
|
|
.join("\n")}
|
|
|
|
${func.returns.length > 0 ? "### Returns" : ""}
|
|
${func.returns
|
|
.map((ret) => {
|
|
return `\`-> ${ret.type}\``;
|
|
})
|
|
.join("\n")}`;
|
|
})
|
|
.join("\n")}`;
|
|
|
|
return classMarkdown;
|
|
})
|
|
.join("\n");
|
|
|
|
const p = path.join(filePath.replace("input", "output")) + ".md";
|
|
|
|
// create the output directory if it doesn't exist
|
|
if (!fs.existsSync(path.dirname(p))) {
|
|
fs.mkdirSync(path.dirname(p), {
|
|
recursive: true,
|
|
});
|
|
}
|
|
|
|
fs.writeFileSync(p, markdown);
|
|
}
|
|
|
|
// Dump(path.join(__dirname, "Bastion.lua"));
|
|
|
|
function DumpDirectory(directory) {
|
|
// get all the files in the directory
|
|
const files = fs.readdirSync(directory);
|
|
|
|
// filter out the files that are not lua files
|
|
const luaFiles = files.filter((file) => file.endsWith(".lua"));
|
|
|
|
// dump each file
|
|
luaFiles.forEach((file) => {
|
|
Dump(path.join(directory, file));
|
|
});
|
|
|
|
// dump the files in the subdirectories
|
|
const subDirectories = files.filter((file) =>
|
|
fs.lstatSync(path.join(directory, file)).isDirectory()
|
|
);
|
|
subDirectories.forEach((subDirectory) => {
|
|
DumpDirectory(path.join(directory, subDirectory));
|
|
});
|
|
}
|
|
|
|
function DumpAPIFile(_funcs) {
|
|
// console.log(_funcs);
|
|
const lua = _funcs
|
|
.map((func) => {
|
|
let str = "";
|
|
|
|
if (func.description !== "") {
|
|
str += `--- ${func.description}\n`;
|
|
}
|
|
|
|
func.params.map((param) => {
|
|
str += `---@param ${param.name} ${param.type}\n`;
|
|
});
|
|
|
|
func.returns.map((ret) => {
|
|
str += `---@return ${ret.type}\n`;
|
|
});
|
|
|
|
str += `function ${func.className}:${func.function} end`;
|
|
|
|
return str;
|
|
})
|
|
.join("\n\n");
|
|
|
|
fs.writeFileSync(path.join(__dirname, "output", "API.lua"), lua);
|
|
}
|
|
|
|
// Wipe the output directory
|
|
fs.rmdirSync(path.join(__dirname, "output"), { recursive: true });
|
|
fs.mkdirSync(path.join(__dirname, "output"));
|
|
|
|
DumpDirectory(path.join(__dirname, "input"));
|
|
DumpAPIFile(globalFunctions);
|
|
|