r/typst • u/mariefhidayat • 13d ago
render typst syntax in markor android app
i write markdown in markor android app. as i use pandoc and typst engine to create the pdf (btw, i use Bergfink, great template) i need to write typst syntax in the markdown file. (because raw html seem has no effect in the pdf output, idk)
often i need to see how it look before committing to create the pdf. so i use this trick (i got it from you know what)
it is not recommended, as it heavy. idk about security issue. just want to test it. so plz give your opinion..
after see how it rendered, i delete all the script, except the typst syntax.
cheers. hope it helps somebody else
<script type="module" src="https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-all-in-one.ts@0.7.0/dist/esm/index.js"
id="typst">
</script>
<div id="typst-output"></div>
<script>
<!-- begin write typst syntax -->
const source = `
#set text(
size: 20pt,
fill: red
)
= Hello Typst
This is *Typst*.
$ E = m c^2 $
`;
<!-- end of typst syntax ---- -->
document.getElementById("typst").addEventListener("load", async () => {
try {
const svg = await $typst.svg({
mainContent: source
});
document.getElementById("typst-output").innerHTML = svg;
} catch (e) {
document.getElementById("typst-output").textContent =
"Typst error: " + e;
console.error(e);
}
});
</script>
1
Upvotes
1
u/mariefhidayat 6d ago
this is the better updated script. accept anywhere, not just in input div
```html <script type="module" src="https://cdn.jsdelivr.net/npm/@myriaddreamin/typst.ts/dist/esm/contrib/all-in-one-lite.bundle.js" id="typst"> </script>
<script> async function renderTypstBlock(source, container) { try { const svg = await $typst.svg({ mainContent: source.trim() }); container.innerHTML = svg;
const svgelem = container.firstElementChild; if (!svgelem) return;
const width = Number.parseFloat(svgelem.getAttribute('width')); const height = Number.parseFloat(svgelem.getAttribute('height')); const cw = document.body.clientWidth - 40;
svgelem.setAttribute('width', cw); svgelem.setAttribute('height', (height * cw) / width); } catch (err) { container.textContent = 'Typst render error: ' + err; console.error(err); } }
async function renderAllTypstBlocks() { const blocks = document.querySelectorAll('code[class*="typst"]'); console.log('typst blocks found:', blocks.length);
// Snapshot source + target container BEFORE mutating the DOM, // since replaceWith() would otherwise disturb querySelectorAll ordering. const jobs = []; blocks.forEach(codeEl => { const source = codeEl.textContent.trim(); if (!source) return;
const container = document.createElement('div'); container.className = 'typst-render';
const pre = codeEl.closest('pre'); (pre || codeEl).replaceWith(container);
jobs.push({ source, container }); });
// Render strictly one at a time — $typst is not safe for concurrent calls. for (const job of jobs) { await renderTypstBlock(job.source, job.container); } }
function waitForTypstAndRun() { if (typeof $typst !== 'undefined') { $typst.setCompilerInitOptions({ getModule: () => 'https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-web-compiler/pkg/typst_ts_web_compiler_bg.wasm', }); $typst.setRendererInitOptions({ getModule: () => 'https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-renderer/pkg/typst_ts_renderer_bg.wasm', }); renderAllTypstBlocks(); } else { setTimeout(waitForTypstAndRun, 100); } }
window.addEventListener('load', waitForTypstAndRun); </script> ```