@solarity/hardhat-markup
Version:
Customizable markdown documentation for smart contracts
83 lines • 3.72 kB
JavaScript
import fs from "fs";
import fsp from "fs/promises";
import path from "path";
import { Parser } from "../parser/Parser.js";
import { MDGenerator } from "./md-generator/MDGenerator.js";
export class Generator {
artifacts;
outDir;
onlyFiles;
skipFiles;
verbose;
mdGenerator;
constructor(hre) {
this.artifacts = hre.artifacts;
this.outDir = path.resolve(hre.config.markup.outdir);
this.mdGenerator = new MDGenerator();
this.onlyFiles = hre.config.markup.onlyFiles.map((p) => this.toUnixPath(path.normalize(p)));
this.skipFiles = hre.config.markup.skipFiles.map((p) => this.toUnixPath(path.normalize(p)));
this.verbose = hre.config.markup.verbose;
}
async generate() {
console.log("\nGenerating markups...");
const _names = (await this.artifacts.getAllFullyQualifiedNames()).keys().toArray();
const filterer = async (n) => {
const src = (await this.artifacts.readArtifact(n)).sourceName;
return (this.onlyFiles.length == 0 || this.contains(this.onlyFiles, src)) && !this.contains(this.skipFiles, src);
};
const filtered = _names.filter(filterer);
this.verboseLog(`\n${_names.length} compiled contracts found, skipping ${_names.length - filtered.length} of them`);
await this.generateMDs(filtered);
return filtered;
}
async generateMDs(artifactNames) {
for (const contractName of artifactNames) {
const [source, name] = contractName.split(":");
this.verboseLog(`\nStarted generating markup for ${name} contract`);
const buildInfoId = await this.artifacts.getBuildInfoId(contractName);
if (buildInfoId === undefined) {
continue;
}
const buildInfoPath = await this.artifacts.getBuildInfoPath(buildInfoId);
const buildInfoOutputPath = await this.artifacts.getBuildInfoOutputPath(buildInfoId);
if (!buildInfoPath || !buildInfoOutputPath) {
continue;
}
const buildInfo = JSON.parse(fs.readFileSync(buildInfoPath, "utf-8"));
const buildInfoOutput = JSON.parse(fs.readFileSync(buildInfoOutputPath, "utf-8"));
const contractInfo = await new Parser(buildInfo, buildInfoOutput).parseContractInfo(source, name);
const genDir = `${this.outDir}/${path.dirname(source)}`;
const genPath = `${genDir}/${name}.md`;
await fsp.mkdir(genDir, { recursive: true });
await fsp.writeFile(genPath, this.mdGenerator.generateContractMDStr(contractInfo));
this.verboseLog(`Markup for ${name} is successfully generated`);
}
}
async clean() {
if (!fs.existsSync(this.outDir)) {
return;
}
const dirStats = await fsp.stat(this.outDir);
if (!dirStats.isDirectory()) {
throw new Error(`outdir is not a directory: ${this.outDir}`);
}
await fsp.rm(this.outDir, { recursive: true });
}
contains(pathList, source) {
const isSubPath = (parent, child) => {
const parentTokens = parent.split(path.posix.sep).filter((i) => i.length);
const childTokens = child.split(path.posix.sep).filter((i) => i.length);
return parentTokens.every((t, i) => childTokens[i] === t);
};
return pathList === undefined ? false : pathList.some((p) => isSubPath(p, source));
}
toUnixPath(userPath) {
return userPath.split(path.sep).join(path.posix.sep);
}
verboseLog(msg) {
if (this.verbose) {
console.log(msg);
}
}
}
//# sourceMappingURL=Generator.js.map