ideate
This commit is contained in:
+11
-11
@@ -85,7 +85,7 @@ Using `~()` - the unquote concept from Clojure's syntax-quote:
|
||||
#t"The value is ~(expr)."
|
||||
|
||||
;; Hiccup expression returns content
|
||||
#t"Click ~([:link {:dest url} label]) to continue."
|
||||
#t"Click ~([:link {:src url} label]) to continue."
|
||||
|
||||
;; Conditional
|
||||
#t"Status: ~(if done? 'Complete' 'Pending')"
|
||||
@@ -128,7 +128,7 @@ Same mental model as macro unquote:
|
||||
[:block {:inset "1em"}
|
||||
[:strong name] [:linebreak]
|
||||
[:emph affiliation] [:linebreak]
|
||||
[:link {:dest (str "mailto:" email)} email]])
|
||||
[:link {:src (str "mailto:" email)} email]])
|
||||
|
||||
(defn results-table [data]
|
||||
[:table {:columns 2 :align ["left" "right"]}
|
||||
@@ -171,8 +171,8 @@ Same mental model as macro unquote:
|
||||
"
|
||||
|
||||
;; Back to hiccup for the technical diagram
|
||||
[:figure {:caption "System architecture overview."}
|
||||
[:image {:width "80%"} "architecture.png"]]
|
||||
[:figure {:caption "System architecture overview." :label :fig/arch}
|
||||
[:image {:src "architecture.png" :width "80%"}]]
|
||||
|
||||
#t"
|
||||
Our method works by first processing the input through
|
||||
@@ -198,7 +198,7 @@ Same mental model as macro unquote:
|
||||
"
|
||||
|
||||
;; Bibliography could be generated
|
||||
[:bibliography "refs.bib"]])
|
||||
[:bibliography {:src "refs.bib"}]])
|
||||
|
||||
;; Compile it
|
||||
(compile-to-typst paper "paper.typ")
|
||||
@@ -303,7 +303,7 @@ Build mini-languages for specific domains:
|
||||
`(do
|
||||
(register-figure! ~id)
|
||||
[:figure {:label ~id :caption ["Figure " (figure-num ~id) ": " ~caption]}
|
||||
[:image {:width ~(or width "100%")} ~src]]))
|
||||
[:image {:src ~src :width ~(or width "100%")}]]))
|
||||
|
||||
(figure :arch
|
||||
:src "architecture.png"
|
||||
@@ -319,15 +319,15 @@ Build mini-languages for specific domains:
|
||||
|
||||
;; Shorthand for references
|
||||
(defmacro ref [id]
|
||||
`[:ref ~(str "@" (name id))])
|
||||
`[:ref {:target ~id}])
|
||||
|
||||
;; Shorthand for citations
|
||||
(defmacro cite [& keys]
|
||||
`[:cite ~@(map #(str "@" (name %)) keys)])
|
||||
`[:cite {:keys [~@keys]}])
|
||||
|
||||
;; Usage
|
||||
(ref :fig:arch) ; => @fig:arch
|
||||
(cite :smith2020 :jones2021) ; => @smith2020 @jones2021
|
||||
(ref :fig/arch) ; => [:ref {:target :fig/arch}]
|
||||
(cite :smith2020 :jones2021) ; => [:cite {:keys [:smith2020 :jones2021]}]
|
||||
```
|
||||
|
||||
### Template Macros
|
||||
@@ -339,7 +339,7 @@ Build mini-languages for specific domains:
|
||||
~@structure))
|
||||
|
||||
(deftemplate ieee-paper [title authors abstract]
|
||||
[[:set :page {:paper "us-letter" :columns 2}]
|
||||
[[:set {:element :page :paper "us-letter" :columns 2}]
|
||||
[:heading {:level 1 :align "center"} ~title]
|
||||
(render-authors ~authors)
|
||||
(render-abstract ~abstract)
|
||||
|
||||
+8
-10
@@ -40,26 +40,24 @@ Hiccup represents markup as nested data structures:
|
||||
;; [1], [2], [3]
|
||||
;; )
|
||||
|
||||
;; Raw content blocks
|
||||
[:raw "= Direct Typst Markup\nJust passed through"]
|
||||
|
||||
;; Code blocks (use :raw with :lang)
|
||||
;; Code blocks (use :raw for displayed code)
|
||||
[:raw {:lang "python" :block true} "print('hello')"]
|
||||
;; => #raw(lang: "python", block: true, "print('hello')")
|
||||
|
||||
;; Math
|
||||
;; Math (inline by default)
|
||||
[:math "x^2 + y^2 = z^2"]
|
||||
;; => $x^2 + y^2 = z^2$
|
||||
|
||||
;; Math (block/display)
|
||||
[:math {:block true} "sum_(i=0)^n i = (n(n+1))/2"]
|
||||
;; => $ sum_(i=0)^n i = (n(n+1))/2 $
|
||||
|
||||
;; Images
|
||||
[:image {:width "50%"} "diagram.png"]
|
||||
;; Images (src in attrs, no children)
|
||||
[:image {:src "diagram.png" :width "50%"}]
|
||||
;; => #image("diagram.png", width: 50%)
|
||||
|
||||
;; Links
|
||||
[:link {:dest "https://typst.app"} "Typst"]
|
||||
;; Links (src in attrs, child is display text)
|
||||
[:link {:src "https://typst.app"} "Typst"]
|
||||
;; => #link("https://typst.app")[Typst]
|
||||
```
|
||||
|
||||
@@ -85,7 +83,7 @@ Hiccup represents markup as nested data structures:
|
||||
|
||||
[:heading {:level 2} "Results"]
|
||||
|
||||
"The result is " [:$ "x = 42"] "."
|
||||
"The result is " [:math "x = 42"] "."
|
||||
|
||||
[:table {:columns 2}
|
||||
[:strong "Input"] [:strong "Output"]
|
||||
|
||||
+140
-45
@@ -1,5 +1,84 @@
|
||||
# Hiccup → Typst Mapping Reference
|
||||
|
||||
## Hiccup Syntax
|
||||
|
||||
All elements follow standard Hiccup:
|
||||
|
||||
```clojure
|
||||
[:tag {attrs} children...]
|
||||
```
|
||||
|
||||
- **tag**: Element type (keyword)
|
||||
- **attrs**: Optional map of attributes
|
||||
- **children**: Content (strings, nested elements, or expressions)
|
||||
|
||||
### Element Categories
|
||||
|
||||
| Category | Examples | Children |
|
||||
|----------|----------|----------|
|
||||
| Content elements | `heading`, `strong`, `emph`, `block` | Display content |
|
||||
| Source elements | `link`, `image`, `bibliography` | `link` has display text; others have none |
|
||||
| List elements | `list`, `enum`, `table` | Each child = one item/cell |
|
||||
| Container elements | `figure` | Single content child (compiled as function arg) |
|
||||
| Math | `math` | Math expression string |
|
||||
| References | `ref`, `cite` | None |
|
||||
| Code | `raw` | Code string to display |
|
||||
| Rules | `set` | None |
|
||||
| Show rules | `show` | A `set` rule as child |
|
||||
|
||||
### Reserved Attributes
|
||||
|
||||
| Attr | Used by | Purpose |
|
||||
|------|---------|---------|
|
||||
| `:src` | `link`, `image`, `bibliography` | Source URL/path |
|
||||
| `:label` | Any element | Makes element referenceable |
|
||||
| `:caption` | `figure` | Figure caption text |
|
||||
| `:target` | `ref` | Label to reference |
|
||||
| `:keys` | `cite` | Citation key(s) |
|
||||
| `:element` | `set`, `show` | Element type to configure |
|
||||
| `:block` | `math`, `raw` | Display as block (default: inline) |
|
||||
| `:lang` | `raw` | Code language for syntax highlighting |
|
||||
|
||||
### Examples
|
||||
|
||||
```clojure
|
||||
;; Content element
|
||||
[:heading {:level 2} "Section Title"]
|
||||
|
||||
;; Source element with children
|
||||
[:link {:src "https://example.com"} "Click here"]
|
||||
|
||||
;; Source element without children
|
||||
[:image {:src "diagram.png" :width "80%"}]
|
||||
|
||||
;; List element
|
||||
[:list "First" "Second" "Third"]
|
||||
|
||||
;; Container with label
|
||||
[:figure {:caption "Results" :label :fig/results}
|
||||
[:image {:src "chart.png"}]]
|
||||
|
||||
;; Math (inline and block)
|
||||
[:math "E = m c^2"]
|
||||
[:math {:block true} "sum_(i=0)^n i"]
|
||||
|
||||
;; Reference and citation
|
||||
[:ref {:target :fig/results}]
|
||||
[:cite {:keys [:smith2020 :jones2021]}]
|
||||
|
||||
;; Code display
|
||||
[:raw {:lang "python" :block true} "print('hello')"]
|
||||
|
||||
;; Set rule
|
||||
[:set {:element :page :margin "2cm"}]
|
||||
|
||||
;; Show rule (child is the set rule to apply)
|
||||
[:show {:element :heading}
|
||||
[:set {:element :text :fill "blue"}]]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Audit of Current Tags
|
||||
|
||||
### ✅ Valid - Direct Typst Functions
|
||||
@@ -9,10 +88,10 @@
|
||||
| `[:heading {:level 2} "Text"]` | `#heading(level: 2)[Text]` | ✅ Works |
|
||||
| `[:strong "text"]` | `#strong[text]` | ✅ Works |
|
||||
| `[:emph "text"]` | `#emph[text]` | ✅ Works |
|
||||
| `[:link {:dest "url"} "text"]` | `#link("url")[text]` | ✅ Works |
|
||||
| `[:image {:width "50%"} "path.png"]` | `#image("path.png", width: 50%)` | ✅ Works |
|
||||
| `[:link {:src "url"} "text"]` | `#link("url")[text]` | ✅ Works |
|
||||
| `[:image {:src "path.png" :width "50%"}]` | `#image("path.png", width: 50%)` | ✅ Works |
|
||||
| `[:block {:inset "1em"} ...]` | `#block(inset: 1em)[...]` | ✅ Works |
|
||||
| `[:bibliography "refs.bib"]` | `#bibliography("refs.bib")` | ✅ Works |
|
||||
| `[:bibliography {:src "refs.bib"}]` | `#bibliography("refs.bib")` | ✅ Works |
|
||||
|
||||
### ❌ Invalid - Don't Exist in Typst
|
||||
|
||||
@@ -34,11 +113,8 @@
|
||||
|---------|---------|---------|
|
||||
| `[:linebreak]` | Function name | `[:linebreak]` → `#linebreak()` ✅ actually works |
|
||||
| `[:h-space "2em"]` | Wrong name | `[:h "2em"]` → `#h(2em)` |
|
||||
| `[:figure [:image ...] [:caption ...]]` | Caption isn't a child | See below |
|
||||
| `[:math "x^2"]` | Need to distinguish inline/block | `$x^2$` vs `$ x^2 $` |
|
||||
| `[:code {:lang "py"} "..."]` | Function is `raw` | `#raw(lang: "python", "...")` |
|
||||
| `[:ref :label]` | Takes label not string | `#ref(<label>)` |
|
||||
| `[:cite :key]` | Takes label | `#cite(<key>)` |
|
||||
| `[:figure [:image ...] [:caption ...]]` | Caption isn't a child | Caption goes in attrs |
|
||||
| `[:code {:lang "py"} "..."]` | Function is `raw` | `[:raw {:lang "python"} "..."]` |
|
||||
|
||||
## Corrected Mappings
|
||||
|
||||
@@ -119,12 +195,12 @@ Caption is a named parameter, not a child element:
|
||||
|
||||
;; NEW (correct)
|
||||
[:figure {:caption "Architecture diagram"}
|
||||
[:image "arch.png"]]
|
||||
[:image {:src "arch.png"}]]
|
||||
;; => #figure(image("arch.png"), caption: [Architecture diagram])
|
||||
|
||||
;; With label for referencing
|
||||
[:figure {:caption "Architecture" :label :fig:arch}
|
||||
[:image {:width "80%"} "arch.png"]]
|
||||
[:figure {:caption "Architecture" :label :fig/arch}
|
||||
[:image {:src "arch.png" :width "80%"}]]
|
||||
;; => #figure(image("arch.png", width: 80%), caption: [Architecture]) <fig:arch>
|
||||
```
|
||||
|
||||
@@ -139,17 +215,13 @@ Caption is a named parameter, not a child element:
|
||||
### Math
|
||||
|
||||
```clojure
|
||||
;; Inline math
|
||||
[:$ "x^2 + y^2"]
|
||||
;; Inline math (default)
|
||||
[:math "x^2 + y^2"]
|
||||
;; => $x^2 + y^2$
|
||||
|
||||
;; Block/display math
|
||||
[:$$ "sum_(i=0)^n i"]
|
||||
;; => $ sum_(i=0)^n i $
|
||||
|
||||
;; Or with explicit flag
|
||||
[:math "x^2"] ;; inline by default
|
||||
[:math {:block true} "sum_(i=0)^n i"]
|
||||
;; => $ sum_(i=0)^n i $
|
||||
```
|
||||
|
||||
### Code/Raw
|
||||
@@ -176,15 +248,15 @@ Caption is a named parameter, not a child element:
|
||||
|
||||
```clojure
|
||||
;; Reference a label
|
||||
[:ref :fig:arch]
|
||||
[:ref {:target :fig/arch}]
|
||||
;; => @fig:arch
|
||||
|
||||
;; Citation
|
||||
[:cite :smith2020]
|
||||
;; Single citation
|
||||
[:cite {:keys [:smith2020]}]
|
||||
;; => @smith2020
|
||||
|
||||
;; Multiple citations
|
||||
[:cite :smith2020 :jones2021]
|
||||
[:cite {:keys [:smith2020 :jones2021]}]
|
||||
;; => @smith2020 @jones2021
|
||||
```
|
||||
|
||||
@@ -197,18 +269,19 @@ Caption is a named parameter, not a child element:
|
||||
|
||||
### Page/Document Settings
|
||||
|
||||
`set` rules are special - they affect following content:
|
||||
`set` and `show` rules configure document styling. Use `:element` attr to specify the target:
|
||||
|
||||
```clojure
|
||||
;; Set rules (affects everything after)
|
||||
[:set :page {:paper "a4" :margin "2cm"}]
|
||||
[:set {:element :page :paper "a4" :margin "2cm"}]
|
||||
;; => #set page(paper: "a4", margin: 2cm)
|
||||
|
||||
[:set :text {:font "New Computer Modern" :size "11pt"}]
|
||||
[:set {:element :text :font "New Computer Modern" :size "11pt"}]
|
||||
;; => #set text(font: "New Computer Modern", size: 11pt)
|
||||
|
||||
;; Show rules
|
||||
[:show :heading {:set {:text {:fill "blue"}}}]
|
||||
;; Show rules (child is the set rule to apply)
|
||||
[:show {:element :heading}
|
||||
[:set {:element :text :fill "blue"}]]
|
||||
;; => #show heading: set text(fill: blue)
|
||||
```
|
||||
|
||||
@@ -235,8 +308,8 @@ Second paragraph.
|
||||
```clojure
|
||||
(def my-doc
|
||||
[;; Set rules at top
|
||||
[:set :page {:paper "a4"}]
|
||||
[:set :text {:font "Linux Libertine"}]
|
||||
[:set {:element :page :paper "a4"}]
|
||||
[:set {:element :text :font "Linux Libertine"}]
|
||||
|
||||
[:heading {:level 1} "My Paper"]
|
||||
|
||||
@@ -256,22 +329,23 @@ Second paragraph.
|
||||
|
||||
[:heading {:level 2} "Results"]
|
||||
|
||||
"See " [:ref :fig:results] " and " [:ref :tab:data] "."
|
||||
"See " [:ref {:target :fig/results}] " and " [:ref {:target :tab/data}] "."
|
||||
|
||||
[:figure {:caption "Results visualization" :label :fig:results}
|
||||
[:image {:width "80%"} "results.png"]]
|
||||
[:figure {:caption "Results visualization" :label :fig/results}
|
||||
[:image {:src "results.png" :width "80%"}]]
|
||||
|
||||
[:table {:columns 2 :label :tab:data}
|
||||
[:figure {:caption "Data table" :label :tab/data}
|
||||
[:table {:columns 2}
|
||||
[:strong "Input"] [:strong "Output"]
|
||||
"1" "1"
|
||||
"2" "4"
|
||||
"3" "9"]
|
||||
"3" "9"]]
|
||||
|
||||
"The equation is " [:$ "E = mc^2"] "."
|
||||
"The equation is " [:math "E = m c^2"] "."
|
||||
|
||||
[:$$ "integral_0^infinity e^(-x^2) dif x = sqrt(pi)/2"]
|
||||
[:math {:block true} "integral_0^infinity e^(-x^2) dif x = sqrt(pi)/2"]
|
||||
|
||||
[:bibliography "refs.bib"]])
|
||||
[:bibliography {:src "refs.bib"}]])
|
||||
```
|
||||
|
||||
**Compiles to:**
|
||||
@@ -303,28 +377,49 @@ See @fig:results and @tab:data.
|
||||
caption: [Results visualization],
|
||||
) <fig:results>
|
||||
|
||||
#table(
|
||||
#figure(
|
||||
table(
|
||||
columns: 2,
|
||||
[#strong[Input]], [#strong[Output]],
|
||||
[1], [1],
|
||||
[2], [4],
|
||||
[3], [9],
|
||||
),
|
||||
caption: [Data table],
|
||||
) <tab:data>
|
||||
|
||||
The equation is $E = mc^2$.
|
||||
The equation is $E = m c^2$.
|
||||
|
||||
$ integral_0^infinity e^(-x^2) dif x = sqrt(pi)/2 $
|
||||
|
||||
#bibliography("refs.bib")
|
||||
```
|
||||
|
||||
## Summary of Changes
|
||||
## Typst Gotchas
|
||||
|
||||
Important Typst behaviors the compiler must handle:
|
||||
|
||||
1. **Math variable spacing**: In math mode, adjacent letters like `mc` are parsed as a single variable name. To represent multiplication, add spaces: `$m c^2$` not `$mc^2$`. The compiler should insert spaces between single-letter variables.
|
||||
|
||||
2. **Referenceable tables**: Tables cannot have labels directly attached. To make a table referenceable with `@label`, wrap it in a `#figure()`:
|
||||
```typst
|
||||
#figure(
|
||||
table(...),
|
||||
caption: [...],
|
||||
) <label>
|
||||
```
|
||||
|
||||
3. **Font availability**: Fonts like "Linux Libertine" may not be installed. The compiler should either bundle fonts or use fallbacks.
|
||||
|
||||
## Summary of Design Decisions
|
||||
|
||||
1. **Removed**: `:p`, `:item`, `:cell`, `:div`, `:span`, `:aside`, `:section`, `:doc`
|
||||
2. **Lists/Tables**: Children are direct content, not wrapped in `:item`/`:cell`
|
||||
3. **Figures**: Caption is an attribute, not a child
|
||||
4. **Math**: Use `:$` for inline, `:$$` for block
|
||||
5. **Code**: Use `:raw` not `:code`
|
||||
3. **Figures**: Caption is an attribute; child element compiles as function argument (no `#`)
|
||||
4. **Math**: Use `:math` with optional `:block` attr (not `:$`/`:$$`)
|
||||
5. **Code**: Use `:raw` for displayed code; `#t"..."` for Typst passthrough
|
||||
6. **Space**: Use `:h`/`:v` not `:h-space`
|
||||
7. **Settings**: `:set` takes element type and attrs
|
||||
8. **Paragraphs**: Use `:parbreak` or just content flow
|
||||
7. **References**: Use `[:ref {:target :label}]` and `[:cite {:keys [...]}]`
|
||||
8. **Settings**: Use `[:set {:element :page ...}]` - attrs first with `:element`
|
||||
9. **Paragraphs**: Use `:parbreak` or just content flow
|
||||
10. **Referenceable tables**: Must wrap in `:figure` with `:label` attribute
|
||||
|
||||
Reference in New Issue
Block a user