summaryrefslogtreecommitdiff
path: root/tests/suite/styling
diff options
context:
space:
mode:
Diffstat (limited to 'tests/suite/styling')
-rw-r--r--tests/suite/styling/fold.typ19
-rw-r--r--tests/suite/styling/set.typ96
-rw-r--r--tests/suite/styling/show-set.typ70
-rw-r--r--tests/suite/styling/show-text.typ133
-rw-r--r--tests/suite/styling/show-where.typ89
-rw-r--r--tests/suite/styling/show.typ262
6 files changed, 669 insertions, 0 deletions
diff --git a/tests/suite/styling/fold.typ b/tests/suite/styling/fold.typ
new file mode 100644
index 00000000..26fe991b
--- /dev/null
+++ b/tests/suite/styling/fold.typ
@@ -0,0 +1,19 @@
+--- fold-vec-order-text-features ---
+// Test fold order of vectors.
+#set text(features: (liga: 1))
+#set text(features: (liga: 0))
+fi
+
+--- fold-vec-order-text-decos ---
+#underline(stroke: aqua + 4pt)[
+ #underline[Hello]
+]
+
+--- fold-vec-order-meta ---
+#let c = counter("mycounter")
+#c.update(1)
+#locate(loc => [
+ #c.update(2)
+ #c.at(loc) \
+ Second: #locate(loc => c.at(loc))
+])
diff --git a/tests/suite/styling/set.typ b/tests/suite/styling/set.typ
new file mode 100644
index 00000000..a31cd165
--- /dev/null
+++ b/tests/suite/styling/set.typ
@@ -0,0 +1,96 @@
+// General tests for set.
+
+--- set-instantiation-site ---
+// Test that text is affected by instantiation-site bold.
+#let x = [World]
+Hello *#x*
+
+--- set-instantiation-site-markup ---
+// Test that lists are affected by correct indents.
+#let fruit = [
+ - Apple
+ - Orange
+ #list(body-indent: 20pt)[Pear]
+]
+
+- Fruit
+#[#set list(indent: 10pt)
+ #fruit]
+- No more fruit
+
+--- set-text-override ---
+// Test that that block spacing and text style are respected from
+// the outside, but the more specific fill is respected.
+#set block(spacing: 4pt)
+#set text(style: "italic", fill: eastern)
+#let x = [And the forest #parbreak() lay silent!]
+#text(fill: forest, x)
+
+--- set-scoped-in-code-block ---
+// Test that scoping works as expected.
+#{
+ if true {
+ set text(blue)
+ [Blue ]
+ }
+ [Not blue]
+}
+
+--- closure-path-resolve-in-layout-phase ---
+// Test relative path resolving in layout phase.
+#let choice = ("monkey.svg", "rhino.png", "tiger.jpg")
+#set enum(numbering: n => {
+ let path = "/assets/images/" + choice.at(n - 1)
+ move(dy: -0.15em, image(path, width: 1em, height: 1em))
+})
+
++ Monkey
++ Rhino
++ Tiger
+
+--- set-if ---
+// Test conditional set.
+#show ref: it => {
+ set text(red) if it.target == <unknown>
+ "@" + str(it.target)
+}
+
+@hello from the @unknown
+
+--- set-if-bad-type ---
+// Error: 19-24 expected boolean, found integer
+#set text(red) if 1 + 2
+
+--- set-in-expr ---
+// Error: 12-26 set is only allowed directly in code and content blocks
+#{ let x = set text(blue) }
+
+--- set-vs-construct-1 ---
+// Ensure that constructor styles aren't passed down the tree.
+// The inner list should have no extra indent.
+#set par(leading: 2pt)
+#list(body-indent: 20pt, [First], list[A][B])
+
+--- set-vs-construct-2 ---
+// Ensure that constructor styles win, but not over outer styles.
+// The outer paragraph should be right-aligned,
+// but the B should be center-aligned.
+#set list(marker: [>])
+#list(marker: [--])[
+ #rect(width: 2cm, fill: conifer, inset: 4pt, list[A])
+]
+
+--- set-vs-construct-3 ---
+// The inner rectangle should also be yellow here.
+// (and therefore invisible)
+#[#set rect(fill: yellow);#text(1em, rect(inset: 5pt, rect()))]
+
+--- set-vs-construct-4 ---
+// The inner rectangle should not be yellow here.
+A #box(rect(fill: yellow, inset: 5pt, rect())) B
+
+--- show-set-vs-construct ---
+// The constructor property should still work
+// when there are recursive show rules.
+#show enum: set text(blue)
+#enum(numbering: "(a)", [A], enum[B])
diff --git a/tests/suite/styling/show-set.typ b/tests/suite/styling/show-set.typ
new file mode 100644
index 00000000..ea788c93
--- /dev/null
+++ b/tests/suite/styling/show-set.typ
@@ -0,0 +1,70 @@
+// Test show-set rules.
+
+--- show-set-override ---
+// Test overriding show-set rules.
+#show strong: set text(red)
+Hello *World*
+
+#show strong: set text(blue)
+Hello *World*
+
+--- show-set-on-same-element ---
+// Test show-set rule on the same element.
+#set figure(supplement: [Default])
+#show figure.where(kind: table): set figure(supplement: [Tableau])
+#figure(
+ table(columns: 2)[A][B][C][D],
+ caption: [Four letters],
+)
+
+--- show-set-same-element-and-order ---
+// Test both things at once.
+#show heading: set text(red)
+= Level 1
+== Level 2
+
+#show heading.where(level: 1): set text(blue)
+#show heading.where(level: 1): set text(green)
+#show heading.where(level: 1): set heading(numbering: "(I)")
+= Level 1
+== Level 2
+
+--- show-set-same-element-matched-field ---
+// Test setting the thing we just matched on.
+// This is quite cursed, but it works.
+#set heading(numbering: "(I)")
+#show heading.where(numbering: "(I)"): set heading(numbering: "1.")
+= Heading
+
+--- show-set-same-element-synthesized-matched-field ---
+// Same thing, but even more cursed, because `kind` is synthesized.
+#show figure.where(kind: table): set figure(kind: raw)
+#figure(table[A], caption: [Code])
+
+--- show-set-same-element-matching-interaction ---
+// Test that show-set rules on the same element don't affect each other. This
+// could be implemented, but isn't as of yet.
+#show heading.where(level: 1): set heading(numbering: "(I)")
+#show heading.where(numbering: "(I)"): set text(red)
+= Heading
+
+--- show-set-on-layoutable-element ---
+// Test show-set rules on layoutable element to ensure it is realized
+// even though it implements `LayoutMultiple`.
+#show table: set text(red)
+#pad(table(columns: 4)[A][B][C][D])
+
+--- show-function-order-with-set ---
+// These are both red because in the expanded form, `set text(red)` ends up
+// closer to the content than `set text(blue)`.
+#show strong: it => { set text(red); it }
+Hello *World*
+
+#show strong: it => { set text(blue); it }
+Hello *World*
+
+--- show-function-set-on-it ---
+// This doesn't have an effect. An element is materialized before any show
+// rules run.
+#show heading: it => { set heading(numbering: "(I)"); it }
+= Heading
diff --git a/tests/suite/styling/show-text.typ b/tests/suite/styling/show-text.typ
new file mode 100644
index 00000000..56b659b2
--- /dev/null
+++ b/tests/suite/styling/show-text.typ
@@ -0,0 +1,133 @@
+// Test text replacement show rules.
+
+--- show-text-basic ---
+// Test classic example.
+#set text(font: "Roboto")
+#show "Der Spiegel": smallcaps
+Die Zeitung Der Spiegel existiert.
+
+--- show-text-regex ---
+// Another classic example.
+#show "TeX": [T#h(-0.145em)#box(move(dy: 0.233em)[E])#h(-0.135em)X]
+#show regex("(Lua)?(La)?TeX"): name => box(text(font: "New Computer Modern")[#name])
+
+TeX, LaTeX, LuaTeX and LuaLaTeX!
+
+--- show-text-cyclic ---
+// Test direct cycle.
+#show "Hello": text(red)[Hello]
+Hello World!
+
+--- show-text-cyclic-raw ---
+// Test replacing text with raw text.
+#show "rax": `rax`
+The register rax.
+
+--- show-text-indirectly-cyclic ---
+// Test indirect cycle.
+#show "Good": [Typst!]
+#show "Typst": [Fun!]
+#show "Fun": [Good!]
+
+#set text(ligatures: false)
+Good \
+Fun \
+Typst \
+
+--- show-text-exactly-once ---
+// Test that replacements happen exactly once.
+#show "A": [BB]
+#show "B": [CC]
+AA (8)
+
+--- show-text-regex-word-boundary ---
+// Test caseless match and word boundaries.
+#show regex("(?i)\bworld\b"): [🌍]
+
+Treeworld, the World of worlds, is a world.
+
+--- show-text-empty ---
+// Test there is no crashing on empty strings
+// Error: 1:7-1:9 text selector is empty
+#show "": []
+
+--- show-text-regex-empty ---
+// Error: 1:7-1:16 regex selector is empty
+#show regex(""): [AA]
+
+--- show-text-regex-matches-empty ---
+// Error: 1:7-1:42 regex matches empty text
+#show regex("(VAR_GLOBAL|END_VAR||BOOL)") : []
+
+--- show-text-regex-character-class ---
+// This is a fun one.
+#set par(justify: true)
+#show regex("\S"): letter => box(stroke: 1pt, inset: 2pt, upper(letter))
+#lorem(5)
+
+--- show-text-regex-case-insensitive ---
+// See also: https://github.com/mTvare6/hello-world.rs
+#show regex("(?i)rust"): it => [#it (🚀)]
+Rust is memory-safe and blazingly fast. Let's rewrite everything in rust.
+
+--- show-text-get-text-on-it ---
+// Test accessing the string itself.
+#show "hello": it => it.text.split("").map(upper).join("|")
+Oh, hello there!
+
+--- show-text-in-other-show ---
+// Replace worlds but only in lists.
+#show list: it => [
+ #show "World": [🌎]
+ #it
+]
+
+World
+- World
+
+--- show-text-path-resolving ---
+// Test absolute path in layout phase.
+
+#show "GRAPH": image("/assets/images/graph.png")
+
+The GRAPH has nodes.
+
+--- show-set-text-order-adjacent-1 ---
+#show "He": set text(red)
+#show "ya": set text(blue)
+Heya
+
+--- show-set-text-order-contained-1 ---
+#show "Heya": set text(red)
+#show "ya": set text(blue)
+Heya
+
+--- show-set-text-order-contained-3 ---
+#show "He": set text(red)
+#show "Heya": set text(blue)
+Heya
+
+--- show-set-text-order-overlapping-1 ---
+#show "Heya": set text(red)
+#show "yaho": set text(blue)
+Heyaho
+
+--- show-set-text-order-adjacent-2 ---
+#show "He": set text(red)
+#show "ya": set text(weight: "bold")
+Heya
+
+--- show-set-text-order-contained-2 ---
+#show "Heya": set text(red)
+#show "ya": set text(weight: "bold")
+Heya
+
+--- show-set-text-order-contained-4 ---
+#show "He": set text(red)
+#show "Heya": set text(weight: "bold")
+Heya
+
+--- show-set-text-order-overlapping-2 ---
+#show "Heya": set text(red)
+#show "yaho": set text(weight: "bold")
+Heyaho
diff --git a/tests/suite/styling/show-where.typ b/tests/suite/styling/show-where.typ
new file mode 100644
index 00000000..72dbae69
--- /dev/null
+++ b/tests/suite/styling/show-where.typ
@@ -0,0 +1,89 @@
+--- show-where-optional-field-raw ---
+// Test that where selectors also trigger on set rule fields.
+#show raw.where(block: false): box.with(
+ fill: luma(220),
+ inset: (x: 3pt, y: 0pt),
+ outset: (y: 3pt),
+ radius: 2pt,
+)
+
+This is #raw("fn main() {}") some text.
+
+--- show-where-optional-field-text ---
+// Note: This show rule is horribly inefficient because it triggers for
+// every individual text element. But it should still work.
+#show text.where(lang: "de"): set text(red)
+
+#set text(lang: "es")
+Hola, mundo!
+
+#set text(lang: "de")
+Hallo Welt!
+
+#set text(lang: "en")
+Hello World!
+
+--- show-where-folding-text-size ---
+// Test that folding is taken into account.
+#set text(5pt)
+#set text(2em)
+
+#[
+ #show text.where(size: 2em): set text(blue)
+ 2em not blue
+]
+
+#[
+ #show text.where(size: 10pt): set text(blue)
+ 10pt blue
+]
+
+--- show-where-folding-stroke ---
+// Test again that folding is taken into account.
+#set rect(width: 40pt, height: 10pt)
+#set rect(stroke: blue)
+#set rect(stroke: 2pt)
+
+#{
+ show rect.where(stroke: blue): "Not Triggered"
+ rect()
+}
+#{
+ show rect.where(stroke: 2pt): "Not Triggered"
+ rect()
+}
+#{
+ show rect.where(stroke: 2pt + blue): "Triggered"
+ rect()
+}
+
+--- show-where-resolving-length ---
+// Test that resolving is *not* taken into account.
+#set line(start: (1em, 1em + 2pt))
+
+#{
+ show line.where(start: (1em, 1em + 2pt)): "Triggered"
+ line()
+}
+#{
+ show line.where(start: (10pt, 12pt)): "Not Triggered"
+ line()
+}
+
+
+--- show-where-resolving-hyphenate ---
+// Test again that resolving is *not* taken into account.
+#set text(hyphenate: auto)
+
+#[
+ #show text.where(hyphenate: auto): underline
+ Auto
+]
+#[
+ #show text.where(hyphenate: true): underline
+ True
+]
+#[
+ #show text.where(hyphenate: false): underline
+ False
+]
diff --git a/tests/suite/styling/show.typ b/tests/suite/styling/show.typ
new file mode 100644
index 00000000..aa121bff
--- /dev/null
+++ b/tests/suite/styling/show.typ
@@ -0,0 +1,262 @@
+// Test show rules.
+
+--- show-selector-basic ---
+// Override lists.
+#show list: it => "(" + it.children.map(v => v.body).join(", ") + ")"
+
+- A
+ - B
+ - C
+- D
+- E
+
+--- show-selector-replace-and-show-set ---
+// Test full reset.
+#show heading: [B]
+#show heading: set text(size: 10pt, weight: 400)
+A #[= Heading] C
+
+--- show-selector-discard ---
+// Test full removal.
+#show heading: none
+
+Where is
+= There are no headings around here!
+my heading?
+
+--- show-selector-realistic ---
+// Test integrated example.
+#show heading: it => block({
+ set text(10pt)
+ box(move(dy: -1pt)[📖])
+ h(5pt)
+ if it.level == 1 {
+ underline(text(1.25em, blue, it.body))
+ } else {
+ text(red, it.body)
+ }
+})
+
+= Task 1
+Some text.
+
+== Subtask
+Some more text.
+
+= Task 2
+Another text.
+
+--- show-in-show ---
+// Test set and show in code blocks.
+#show heading: it => {
+ set text(red)
+ show "ding": [🛎]
+ it.body
+}
+
+= Heading
+
+--- show-nested-scopes ---
+// Test that scoping works as expected.
+#{
+ let world = [ World ]
+ show "W": strong
+ world
+ {
+ set text(blue)
+ show: it => {
+ show "o": "Ø"
+ it
+ }
+ world
+ }
+ world
+}
+
+--- show-selector-replace ---
+#show heading: [1234]
+= Heading
+
+--- show-unknown-field ---
+// Error: 25-29 content does not contain field "page"
+#show heading: it => it.page
+= Heading
+
+--- show-text-element-discard ---
+#show text: none
+Hey
+
+--- show-selector-not-an-element-function ---
+// Error: 7-12 only element functions can be used as selectors
+#show upper: it => {}
+
+--- show-bad-replacement-type ---
+// Error: 16-20 expected content or function, found integer
+#show heading: 1234
+= Heading
+
+--- show-bad-selector-type ---
+// Error: 7-10 expected symbol, string, label, function, regex, or selector, found color
+#show red: []
+
+--- show-selector-in-expression ---
+// Error: 7-25 show is only allowed directly in code and content blocks
+#(1 + show heading: none)
+
+--- show-bare-basic ---
+#set page(height: 130pt)
+#set text(0.7em)
+
+#align(center)[
+ #text(1.3em)[*Essay on typography*] \
+ T. Ypst
+]
+
+#show: columns.with(2)
+Great typography is at the essence of great storytelling. It is the medium that
+transports meaning from parchment to reader, the wave that sparks a flame
+in booklovers and the great fulfiller of human need.
+
+--- show-bare-content-block ---
+// Test bare show in content block.
+A #[_B #show: c => [*#c*]; C_] D
+
+--- show-bare-vs-set-text ---
+// Test style precedence.
+#set text(fill: eastern, size: 1.5em)
+#show: text.with(fill: forest)
+Forest
+
+--- show-bare-replace-with-content ---
+#show: [Shown]
+Ignored
+
+--- show-bare-in-expression ---
+// Error: 4-19 show is only allowed directly in code and content blocks
+#((show: body => 2) * body)
+
+--- show-bare-missing-colon-closure ---
+// Error: 6 expected colon
+#show it => {}
+
+--- show-bare-missing-colon ---
+// Error: 6 expected colon
+#show it
+
+--- show-recursive-identity ---
+// Test basic identity.
+#show heading: it => it
+= Heading
+
+--- show-multiple-rules ---
+// Test more recipes down the chain.
+#show list: scale.with(origin: left, x: 80%)
+#show heading: []
+#show enum: []
+- Actual
+- Tight
+- List
+= Nope
+
+--- show-rule-in-function ---
+// Test show rule in function.
+#let starwars(body) = {
+ show list: it => block({
+ stack(dir: ltr,
+ text(red, it),
+ 1fr,
+ scale(x: -100%, text(blue, it)),
+ )
+ })
+ body
+}
+
+- Normal list
+
+#starwars[
+ - Star
+ - Wars
+ - List
+]
+
+- Normal list
+
+--- show-recursive-multiple ---
+// Test multi-recursion with nested lists.
+#set rect(inset: 3pt)
+#show list: rect.with(stroke: blue)
+#show list: rect.with(stroke: red)
+#show list: block
+
+- List
+ - Nested
+ - List
+- Recursive!
+
+--- show-selector-where ---
+// Inline code.
+#show raw.where(block: false): box.with(
+ radius: 2pt,
+ outset: (y: 2.5pt),
+ inset: (x: 3pt, y: 0pt),
+ fill: luma(230),
+)
+
+// Code blocks.
+#show raw.where(block: true): block.with(
+ outset: -3pt,
+ inset: 11pt,
+ fill: luma(230),
+ stroke: (left: 1.5pt + luma(180)),
+)
+
+#set page(margin: (top: 12pt))
+#set par(justify: true)
+
+This code tests `code`
+with selectors and justification.
+
+```rs
+code!("it");
+```
+
+You can use the ```rs *const T``` pointer or
+the ```rs &mut T``` reference.
+
+--- show-set-where-override ---
+#show heading: set text(green)
+#show heading.where(level: 1): set text(red)
+#show heading.where(level: 2): set text(blue)
+= Red
+== Blue
+=== Green
+
+--- show-selector-or-elements-with-set ---
+// Looking forward to `heading.where(level: 1 | 2)` :)
+#show heading.where(level: 1).or(heading.where(level: 2)): set text(red)
+= L1
+== L2
+=== L3
+==== L4
+
+--- show-selector-element-or-label ---
+// Test element selector combined with label selector.
+#show selector(strong).or(<special>): highlight
+I am *strong*, I am _emphasized_, and I am #[special<special>].
+
+--- show-selector-element-or-text ---
+// Ensure that text selector cannot be nested in and/or. That's too complicated,
+// at least for now.
+
+// Error: 7-41 this selector cannot be used with show
+#show heading.where(level: 1).or("more"): set text(red)
+
+--- show-delayed-error ---
+// Error: 21-34 panicked with: "hey1"
+#show heading: _ => panic("hey1")
+
+// Error: 20-33 panicked with: "hey2"
+#show strong: _ => panic("hey2")
+
+= Hello
+*strong*