import hl from "highlight.js/lib/core"; import hl_typescript from "highlight.js/lib/languages/typescript"; import {marked} from "marked"; import fs from "node:fs"; import {parseArgs} from "node:util"; hl.registerLanguage("typescript", hl_typescript); let {positionals, values} = parseArgs({ allowPositionals: true, options: { component: { type: "string", multiple: true, }, system: { type: "string", multiple: true, }, library: { type: "string", multiple: true, }, utility: { type: "string", multiple: true, }, }, }); let source_ts = positionals.shift(); let content = fs.readFileSync(source_ts); let lines = content.toString().split("\n"); let source_gh = "https://github.com/piesku/goodluck/blob/main/" + source_ts.slice(3); class Section { constructor(docs, code) { this.docs = docs; this.code = code; } } class Line { constructor(lineno, text) { this.lineno = lineno; this.value = text; } } let sections = []; let in_comment = false; let in_indent = false; let code = []; let docs = []; let lineno = 0; for (let line of lines) { lineno++; if (line.startsWith("/**")) { in_comment = true; } else if (in_comment && line.startsWith(" *")) { let lineobj = new Line(lineno, line.slice(3)); docs.push(lineobj); } else if (in_comment && line.startsWith("*/")) { in_comment = false; } else if (line === "" && !in_indent) { let section = new Section(docs, code); sections.push(section); code = []; docs = []; } else { in_comment = false; if (/^\s/.test(line)) { in_indent = true; } else { in_indent = false; } let lineobj = new Line(lineno, line); code.push(lineobj); } } //console.log(JSON.stringify(sections, null, 4)); marked.setOptions({ renderer: new marked.Renderer(), highlight: function (code, lang) { const language = hl.getLanguage(lang) ? lang : "typescript"; return hl.highlight(code, {language}).value; }, langPrefix: "hljs language-", // highlight.js css expects a top-level 'hljs' class. pedantic: false, gfm: true, breaks: false, sanitize: false, smartLists: true, smartypants: false, xhtml: false, }); marked.use({ extensions: [ { name: "definition_list", level: "block", start(src) { // Hint to Marked.js to stop and check for a match return src.match(/@(param|returns)/)?.index; }, tokenizer(src, tokens) { if (src.startsWith("@param") || src.startsWith("@returns")) { let token = { // Token to generate type: "definition_list", // Should match "name" above raw: src, // Text to consume from the source tokens: [], // Array where child inline tokens will be generated }; // Queue this data to be processed for inline tokens this.lexer.inline(src.trim(), token.tokens); return token; } }, renderer(token) { return `
${token.dt}` : ""}
${token.tag}
${hl.highlight(content, {language: "typescript"}).value}