Initial Commit
This commit is contained in:
@@ -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, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 };
|
||||
Reference in New Issue
Block a user