Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
f0a7436
lib: don't prepend mailto to url in autolink Event
hellux Mar 19, 2023
3b12052
lib: Add SpanLinkTag::Unresolved variant
hellux Mar 19, 2023
71dffed
PR #27 Expose tag for unresolved links
hellux Mar 20, 2023
76c2c1d
make: nonzero exit when afl_quick detects crashes
hellux Mar 20, 2023
1ed561b
html: avoid peek of next event
hellux Mar 17, 2023
524d959
html: rm FilteredEvents
hellux Mar 17, 2023
2a65ce2
html: rm events/out from Writer
hellux Mar 17, 2023
3cd1d6d
html: extract Writer::render_{event, epilogue}
hellux Mar 19, 2023
ccdaf2b
mv push/write examples from html to Render trait
hellux Mar 19, 2023
f940d5c
lib: add Render::render_{event, prologue, epilogue}
hellux Mar 19, 2023
f186ca9
lib: add Render::{push, write}_borrowed
hellux Mar 17, 2023
d285420
bench-crit: add html_borrow, html_clone
hellux Mar 21, 2023
0884be2
PR #29 Allow rendering borrowed events
hellux Mar 25, 2023
130af1c
jotdown_wasm: rm debug print
hellux Mar 26, 2023
9f97756
jotdown_wasm: rm unmatched closing div
hellux Mar 26, 2023
16dbd61
jotdown_wasm: create html wrapper
hellux Mar 26, 2023
d6582eb
jotdown_wasm: use full viewport
hellux Mar 26, 2023
2ab2781
attr: impl Debug for Attributes manually
hellux Mar 26, 2023
1ab043e
jotdown_wasm: add option to show events
hellux Mar 26, 2023
3991888
jotdown_wasm: add output option for indented events
hellux Mar 26, 2023
9272e03
readme: correct online -> web
hellux Mar 26, 2023
fffa77b
readme: note web demo usefulness
hellux Mar 26, 2023
0c0e362
PR #32 wasm demo improvements
hellux Mar 27, 2023
cd65a7c
clippy: allow blocks_in_if_conditions everywhere
hellux Mar 1, 2023
af4490c
lib: add test attr_multiline
hellux Feb 25, 2023
a7ac36c
lib: add test link_reference_multiline
hellux Mar 1, 2023
e4f80a2
only assert in debug builds
hellux Feb 26, 2023
fb0333b
inline: reuse event buffer between blocks
hellux Feb 9, 2023
c8ff31d
inline: always push events from parse methods
hellux Feb 15, 2023
a0de1b1
inline: use ? to flatten methods
hellux Feb 15, 2023
a8d53f8
inline: use lex kinds
hellux Feb 15, 2023
d29e9b1
inline: separate lex, span to separate Input object
hellux Feb 22, 2023
436541f
inline: impl verbatim w/o lookahead
hellux Feb 15, 2023
7a350cd
inline: replace Delim by Opener
hellux Feb 19, 2023
c922df4
inline: impl links w/o lookahead
hellux Feb 19, 2023
7628087
inline: take str per line instead of full inline iter
hellux Feb 19, 2023
1d539ae
lib: derive Clone for Parser
hellux Mar 19, 2023
6a98b1a
inline: allow reading src
hellux Feb 25, 2023
64ca1ac
inline: extract merge_str_events
hellux Feb 27, 2023
797261d
inline: apply word attribute when flushing event buf
hellux Feb 19, 2023
23d8c6d
lex: rm lex::Kind::Whitespace
hellux Feb 19, 2023
9722f15
attr: rename State::{Attribute->Key}
hellux Feb 17, 2023
28651a6
attr: step one char at a time
hellux Feb 17, 2023
203d303
attr: mv wildcard State use to Parser methods
hellux Feb 18, 2023
61a46de
attr: impl valid without Parser
hellux Feb 18, 2023
a324f3b
attr: Parser overhaul
hellux Feb 17, 2023
46961b9
inline: parse multi-line link tags/urls
hellux Mar 14, 2023
2dce1b3
inline: store link cowstrs in vec (squash)
hellux Mar 23, 2023
4414119
inline: keep track of lines ahead
hellux Feb 25, 2023
a3337ed
inline: add ControlFlow enum
hellux Feb 25, 2023
2fe35f2
inline: parse multiline attributes
hellux Feb 18, 2023
14f6c41
inline: store attributes in vec (squash)
hellux Mar 23, 2023
c5814c9
feat: add custom CowStr type
kmaasrud Mar 15, 2023
2000914
cowstr: add docstrings
kmaasrud Apr 1, 2023
f067cbd
cowstr: add tests for push, push_str and replace
kmaasrud Apr 1, 2023
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
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ afl_quick:
cargo afl build --no-default-features --release --config profile.release.debug-assertions=true && \
AFL_NO_UI=1 AFL_BENCH_UNTIL_CRASH=1 \
cargo afl fuzz -i in -o out -V 60 target/release/${AFL_TARGET})
[ -z "$$(find tests/afl/out/default/crashes -type f -name 'id:*')" ]

afl_crash:
set +e; \
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Jotdown supports Rust edition 2021, i.e. Rust 1.56 and above.
## Usage

Jotdown is primarily a parsing library but also has a minimal CLI
implementation and a simple online demo version.
implementation and a simple web demo version.

### Library

Expand Down Expand Up @@ -62,9 +62,12 @@ It will be placed in `~/.cargo/bin/jotdown`.

### Web demo

A version of Jotdown compiled to WebAssembly and runnable in a web browser is
available at <https://hllmn.net/projects/jotdown/demo>. It can also be run
locally:
The web demo is a version of Jotdown compiled to WebAssembly and runnable in a
web browser. It is useful for experimenting with the djot syntax and exploring
what events are emitted or what output is rendered.

An online version is available at <https://hllmn.net/projects/jotdown/demo>. It
can also be run locally:

```
$ cd examples/jotdown_wasm
Expand Down
62 changes: 59 additions & 3 deletions bench/criterion/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ fn gen_html(c: &mut criterion::Criterion) {
|| jotdown::Parser::new(input).collect::<Vec<_>>(),
|p| {
let mut s = String::new();
jotdown::html::Renderer.push(p.into_iter(), &mut s).unwrap();
jotdown::html::Renderer::default()
.push(p.into_iter(), &mut s)
.unwrap();
s
},
criterion::BatchSize::SmallInput,
Expand All @@ -62,6 +64,60 @@ fn gen_html(c: &mut criterion::Criterion) {
}
criterion_group!(html, gen_html);

fn gen_html_borrow(c: &mut criterion::Criterion) {
let mut group = c.benchmark_group("html_borrow");
for (name, input) in bench_input::INPUTS {
group.throughput(criterion::Throughput::Elements(
jotdown::Parser::new(input).count() as u64,
));
group.bench_with_input(
criterion::BenchmarkId::from_parameter(name),
input,
|b, &input| {
b.iter_batched(
|| jotdown::Parser::new(input).collect::<Vec<_>>(),
|p| {
let mut s = String::new();
jotdown::html::Renderer::default()
.push_borrowed(p.as_slice().iter(), &mut s)
.unwrap();
s
},
criterion::BatchSize::SmallInput,
);
},
);
}
}
criterion_group!(html_borrow, gen_html_borrow);

fn gen_html_clone(c: &mut criterion::Criterion) {
let mut group = c.benchmark_group("html_clone");
for (name, input) in bench_input::INPUTS {
group.throughput(criterion::Throughput::Elements(
jotdown::Parser::new(input).count() as u64,
));
group.bench_with_input(
criterion::BenchmarkId::from_parameter(name),
input,
|b, &input| {
b.iter_batched(
|| jotdown::Parser::new(input).collect::<Vec<_>>(),
|p| {
let mut s = String::new();
jotdown::html::Renderer::default()
.push(p.iter().cloned(), &mut s)
.unwrap();
s
},
criterion::BatchSize::SmallInput,
);
},
);
}
}
criterion_group!(html_clone, gen_html_clone);

fn gen_full(c: &mut criterion::Criterion) {
let mut group = c.benchmark_group("full");
for (name, input) in bench_input::INPUTS {
Expand All @@ -72,7 +128,7 @@ fn gen_full(c: &mut criterion::Criterion) {
|b, &input| {
b.iter_with_large_drop(|| {
let mut s = String::new();
jotdown::html::Renderer
jotdown::html::Renderer::default()
.push(jotdown::Parser::new(input), &mut s)
.unwrap();
s
Expand All @@ -83,4 +139,4 @@ fn gen_full(c: &mut criterion::Criterion) {
}
criterion_group!(full, gen_full);

criterion_main!(block, inline, html, full);
criterion_main!(block, inline, html, html_borrow, html_clone, full);
2 changes: 1 addition & 1 deletion bench/iai/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn block_inline() -> Option<jotdown::Event<'static>> {

fn full() -> String {
let mut s = String::new();
jotdown::html::Renderer
jotdown::html::Renderer::default()
.push(jotdown::Parser::new(bench_input::ALL), &mut s)
.unwrap();
s
Expand Down
14 changes: 12 additions & 2 deletions examples/jotdown_wasm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@ ${WASM}: ${SRC}

wasm: ${WASM}

run: ${WASM}
index.html: Makefile demo.html
echo '<!DOCTYPE html><html>' > $@
echo '<head>' >> $@
echo '<title>Jotdown Demo</title>' >> $@
echo '</head>' >> $@
echo '<body style="display:flex;flex-direction:column;height:100vh;margin:0">' >> $@
cat demo.html >> $@
echo '</body>' >> $@
echo '</html>' >> $@

run: ${WASM} index.html
python -m http.server

clean:
rm -rf pkg
rm -rf pkg index.html
cargo clean
50 changes: 50 additions & 0 deletions examples/jotdown_wasm/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<div id="jotdown" style="flex-grow:1;display:flex;flex-direction:column">
<script type="module">
import init, {
jotdown_render,
jotdown_parse,
jotdown_parse_indent,
} from './pkg/jotdown_wasm.js';
await init();

let output = document.getElementById("output");
let input = document.getElementById("input");
let fmt = document.getElementById("fmt");

function render() {
if (fmt.value == "html") {
output.classList.add("verbatim")
output.innerText = jotdown_render(input.innerText);
} else if (fmt.value == "events") {
output.classList.add("verbatim")
output.innerText = jotdown_parse(input.innerText);
} else if (fmt.value == "events_indent") {
output.classList.add("verbatim")
output.innerText = jotdown_parse_indent(input.innerText);
} else if (fmt.value == "preview") {
output.classList.remove("verbatim")
output.innerHTML = jotdown_render(input.innerText);
}
}

render()

input.onkeyup = render;
fmt.onchange = render;

// auto focus on input on load
setTimeout(() => { input.focus(); }, 0);
</script>
<div>
<select id="fmt">
<option value="preview">preview</option>
<option value="html">html</option>
<option value="events">events</option>
<option value="events_indent">events (indented)</option>
</select>
</div>
<div id="panes" style="display:flex;height:100%;gap:1rem">
<pre id="input" contenteditable="true" placeholder="Input djot here" style="width:50%;height:100%;overflow:scroll;resize:none;box-sizing:border-box;margin:0">*Hello world!*</pre>
<pre id="output" readonly style="width:50%;height:100%;overflow:scroll;box-sizing:border-box;margin:0"></pre>
</div>
</div>
33 changes: 0 additions & 33 deletions examples/jotdown_wasm/index.html

This file was deleted.

54 changes: 53 additions & 1 deletion examples/jotdown_wasm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,64 @@
use wasm_bindgen::prelude::*;

use jotdown::Render;
use std::fmt::Write;

#[must_use]
#[wasm_bindgen]
pub fn jotdown_render(djot: &str) -> String {
let events = jotdown::Parser::new(djot);
let mut html = String::new();
jotdown::html::Renderer.push(events, &mut html).unwrap();
jotdown::html::Renderer::default()
.push(events, &mut html)
.unwrap();
html
}

#[must_use]
#[wasm_bindgen]
pub fn jotdown_parse(djot: &str) -> String {
jotdown::Parser::new(djot)
.map(|e| format!("{:?}\n", e))
.collect()
}

#[must_use]
#[wasm_bindgen]
pub fn jotdown_parse_indent(djot: &str) -> String {
let mut level = 0;
let mut out = String::new();
for e in jotdown::Parser::new(djot) {
if !matches!(e, jotdown::Event::End(..)) {
// use non-breaking space for indent because normal spaces gets squeezed by browser
let nbsp = '\u{00a0}';
(0..4 * level).for_each(|_| out.push(nbsp));
}
match e {
jotdown::Event::Start(c, attrs) => {
level += 1;
if c.is_block() {
out.push('[');
} else {
out.push('(');
}
out.write_fmt(format_args!("{:?}", c)).unwrap();
if c.is_block() {
out.push(']');
} else {
out.push(')');
}
if !attrs.is_empty() {
out.write_fmt(format_args!(" {:?}", attrs)).unwrap();
}
out.push('\n');
}
jotdown::Event::End(..) => {
level -= 1;
}
e => {
out.write_fmt(format_args!("{:?}\n", e)).unwrap();
}
};
}
out
}
Loading