Added
Extending functions
The new .extend function lets you wrap any previously-declared function, transforming or replacing its output without losing the original definition:
.function {greet}
greeting name:
.greeting, .name!
.greet {Hello} {world}
.extend {greet}
super name:
.if {.name::equals {world}}
.super::uppercase
.ifnot {.name::equals {world}}
.super
.greet {Hello} {world}
.greet {Hey} {everyone}Output:
Hello, world!
HELLO, WORLD!
Hey, everyone!The wrapper body receives the result of the original function (conventionally called super) as its first parameter, followed by the original function's parameters.
Overwriting functions
It is now possible to overwrite any previously-declared function:
.uppercase {Quarkdown}
.function {uppercase}
text:
.text::lowercase
.uppercase {Quarkdown}Output:
QUARKDOWN
quarkdownThis behavior can be turned off with the new --forbid-function-overwriting CLI flag, which raises a compilation error instead.
Unlike .extend, which wraps the previous function and keeps its output reachable via super, this fully replaces the previous definition, so its return value and parameters are no longer accessible.
Custom HTML title
The new title parameter of .htmloptions lets you override the text that appears in the browser tab and in search engine results, independently of the document name:
.docname {Quarkdown}
.htmloptions title:{Quarkdown | Markdown with superpowers}The docs project creator was also updated to automatically include this attribute on each page as .docname | My project name.
File tree explicit directories
The .filetree block now accepts a trailing slash (/) marker so you can explicitly render directories, including empty ones.
For example:
.filetree
- src/
- main.c
- target/
- docs
- guide.md
- README.mdIn this example, target/ is now rendered as an empty folder, while entries with children still work as directories without needing the slash.
Thanks @CarmJos!
listfiles recursive traversal and name filtering
The .listfiles function now supports two new optional parameters:
recursive:{yes}to include files from nested subdirectories.pattern:{regex}to keep only entries whose file name matches the given regular expression.
This makes it easier to target files in deep folder trees and build pattern-based inclusion flows.
Thanks @CarmJos!
Changed
Dictionary lookup chaining (breaking change)
The .get function now takes the dictionary as its first argument, making chained lookups feel natural:
.docauthors
- John
- country: USA
- Maria
- country: Italy
.docauthors::get {John}::get {country}Output:
USAPreviously, the dictionary had to be passed as a named from argument (.get {John} from:{.docauthors}). Existing documents using that form will need to switch to the new positional or chained syntax.
Unique anchor identifiers for duplicate headings
Two or more headings sharing the same title used to produce the same HTML anchor identifier, making in-document links (such as table of contents entries and cross-references) always navigate to the first match.
Each subsequent occurrence now receives an automatic -2, -3, ... suffix on its identifier, so links target the intended heading.
For example, the following:
# Chapter 1
## Examples
# Chapter 2
## Examplesnow generates the identifiers examples and examples-2 for the two Examples headings, and any link or table of contents entry points to the correct one.
Fixed
Preserve Unicode characters in output names
Output file names now preserve Unicode letters and numbers instead of replacing them with dashes.
For example, this command now keeps the Chinese characters in the file name:
quarkdown c main.qd --pdf --out-name abc123我爱你The generated PDF file is now abc123我爱你.pdf.
Thanks @CarmJos!
File tree font size shrinking at nested levels
Entries in a .filetree block used to incorrectly get progressively smaller at each level of nesting.
Sponsors
Thanks to our sponsors! 🎉
