Quarkup is an extremely lightweight, predictable, and context-aware markup language designed for speed and human-readability. Inspired by the principles of Quantum Chromodynamics (QCD), Quarkup replaces complex bracket hierarchies and bulky tags with an elegant system of Quarks (fundamental formatting particles), Leptons (light structural elements), and Annihilators (field stoppers).
Unlike other markup languages that suffer from visual noise, Quarkup looks like natural, unformatted text while remaining incredibly simple and lightning-fast to parse.
In Quarkup, we do not have "tags" or "elements". We only have Particles and Forces.
Formatting behaviors are controlled by a minimal set of flavor letters:
- Up (
u): Pulls text upwards (Headings / Superscript). - Down (
d): Pushes text downwards (Subscript / Footnotes). - Charm (
c): Enhances aesthetic appeal (Italics / Emphasis). - Strange (
s): Represents foreign, unformatted matter (Code / Listings). - Muon (
m): A heavier cousin of the electron β adds visual mass (Bold / Strong). - Top (
t): Global metadata properties defined at the top of a document. - Graphic (
g): Embedded visual media (Images / Figures). - Lattice (
l): A crystalline grid structure β as a block it builds Tables, as an inline particle it forms Links.
Lists are powered by light, fundamental leptons:
- Neutrino (
n): An uncharged particle used for unordered bullet lists. - Electron (
e): A countable, charged particle used for ordered, numbered lists.
Every Quarkup command follows one unyielding, predictable rule:
[Dot][Particle-Letter(s)][Space]
If a dot is followed by a letter and a space (e.g., .u or .n ), it is an active operator. If it is not followed by a space (e.g., file.txt or e.g.), it remains a dormant, natural punctuation mark. No backslash escaping required!
Quarkup classifies elements into two states of matter: Block Elements and Inline Elements.
A Block Element starts at the beginning of a line and automatically collapses (ends) at the next line break (\n).
Rather than introducing arbitrary heading markers, Quarkup increases the "mass" of the Up quark by stacking the letters. More quarks yield a smaller, denser heading level.
.u Heading 1β<h1>Heading 1</h1>.uu Heading 2β<h2>Heading 2</h2>.uuu Heading 3β<h3>Heading 3</h3>
Sequential lepton blocks of the same type are automatically grouped together. Stacking the particle letters sinks them deeper into the hierarchical structure, creating sub-lists.
- Unordered (Neutrinos):
.n Main Point .nn Sub-point level 2 .nnn Sub-point level 3 .n Back to Main Point - Ordered (Electrons):
.e First step .e Second step
.t title My First Quarkup Document.g terrace.jpg A beautiful view from the terrace
A .l block opens a table; it closes on a solitary Annihilator (..) on its own line. Each line inside is one row, with cells separated by ;.
Rows can carry an optional type prefix:
h:β Header row (wrapped in<thead>)f:β Footer row (wrapped in<tfoot>)s:β Section row (a single centered cell spanning the full table width, e.g. as a group divider)- (no prefix) β Regular body row
Within Header, Body, and Footer rows, a cell containing only > merges into the cell to its left (colspan), and a cell containing only _ merges into the cell above it (rowspan).
Cell content can carry an alignment marker as a prefix β left is the default and needs no marker:
.>β right-aligned.^β centered
.l
h: Product ; Qty ; Price
Widget ; .^ 3 ; .> 9.99
Gadget ; .^ 1 ; .> 199.00
f: Total ; > ; .> 208.99
..
renders a table with a header row, two body rows with centered quantities and right-aligned prices, and a footer row whose first two columns merge into a single "Total" cell.
A .b condition block includes its enclosed blocks only when condition matches the active defines, then closes on a solitary Annihilator (..). Defines are supplied via the CLI's repeatable -d KEY=VALUE flag (bare -d KEY counts as KEY=true), or via the "Defines" field in the web playground.
.b target=web
.u Web-only heading
This paragraph only appears in the browser build.
..
Compiled with -d target=web, the heading and paragraph are included; compiled without it, the whole block β and its condition line β disappear without a trace. Prefix the condition with ! to negate it, e.g. .b !target=web renders only when target is not set to web.
Inline Elements exist within a line of text. Since they do not end at a line break, they must be collapsed manually using the Annihilator (..) particle.
To maintain perfect legibility, the command particle "clings" to the left word but separates itself from the formatted content with a space.
- Style & Formatting (Charm):
This is a .c charming.. experience. - Bold (Muon):
This is .m important.. news.β nests freely with Charm in either direction, e.g..m bold with .c nested italic.. inside.. - Inline Code (Strange):
Run the .s cargo build.. command. - Superscript & Subscript (Up/Down): *
a.u 2.. + b.u 2.. = c.u 2..H.d 2..O is essential for life.
- Conditional (Bottom):
This feature is available .b target=web|only in your browser...keeps the phrase when compiled with-d target=weband drops it (surrounding text and punctuation stay put) otherwise. Negate with!, same as the block form. Note thecondition|textform only triggers when.bis not the first token on the line β a line-opening.bis always parsed as the block form described above.
For multi-line source code, we use the .s (Strange) block. It opens with .s [language] and captures all text exactly as written β ignoring all inner punctuation and formatting β until it encounters a solitary Annihilator (..) on its own line.
.s rust
fn main() {
let ans = 42;
println!("The answer is: {}", ans);
}
..
This repository features a robust, Zero-Copy Parser written in pure Rust. It features:
- Zero-Heap Allocations: The Lexer yields string slices (
&str) pointing directly into your original document, making it blisteringly fast and light on memory. - Context-Aware Parser: A hand-written predictive parser that effortlessly distinguishes between block-level commands, inline styling, nested lists, and raw code listings.
- Clean HTML5 Output: Transforms your Quarkup document into semantic, standard-compliant HTML5 without auxiliary wrapping tags.
Since the compiler reads directly from standard input (stdin), you can effortlessly pipe your .qu files directly into it:
cargo run < example/demo.qu > demo.htmlYou can embed referenced images using Data URLs using the --monolithic switch:
cargo run -- --monolithic < example/demo.qu > demo.htmlInput (test.qu):
.u Welcome to Quarkup
This is a molecule of H.d 2..O.
Here is what we need to do:
.e Clone repo
.e Run tests
.s rust
fn hello() {
println!("Hello, World!");
}
..
Generated HTML:
<h1>Welcome to Quarkup</h1>
<p>This is a molecule of H<sub>2</sub>O.</p>
<p>Here is what we need to do:</p>
<ol>
<li>Clone repo</li>
<li>Run tests</li>
</ol>
<pre class="language-rust">fn hello() {
println!("Hello, World!");
}</pre>This is how the sample document looks like in a web browser:
The compiler also runs entirely client-side in the browser via WebAssembly β no server, no data leaves the machine. The frontend lives in web/index.html and talks to a quarkup crate built with crate-type = ["cdylib", "rlib"] (see Cargo.toml and src/wasm.rs).
Build the wasm module and JS bindings:
./web/build.shThis requires the wasm32-unknown-unknown target (rustup target add wasm32-unknown-unknown) and a matching wasm-bindgen-cli version (cargo install wasm-bindgen-cli --version <version-of-wasm-bindgen-in-Cargo.toml>).
Note that LaTeX rendering (.s math / inline .s math ...) works differently in the browser: mathjax-svg-rs renders by spawning an OS thread, which wasm32-unknown-unknown cannot support, so the wasm target compiles without that dependency and instead emits a placeholder holding the raw LaTeX source. web/index.html typesets those placeholders client-side with the vendored KaTeX (MIT-licensed, bundled locally under web/vendor/katex/) once the preview loads. The CLI is unaffected and keeps using mathjax-svg-rs directly.
Then serve the web/ directory with any static HTTP server (ES modules require http://, not file://):
python3 -m http.server -d web 8080and open http://localhost:8080.
Syntax highlighting and a live preview inside VS Code, reusing the same wasm build as the web app β see vscode-extension/ for features and setup.
Quarkup is currently in its pre-alpha orbital state. Contributions to the parser or link-refinement mechanics are highly welcome!