Initial Commit

This commit is contained in:
2026-08-20 22:51:22 -03:00
commit 8a597e19a8
13 changed files with 5055 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
//
// render.js — assembles the HTML document Nova's preview tab will load.
//
// Nothing is rendered here. Markdown-to-HTML and Mermaid both need to run in a
// browser, and the preview tab is a real WebView, so this file only builds a
// shell: the Markdown source as data, plus the scripts that turn it into a page.
// That keeps the diagram code where a DOM exists, and keeps regeneration cheap
// — a save rewrites a few kilobytes, not a three-megabyte bundle.
//
/** Escapes a string for embedding in a <script type="application/json"> block. */
function embedJSON(value) {
return JSON.stringify(value)
.replace(/</g, "\\u003c")
.replace(/>/g, "\\u003e")
.replace(/&/g, "\\u0026")
.replace(/\u2028/g, "\\u2028")
.replace(/\u2029/g, "\\u2029");
}
function escapeHTML(text) {
return String(text)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
/**
* Builds the preview document.
*
* @param {object} options
* @param {string} options.markdown Source text of the file being previewed.
* @param {string} options.title Tab and document title.
* @param {string} options.sourcePath Absolute path of the source file.
* @param {string} options.sourceRelDir Directory of the source file, relative to
* the generated HTML, so links and images
* in the Markdown still resolve.
* @param {string} options.assetsRelDir Assets directory, relative to the HTML.
* @param {string} options.mode "markdown" or "mermaid".
* @param {string} options.theme "auto", "light" or "dark".
* @param {number} options.contentWidth Max width of the text column, in pixels.
*/
function buildDocument(options) {
const data = {
markdown: options.markdown,
title: options.title,
sourcePath: options.sourcePath,
sourceRelDir: options.sourceRelDir,
mode: options.mode,
theme: options.theme,
generatedAt: Date.now(),
};
const assets = options.assetsRelDir;
return `<!DOCTYPE html>
<html lang="en" data-theme="${escapeHTML(options.theme)}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="generator" content="Mermaid Preview for Nova">
<title>${escapeHTML(options.title)}</title>
<link rel="stylesheet" href="${escapeHTML(assets)}/preview.css">
<style>:root { --content-width: ${Number(options.contentWidth) || 860}px; }</style>
</head>
<body>
<main id="content" class="markdown-body" aria-busy="true"></main>
<div id="error" hidden></div>
<script type="application/json" id="preview-data">${embedJSON(data)}</script>
<script src="${escapeHTML(assets)}/vendor/markdown-it.min.js"></script>
<script src="${escapeHTML(assets)}/vendor/mermaid.min.js"></script>
<script src="${escapeHTML(assets)}/preview.js"></script>
</body>
</html>
`;
}
module.exports = { buildDocument };