orgize/wasm/index.html
2023-11-13 16:33:04 +08:00

274 lines
6.2 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Orgize</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.2.0/github-markdown-light.min.css"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.22.0/ace.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.0/beautify-html.js"></script>
<style>
body,
html {
height: 100%;
margin: 0;
}
.bordered {
overflow: auto;
width: 50%;
flex: 1;
display: flex;
flex-direction: column;
border: 1px solid #dbdbdb;
border-radius: 4px;
}
#took {
color: #808080;
font-size: 14px;
padding: 0.5em 1em;
}
#tabsList {
align-items: center;
border-bottom-color: #dbdbdb;
border-bottom-style: solid;
border-bottom-width: 1px;
display: flex;
flex-grow: 0;
flex-shrink: 0;
justify-content: flex-start;
list-style: none;
margin: 0;
padding: 0;
}
#tabsList span {
text-align: center;
color: #4a4a4a;
padding: 0.5em 1em;
user-select: none;
cursor: pointer;
}
#spacer {
flex: 1;
}
#tabsList span.is-active {
color: #485fc7;
}
.markdown-body a[data-range] {
color: #485fc7;
cursor: pointer;
}
</style>
</head>
<body style="height: 100%; display: flex">
<div
style="
margin: 16px;
display: flex;
flex-direction: row;
flex: 1;
min-height: 0;
gap: 16px;
"
>
<div class="bordered">
<div style="height: 100%" id="editor"></div>
</div>
<div class="bordered markdown-body">
<div id="tabsList">
<span class="is-active" data-value="html-rendered">
HTML (rendered)
</span>
<span data-value="html">HTML</span>
<span data-value="syntax">Syntax</span>
<div id="spacer"></div>
<div id="took"></div>
</div>
<div style="flex: 1; overflow: auto">
<div id="result"></div>
</div>
</div>
</div>
</body>
<script type="module">
import init, { Org } from "./dist/orgize.js";
let org;
const result = document.getElementById("result");
const took = document.getElementById("took");
let type = "html-rendered";
const editor = ace.edit("editor");
editor.setTheme("ace/theme/tomorrow");
// render by type
const render = () => {
const startTime = performance.now();
org.update(editor.session.getValue());
switch (type) {
case "html-rendered": {
const html = injectHeadingClass(org.html());
result.innerHTML =
"<div style='padding:1.25rem 1.5rem'>" + html + "</div>";
break;
}
case "html": {
const html = html_beautify(org.html(), { indent_size: 2 });
result.innerHTML = "<pre>" + escapeHtml(html) + "</pre>";
break;
}
case "syntax": {
const syntax = escapeHtml(org.syntax())
.split("\n")
.map((line) =>
line.replace(
/([A-Z0-9_-]*)\@(\d+)\.\.(\d+)/,
(text, name, start, end) =>
`<b>${name}</b><a data-range="${start}-${end}">@${start}..${end}</a>`
)
)
.join("\n");
result.innerHTML = "<pre>" + syntax + "</pre>";
break;
}
}
const finishTime = performance.now();
took.innerText = "took " + (finishTime - startTime).toFixed(2) + "ms";
};
// select token or node range by click
result.addEventListener("click", (ev) => {
if (!ev.target.dataset.range) return;
const [start, end] = ev.target.dataset.range.split("-");
const startPos = editor.session.doc.indexToPosition(parseInt(start));
const endPos = editor.session.doc.indexToPosition(parseInt(end));
const range = new ace.Range(
startPos.row,
startPos.column,
endPos.row,
endPos.column
);
editor.selection.setRange(range);
});
// switch render type
document.getElementById("tabsList").addEventListener("click", (ev) => {
const clicked = event.target.closest("span");
if (!clicked) return;
type = clicked.dataset.value;
document.querySelectorAll("#tabsList span").forEach((el) => {
if (el === clicked) {
el.classList.add("is-active");
} else {
el.classList.remove("is-active");
}
});
render();
});
// utils
const escapeHtml = (html) =>
html
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
const injectHeadingClass = (html) =>
html.replace(/<h(\d)>/g, (_, l) => `<h${l} class="title is-${l}">`);
// init
init().then(() => {
org = new Org("");
editor.session.setValue(`# git hash: ${Org.gitHash}
# build time: ${Org.buildTime}
*Orgize*, a /pure/ =Rust= library for
parsing +Emacs+ _org-mode_ files.
See also:
[[https://github.com/PoiScript/orgize][GitHub]] |
[[https://crates.io/crates/orgize][crates.io]] |
[[https://www.npmjs.com/package/orgize][NPM]]
-----
* Heading 1 *bold*
** Heading 2 =verbatim=
*** Heading 3 ~code~
**** Heading 4 /italic/
***** Heading 5 +strike+
****** Heading 6 _underline_
This's section
#+begin_quote
This is a quote
#+end_quote
#+begin_example
This is an example block
#+end_example
1. First item
2. Second item
3. Third item
* Indented item
* Indented item
4. Fourth item
Table:
|Syntax |Description|
|-----------|-----------|
|Header |Title |
|Paragraph |Text |
Image:
[[https://www.rust-lang.org/static/images/rust-logo-blk.svg]]
`);
editor.session.on("change", () => render());
render();
});
</script>
</html>