Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ jobs:
~/.ghc-wasm/add_to_github_path.sh
popd

- name: checkout
uses: actions/checkout@v4

- name: checkout
uses: actions/checkout@v4
with:
Expand All @@ -57,10 +60,11 @@ jobs:
wasm32-wasi-cabal build pandoc-cli
popd

- name: wasm-opt
- name: dist
run: |
mkdir dist
wasm-opt --low-memory-unused --converge --gufa --flatten --rereloop -Oz $(find pandoc -type f -name pandoc.wasm) -o dist/pandoc.wasm
cp frontend/*.html frontend/*.js dist

- name: test
run: |
Expand Down
92 changes: 92 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>pandoc-wasm playground</title>
<style>
body {
display: flex;
flex-direction: column;
height: 100vh;
margin: 0;
font-family: monospace;
}

#container {
display: flex;
flex: 1;
overflow: hidden;
}

textarea {
width: 50%;
height: 100%;
border: none;
padding: 1rem;
resize: none;
box-sizing: border-box;
font-size: 1rem;
font-family: monospace;
}

#input {
border-right: 1px solid #ccc;
}

#output {
background-color: #f5f5f5;
color: #333;
}

#arguments-container {
padding: 0.5rem;
border-top: 1px solid #ccc;
background-color: #f9f9f9;
}

#arguments {
width: calc(100% - 1rem);
padding: 0.5rem;
font-size: 1rem;
box-sizing: border-box;
font-family: monospace;
}
</style>
</head>
<body>
<div id="container">
<textarea id="input" placeholder="Enter your input here..."></textarea>
<textarea
id="output"
readonly
placeholder="Output will be displayed here..."
></textarea>
</div>
<div id="arguments-container">
<input type="text" id="arguments" value="-f markdown -t rst" />
</div>
<script type="module">
import { run_pandoc } from "./index.js";

async function updateOutput() {
const inputText = document.getElementById("input").value;
const argumentsText = document
.getElementById("arguments")
.value.trim()
.split(" ");
try {
const output = await run_pandoc(argumentsText, inputText);
document.getElementById("output").value = output;
} catch (err) {
document.getElementById("output").value = `Error: ${err.message}`;
}
}

document.getElementById("input").addEventListener("input", updateOutput);
document
.getElementById("arguments")
.addEventListener("input", updateOutput);
</script>
</body>
</html>
62 changes: 62 additions & 0 deletions frontend/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
WASI,
OpenFile,
File,
ConsoleStdout,
} from "https://cdn.jsdelivr.net/npm/@bjorn3/[email protected]/dist/index.js";

const mod = await WebAssembly.compileStreaming(fetch("./pandoc.wasm"));

const instance_promise_pool_size = 8;

const instance_promise_pool = [];

function instance_promise_pool_fill() {
if (instance_promise_pool.length < instance_promise_pool_size) {
for (
let i = instance_promise_pool.length;
i < instance_promise_pool_size;
++i
) {
const args = [];
const env = [];
const stdin_file = new File(new Uint8Array(), { readonly: true });
const stdout_file = new File(new Uint8Array(), { readonly: false });
const fds = [
new OpenFile(stdin_file),
new OpenFile(stdout_file),
ConsoleStdout.lineBuffered((msg) =>
console.warn(`[WASI stderr] ${msg}`)
),
];
const options = { debug: false };
const wasi = new WASI(args, env, fds, options);
instance_promise_pool.push(
WebAssembly.instantiate(mod, {
wasi_snapshot_preview1: wasi.wasiImport,
}).then((instance) => ({ instance, wasi, stdin_file, stdout_file }))
);
}
}
}

instance_promise_pool_fill();

const instances = (async function* () {
while (true) {
yield await instance_promise_pool.shift();
instance_promise_pool_fill();
}
})();

export async function run_pandoc(args, stdin_str) {
const { instance, wasi, stdin_file, stdout_file } = (await instances.next())
.value;
wasi.args = ["pandoc.wasm", ...args];
stdin_file.data = new TextEncoder().encode(stdin_str);
const ec = wasi.start(instance);
if (ec !== 0) {
throw new Error(`Non-zero exit code ${ec}`);
}
return new TextDecoder("utf-8", { fatal: true }).decode(stdout_file.data);
}
Loading