// Copyright (c) 2024 yellows111 // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. // local const Package = require("./package.json"); // npm const Remarkable = require("remarkable").Remarkable; // remove .Remarkable if you're using Remarkable ^1.0.0! const TOCGenerator = require("markdown-toc"); const RemarkableHeaderIDs = require("remarkable-header-ids"); const HTMLFormatter = require("@liquify/prettify").formatSync; // natives const Process = require("process"); const Filesystem = require("fs"); const Path = require("path"); if(Process.argv.length < 4 && require.main === module) { console.error("You need a source.md and target.htm path!"); Process.exit(1); } function markup(input, options) { var usedSlugs = {}; let tableOfContents = new Remarkable().use(TOCGenerator.plugin(options)).render(input); let output = new Remarkable().use( RemarkableHeaderIDs({ levels: [1,2,3,4,5,6], anchorClassName: "header-anchor", anchorText: "#", headerId: function(slug) { if(usedSlugs[slug] > 0) { const out_ = `${slug}-${usedSlugs[slug]}`; usedSlugs[slug] = usedSlugs[slug] + 1; return out_; } else { if(!usedSlugs.hasOwnProperty(slug)) { usedSlugs[slug] = 0; } usedSlugs[slug] = usedSlugs[slug] + 1; return slug; } } }) ).render("# Table of contents:\n"+tableOfContents.content+"\n\n"+input); return output; } function format(data, name) { var wikiName = "A new yiki!"; var rootPrefix = "/"; if(process.env["WIKINAME"]) { wikiName = process.env["WIKINAME"]; } if(process.env["VPREFIX"]) { rootPrefix = process.env["VPREFIX"]; } // forceIndent screws with text nodes pretty bad but the alternative is to not allow the full document to be formatted const formatterRules = {"indentChar": "\t", "indentSize": 1, "markup": {"forceAttribute": false, "forceIndent": true}}; function render() { return HTMLFormatter(data, formatterRules) .split("\n") /* split by every newline */ .join("\n\t\t\t") /* then add padding and convert back into string */ .replace( /* multitag text node fix (should really just encase all text with , but whatever) */ /(\t*)(<(?:code|a href=".+?")>)\n\t*(.*?)\n\t*(<\/(?:code|a)>)/g, "$1$2$3$4" ) .replace( /* multitag prefix fix for (, [ and - */ /([(\[\-]|")\n\t*(<(?:code|a href=".+?")>.*<\/(?:code|a)>)/g, "$1$2" ) .replace( /* multitag suffix fix for special characters. */ /(<\/(?:a|code)>)\n\t*([.)\];:,?!+\-']|")/g, "$1$2" ) .replace( /* fix tag attached to word and not whitespace */ /(\w+)(<[a-zA-Z]\w*>)/g, "$1 $2" ) .replace( /* replace .md links to html ones */ /href="(.+?)\.md"/g, "href=\"$1.html\"" ) .replace( /* evil codeblock fix */ /
((.|\n)*?)<\/code><\/pre>/g,
				function(match, inline) {
					return "
" + inline.replace(/\t/g, "") + "
"; } ) .replace( /* fix monospace'd links */ /\n\t+(.*?)<\/code>\n\t+<\/a>/g, "$2" ) .replace( /* add one space to words that have a tag next to them */ /([a-zA-Z0-9]+?)/g, "$1" ); } // probably should bring in a better templating engine but whatever return ( /* eslint-disable indent */ ` ${name} - Documentation
${render()}

` ); /* eslint-enable indent */ } module.exports = {"markup": markup, "format": format}; if(require.main === module) { let content = markup(Filesystem.readFileSync(Process.argv[2]).toString()); Filesystem.writeFileSync(Process.argv[3], format(content, Path.basename(Process.argv[3], ".html").replace(/_/g, " "))); }