diff options
| author | Laurenz <laurmaedje@gmail.com> | 2024-04-13 10:39:45 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-13 08:39:45 +0000 |
| commit | 020294fca9a7065d4b9cf4e677f606ebaaa29b00 (patch) | |
| tree | c0027ad22046e2726c22298461327823d6b88d53 /tests/typ/compiler | |
| parent | 72dd79210602ecc799726fc096b078afbb47f299 (diff) | |
Better test runner (#3922)
Diffstat (limited to 'tests/typ/compiler')
59 files changed, 0 insertions, 5489 deletions
diff --git a/tests/typ/compiler/array.typ b/tests/typ/compiler/array.typ deleted file mode 100644 index 597f242c..00000000 --- a/tests/typ/compiler/array.typ +++ /dev/null @@ -1,392 +0,0 @@ -// Test arrays. -// Ref: false - ---- -// Ref: true - -#set page(width: 150pt) - -// Empty. -#() - -// Not an array, just a parenthesized expression. -#(1) - -// One item and trailing comma. -#(-1,) - -// No trailing comma. -#(true, false) - -// Multiple lines and items and trailing comma. -#("1" - , rgb("002") - ,) - ---- -// Test the `len` method. -#test(().len(), 0) -#test(("A", "B", "C").len(), 3) - ---- -// Test lvalue and rvalue access. -#{ - let array = (1, 2) - array.at(1) += 5 + array.at(0) - test(array, (1, 8)) -} - ---- -// Test different lvalue method. -#{ - let array = (1, 2, 3) - array.first() = 7 - array.at(1) *= 8 - test(array, (7, 16, 3)) -} - ---- -// Test rvalue out of bounds. -// Error: 2-17 array index out of bounds (index: 5, len: 3) and no default value was specified -#(1, 2, 3).at(5) - ---- -// Test lvalue out of bounds. -#{ - let array = (1, 2, 3) - // Error: 3-14 array index out of bounds (index: 3, len: 3) - array.at(3) = 5 -} - ---- -// Test default value. -#test((1, 2, 3).at(2, default: 5), 3) -#test((1, 2, 3).at(3, default: 5), 5) - ---- -// Test remove with default value. - -#{ - let array = (1, 2, 3) - test(array.remove(2, default: 5), 3) -} - -#{ - let array = (1, 2, 3) - test(array.remove(3, default: 5), 5) -} - ---- -// Test bad lvalue. -// Error: 2:3-2:14 cannot mutate a temporary value -#let array = (1, 2, 3) -#(array.len() = 4) - ---- -// Test bad lvalue. -// Error: 2:9-2:13 type array has no method `yolo` -#let array = (1, 2, 3) -#(array.yolo() = 4) - ---- -// Test negative indices. -#{ - let array = (1, 2, 3, 4) - test(array.at(0), 1) - test(array.at(-1), 4) - test(array.at(-2), 3) - test(array.at(-3), 2) - test(array.at(-4), 1) -} - ---- -// The the `first` and `last` methods. -#test((1,).first(), 1) -#test((2,).last(), 2) -#test((1, 2, 3).first(), 1) -#test((1, 2, 3).last(), 3) - ---- -// Error: 2-12 array is empty -#().first() - ---- -// Error: 2-11 array is empty -#().last() - ---- -// Test the `push` and `pop` methods. -#{ - let tasks = (a: (1, 2, 3), b: (4, 5, 6)) - test(tasks.at("a").pop(), 3) - tasks.b.push(7) - test(tasks.a, (1, 2)) - test(tasks.at("b"), (4, 5, 6, 7)) -} - ---- -// Test the `insert` and `remove` methods. -#{ - let array = (0, 1, 2, 4, 5) - array.insert(3, 3) - test(array, range(6)) - array.remove(1) - test(array, (0, 2, 3, 4, 5)) -} - ---- -// Error: 2:2-2:18 missing argument: index -#let numbers = () -#numbers.insert() - ---- -// Test the `slice` method. -#test((1, 2, 3, 4).slice(2), (3, 4)) -#test(range(10).slice(2, 6), (2, 3, 4, 5)) -#test(range(10).slice(4, count: 3), (4, 5, 6)) -#test(range(10).slice(-5, count: 2), (5, 6)) -#test((1, 2, 3).slice(2, -2), ()) -#test((1, 2, 3).slice(-2, 2), (2,)) -#test((1, 2, 3).slice(-3, 2), (1, 2)) -#test("ABCD".split("").slice(1, -1).join("-"), "A-B-C-D") - ---- -// Error: 2-30 array index out of bounds (index: 12, len: 10) -#range(10).slice(9, count: 3) - ---- -// Error: 2-24 array index out of bounds (index: -4, len: 3) -#(1, 2, 3).slice(0, -4) - ---- -// Test the `position` method. -#test(("Hi", "β€οΈ", "Love").position(s => s == "β€οΈ"), 1) -#test(("Bye", "π", "Apart").position(s => s == "β€οΈ"), none) -#test(("A", "B", "CDEF", "G").position(v => v.len() > 2), 2) - ---- -// Test the `filter` method. -#test(().filter(calc.even), ()) -#test((1, 2, 3, 4).filter(calc.even), (2, 4)) -#test((7, 3, 2, 5, 1).filter(x => x < 5), (3, 2, 1)) - ---- -// Test the `map` method. -#test(().map(x => x * 2), ()) -#test((2, 3).map(x => x * 2), (4, 6)) - ---- -// Test the `fold` method. -#test(().fold("hi", grid), "hi") -#test((1, 2, 3, 4).fold(0, (s, x) => s + x), 10) - ---- -// Error: 20-22 unexpected argument -#(1, 2, 3).fold(0, () => none) - ---- -// Test the `sum` method. -#test(().sum(default: 0), 0) -#test(().sum(default: []), []) -#test((1, 2, 3).sum(), 6) - ---- -// Error: 2-10 cannot calculate sum of empty array with no default -#().sum() - ---- -// Test the `product` method. -#test(().product(default: 0), 0) -#test(().product(default: []), []) -#test(([ab], 3).product(), [ab]*3) -#test((1, 2, 3).product(), 6) - ---- -// Error: 2-14 cannot calculate product of empty array with no default -#().product() - ---- -// Test the `rev` method. -#test(range(3).rev(), (2, 1, 0)) - ---- -// Test the `join` method. -#test(().join(), none) -#test((1,).join(), 1) -#test(("a", "b", "c").join(), "abc") -#test("(" + ("a", "b", "c").join(", ") + ")", "(a, b, c)") - ---- -// Error: 2-22 cannot join boolean with boolean -#(true, false).join() - ---- -// Error: 2-20 cannot join string with integer -#("a", "b").join(1) - ---- -// Test joining content. -// Ref: true -#([One], [Two], [Three]).join([, ], last: [ and ]). - ---- -// Test the `intersperse` method -#test(().intersperse("a"), ()) -#test((1,).intersperse("a"), (1,)) -#test((1, 2).intersperse("a"), (1, "a", 2)) -#test((1, 2, "b").intersperse("a"), (1, "a", 2, "a", "b")) - ---- -// Test the `chunks` method. -#test(().chunks(10), ()) -#test((1, 2, 3).chunks(10), ((1, 2, 3),)) -#test((1, 2, 3, 4, 5, 6).chunks(3), ((1, 2, 3), (4, 5, 6))) -#test((1, 2, 3, 4, 5, 6, 7, 8).chunks(3), ((1, 2, 3), (4, 5, 6), (7, 8))) - -#test(().chunks(10, exact: true), ()) -#test((1, 2, 3).chunks(10, exact: true), ()) -#test((1, 2, 3, 4, 5, 6).chunks(3, exact: true), ((1, 2, 3), (4, 5, 6))) -#test((1, 2, 3, 4, 5, 6, 7, 8).chunks(3, exact: true), ((1, 2, 3), (4, 5, 6))) - ---- -// Error: 19-20 number must be positive -#(1, 2, 3).chunks(0) - ---- -// Error: 19-21 number must be positive -#(1, 2, 3).chunks(-5) - ---- -// Test the `sorted` method. -#test(().sorted(), ()) -#test(().sorted(key: x => x), ()) -#test(((true, false) * 10).sorted(), (false,) * 10 + (true,) * 10) -#test(("it", "the", "hi", "text").sorted(), ("hi", "it", "text", "the")) -#test(("I", "the", "hi", "text").sorted(key: x => x), ("I", "hi", "text", "the")) -#test(("I", "the", "hi", "text").sorted(key: x => x.len()), ("I", "hi", "the", "text")) -#test((2, 1, 3, 10, 5, 8, 6, -7, 2).sorted(), (-7, 1, 2, 2, 3, 5, 6, 8, 10)) -#test((2, 1, 3, -10, -5, 8, 6, -7, 2).sorted(key: x => x), (-10, -7, -5, 1, 2, 2, 3, 6, 8)) -#test((2, 1, 3, -10, -5, 8, 6, -7, 2).sorted(key: x => x * x), (1, 2, 2, 3, -5, 6, -7, 8, -10)) - ---- -// Error: 12-18 unexpected argument -#().sorted(x => x) - ---- -// Test the `zip` method. -#test(().zip(()), ()) -#test((1,).zip(()), ()) -#test((1,).zip((2,)), ((1, 2),)) -#test((1, 2).zip((3, 4)), ((1, 3), (2, 4))) -#test((1, 2, 3, 4).zip((5, 6)), ((1, 5), (2, 6))) -#test(((1, 2), 3).zip((4, 5)), (((1, 2), 4), (3, 5))) -#test((1, "hi").zip((true, false)), ((1, true), ("hi", false))) -#test((1, 2, 3).zip((3, 4, 5), (6, 7, 8)), ((1, 3, 6), (2, 4, 7), (3, 5, 8))) -#test(().zip((), ()), ()) -#test((1,).zip((2,), (3,)), ((1, 2, 3),)) -#test((1, 2, 3).zip(), ((1,), (2,), (3,))) -#test(array.zip(()), ()) - - ---- -// Test the `enumerate` method. -#test(().enumerate(), ()) -#test(().enumerate(start: 5), ()) -#test(("a", "b", "c").enumerate(), ((0, "a"), (1, "b"), (2, "c"))) -#test(("a", "b", "c").enumerate(start: 1), ((1, "a"), (2, "b"), (3, "c"))) -#test(("a", "b", "c").enumerate(start: 42), ((42, "a"), (43, "b"), (44, "c"))) -#test(("a", "b", "c").enumerate(start: -7), ((-7, "a"), (-6, "b"), (-5, "c"))) - ---- -// Test the `dedup` method. -#test(().dedup(), ()) -#test((1,).dedup(), (1,)) -#test((1, 1).dedup(), (1,)) -#test((1, 2, 1).dedup(), (1, 2)) -#test(("Jane", "John", "Eric").dedup(), ("Jane", "John", "Eric")) -#test(("Jane", "John", "Eric", "John").dedup(), ("Jane", "John", "Eric")) - ---- -// Test the `dedup` method with the `key` argument. -#test((1, 2, 3, 4, 5, 6).dedup(key: x => calc.rem(x, 2)), (1, 2)) -#test((1, 2, 3, 4, 5, 6).dedup(key: x => calc.rem(x, 3)), (1, 2, 3)) -#test(("Hello", "World", "Hi", "There").dedup(key: x => x.len()), ("Hello", "Hi")) -#test(("Hello", "World", "Hi", "There").dedup(key: x => x.at(0)), ("Hello", "World", "There")) - ---- -// Test the `to-dict` method. -#test(().to-dict(), (:)) -#test((("a", 1), ("b", 2), ("c", 3)).to-dict(), (a: 1, b: 2, c: 3)) -#test((("a", 1), ("b", 2), ("c", 3), ("b", 4)).to-dict(), (a: 1, b: 4, c: 3)) - ---- -// Error: 2-16 expected (str, any) pairs, found integer -#(1,).to-dict() - ---- -// Error: 2-19 expected pairs of length 2, found length 1 -#((1,),).to-dict() - ---- -// Error: 2-26 expected pairs of length 2, found length 3 -#(("key",1,2),).to-dict() - ---- -// Error: 2-21 expected key of type str, found integer -#((1, 2),).to-dict() - ---- -// Error: 9-26 unexpected argument: val -#().zip(val: "applicable") - ---- -// Error: 13-30 unexpected argument: val -#().zip((), val: "applicable") - ---- -// Error: 32-37 cannot divide by zero -#(1, 2, 0, 3).sorted(key: x => 5 / x) - ---- -// Error: 2-26 cannot compare content and content -#([Hi], [There]).sorted() - ---- -// Error: 2-26 cannot compare 3em with 2pt -#(1pt, 2pt, 3em).sorted() - ---- -// Error: 42-52 unexpected argument -#((k: "a", v: 2), (k: "b", v: 1)).sorted(it => it.v) - ---- -// Error: 2-18 array index out of bounds (index: -4, len: 3) and no default value was specified -#(1, 2, 3).at(-4) - ---- -// Error: 3-4 unclosed delimiter -#{(} - -// Error: 2-3 unclosed delimiter -#{)} - -// Error: 4-6 unexpected end of block comment -#(1*/2) - -// Error: 6-8 invalid number suffix: u -#(1, 1u 2) - -// Error: 3-4 unexpected comma -#(,1) - -// Missing expression makes named pair incomplete, making this an empty array. -// Error: 5 expected expression -#(a:) - -// Named pair after this is already identified as an array. -// Error: 6-10 expected expression, found named pair -#(1, b: 2) - -// Keyed pair after this is already identified as an array. -// Error: 6-14 expected expression, found keyed pair -#(1, "key": 2) diff --git a/tests/typ/compiler/backtracking.typ b/tests/typ/compiler/backtracking.typ deleted file mode 100644 index 9c3ab8ec..00000000 --- a/tests/typ/compiler/backtracking.typ +++ /dev/null @@ -1,33 +0,0 @@ -// Ensure that parser backtracking doesn't lead to exponential time consumption. -// If this regresses, the test suite will not terminate, which is a bit -// unfortunate compared to a good error, but at least we know something is up. -// -// Ref: false - ---- -#{ - let s = "(x: 1) => x" - let pat = "(x: {}) => 1 + x()" - for _ in range(50) { - s = pat.replace("{}", s) - } - test(eval(s)(), 51) -} - ---- -#{ - let s = "(x) = 1" - let pat = "(x: {_}) = 1" - for _ in range(100) { - s = pat.replace("_", s) - } - // Error: 8-9 cannot destructure integer - eval(s) -} - ---- -// Test whitespace after memoized part. -#( (x: () => 1 ) => 1 ) -// ------- -// This is memoized and we want to ensure that whitespace after this -// is handled correctly. diff --git a/tests/typ/compiler/block.typ b/tests/typ/compiler/block.typ deleted file mode 100644 index 48c9fefc..00000000 --- a/tests/typ/compiler/block.typ +++ /dev/null @@ -1,145 +0,0 @@ -// Test code blocks. -// Ref: false - ---- -// Ref: true - -// Evaluates to join of none, [My ] and the two loop bodies. -#{ - let parts = ("my fri", "end.") - [Hello, ] - for s in parts [#s] -} - -// Evaluates to join of the content and strings. -#{ - [How] - if true { - " are" - } - [ ] - if false [Nope] - [you] + "?" -} - ---- -// Nothing evaluates to none. -#test({}, none) - -// Let evaluates to none. -#test({ let v = 0 }, none) - -// Evaluates to single expression. -#test({ "hello" }, "hello") - -// Evaluates to string. -#test({ let x = "m"; x + "y" }, "my") - -// Evaluated to int. -#test({ - let x = 1 - let y = 2 - x + y -}, 3) - -// String is joined with trailing none, evaluates to string. -#test({ - type("") - none -}, str) - ---- -// Some things can't be joined. -#{ - [A] - // Error: 3-4 cannot join content with integer - 1 - [B] -} - ---- -// Block directly in markup also creates a scope. -#{ let x = 1 } - -// Error: 7-8 unknown variable: x -#test(x, 1) - ---- -// Block in expression does create a scope. -#let a = { - let b = 1 - b -} - -#test(a, 1) - -// Error: 3-4 unknown variable: b -#{b} - ---- -// Double block creates a scope. -#{{ - import "module.typ": b - test(b, 1) -}} - -// Error: 2-3 unknown variable: b -#b - ---- -// Multiple nested scopes. -#{ - let a = "a1" - { - let a = "a2" - { - test(a, "a2") - let a = "a3" - test(a, "a3") - } - test(a, "a2") - } - test(a, "a1") -} - ---- -// Content blocks also create a scope. -#[#let x = 1] - -// Error: 2-3 unknown variable: x -#x - ---- -// Multiple unseparated expressions in one line. - -// Error: 2-4 invalid number suffix: u -#1u - -// Should output `1`. -// Error: 4 expected semicolon or line break -#{1 2} - -// Should output `2`. -// Error: 13 expected semicolon or line break -// Error: 23 expected semicolon or line break -#{let x = -1 let y = 3 x + y} - -// Should output `3`. -#{ - // Error: 7-10 expected pattern, found string - for "v" - - // Error: 8 expected keyword `in` - // Error: 22 expected block - for v let z = 1 + 2 - - z -} - ---- -// Error: 2-3 unclosed delimiter -#{ - ---- -// Error: 2-3 unexpected closing brace -#} diff --git a/tests/typ/compiler/break-continue.typ b/tests/typ/compiler/break-continue.typ deleted file mode 100644 index 4c4738bb..00000000 --- a/tests/typ/compiler/break-continue.typ +++ /dev/null @@ -1,162 +0,0 @@ -// Test break and continue in loops. -// Ref: false - ---- -// Test break. - -#let var = 0 -#let error = false - -#for i in range(10) { - var += i - if i > 5 { - break - error = true - } -} - -#test(var, 21) -#test(error, false) - ---- -// Test joining with break. - -#let i = 0 -#let x = while true { - i += 1 - str(i) - if i >= 5 { - "." - break - } -} - -#test(x, "12345.") - ---- -// Test continue. - -#let i = 0 -#let x = 0 - -#while x < 8 { - i += 1 - if calc.rem(i, 3) == 0 { - continue - } - x += i -} - -// If continue did not work, this would equal 10. -#test(x, 12) - ---- -// Test joining with continue. - -#let x = for i in range(5) { - "a" - if calc.rem(i, 3) == 0 { - "_" - continue - } - str(i) -} - -#test(x, "a_a1a2a_a4") - ---- -// Test break outside of loop. -#let f() = { - // Error: 3-8 cannot break outside of loop - break -} - -#for i in range(1) { - f() -} - ---- -// Test break in function call. -#let identity(x) = x -#let out = for i in range(5) { - "A" - identity({ - "B" - break - }) - "C" -} - -#test(out, "AB") - ---- -// Test continue outside of loop. - -// Error: 12-20 cannot continue outside of loop -#let x = { continue } - ---- -// Error: 2-10 cannot continue outside of loop -#continue - ---- -// Ref: true -// Should output `Hello World π`. -#for _ in range(10) { - [Hello ] - [World #{ - [π] - break - }] -} - ---- -// Ref: true -// Should output `Some` in red, `Some` in blue and `Last` in green. -// Everything should be in smallcaps. -#for color in (red, blue, green, yellow) [ - #set text(font: "Roboto") - #show: it => text(fill: color, it) - #smallcaps(if color != green [ - Some - ] else [ - Last - #break - ]) -] - ---- -// Ref: true -// Test break in set rule. -// Should output `Hi` in blue. -#for i in range(10) { - [Hello] - set text(blue, ..break) - [Not happening] -} - ---- -// Test second block during break flow. -// Ref: true - -#for i in range(10) { - table( - { [A]; break }, - for _ in range(3) [B] - ) -} - ---- -// Ref: true -// Test continue while destructuring. -// Should output "one = I \ two = II \ one = I". -#for num in (1, 2, 3, 1) { - let (word, roman) = if num == 1 { - ("one", "I") - } else if num == 2 { - ("two", "II") - } else { - continue - } - [#word = #roman \ ] -} diff --git a/tests/typ/compiler/bytes.typ b/tests/typ/compiler/bytes.typ deleted file mode 100644 index a9249bdd..00000000 --- a/tests/typ/compiler/bytes.typ +++ /dev/null @@ -1,32 +0,0 @@ -// Test the bytes type. -// Ref: false - ---- -#let data = read("/assets/images/rhino.png", encoding: none) -#test(data.len(), 232243) -#test(data.slice(0, count: 5), bytes((137, 80, 78, 71, 13))) -#test(str(data.slice(1, 4)), "PNG") -#test(repr(data), "bytes(232243)") - ---- -#test(str(bytes(range(0x41, 0x50))), "ABCDEFGHIJKLMNO") -#test(array(bytes("Hello")), (0x48, 0x65, 0x6C, 0x6C, 0x6F)) - ---- -// Test addition and joining. -#test(bytes((1, 2)) + bytes(()), bytes((1, 2))) -#test(bytes((1, 2)) + bytes((3, 4)), bytes((1, 2, 3, 4))) -#test(bytes(()) + bytes((3, 4)), bytes((3, 4))) -#test(str({ - bytes("Hello") - bytes((0x20,)) - bytes("World") -}), "Hello World") - ---- -// Error: 8-14 expected string, array, or bytes, found dictionary -#bytes((a: 1)) - ---- -// Error: 8-15 expected array, bytes, or version, found string -#array("hello") diff --git a/tests/typ/compiler/call.typ b/tests/typ/compiler/call.typ deleted file mode 100644 index 0c225a1c..00000000 --- a/tests/typ/compiler/call.typ +++ /dev/null @@ -1,111 +0,0 @@ -// Test function calls. -// Ref: false - ---- -// Ref: true - -// Omitted space. -#let f() = {} -#[#f()*Bold*] - -// Call return value of function with body. -#let f(x, body) = (y) => [#x] + body + [#y] -#f(1)[2](3) - -// Don't parse this as a function. -#test (it) - -#let f(body) = body -#f[A] -#f()[A] -#f([A]) - -#let g(a, b) = a + b -#g[A][B] -#g([A], [B]) -#g()[A][B] - ---- -// Trailing comma. -#test(1 + 1, 2,) - -// Call function assigned to variable. -#let alias = type -#test(alias(alias), type) - -// Callee expressions. -#{ - // Wrapped in parens. - test((type)("hi"), str) - - // Call the return value of a function. - let adder(dx) = x => x + dx - test(adder(2)(5), 7) -} - ---- -// Error: 26-30 duplicate argument: font -#set text(font: "Arial", font: "Helvetica") - ---- -// Error: 4-15 the argument `amount` is positional -// Hint: 4-15 try removing `amount:` -#h(amount: 0.5) - ---- -// Error: 2-6 expected function, found boolean -#true() - ---- -#let x = "x" - -// Error: 2-3 expected function, found string -#x() - ---- -#let f(x) = x - -// Error: 2-6 expected function, found integer -#f(1)(2) - ---- -#let f(x) = x - -// Error: 2-6 expected function, found content -#f[1](2) - ---- -// Error: 7-8 unexpected colon -#func(:) - -// Error: 10-12 unexpected end of block comment -#func(a:1*/) - -// Error: 8 expected comma -#func(1 2) - -// Error: 7-8 expected identifier, found integer -// Error: 9 expected expression -#func(1:) - -// Error: 7-8 expected identifier, found integer -#func(1:2) - -// Error: 7-12 expected identifier, found string -#func("abc": 2) - -// Error: 7-10 expected identifier, found group -#func((x):1) - ---- -// Error: 6-7 unclosed delimiter -#func[`a]` - ---- -// Error: 7-8 unclosed delimiter -#{func(} - ---- -// Error: 6-7 unclosed delimiter -// Error: 1:7-2:1 unclosed string -#func("] diff --git a/tests/typ/compiler/closure.typ b/tests/typ/compiler/closure.typ deleted file mode 100644 index 29c092b7..00000000 --- a/tests/typ/compiler/closure.typ +++ /dev/null @@ -1,219 +0,0 @@ -// Test closures. -// Ref: false - ---- -// Don't parse closure directly in content. -// Ref: true - -#let x = "x" - -// Should output `x => y`. -#x => y - ---- -// Basic closure without captures. -#{ - let adder = (x, y) => x + y - test(adder(2, 3), 5) -} - ---- -// Pass closure as argument and return closure. -// Also uses shorthand syntax for a single argument. -#{ - let chain = (f, g) => (x) => f(g(x)) - let f = x => x + 1 - let g = x => 2 * x - let h = chain(f, g) - test(h(2), 5) -} - ---- -// Capture environment. -#{ - let mark = "!" - let greet = { - let hi = "Hi" - name => { - hi + ", " + name + mark - } - } - - test(greet("Typst"), "Hi, Typst!") - - // Changing the captured variable after the closure definition has no effect. - mark = "?" - test(greet("Typst"), "Hi, Typst!") -} - ---- -// Redefined variable. -#{ - let x = 1 - let f() = { - let x = x + 2 - x - } - test(f(), 3) -} - ---- -// Import bindings. -#{ - let b = "module.typ" - let f() = { - import b: b - b - } - test(f(), 1) -} - ---- -// For loop bindings. -#{ - let v = (1, 2, 3) - let f() = { - let s = 0 - for v in v { s += v } - s - } - test(f(), 6) -} - ---- -// Let + closure bindings. -#{ - let g = "hi" - let f() = { - let g() = "bye" - g() - } - test(f(), "bye") -} - ---- -// Parameter bindings. -#{ - let x = 5 - let g() = { - let f(x, y: x) = x + y - f - } - - test(g()(8), 13) -} - ---- -// Don't leak environment. -#{ - // Error: 16-17 unknown variable: x - let func() = x - let x = "hi" - func() -} - ---- -// Too few arguments. -#{ - let types(x, y) = "[" + str(type(x)) + ", " + str(type(y)) + "]" - test(types(14%, 12pt), "[ratio, length]") - - // Error: 8-21 missing argument: y - test(types("nope"), "[string, none]") -} - ---- -// Too many arguments. -#{ - let f(x) = x + 1 - - // Error: 8-13 unexpected argument - f(1, "two", () => x) -} - ---- -// Mutable method with capture in argument. -#let x = "b" -#let f() = { - let a = (b: 5) - a.at(x) = 10 - a -} -#f() - ---- -#let x = () -#let f() = { - // Error: 3-4 variables from outside the function are read-only and cannot be modified - x.at(1) = 2 -} -#f() - ---- -// Named arguments. -#{ - let greet(name, birthday: false) = { - if birthday { "Happy Birthday, " } else { "Hey, " } + name + "!" - } - - test(greet("Typst"), "Hey, Typst!") - test(greet("Typst", birthday: true), "Happy Birthday, Typst!") - - // Error: 23-35 unexpected argument: whatever - test(greet("Typst", whatever: 10)) -} - ---- -// Parameter unpacking. -#let f((a, b), ..c) = (a, b, c) -#test(f((1, 2), 3, 4), (1, 2, (3, 4))) - -#let f((k: a, b), c: 3, (d,)) = (a, b, c, d) -#test(f((k: 1, b: 2), (4,)), (1, 2, 3, 4)) - -// Error: 8-14 expected identifier, found destructuring pattern -#let f((a, b): 0) = none - -// Error: 10-19 expected pattern, found array -#let f(..(a, b: c)) = none - -// Error: 10-16 expected pattern, found array -#let f(..(a, b)) = none - ---- -// Error: 11-12 duplicate parameter: x -#let f(x, x) = none - ---- -// Error: 21 expected comma -// Error: 22-23 expected pattern, found integer -// Error: 24-25 unexpected plus -// Error: 26-27 expected pattern, found integer -#let f = (x: () => 1 2 + 3) => 4 - ---- -// Error: 14-15 duplicate parameter: a -// Error: 23-24 duplicate parameter: b -// Error: 35-36 duplicate parameter: b -#let f(a, b, a: none, b: none, c, b) = none - ---- -// Error: 13-14 duplicate parameter: a -#let f(a, ..a) = none - ---- -// Error: 7-14 expected pattern, found string -#((a, "named": b) => none) - ---- -// Error: 10-15 expected pattern, found string -#let foo("key": b) = key - ---- -// Error: 10-14 expected pattern, found `none` -// Hint: 10-14 keyword `none` is not allowed as an identifier; try `none_` instead -#let foo(none: b) = key - ---- -// Error: 10-11 expected identifier, found underscore -#let foo(_: 3) = none diff --git a/tests/typ/compiler/color.typ b/tests/typ/compiler/color.typ deleted file mode 100644 index ac83355d..00000000 --- a/tests/typ/compiler/color.typ +++ /dev/null @@ -1,101 +0,0 @@ -// Test color modification methods. - ---- -// Test CMYK color conversion. -#let c = cmyk(50%, 64%, 16%, 17%) -#stack( - dir: ltr, - spacing: 1fr, - rect(width: 1cm, fill: cmyk(69%, 11%, 69%, 41%)), - rect(width: 1cm, fill: c), - rect(width: 1cm, fill: c.negate(space: cmyk)), -) - -#for x in range(0, 11) { - box(square(size: 9pt, fill: c.lighten(x * 10%))) -} -#for x in range(0, 11) { - box(square(size: 9pt, fill: c.darken(x * 10%))) -} - ---- -// The the different color spaces -#let col = rgb(50%, 64%, 16%) -#box(square(size: 9pt, fill: col)) -#box(square(size: 9pt, fill: rgb(col))) -#box(square(size: 9pt, fill: oklab(col))) -#box(square(size: 9pt, fill: oklch(col))) -#box(square(size: 9pt, fill: luma(col))) -#box(square(size: 9pt, fill: cmyk(col))) -#box(square(size: 9pt, fill: color.linear-rgb(col))) -#box(square(size: 9pt, fill: color.hsl(col))) -#box(square(size: 9pt, fill: color.hsv(col))) - ---- -// Colors outside the sRGB gamut. -#box(square(size: 9pt, fill: oklab(90%, -0.2, -0.1))) -#box(square(size: 9pt, fill: oklch(50%, 0.5, 0deg))) - ---- -// Test hue rotation -#let col = rgb(50%, 64%, 16%) - -// Oklch -#for x in range(0, 11) { - box(square(size: 9pt, fill: rgb(col).rotate(x * 36deg))) -} - -// HSL -#for x in range(0, 11) { - box(square(size: 9pt, fill: rgb(col).rotate(x * 36deg, space: color.hsl))) -} - -// HSV -#for x in range(0, 11) { - box(square(size: 9pt, fill: rgb(col).rotate(x * 36deg, space: color.hsv))) -} - ---- -// Test saturation -#let col = color.hsl(180deg, 0%, 50%) -#for x in range(0, 11) { - box(square(size: 9pt, fill: col.saturate(x * 10%))) -} - -#let col = color.hsl(180deg, 100%, 50%) -#for x in range(0, 11) { - box(square(size: 9pt, fill: col.desaturate(x * 10%))) -} - -#let col = color.hsv(180deg, 0%, 50%) -#for x in range(0, 11) { - box(square(size: 9pt, fill: col.saturate(x * 10%))) -} - -#let col = color.hsv(180deg, 100%, 50%) -#for x in range(0, 11) { - box(square(size: 9pt, fill: col.desaturate(x * 10%))) -} - ---- -// Test gray color modification. -// Ref: false -#test-repr(luma(20%).lighten(50%), luma(60%)) -#test-repr(luma(80%).darken(20%), luma(64%)) -#test-repr(luma(80%).negate(space: luma), luma(20%)) - ---- -// Test alpha modification. -// Ref: false -#test-repr(luma(100%, 100%).transparentize(50%), luma(100%, 50%)) -#test-repr(luma(100%, 100%).transparentize(75%), luma(100%, 25%)) -#test-repr(luma(100%, 50%).transparentize(50%), luma(100%, 25%)) -#test-repr(luma(100%, 10%).transparentize(250%), luma(100%, 0%)) -#test-repr(luma(100%, 40%).transparentize(-50%), luma(100%, 70%)) -#test-repr(luma(100%, 0%).transparentize(-100%), luma(100%, 100%)) - -#test-repr(luma(100%, 50%).opacify(50%), luma(100%, 75%)) -#test-repr(luma(100%, 20%).opacify(100%), luma(100%, 100%)) -#test-repr(luma(100%, 100%).opacify(250%), luma(100%, 100%)) -#test-repr(luma(100%, 50%).opacify(-50%), luma(100%, 25%)) -#test-repr(luma(100%, 0%).opacify(0%), luma(100%, 0%)) diff --git a/tests/typ/compiler/comment.typ b/tests/typ/compiler/comment.typ deleted file mode 100644 index 31025de6..00000000 --- a/tests/typ/compiler/comment.typ +++ /dev/null @@ -1,34 +0,0 @@ -// Test line and block comments. - ---- -// Line comment acts as spacing. -A// you -B - -// Block comment does not act as spacing, nested block comments. -C/* - /* */ -*/D - -// Works in code. -#test(type(/*1*/ 1) // -, int) - -// End of block comment in line comment. -// Hello */ - -// Nested "//" doesn't count as line comment. -/* // */ -E - -/*//*/ -This is a comment. -*/*/ - ---- -// End should not appear without start. -// Error: 7-9 unexpected end of block comment -/* */ */ - -// Unterminated is okay. -/* diff --git a/tests/typ/compiler/construct.typ b/tests/typ/compiler/construct.typ deleted file mode 100644 index da077e7e..00000000 --- a/tests/typ/compiler/construct.typ +++ /dev/null @@ -1,31 +0,0 @@ -// Test constructors. - ---- -// 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]) - ---- -// 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]) -] - ---- -// The inner rectangle should also be yellow here. -// (and therefore invisible) -#[#set rect(fill: yellow);#text(1em, rect(inset: 5pt, rect()))] - ---- -// The inner rectangle should not be yellow here. -A #box(rect(fill: yellow, inset: 5pt, rect())) B - ---- -// 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/typ/compiler/content-field.typ b/tests/typ/compiler/content-field.typ deleted file mode 100644 index 96ce1dca..00000000 --- a/tests/typ/compiler/content-field.typ +++ /dev/null @@ -1,63 +0,0 @@ -// Tests content field access. - ---- -// Ensure that fields from set rules are materialized into the element before -// a show rule runs. -#set table(columns: (10pt, auto)) -#show table: it => it.columns -#table[A][B][C][D] - ---- -// Test it again with a different element. -#set heading(numbering: "(I)") -#show heading: set text(size: 11pt, weight: "regular") -#show heading: it => it.numbering -= Heading - ---- -// Test it with query. -#set raw(lang: "rust") -#context query(<myraw>).first().lang -`raw` <myraw> - ---- -// Integrated test for content fields. -#let compute(equation, ..vars) = { - let vars = vars.named() - let f(elem) = { - let func = elem.func() - if func == text { - let text = elem.text - if regex("^\d+$") in text { - int(text) - } else if text in vars { - int(vars.at(text)) - } else { - panic("unknown math variable: " + text) - } - } else if func == math.attach { - let value = f(elem.base) - if elem.has("t") { - value = calc.pow(value, f(elem.t)) - } - value - } else if elem.has("children") { - elem - .children - .filter(v => v != [ ]) - .split[+] - .map(xs => xs.fold(1, (prod, v) => prod * f(v))) - .fold(0, (sum, v) => sum + v) - } - } - let result = f(equation.body) - [With ] - vars - .pairs() - .map(p => $#p.first() = #p.last()$) - .join(", ", last: " and ") - [ we have:] - $ equation = result $ -} - -#compute($x y + y^2$, x: 2, y: 3) diff --git a/tests/typ/compiler/delayed-error.typ b/tests/typ/compiler/delayed-error.typ deleted file mode 100644 index eff6b85b..00000000 --- a/tests/typ/compiler/delayed-error.typ +++ /dev/null @@ -1,11 +0,0 @@ -// Test that errors in show rules are delayed: There can be multiple at once. - ---- -// Error: 21-34 panicked with: "hey1" -#show heading: _ => panic("hey1") - -// Error: 20-33 panicked with: "hey2" -#show strong: _ => panic("hey2") - -= Hello -*strong* diff --git a/tests/typ/compiler/dict.typ b/tests/typ/compiler/dict.typ deleted file mode 100644 index 552b243c..00000000 --- a/tests/typ/compiler/dict.typ +++ /dev/null @@ -1,160 +0,0 @@ -// Test dictionaries. -// Ref: false - ---- -// Ref: true - -// Empty -#(:) - -// Two pairs and string key. -#let dict = (normal: 1, "spacy key": 2) -#dict - -#test(dict.normal, 1) -#test(dict.at("spacy key"), 2) - ---- -// Test lvalue and rvalue access. -#{ - let dict = (a: 1, "b b": 1) - dict.at("b b") += 1 - dict.state = (ok: true, err: false) - test(dict, (a: 1, "b b": 2, state: (ok: true, err: false))) - test(dict.state.ok, true) - dict.at("state").ok = false - test(dict.state.ok, false) - test(dict.state.err, false) -} - ---- -// Test rvalue missing key. -#{ - let dict = (a: 1, b: 2) - // Error: 11-23 dictionary does not contain key "c" and no default value was specified - let x = dict.at("c") -} - ---- -// Test default value. -#test((a: 1, b: 2).at("b", default: 3), 2) -#test((a: 1, b: 2).at("c", default: 3), 3) - ---- -// Test insert. -#{ - let dict = (a: 1, b: 2) - dict.insert("b", 3) - test(dict, (a: 1, b: 3)) - dict.insert("c", 5) - test(dict, (a: 1, b: 3, c: 5)) -} - ---- -// Test remove with default value. -#{ - let dict = (a: 1, b: 2) - test(dict.remove("b", default: 3), 2) -} - -#{ - let dict = (a: 1, b: 2) - test(dict.remove("c", default: 3), 3) -} - ---- -// Missing lvalue is not automatically none-initialized. -#{ - let dict = (:) - // Error: 3-9 dictionary does not contain key "b" - // Hint: 3-9 use `insert` to add or update values - dict.b += 1 -} - ---- -// Test dictionary methods. -#let dict = (a: 3, c: 2, b: 1) -#test("c" in dict, true) -#test(dict.len(), 3) -#test(dict.values(), (3, 2, 1)) -#test(dict.pairs().map(p => p.first() + str(p.last())).join(), "a3c2b1") - -#dict.remove("c") -#test("c" in dict, false) -#test(dict, (a: 3, b: 1)) - ---- -// Test dictionary constructor -#dictionary(sys).at("version") -#dictionary(sys).at("no_crash", default: none) - ---- -// Test that removal keeps order. -#let dict = (a: 1, b: 2, c: 3, d: 4) -#dict.remove("b") -#test(dict.keys(), ("a", "c", "d")) - ---- -// Error: 24-29 duplicate key: first -#(first: 1, second: 2, first: 3) - ---- -// Error: 17-20 duplicate key: a -#(a: 1, "b": 2, "a": 3) - ---- -// Simple expression after already being identified as a dictionary. -// Error: 9-10 expected named or keyed pair, found identifier -#(a: 1, b) - -// Identified as dictionary due to initial colon. -// The boolean key is allowed for now since it will only cause an error at the evaluation stage. -// Error: 4-5 expected named or keyed pair, found integer -// Error: 17 expected expression -#(:1 b:"", true:) - ---- -// Error: 3-15 cannot mutate a temporary value -#((key: "val").other = "some") - ---- -#{ - let dict = ( - call-me: () => 1, - ) - // Error: 8-15 type dictionary has no method `call-me` - // Hint: 8-15 to call the function stored in the dictionary, surround the field access with parentheses, e.g. `(dict.call-me)(..)` - dict.call-me() -} - ---- -#{ - let dict = ( - nonfunc: 1 - ) - - // Error: 8-15 type dictionary has no method `nonfunc` - // Hint: 8-15 did you mean to access the field `nonfunc`? - dict.nonfunc() -} - ---- -#let a = "hello" -#let b = "world" -#let c = "value" -#let d = "conflict" - -#assert.eq(((a): b), ("hello": "world")) -#assert.eq(((a): 1, (a): 2), ("hello": 2)) -#assert.eq((hello: 1, (a): 2), ("hello": 2)) -#assert.eq((a + b: c, (a + b): d, (a): "value2", a: "value3"), ("helloworld": "conflict", "hello": "value2", "a": "value3")) - ---- -// Error: 7-10 expected identifier, found group -// Error: 12-14 expected pattern, found integer -#let ((a): 10) = "world" - ---- -// Error: 3-7 expected string, found boolean -// Error: 16-18 expected string, found integer -#(true: false, 42: 3) diff --git a/tests/typ/compiler/duration.typ b/tests/typ/compiler/duration.typ deleted file mode 100644 index 1d831a6f..00000000 --- a/tests/typ/compiler/duration.typ +++ /dev/null @@ -1,104 +0,0 @@ -// Test durations. -// Ref: false - ---- -// Test negating durations. -#test(-duration(hours: 2), duration(hours: -2)) - ---- -// Test adding and subtracting durations. -#test(duration(weeks: 1, hours: 1), duration(weeks: 1) + duration(hours: 1)) -#test(duration(weeks: 1, hours: -1), duration(weeks: 1) - duration(hours: 1)) -#test(duration(days: 6, hours: 23), duration(weeks: 1) - duration(hours: 1)) - ---- -// Test adding and subtracting durations and dates. -#let d = datetime(day: 1, month: 1, year: 2000) -#let d2 = datetime(day: 1, month: 2, year: 2000) -#test(d + duration(weeks: 2), datetime(day: 15, month: 1, year: 2000)) -#test(d + duration(days: 3), datetime(day: 4, month: 1, year: 2000)) -#test(d + duration(weeks: 1, days: 3), datetime(day: 11, month: 1, year: 2000)) -#test(d2 + duration(days: -1), datetime(day: 31, month: 1, year: 2000)) -#test(d2 + duration(days: -3), datetime(day: 29, month: 1, year: 2000)) -#test(d2 + duration(weeks: -1), datetime(day: 25, month: 1, year: 2000)) -#test(d + duration(days: -1), datetime(day: 31, month: 12, year: 1999)) -#test(d + duration(weeks: 1, days: -7), datetime(day: 1, month: 1, year: 2000)) -#test(d2 - duration(days: 1), datetime(day: 31, month: 1, year: 2000)) -#test(d2 - duration(days: 3), datetime(day: 29, month: 1, year: 2000)) -#test(d2 - duration(weeks: 1), datetime(day: 25, month: 1, year: 2000)) -#test(d - duration(days: 1), datetime(day: 31, month: 12, year: 1999)) -#test(datetime(day: 31, month: 1, year: 2000) + duration(days: 1), d2) -#test( - datetime(day: 31, month: 12, year: 2000) + duration(days: 1), - datetime(day: 1, month: 1, year: 2001), -) - ---- -// Test adding and subtracting durations and times. -#let a = datetime(hour: 12, minute: 0, second: 0) -#test(a + duration(hours: 1, minutes: -60), datetime(hour: 12, minute: 0, second: 0)) -#test(a + duration(hours: 2), datetime(hour: 14, minute: 0, second: 0)) -#test(a + duration(minutes: 10), datetime(hour: 12, minute: 10, second: 0)) -#test(a + duration(seconds: 30), datetime(hour: 12, minute: 0, second: 30)) -#test(a + duration(hours: -2), datetime(hour: 10, minute: 0, second: 0)) -#test(a - duration(hours: 2), datetime(hour: 10, minute: 0, second: 0)) -#test(a + duration(minutes: -10), datetime(hour: 11, minute: 50, second: 0)) -#test(a - duration(minutes: 10), datetime(hour: 11, minute: 50, second: 0)) -#test(a + duration(seconds: -30), datetime(hour: 11, minute: 59, second: 30)) -#test(a - duration(seconds: 30), datetime(hour: 11, minute: 59, second: 30)) -#test( - a + duration(hours: 1, minutes: 13, seconds: 13), - datetime(hour: 13, minute: 13, second: 13), -) - ---- -// Test adding and subtracting durations and datetimes. -#test( - datetime(day: 1, month: 1, year: 2000, hour: 12, minute: 0, second: 0) - + duration(weeks: 1, days: 3, hours: -13, minutes: 10, seconds: -10 ), - datetime(day: 10, month: 1, year: 2000, hour: 23, minute: 9, second: 50), -) -#test( - datetime(day: 1, month: 1, year: 2000, hour: 12, minute: 0, second: 0) - + duration(weeks: 1, days: 3, minutes: 10) - - duration(hours: 13, seconds: 10), - datetime(day: 10, month: 1, year: 2000, hour: 23, minute: 9, second: 50), -) - ---- -// Test subtracting dates. -#let a = datetime(hour: 12, minute: 0, second: 0) -#let b = datetime(day: 1, month: 1, year: 2000) -#test(datetime(hour: 14, minute: 0, second: 0) - a, duration(hours: 2)) -#test(datetime(hour: 14, minute: 0, second: 0) - a, duration(minutes: 120)) -#test(datetime(hour: 13, minute: 0, second: 0) - a, duration(seconds: 3600)) -#test(datetime(day: 1, month: 2, year: 2000) - b, duration(days: 31)) -#test(datetime(day: 15, month: 1, year: 2000) - b, duration(weeks: 2)) - ---- -// Test multiplying and dividing durations with numbers. -#test(duration(minutes: 10) * 6, duration(hours: 1)) -#test(duration(minutes: 10) * 2, duration(minutes: 20)) -#test(duration(minutes: 10) * 2.5, duration(minutes: 25)) -#test(duration(minutes: 10) / 2, duration(minutes: 5)) -#test(duration(minutes: 10) / 2.5, duration(minutes: 4)) - ---- -// Test dividing durations with durations -#test(duration(minutes: 20) / duration(hours: 1), 1 / 3) -#test(duration(minutes: 20) / duration(minutes: 10), 2) -#test(duration(minutes: 20) / duration(minutes: 8), 2.5) - ---- -// Test comparing durations -#test(duration(minutes: 20) > duration(minutes: 10), true) -#test(duration(minutes: 20) >= duration(minutes: 10), true) -#test(duration(minutes: 10) < duration(minutes: 20), true) -#test(duration(minutes: 10) <= duration(minutes: 20), true) -#test(duration(minutes: 10) == duration(minutes: 10), true) -#test(duration(minutes: 10) != duration(minutes: 20), true) -#test(duration(minutes: 10) <= duration(minutes: 10), true) -#test(duration(minutes: 10) >= duration(minutes: 10), true) -#test(duration(minutes: 20) < duration(minutes: 10), false) -#test(duration(minutes: 20) <= duration(minutes: 10), false) -#test(duration(minutes: 20) == duration(minutes: 10), false) diff --git a/tests/typ/compiler/embedded-expr.typ b/tests/typ/compiler/embedded-expr.typ deleted file mode 100644 index ee6e07f9..00000000 --- a/tests/typ/compiler/embedded-expr.typ +++ /dev/null @@ -1,22 +0,0 @@ -// Test embedded expressions. -// Ref: false - ---- -// Error: 6-8 expected pattern, found keyword `as` -// Hint: 6-8 keyword `as` is not allowed as an identifier; try `as_` instead -#let as = 1 + 2 - ---- -#{ - // Error: 7-9 expected pattern, found keyword `as` - // Hint: 7-9 keyword `as` is not allowed as an identifier; try `as_` instead - let as = 10 -} - ---- -// Error: 2-2 expected expression -# - ---- -// Error: 2-2 expected expression -# hello diff --git a/tests/typ/compiler/field.typ b/tests/typ/compiler/field.typ deleted file mode 100644 index 35768ec5..00000000 --- a/tests/typ/compiler/field.typ +++ /dev/null @@ -1,200 +0,0 @@ -// Test field access. -// Ref: false - ---- -// Test field on dictionary. -#let dict = (nothing: "ness", hello: "world") -#test(dict.nothing, "ness") -#{ - let world = dict - .hello - - test(world, "world") -} - ---- -// Test fields on elements. -#show list: it => { - test(it.children.len(), 3) -} - -- A -- B -- C - ---- -// Test fields on function scopes. -#enum.item -#assert.eq -#assert.ne - ---- -// Error: 9-16 function `assert` does not contain field `invalid` -#assert.invalid - ---- -// Error: 7-14 function `enum` does not contain field `invalid` -#enum.invalid - ---- -// Error: 7-14 function `enum` does not contain field `invalid` -#enum.invalid() - ---- -// Closures cannot have fields. -#let f(x) = x -// Error: 4-11 cannot access fields on user-defined functions -#f.invalid - ---- -// Error: 6-13 dictionary does not contain key "invalid" -#(:).invalid - ---- -// Error: 8-10 cannot access fields on type boolean -#false.ok - ---- -// Error: 25-28 content does not contain field "fun" -#show heading: it => it.fun -= A - ---- -// Error: 9-13 cannot access fields on type boolean -#{false.true} - ---- -// Test relative length fields. -#test((100% + 2em + 2pt).ratio, 100%) -#test((100% + 2em + 2pt).length, 2em + 2pt) -#test((100% + 2pt).length, 2pt) -#test((100% + 2pt - 2pt).length, 0pt) -#test((56% + 2pt - 56%).ratio, 0%) - ---- -// Test length fields. -#test((1pt).em, 0.0) -#test((1pt).abs, 1pt) -#test((3em).em, 3.0) -#test((3em).abs, 0pt) -#test((2em + 2pt).em, 2.0) -#test((2em + 2pt).abs, 2pt) - ---- -// Test stroke fields for simple strokes. -#test((1em + blue).paint, blue) -#test((1em + blue).thickness, 1em) -#test((1em + blue).cap, auto) -#test((1em + blue).join, auto) -#test((1em + blue).dash, auto) -#test((1em + blue).miter-limit, auto) - ---- -// Test complex stroke fields. -#let r1 = rect(stroke: (paint: cmyk(1%, 2%, 3%, 4%), thickness: 4em + 2pt, cap: "round", join: "bevel", miter-limit: 5.0, dash: none)) -#let r2 = rect(stroke: (paint: cmyk(1%, 2%, 3%, 4%), thickness: 4em + 2pt, cap: "round", join: "bevel", miter-limit: 5.0, dash: (3pt, "dot", 4em))) -#let r3 = rect(stroke: (paint: cmyk(1%, 2%, 3%, 4%), thickness: 4em + 2pt, cap: "round", join: "bevel", dash: (array: (3pt, "dot", 4em), phase: 5em))) -#let s1 = r1.stroke -#let s2 = r2.stroke -#let s3 = r3.stroke -#test(s1.paint, cmyk(1%, 2%, 3%, 4%)) -#test(s1.thickness, 4em + 2pt) -#test(s1.cap, "round") -#test(s1.join, "bevel") -#test(s1.miter-limit, 5.0) -#test(s3.miter-limit, auto) -#test(s1.dash, none) -#test(s2.dash, (array: (3pt, "dot", 4em), phase: 0pt)) -#test(s3.dash, (array: (3pt, "dot", 4em), phase: 5em)) - ---- -// Test 2d alignment 'horizontal' field. -#test((start + top).x, start) -#test((end + top).x, end) -#test((left + top).x, left) -#test((right + top).x, right) -#test((center + top).x, center) -#test((start + bottom).x, start) -#test((end + bottom).x, end) -#test((left + bottom).x, left) -#test((right + bottom).x, right) -#test((center + bottom).x, center) -#test((start + horizon).x, start) -#test((end + horizon).x, end) -#test((left + horizon).x, left) -#test((right + horizon).x, right) -#test((center + horizon).x, center) -#test((top + start).x, start) -#test((bottom + end).x, end) -#test((horizon + center).x, center) - ---- -// Test 2d alignment 'vertical' field. -#test((start + top).y, top) -#test((end + top).y, top) -#test((left + top).y, top) -#test((right + top).y, top) -#test((center + top).y, top) -#test((start + bottom).y, bottom) -#test((end + bottom).y, bottom) -#test((left + bottom).y, bottom) -#test((right + bottom).y, bottom) -#test((center + bottom).y, bottom) -#test((start + horizon).y, horizon) -#test((end + horizon).y, horizon) -#test((left + horizon).y, horizon) -#test((right + horizon).y, horizon) -#test((center + horizon).y, horizon) -#test((top + start).y, top) -#test((bottom + end).y, bottom) -#test((horizon + center).y, horizon) - ---- -#{ - let object = sym.eq.not - // Error: 3-9 cannot mutate fields on symbol - object.property = "value" -} - ---- -#{ - let object = [hi] - // Error: 3-9 cannot mutate fields on content - object.property = "value" -} - ---- -#{ - let object = calc - // Error: 3-9 cannot mutate fields on module - object.property = "value" -} - ---- -#{ - let object = calc.sin - // Error: 3-9 cannot mutate fields on function - object.property = "value" -} - ---- -#{ - let object = none - // Error: 3-9 none does not have accessible fields - object.property = "value" -} - ---- -#{ - let object = 10 - // Error: 3-9 integer does not have accessible fields - object.property = "value" -} - ---- -#{ - let s = 1pt + red - // Error: 3-4 fields on stroke are not yet mutable - // Hint: 3-4 try creating a new stroke with the updated field value instead - s.thickness = 5pt -} diff --git a/tests/typ/compiler/for.typ b/tests/typ/compiler/for.typ deleted file mode 100644 index 392dd676..00000000 --- a/tests/typ/compiler/for.typ +++ /dev/null @@ -1,136 +0,0 @@ -// Test for loops. -// Ref: false - ---- -// Ref: true - -// Empty array. -#for x in () [Nope] - -// Dictionary is traversed in insertion order. -// Should output `Name: Typst. Age: 2.`. -#for (k, v) in (Name: "Typst", Age: 2) [ - #k: #v. -] - -// Block body. -// Should output `[1st, 2nd, 3rd, 4th]`. -#{ - "[" - for v in (1, 2, 3, 4) { - if v > 1 [, ] - [#v] - if v == 1 [st] - if v == 2 [nd] - if v == 3 [rd] - if v >= 4 [th] - } - "]" -} - -// Content block body. -// Should output `2345`. -#for v in (1, 2, 3, 4, 5, 6, 7) [#if v >= 2 and v <= 5 { repr(v) }] - -// Map captured arguments. -#let f1(..args) = args.pos().map(repr) -#let f2(..args) = args.named().pairs().map(p => repr(p.first()) + ": " + repr(p.last())) -#let f(..args) = (f1(..args) + f2(..args)).join(", ") -#f(1, a: 2) - ---- -#let out = () - -// Values of array. -#for v in (1, 2, 3) { - out += (v,) -} - -// Indices and values of array. -#for (i, v) in ("1", "2", "3").enumerate() { - test(repr(i + 1), v) -} - -// Pairs of dictionary. -#for v in (a: 4, b: 5) { - out += (v,) -} - -// Keys and values of dictionary. -#for (k, v) in (a: 6, b: 7) { - out += (k,) - out += (v,) -} - -#test(out, (1, 2, 3, ("a", 4), ("b", 5), "a", 6, "b", 7)) - -// Grapheme clusters of string. -#let first = true -#let joined = for c in "abcπ©βπ©βπ¦βπ¦" { - if not first { ", " } - first = false - c -} - -#test(joined, "a, b, c, π©βπ©βπ¦βπ¦") - -// Return value. -#test(for v in "" [], none) -#test(type(for v in "1" []), content) - ---- -// Uniterable expression. -// Error: 11-15 cannot loop over boolean -#for v in true {} - ---- -// Keys and values of strings. -// Error: 6-12 cannot destructure values of string -#for (k, v) in "hi" { - dont-care -} - ---- -// Destructuring without parentheses. -// Error: 7-8 unexpected comma -// Hint: 7-8 destructuring patterns must be wrapped in parentheses -#for k, v in (a: 4, b: 5) { - dont-care -} - -// Error: 7-8 unexpected comma -// Hint: 7-8 destructuring patterns must be wrapped in parentheses -#for k, in () {} - ---- -// Error: 5 expected pattern -#for - -// Error: 5 expected pattern -#for// - -// Error: 6 expected pattern -#{for} - -// Error: 7 expected keyword `in` -#for v - -// Error: 10 expected expression -#for v in - -// Error: 15 expected block -#for v in iter - -// Error: 5 expected pattern -#for -v in iter {} - -// Error: 7-10 expected pattern, found string -// Error: 16 expected block -A#for "v" thing - -// Error: 6-9 expected pattern, found string -#for "v" in iter {} - -// Error: 7 expected keyword `in` -#for a + b in iter {} diff --git a/tests/typ/compiler/highlight.typ b/tests/typ/compiler/highlight.typ deleted file mode 100644 index 1cbeaf9d..00000000 --- a/tests/typ/compiler/highlight.typ +++ /dev/null @@ -1,42 +0,0 @@ -#set page(width: auto) - -```typ -#set hello() -#set hello() -#set hello.world() -#set hello.my.world() -#let foo(x) = x * 2 -#show heading: func -#show module.func: func -#show module.func: it => {} -#foo(ident: ident) -#hello -#hello() -#box[] -#hello.world -#hello.world() -#hello().world() -#hello.my.world -#hello.my.world() -#hello.my().world -#hello.my().world() -#{ hello } -#{ hello() } -#{ hello.world() } -$ hello $ -$ hello() $ -$ box[] $ -$ hello.world $ -$ hello.world() $ -$ hello.my.world() $ -$ f_zeta(x), f_zeta(x)/1 $ -$ emph(hello.my.world()) $ -$ emph(hello.my().world) $ -$ emph(hello.my().world()) $ -$ #hello $ -$ #hello() $ -$ #hello.world $ -$ #hello.world() $ -$ #box[] $ -#if foo [] -``` diff --git a/tests/typ/compiler/hint.typ b/tests/typ/compiler/hint.typ deleted file mode 100644 index 1a5efcaa..00000000 --- a/tests/typ/compiler/hint.typ +++ /dev/null @@ -1,41 +0,0 @@ -// Test hints on diagnostics. -// Ref: false - ---- -// Error: 1:17-1:19 expected length, found integer: a length needs a unit - did you mean 12pt? -#set text(size: 12) - ---- -#{ - let a = 2 - a = 1-a - a = a -1 - - // Error: 7-10 unknown variable: a-1 - // Hint: 7-10 if you meant to use subtraction, try adding spaces around the minus sign - a = a-1 -} - ---- -#{ - // Error: 3-6 unknown variable: a-1 - // Hint: 3-6 if you meant to use subtraction, try adding spaces around the minus sign - a-1 = 2 -} - ---- -= Heading <intro> - -// Error: 1:20-1:26 cannot reference heading without numbering -// Hint: 1:20-1:26 you can enable heading numbering with `#set heading(numbering: "1.")` -Can not be used as @intro - ---- -// This test is more of a tooling test. It checks if hint annotation validation -// can be turned off. -// Hints: false - -= Heading <intro> - -// Error: 1:20-1:26 cannot reference heading without numbering -Can not be used as @intro diff --git a/tests/typ/compiler/if.typ b/tests/typ/compiler/if.typ deleted file mode 100644 index 1d2ed88b..00000000 --- a/tests/typ/compiler/if.typ +++ /dev/null @@ -1,136 +0,0 @@ -// Test if-else expressions. - ---- -// Test condition evaluation. -#if 1 < 2 [ - One. -] - -#if true == false [ - {Bad}, but we {dont-care}! -] - ---- -// Braced condition. -#if {true} [ - One. -] - -// Content block in condition. -#if [] != none [ - Two. -] - -// Multi-line condition with parens. -#if ( - 1 + 1 - == 1 -) [ - Nope. -] else { - "Three." -} - -// Multiline. -#if false [ - Bad. -] else { - let point = "." - "Four" + point -} - -// Content block can be argument or body depending on whitespace. -#{ - if content == type[b] [Fi] else [Nope] - if content == type [Nope] else [ve.] -} - -#let i = 3 -#if i < 2 [ - Five. -] else if i < 4 [ - Six. -] else [ - Seven. -] - ---- -// Test else if. -// Ref: false - -#let nth(n) = { - str(n) - if n == 1 { "st" } - else if n == 2 { "nd" } - else if n == 3 { "rd" } - else { "th" } -} - -#test(nth(1), "1st") -#test(nth(2), "2nd") -#test(nth(3), "3rd") -#test(nth(4), "4th") -#test(nth(5), "5th") - ---- -// Value of if expressions. -// Ref: false - -#{ - let x = 1 - let y = 2 - let z - - // Returns if branch. - z = if x < y { "ok" } - test(z, "ok") - - // Returns else branch. - z = if x > y { "bad" } else { "ok" } - test(z, "ok") - - // Missing else evaluates to none. - z = if x > y { "bad" } - test(z, none) -} - ---- -// Condition must be boolean. -// If it isn't, neither branch is evaluated. -// Error: 5-14 expected boolean, found string -#if "a" + "b" { nope } else { nope } - ---- -// Make sure that we don't complain twice. -// Error: 5-12 cannot add integer and string -#if 1 + "2" {} - ---- -// Error: 4 expected expression -#if - -// Error: 5 expected expression -#{if} - -// Error: 6 expected block -#if x - -// Error: 2-6 unexpected keyword `else` -#else {} - -// Should output `x`. -// Error: 4 expected expression -#if -x {} - -// Should output `something`. -// Error: 6 expected block -#if x something - -// Should output `A thing.` -// Error: 19 expected block -A#if false {} else thing - -#if a []else [b] -#if a [] else [b] -#if a {} else [b] diff --git a/tests/typ/compiler/import.typ b/tests/typ/compiler/import.typ deleted file mode 100644 index 5c3a05c9..00000000 --- a/tests/typ/compiler/import.typ +++ /dev/null @@ -1,262 +0,0 @@ -// Test function and module imports. -// Ref: false - ---- -// Test basic syntax and semantics. -// Ref: true - -// Test that this will be overwritten. -#let value = [foo] - -// Import multiple things. -#import "module.typ": fn, value -#fn[Like and Subscribe!] -#value - -// Should output `bye`. -// Stop at semicolon. -#import "module.typ": a, c;bye - ---- -// An item import. -#import "module.typ": item -#test(item(1, 2), 3) - -// Code mode -{ - import "module.typ": b - test(b, 1) -} - -// A wildcard import. -#import "module.typ": * - -// It exists now! -#test(d, 3) - ---- -// A renamed item import. -#import "module.typ": item as something -#test(something(1, 2), 3) - -// Mixing renamed and not renamed items. -#import "module.typ": fn, b as val, item as other -#test(val, 1) -#test(other(1, 2), 3) - ---- -// Test importing from function scopes. -// Ref: true - -#import enum: item -#import assert.with(true): * - -#enum( - item(1)[First], - item(5)[Fifth] -) -#eq(10, 10) -#ne(5, 6) - ---- -// Test renaming items imported from function scopes. -#import assert: eq as aseq -#aseq(10, 10) - ---- -// A module import without items. -#import "module.typ" -#test(module.b, 1) -#test(module.item(1, 2), 3) -#test(module.push(2), 3) - ---- -// A renamed module import without items. -#import "module.typ" as other -#test(other.b, 1) -#test(other.item(1, 2), 3) -#test(other.push(2), 3) - ---- -// Mixing renamed module and items. -#import "module.typ" as newname: b as newval, item -#test(newname.b, 1) -#test(newval, 1) -#test(item(1, 2), 3) -#test(newname.item(1, 2), 3) - ---- -// Renamed module import with function scopes. -#import enum as othernum -#test(enum, othernum) - ---- -// Mixing renamed module import from function with renamed item import. -#import assert as asrt -#import asrt: ne as asne -#asne(1, 2) - ---- -// Edge case for module access that isn't fixed. -#import "module.typ" - -// Works because the method name isn't categorized as mutating. -#test((module,).at(0).item(1, 2), 3) - -// Doesn't work because of mutating name. -// Error: 2-11 cannot mutate a temporary value -#(module,).at(0).push() - ---- -// Who needs whitespace anyways? -#import"module.typ":* - -// Allow the trailing comma. -#import "module.typ": a, c, - ---- -// Usual importing syntax also works for function scopes -#let d = (e: enum) -#import d.e -#import d.e as renamed -#import d.e: item -#item(2)[a] - ---- -// Warning: 23-27 unnecessary import rename to same name -#import enum: item as item - ---- -// Warning: 17-21 unnecessary import rename to same name -#import enum as enum - ---- -// Warning: 17-21 unnecessary import rename to same name -#import enum as enum: item -// Warning: 17-21 unnecessary import rename to same name -// Warning: 31-35 unnecessary import rename to same name -#import enum as enum: item as item - ---- -// No warning on a case that isn't obviously pathological -#import "module.typ" as module - ---- -// Can't import from closures. -#let f(x) = x -// Error: 9-10 cannot import from user-defined functions -#import f: x - ---- -// Can't import from closures, despite renaming. -#let f(x) = x -// Error: 9-10 cannot import from user-defined functions -#import f as g - ---- -// Can't import from closures, despite modifiers. -#let f(x) = x -// Error: 9-18 cannot import from user-defined functions -#import f.with(5): x - ---- -// Error: 9-18 cannot import from user-defined functions -#import () => {5}: x - ---- -// Error: 9-10 expected path, module, function, or type, found integer -#import 5: something - ---- -// Error: 9-10 expected path, module, function, or type, found integer -#import 5 as x - ---- -// Error: 9-11 failed to load file (is a directory) -#import "": name - ---- -// Error: 9-11 failed to load file (is a directory) -#import "" as x - ---- -// Error: 9-20 file not found (searched at typ/compiler/lib/0.2.1) -#import "lib/0.2.1" - ---- -// Error: 9-20 file not found (searched at typ/compiler/lib/0.2.1) -#import "lib/0.2.1" as x - ---- -// Some non-text stuff. -// Error: 9-35 file is not valid utf-8 -#import "/assets/images/rhino.png" - ---- -// Unresolved import. -// Error: 23-35 unresolved import -#import "module.typ": non_existing - ---- -// Cyclic import of this very file. -// Error: 9-23 cyclic import -#import "./import.typ" - ---- -// Cyclic import in other file. -#import "./modules/cycle1.typ": * - -This is never reached. - ---- -// Renaming does not import the old name (without items). -#import "module.typ" as something -// Error: 7-12 unknown variable: mymod -#test(mymod.b, 1) - ---- -// Renaming does not import the old name (with items). -#import "module.typ" as something: b as other -// Error: 7-12 unknown variable: mymod -#test(mymod.b, 1) - ---- -// Error: 8 expected expression -#import - ---- -// Error: 26-29 unexpected string -#import "module.typ": a, "b", c - ---- -// Error: 23-24 unexpected equals sign -#import "module.typ": = - ---- -// An additional trailing comma. -// Error: 31-32 unexpected comma -#import "module.typ": a, b, c,, - ---- -// Error: 2:2 expected semicolon or line break -#import "module.typ -"stuff - ---- -// A star in the list. -// Error: 26-27 unexpected star -#import "module.typ": a, *, b - ---- -// An item after a star. -// Error: 24 expected semicolon or line break -#import "module.typ": *, a - ---- -// Error: 14-15 unexpected colon -// Error: 16-17 unexpected integer -#import "": a: 1 - ---- -// Error: 14 expected comma -#import "": a b diff --git a/tests/typ/compiler/include.typ b/tests/typ/compiler/include.typ deleted file mode 100644 index 586e869b..00000000 --- a/tests/typ/compiler/include.typ +++ /dev/null @@ -1,32 +0,0 @@ -// Test module includes. - ---- -#set page(width: 200pt) - -= Document - -// Include a file -#include "modules/chap1.typ" - -// Expression as a file name. -#let chap2 = include "modu" + "les/chap" + "2.typ" - --- _Intermission_ -- -#chap2 - ---- -#{ - // Error: 19-38 file not found (searched at typ/compiler/modules/chap3.typ) - let x = include "modules/chap3.typ" -} - ---- -#include "modules/chap1.typ" - -// The variables of the file should not appear in this scope. -// Error: 2-6 unknown variable: name -#name - ---- -// Error: 18 expected semicolon or line break -#include "hi.typ" Hi diff --git a/tests/typ/compiler/label.typ b/tests/typ/compiler/label.typ deleted file mode 100644 index fabbac80..00000000 --- a/tests/typ/compiler/label.typ +++ /dev/null @@ -1,72 +0,0 @@ -// Test labels. - ---- -// Test labelled headings. -#show heading: set text(10pt) -#show heading.where(label: <intro>): underline - -= Introduction <intro> -The beginning. - -= Conclusion -The end. - ---- -// Test label after expression. -#show strong.where(label: <v>): set text(red) - -#let a = [*A*] -#let b = [*B*] -#a <v> #b - ---- -// Test labelled text. -#show "t": it => { - set text(blue) if it.has("label") and it.label == <last> - it -} - -This is a thing #[that <last>] happened. - ---- -// Test abusing dynamic labels for styling. -#show <red>: set text(red) -#show <blue>: set text(blue) - -*A* *B* <red> *C* #label("bl" + "ue") *D* - ---- -// Test that label ignores parbreak. -#show <hide>: none - -_Hidden_ -<hide> - -_Hidden_ - -<hide> -_Visible_ - ---- -// Test that label only works within one content block. -#show <strike>: strike -*This is* #[<strike>] *protected.* -*This is not.* <strike> - ---- -// Test that incomplete label is text. -1 < 2 is #if 1 < 2 [not] a label. - ---- -// Test label on text, styled, and sequence. -// Ref: false -#test([Hello<hi>].label, <hi>) -#test([#[A *B* C]<hi>].label, <hi>) -#test([#text(red)[Hello]<hi>].label, <hi>) - ---- -// Test getting the name of a label. -// Ref: false -#test(str(<hey>), "hey") -#test(str(label("hey")), "hey") -#test(str([Hmm<hey>].label), "hey") diff --git a/tests/typ/compiler/let.typ b/tests/typ/compiler/let.typ deleted file mode 100644 index 411509ff..00000000 --- a/tests/typ/compiler/let.typ +++ /dev/null @@ -1,302 +0,0 @@ -// Test let bindings. - ---- -// Automatically initialized with none. -#let x -#test(x, none) - -// Manually initialized with one. -#let z = 1 -#test(z, 1) - -// Syntax sugar for function definitions. -#let fill = conifer -#let f(body) = rect(width: 2cm, fill: fill, inset: 5pt, body) -#f[Hi!] - ---- -// Termination. - -// Terminated by line break. -#let v1 = 1 -One - -// Terminated by semicolon. -#let v2 = 2; Two - -// Terminated by semicolon and line break. -#let v3 = 3; -Three - -#test(v1, 1) -#test(v2, 2) -#test(v3, 3) - ---- -// Test what constitutes a valid Typst identifier. -// Ref: false -#let name = 1 -#test(name, 1) -#let name_ = 1 -#test(name_, 1) -#let name-2 = 1 -#test(name-2, 1) -#let name_2 = 1 -#test(name_2, 1) -#let __name = 1 -#test(__name, 1) -#let Ε―Γ±Δ±ΔΓ³Γ°Δ = 1 -#test(Ε―Γ±Δ±ΔΓ³Γ°Δ, 1) - ---- -// Test parenthesised assignments. -// Ref: false -#let (a) = (1, 2) - ---- -// Ref: false -// Simple destructuring. -#let (a, b) = (1, 2) -#test(a, 1) -#test(b, 2) - ---- -// Ref: false -#let (a,) = (1,) -#test(a, 1) - ---- -// Ref: false -// Destructuring with multiple placeholders. -#let (a, _, c, _) = (1, 2, 3, 4) -#test(a, 1) -#test(c, 3) - ---- -// Ref: false -// Destructuring with a sink. -#let (a, b, ..c) = (1, 2, 3, 4, 5, 6) -#test(a, 1) -#test(b, 2) -#test(c, (3, 4, 5, 6)) - ---- -// Ref: false -// Destructuring with a sink in the middle. -#let (a, ..b, c) = (1, 2, 3, 4, 5, 6) -#test(a, 1) -#test(b, (2, 3, 4, 5)) -#test(c, 6) - ---- -// Ref: false -// Destructuring with an empty sink. -#let (..a, b, c) = (1, 2) -#test(a, ()) -#test(b, 1) -#test(c, 2) - ---- -// Ref: false -// Destructuring with an empty sink. -#let (a, ..b, c) = (1, 2) -#test(a, 1) -#test(b, ()) -#test(c, 2) - ---- -// Ref: false -// Destructuring with an empty sink. -#let (a, b, ..c) = (1, 2) -#test(a, 1) -#test(b, 2) -#test(c, ()) - ---- -// Ref: false -// Destructuring with an empty sink and empty array. -#let (..a) = () -#test(a, ()) - ---- -// Ref: false -// Destructuring with unnamed sink. -#let (a, .., b) = (1, 2, 3, 4) -#test(a, 1) -#test(b, 4) - -// Error: 10-11 duplicate binding: a -#let (a, a) = (1, 2) - -// Error: 12-15 only one destructuring sink is allowed -#let (..a, ..a) = (1, 2) - -// Error: 12-13 duplicate binding: a -#let (a, ..a) = (1, 2) - -// Error: 13-14 duplicate binding: a -#let (a: a, a) = (a: 1, b: 2) - -// Error: 13-20 expected pattern, found function call -#let (a, b: b.at(0)) = (a: 1, b: 2) - -// Error: 7-14 expected pattern, found function call -#let (a.at(0),) = (1,) - ---- -// Error: 13-14 not enough elements to destructure -#let (a, b, c) = (1, 2) - ---- -// Error: 7-10 not enough elements to destructure -#let (..a, b, c, d) = (1, 2) - ---- -// Error: 6-12 cannot destructure boolean -#let (a, b) = true - ---- -// Ref: false -// Simple destructuring. -#let (a: a, b, x: c) = (a: 1, b: 2, x: 3) -#test(a, 1) -#test(b, 2) -#test(c, 3) - ---- -// Ref: false -// Destructuring with a sink. -#let (a: _, ..b) = (a: 1, b: 2, c: 3) -#test(b, (b: 2, c: 3)) - ---- -// Ref: false -// Destructuring with a sink in the middle. -#let (a: _, ..b, c: _) = (a: 1, b: 2, c: 3) -#test(b, (b: 2)) - ---- -// Ref: false -// Destructuring with an empty sink. -#let (a: _, ..b) = (a: 1) -#test(b, (:)) - ---- -// Ref: false -// Destructuring with an empty sink and empty dict. -#let (..a) = (:) -#test(a, (:)) - ---- -// Ref: false -// Destructuring with unnamed sink. -#let (a, ..) = (a: 1, b: 2) -#test(a, 1) - ---- -// Ref: false -// Nested destructuring. -#let ((a, b), (key: c)) = ((1, 2), (key: 3)) -#test((a, b, c), (1, 2, 3)) - ---- -// Keyed destructuring is not currently supported. -// Error: 7-18 expected pattern, found string -#let ("spacy key": val) = ("spacy key": 123) -#val - ---- -// Keyed destructuring is not currently supported. -#let x = "spacy key" -// Error: 7-10 expected identifier, found group -#let ((x): v) = ("spacy key": 123) - ---- -// Trailing placeholders. -// Error: 10-11 not enough elements to destructure -#let (a, _, _, _, _) = (1,) -#test(a, 1) - ---- -// Error: 10-13 expected pattern, found string -// Error: 18-19 expected pattern, found integer -#let (a: "a", b: 2) = (a: 1, b: 2) - ---- -// Error: 10-11 dictionary does not contain key "b" -#let (a, b) = (a: 1) - ---- -// Error: 10-11 dictionary does not contain key "b" -#let (a, b: b) = (a: 1) - ---- -// Error: 7-11 cannot destructure named pattern from an array -#let (a: a, b) = (1, 2, 3) - ---- -// Error: 5 expected pattern -#let - -// Error: 6 expected pattern -#{let} - -// Error: 6-9 expected pattern, found string -#let "v" - -// Error: 7 expected semicolon or line break -#let v 1 - -// Error: 9 expected expression -#let v = - -// Error: 6-9 expected pattern, found string -#let "v" = 1 - -// Terminated because expression ends. -// Error: 12 expected semicolon or line break -#let v4 = 4 Four - -// Terminated by semicolon even though we are in a paren group. -// Error: 18 expected expression -// Error: 11-12 unclosed delimiter -#let v5 = (1, 2 + ; Five - -// Error: 9-13 expected pattern, found boolean -#let (..true) = false - ---- -#let _ = 4 - -#for _ in range(2) [] - -// Error: 2-3 unexpected underscore -#_ - -// Error: 8-9 expected expression, found underscore -#lorem(_) - -// Error: 3-4 expected expression, found underscore -#(_,) - -// Error: 3-4 expected expression, found underscore -#{_} - -// Error: 8-9 expected expression, found underscore -#{ 1 + _ } - ---- -// Error: 13 expected equals sign -#let func(x) - -// Error: 15 expected expression -#let func(x) = - ---- -// Error: 12 expected equals sign -#let (func)(x) - ---- -// Error: 12 expected equals sign -// Error: 15-15 expected semicolon or line break -#let (func)(x) = 3 diff --git a/tests/typ/compiler/methods.typ b/tests/typ/compiler/methods.typ deleted file mode 100644 index 8d5484ed..00000000 --- a/tests/typ/compiler/methods.typ +++ /dev/null @@ -1,287 +0,0 @@ -// Test method calls. -// Ref: false - ---- -// Test whitespace around dot. -#test( "Hi there" . split() , ("Hi", "there")) - ---- -// Test mutating indexed value. -#{ - let matrix = (((1,), (2,)), ((3,), (4,))) - matrix.at(1).at(0).push(5) - test(matrix, (((1,), (2,)), ((3, 5), (4,)))) -} - ---- -// Test multiline chain in code block. -#{ - let rewritten = "Hello. This is a sentence. And one more." - .split(".") - .map(s => s.trim()) - .filter(s => s != "") - .map(s => s + "!") - .join("\n ") - - test(rewritten, "Hello!\n This is a sentence!\n And one more!") -} - ---- -// Test .at() default values for content. -#test(auto, [a].at("doesn't exist", default: auto)) - ---- -// Error: 2:10-2:13 type array has no method `fun` -#let numbers = () -#numbers.fun() - ---- -// Error: 2:4-2:10 type content has no method `stroke` -// Hint: 2:4-2:10 did you mean to access the field `stroke`? -#let l = line(stroke: red) -#l.stroke() - ---- -// Error: 2:2-2:43 cannot mutate a temporary value -#let numbers = (1, 2, 3) -#numbers.map(v => v / 2).sorted().map(str).remove(4) - ---- -// Error: 2:3-2:19 cannot mutate a temporary value -#let numbers = (1, 2, 3) -#(numbers.sorted() = 1) - ---- -// Error: 2-5 cannot mutate a constant: box -#box.push(1) - ---- -// Test content fields method. -#test([a].fields(), (text: "a")) -#test([a *b*].fields(), (children: ([a], [ ], strong[b]))) - ---- -// Test length unit conversions. -#test((500.934pt).pt(), 500.934) -#test((3.3453cm).cm(), 3.3453) -#test((4.3452mm).mm(), 4.3452) -#test((5.345in).inches(), 5.345) -#test((500.333666999pt).pt(), 500.333666999) -#test((3.5234354cm).cm(), 3.5234354) -#test((4.12345678mm).mm(), 4.12345678) -#test((5.333666999in).inches(), 5.333666999) -#test((4.123456789123456mm).mm(), 4.123456789123456) -#test((254cm).mm(), 2540.0) -#test(calc.round((254cm).inches(), digits: 2), 100.0) -#test((2540mm).cm(), 254.0) -#test(calc.round((2540mm).inches(), digits: 2), 100.0) -#test((100in).pt(), 7200.0) -#test(calc.round((100in).cm(), digits: 2), 254.0) -#test(calc.round((100in).mm(), digits: 2), 2540.0) -#test(5em.abs.cm(), 0.0) -#test((5em + 6in).abs.inches(), 6.0) - ---- -// Test length `to-absolute` method. -#set text(size: 12pt) -#context { - test((6pt).to-absolute(), 6pt) - test((6pt + 10em).to-absolute(), 126pt) - test((10em).to-absolute(), 120pt) -} - -#set text(size: 64pt) -#context { - test((6pt).to-absolute(), 6pt) - test((6pt + 10em).to-absolute(), 646pt) - test((10em).to-absolute(), 640pt) -} - ---- -// Error: 2-21 cannot convert a length with non-zero em units (`-6pt + 10.5em`) to pt -// Hint: 2-21 use `length.abs.pt()` instead to ignore its em component -#(10.5em - 6pt).pt() - ---- -// Error: 2-12 cannot convert a length with non-zero em units (`3em`) to cm -// Hint: 2-12 use `length.abs.cm()` instead to ignore its em component -#(3em).cm() - ---- -// Error: 2-20 cannot convert a length with non-zero em units (`-226.77pt + 93em`) to mm -// Hint: 2-20 use `length.abs.mm()` instead to ignore its em component -#(93em - 80mm).mm() - ---- -// Error: 2-24 cannot convert a length with non-zero em units (`432pt + 4.5em`) to inches -// Hint: 2-24 use `length.abs.inches()` instead to ignore its em component -#(4.5em + 6in).inches() - ---- -// Test color kind method. -#test(rgb(1, 2, 3, 4).space(), rgb) -#test(cmyk(4%, 5%, 6%, 7%).space(), cmyk) -#test(luma(40).space(), luma) -#test(rgb(1, 2, 3, 4).space() != luma, true) - ---- -// Test color '.components()' without conversions - -#let test-components(col, ref, has-alpha: true) = { - // Perform an approximate scalar comparison. - let are-equal((a, b)) = { - let to-float(x) = if type(x) == angle { x.rad() } else { float(x) } - let epsilon = 1e-4 // The maximum error between both numbers - assert.eq(type(a), type(b)) - calc.abs(to-float(a) - to-float(b)) < epsilon - } - - let ref-without-alpha = if has-alpha { ref.slice(0, -1) } else { ref } - assert.eq(col.components().len(), ref.len()) - assert(col.components().zip(ref).all(are-equal)) - assert(col.components(alpha: false).zip(ref-without-alpha).all(are-equal)) -} -#test-components(rgb(1, 2, 3, 4), (0.39%, 0.78%, 1.18%, 1.57%)) -#test-components(luma(40), (15.69%, 100%)) -#test-components(luma(40, 50%), (15.69%, 50%)) -#test-components(cmyk(4%, 5%, 6%, 7%), (4%, 5%, 6%, 7%), has-alpha: false) -#test-components(oklab(10%, 0.2, 0.4), (10%, 0.2, 0.4, 100%)) -#test-components(oklch(10%, 0.2, 90deg), (10%, 0.2, 90deg, 100%)) -#test-components(oklab(10%, 50%, 200%), (10%, 0.2, 0.8, 100%)) -#test-components(oklch(10%, 50%, 90deg), (10%, 0.2, 90deg, 100%)) -#test-components(color.linear-rgb(10%, 20%, 30%), (10%, 20%, 30%, 100%)) -#test-components(color.hsv(10deg, 20%, 30%), (10deg, 20%, 30%, 100%)) -#test-components(color.hsl(10deg, 20%, 30%), (10deg, 20%, 30%, 100%)) - ---- -// Test color conversions. -#test(rgb(1, 2, 3).to-hex(), "#010203") -#test(rgb(1, 2, 3, 4).to-hex(), "#01020304") -#test(luma(40).to-hex(), "#282828") -#test-repr(cmyk(4%, 5%, 6%, 7%).to-hex(), "#e0dcda") -#test-repr(rgb(cmyk(4%, 5%, 6%, 7%)), rgb(87.84%, 86.27%, 85.49%, 100%)) -#test-repr(rgb(luma(40%)), rgb(40%, 40%, 40%)) -#test-repr(cmyk(luma(40)), cmyk(11.76%, 10.67%, 10.51%, 14.12%)) -#test-repr(cmyk(rgb(1, 2, 3)), cmyk(66.67%, 33.33%, 0%, 98.82%)) -#test-repr(luma(rgb(1, 2, 3)), luma(0.73%)) -#test-repr(color.hsl(luma(40)), color.hsl(0deg, 0%, 15.69%)) -#test-repr(color.hsv(luma(40)), color.hsv(0deg, 0%, 15.69%)) -#test-repr(color.linear-rgb(luma(40)), color.linear-rgb(2.12%, 2.12%, 2.12%)) -#test-repr(color.linear-rgb(rgb(1, 2, 3)), color.linear-rgb(0.03%, 0.06%, 0.09%)) -#test-repr(color.hsl(rgb(1, 2, 3)), color.hsl(-150deg, 50%, 0.78%)) -#test-repr(color.hsv(rgb(1, 2, 3)), color.hsv(-150deg, 66.67%, 1.18%)) -#test-repr(oklab(luma(40)), oklab(27.68%, 0.0, 0.0, 100%)) -#test-repr(oklab(rgb(1, 2, 3)), oklab(8.23%, -0.004, -0.007, 100%)) -#test-repr(oklch(oklab(40%, 0.2, 0.2)), oklch(40%, 0.283, 45deg, 100%)) -#test-repr(oklch(luma(40)), oklch(27.68%, 0.0, 72.49deg, 100%)) -#test-repr(oklch(rgb(1, 2, 3)), oklch(8.23%, 0.008, 240.75deg, 100%)) - ---- -// Test gradient functions. -#test(gradient.linear(red, green, blue).kind(), gradient.linear) -#test(gradient.linear(red, green, blue).stops(), ((red, 0%), (green, 50%), (blue, 100%))) -#test(gradient.linear(red, green, blue, space: rgb).sample(0%), red) -#test(gradient.linear(red, green, blue, space: rgb).sample(25%), rgb("#97873b")) -#test(gradient.linear(red, green, blue, space: rgb).sample(50%), green) -#test(gradient.linear(red, green, blue, space: rgb).sample(75%), rgb("#17a08c")) -#test(gradient.linear(red, green, blue, space: rgb).sample(100%), blue) -#test(gradient.linear(red, green, space: rgb).space(), rgb) -#test(gradient.linear(red, green, space: oklab).space(), oklab) -#test(gradient.linear(red, green, space: oklch).space(), oklch) -#test(gradient.linear(red, green, space: cmyk).space(), cmyk) -#test(gradient.linear(red, green, space: luma).space(), luma) -#test(gradient.linear(red, green, space: color.linear-rgb).space(), color.linear-rgb) -#test(gradient.linear(red, green, space: color.hsl).space(), color.hsl) -#test(gradient.linear(red, green, space: color.hsv).space(), color.hsv) -#test(gradient.linear(red, green, relative: "self").relative(), "self") -#test(gradient.linear(red, green, relative: "parent").relative(), "parent") -#test(gradient.linear(red, green).relative(), auto) -#test(gradient.linear(red, green).angle(), 0deg) -#test(gradient.linear(red, green, dir: ltr).angle(), 0deg) -#test(gradient.linear(red, green, dir: rtl).angle(), 180deg) -#test(gradient.linear(red, green, dir: ttb).angle(), 90deg) -#test(gradient.linear(red, green, dir: btt).angle(), 270deg) -#test( - gradient.linear(red, green, blue).repeat(2).stops(), - ((red, 0%), (green, 25%), (blue, 50%), (red, 50%), (green, 75%), (blue, 100%)) -) -#test( - gradient.linear(red, green, blue).repeat(2, mirror: true).stops(), - ((red, 0%), (green, 25%), (blue, 50%), (green, 75%), (red, 100%)) -) - ---- -// Test alignment methods. -#test(start.axis(), "horizontal") -#test(end.axis(), "horizontal") -#test(left.axis(), "horizontal") -#test(right.axis(), "horizontal") -#test(center.axis(), "horizontal") -#test(top.axis(), "vertical") -#test(bottom.axis(), "vertical") -#test(horizon.axis(), "vertical") -#test(start.inv(), end) -#test(end.inv(), start) -#test(left.inv(), right) -#test(right.inv(), left) -#test(center.inv(), center) -#test(top.inv(), bottom) -#test(bottom.inv(), top) -#test(horizon.inv(), horizon) - ---- -// Test 2d alignment methods. -#test((start + top).inv(), (end + bottom)) -#test((end + top).inv(), (start + bottom)) -#test((left + top).inv(), (right + bottom)) -#test((right + top).inv(), (left + bottom)) -#test((center + top).inv(), (center + bottom)) -#test((start + bottom).inv(), (end + top)) -#test((end + bottom).inv(), (start + top)) -#test((left + bottom).inv(), (right + top)) -#test((right + bottom).inv(), (left + top)) -#test((center + bottom).inv(), (center + top)) -#test((start + horizon).inv(), (end + horizon)) -#test((end + horizon).inv(), (start + horizon)) -#test((left + horizon).inv(), (right + horizon)) -#test((right + horizon).inv(), (left + horizon)) -#test((center + horizon).inv(), (center + horizon)) -#test((top + start).inv(), (end + bottom)) -#test((bottom + end).inv(), (start + top)) -#test((horizon + center).inv(), (center + horizon)) - ---- -// Test direction methods. -#test(ltr.axis(), "horizontal") -#test(rtl.axis(), "horizontal") -#test(ttb.axis(), "vertical") -#test(btt.axis(), "vertical") -#test(ltr.start(), left) -#test(rtl.start(), right) -#test(ttb.start(), top) -#test(btt.start(), bottom) -#test(ltr.end(), right) -#test(rtl.end(), left) -#test(ttb.end(), bottom) -#test(btt.end(), top) -#test(ltr.inv(), rtl) -#test(rtl.inv(), ltr) -#test(ttb.inv(), btt) -#test(btt.inv(), ttb) - ---- -// Test angle methods. -#test(1rad.rad(), 1.0) -#test(1.23rad.rad(), 1.23) -#test(0deg.rad(), 0.0) -#test(2deg.deg(), 2.0) -#test(2.94deg.deg(), 2.94) -#test(0rad.deg(), 0.0) - ---- -// Test date methods. -#test(datetime(day: 1, month: 1, year: 2000).ordinal(), 1); -#test(datetime(day: 1, month: 3, year: 2000).ordinal(), 31 + 29 + 1); -#test(datetime(day: 31, month: 12, year: 2000).ordinal(), 366); -#test(datetime(day: 1, month: 3, year: 2001).ordinal(), 31 + 28 + 1); -#test(datetime(day: 31, month: 12, year: 2001).ordinal(), 365); diff --git a/tests/typ/compiler/module.typ b/tests/typ/compiler/module.typ deleted file mode 100644 index f0652677..00000000 --- a/tests/typ/compiler/module.typ +++ /dev/null @@ -1,13 +0,0 @@ -// A file to import in import / include tests. -// Ref: false - -#let a -#let b = 1 -#let c = 2 -#let d = 3 -#let value = [hi] -#let item(a, b) = a + b -#let push(a) = a + 1 -#let fn = rect.with(fill: conifer, inset: 5pt) - -Some _includable_ text. diff --git a/tests/typ/compiler/modules/chap1.typ b/tests/typ/compiler/modules/chap1.typ deleted file mode 100644 index 06a4c1a1..00000000 --- a/tests/typ/compiler/modules/chap1.typ +++ /dev/null @@ -1,9 +0,0 @@ -// Ref: false - -#let name = "Klaus" - -== Chapter 1 -#name stood in a field of wheat. There was nothing of particular interest about -the field #name just casually surveyed for any paths on which the corn would not -totally ruin his semi-new outdorsy jacket but then again, most of us spend -considerable time in non-descript environments. diff --git a/tests/typ/compiler/modules/chap2.typ b/tests/typ/compiler/modules/chap2.typ deleted file mode 100644 index d4aedc60..00000000 --- a/tests/typ/compiler/modules/chap2.typ +++ /dev/null @@ -1,11 +0,0 @@ -// Ref: false - -#let name = "Klaus" - -== Chapter 2 -Their motivations, however, were pretty descript, so to speak. #name had not yet -conceptualized their consequences, but that should change pretty quickly. #name -approached the center of the field and picked up a 4-foot long disk made from -what could only be cow manure. The hair on the back of #name' neck bristled as -he stared at the unusual sight. After studying the object for a while, he -promptly popped the question, "How much?" diff --git a/tests/typ/compiler/modules/cycle1.typ b/tests/typ/compiler/modules/cycle1.typ deleted file mode 100644 index 02067b71..00000000 --- a/tests/typ/compiler/modules/cycle1.typ +++ /dev/null @@ -1,6 +0,0 @@ -// Ref: false - -#import "cycle2.typ": * -#let inaccessible = "wow" - -This is the first element of an import cycle. diff --git a/tests/typ/compiler/modules/cycle2.typ b/tests/typ/compiler/modules/cycle2.typ deleted file mode 100644 index 191647db..00000000 --- a/tests/typ/compiler/modules/cycle2.typ +++ /dev/null @@ -1,6 +0,0 @@ -// Ref: false - -#import "cycle1.typ": * -#let val = "much cycle" - -This is the second element of an import cycle. diff --git a/tests/typ/compiler/ops-assoc.typ b/tests/typ/compiler/ops-assoc.typ deleted file mode 100644 index ec128c61..00000000 --- a/tests/typ/compiler/ops-assoc.typ +++ /dev/null @@ -1,18 +0,0 @@ -// Test operator associativity. -// Ref: false - ---- -// Math operators are left-associative. -#test(10 / 2 / 2 == (10 / 2) / 2, true) -#test(10 / 2 / 2 == 10 / (2 / 2), false) -#test(1 / 2 * 3, 1.5) - ---- -// Assignment is right-associative. -{ - let x = 1 - let y = 2 - x = y = "ok" - test(x, none) - test(y, "ok") -} diff --git a/tests/typ/compiler/ops-invalid.typ b/tests/typ/compiler/ops-invalid.typ deleted file mode 100644 index 64e3a878..00000000 --- a/tests/typ/compiler/ops-invalid.typ +++ /dev/null @@ -1,134 +0,0 @@ -// Test invalid operations. -// Ref: false - ---- -// Error: 4 expected expression -#(-) - ---- -// Error: 10 expected expression -#test({1+}, 1) - ---- -// Error: 10 expected expression -#test({2*}, 2) - ---- -// Error: 3-13 cannot apply unary '+' to content -#(+([] + [])) - ---- -// Error: 3-6 cannot apply '-' to string -#(-"") - ---- -// Error: 3-9 cannot apply 'not' to array -#(not ()) - ---- -// Error: 3-19 cannot compare relative length and ratio -#(30% + 1pt <= 40%) - ---- -// Error: 3-14 cannot compare 1em with 10pt -#(1em <= 10pt) - ---- -// Error: 3-22 cannot compare 2.2 with NaN -#(2.2 <= float("nan")) - ---- -// Error: 3-26 cannot compare integer and string -#((0, 1, 3) > (0, 1, "a")) - ---- -// Error: 3-42 cannot compare 3.5 with NaN -#((0, "a", 3.5) <= (0, "a", float("nan"))) - ---- -// Error: 3-12 cannot divide by zero -#(1.2 / 0.0) - ---- -// Error: 3-8 cannot divide by zero -#(1 / 0) - ---- -// Error: 3-15 cannot divide by zero -#(15deg / 0deg) - ---- -// Special messages for +, -, * and /. -// Error: 3-10 cannot add integer and string -#(1 + "2", 40% - 1) - ---- -// Error: 15-23 cannot add integer and string -#{ let x = 1; x += "2" } - ---- -// Error: 4-13 cannot divide ratio by length -#( 10% / 5pt ) - ---- -// Error: 3-12 cannot divide these two lengths -#(1em / 5pt) - ---- -// Error: 3-19 cannot divide relative length by ratio -#((10% + 1pt) / 5%) - ---- -// Error: 3-28 cannot divide these two relative lengths -#((10% + 1pt) / (20% + 1pt)) - ---- -// Error: 13-20 cannot subtract integer from ratio -#((1234567, 40% - 1)) - ---- -// Error: 3-11 cannot multiply integer with boolean -#(2 * true) - ---- -// Error: 3-11 cannot divide integer by length -#(3 / 12pt) - ---- -// Error: 3-10 number must be at least zero -#(-1 * "") - ---- -// Error: 4-5 unknown variable: x -#((x) = "") - ---- -// Error: 4-5 unknown variable: x -#((x,) = (1,)) - ---- -// Error: 3-8 cannot mutate a temporary value -#(1 + 2 += 3) - ---- -// Error: 2:3-2:8 cannot apply 'not' to string -#let x = "Hey" -#(not x = "a") - ---- -// Error: 7-8 unknown variable: x -#(1 + x += 3) - ---- -// Error: 3-4 unknown variable: z -#(z = 1) - ---- -// Error: 3-7 cannot mutate a constant: rect -#(rect = "hi") - ---- -// Works if we define rect beforehand -// (since then it doesn't resolve to the standard library version anymore). -#let rect = "" -#(rect = "hi") diff --git a/tests/typ/compiler/ops-prec.typ b/tests/typ/compiler/ops-prec.typ deleted file mode 100644 index d3fe01b5..00000000 --- a/tests/typ/compiler/ops-prec.typ +++ /dev/null @@ -1,36 +0,0 @@ -// Test operator precedence. -// Ref: false - ---- -// Multiplication binds stronger than addition. -#test(1+2*-3, -5) - -// Subtraction binds stronger than comparison. -#test(3 == 5 - 2, true) - -// Boolean operations bind stronger than '=='. -#test("a" == "a" and 2 < 3, true) -#test(not "b" == "b", false) - ---- -// Assignment binds stronger than boolean operations. -// Error: 2:3-2:8 cannot mutate a temporary value -#let x = false -#(not x = "a") - ---- -// Precedence doesn't matter for chained unary operators. -// Error: 3-12 cannot apply '-' to boolean -#(-not true) - ---- -// Not in handles precedence. -#test(-1 not in (1, 2, 3), true) - ---- -// Parentheses override precedence. -#test((1), 1) -#test((1+2)*-3, -9) - -// Error: 8-9 unclosed delimiter -#test({(1 + 1}, 2) diff --git a/tests/typ/compiler/ops.typ b/tests/typ/compiler/ops.typ deleted file mode 100644 index e148dd19..00000000 --- a/tests/typ/compiler/ops.typ +++ /dev/null @@ -1,359 +0,0 @@ -// Test binary expressions. -// Ref: false - ---- -// Test adding content. -// Ref: true -#([*Hello* ] + [world!]) - ---- -// Test math operators. - -// Test plus and minus. -#for v in (1, 3.14, 12pt, 45deg, 90%, 13% + 10pt, 6.3fr) { - // Test plus. - test(+v, v) - - // Test minus. - test(-v, -1 * v) - test(--v, v) - - // Test combination. - test(-++ --v, -v) -} - -#test(-(4 + 2), 6-12) - -// Addition. -#test(2 + 4, 6) -#test("a" + "b", "ab") -#test("a" + if false { "b" }, "a") -#test("a" + if true { "b" }, "ab") -#test(13 * "a" + "bbbbbb", "aaaaaaaaaaaaabbbbbb") -#test((1, 2) + (3, 4), (1, 2, 3, 4)) -#test((a: 1) + (b: 2, c: 3), (a: 1, b: 2, c: 3)) - ---- -// Error: 3-26 value is too large -#(9223372036854775807 + 1) - ---- -// Subtraction. -#test(1-4, 3*-1) -#test(4cm - 2cm, 2cm) -#test(1e+2-1e-2, 99.99) - -// Multiplication. -#test(2 * 4, 8) - -// Division. -#test(12pt/.4, 30pt) -#test(7 / 2, 3.5) - -// Combination. -#test(3-4 * 5 < -10, true) -#test({ let x; x = 1 + 4*5 >= 21 and { x = "a"; x + "b" == "ab" }; x }, true) - -// With block. -#test(if true { - 1 -} + 2, 3) - -// Mathematical identities. -#let nums = ( - 1, 3.14, - 12pt, 3em, 12pt + 3em, - 45deg, - 90%, - 13% + 10pt, 5% + 1em + 3pt, - 2.3fr, -) - -#for v in nums { - // Test plus and minus. - test(v + v - v, v) - test(v - v - v, -v) - - // Test plus/minus and multiplication. - test(v - v, 0 * v) - test(v + v, 2 * v) - - // Integer addition does not give a float. - if type(v) != int { - test(v + v, 2.0 * v) - } - - if type(v) != relative and ("pt" not in repr(v) or "em" not in repr(v)) { - test(v / v, 1.0) - } -} - -// Make sure length, ratio and relative length -// - can all be added to / subtracted from each other, -// - multiplied with integers and floats, -// - divided by integers and floats. -#let dims = (10pt, 1em, 10pt + 1em, 30%, 50% + 3cm, 40% + 2em + 1cm) -#for a in dims { - for b in dims { - test(type(a + b), type(a - b)) - } - - for b in (7, 3.14) { - test(type(a * b), type(a)) - test(type(b * a), type(a)) - test(type(a / b), type(a)) - } -} - -// Test division of different numeric types with zero components. -#for a in (0pt, 0em, 0%) { - for b in (10pt, 10em, 10%) { - test((2 * b) / b, 2) - test((a + b * 2) / b, 2) - test(b / (b * 2 + a), 0.5) - } -} - ---- -// Test numbers with alternative bases. -#test(0x10, 16) -#test(0b1101, 13) -#test(0xA + 0xa, 0x14) - ---- -// Error: 2-7 invalid binary number: 0b123 -#0b123 - ---- -// Error: 2-8 invalid hexadecimal number: 0x123z -#0x123z - ---- -// Test that multiplying infinite numbers by certain units does not crash. -#(float("inf") * 1pt) -#(float("inf") * 1em) -#(float("inf") * (1pt + 1em)) - ---- -// Test that trying to produce a NaN scalar (such as in lengths) does not crash. -#let infpt = float("inf") * 1pt -#test(infpt - infpt, 0pt) -#test(infpt + (-infpt), 0pt) -// TODO: this result is surprising -#test(infpt / float("inf"), 0pt) - ---- -// Test boolean operators. - -// Test not. -#test(not true, false) -#test(not false, true) - -// And. -#test(false and false, false) -#test(false and true, false) -#test(true and false, false) -#test(true and true, true) - -// Or. -#test(false or false, false) -#test(false or true, true) -#test(true or false, true) -#test(true or true, true) - -// Short-circuiting. -#test(false and dont-care, false) -#test(true or dont-care, true) - ---- -// Test equality operators. - -// Most things compare by value. -#test(1 == "hi", false) -#test(1 == 1.0, true) -#test(30% == 30% + 0cm, true) -#test(1in == 0% + 72pt, true) -#test(30% == 30% + 1cm, false) -#test("ab" == "a" + "b", true) -#test(() == (1,), false) -#test((1, 2, 3) == (1, 2.0) + (3,), true) -#test((:) == (a: 1), false) -#test((a: 2 - 1.0, b: 2) == (b: 2, a: 1), true) -#test("a" != "a", false) - -// Functions compare by identity. -#test(test == test, true) -#test((() => {}) == (() => {}), false) - -// Content compares field by field. -#let t = [a] -#test(t == t, true) -#test([] == [], true) -#test([a] == [a], true) -#test(grid[a] == grid[a], true) -#test(grid[a] == grid[b], false) - ---- -// Test comparison operators. - -#test(13 * 3 < 14 * 4, true) -#test(5 < 10, true) -#test(5 > 5, false) -#test(5 <= 5, true) -#test(5 <= 4, false) -#test(45deg < 1rad, true) -#test(10% < 20%, true) -#test(50% < 40% + 0pt, false) -#test(40% + 0pt < 50% + 0pt, true) -#test(1em < 2em, true) -#test((0, 1, 2, 4) < (0, 1, 2, 5), true) -#test((0, 1, 2, 4) < (0, 1, 2, 3), false) -#test((0, 1, 2, 3.3) > (0, 1, 2, 4), false) -#test((0, 1, 2) < (0, 1, 2, 3), true) -#test((0, 1, "b") > (0, 1, "a", 3), true) -#test((0, 1.1, 3) >= (0, 1.1, 3), true) -#test((0, 1, datetime(day: 1, month: 12, year: 2023)) <= (0, 1, datetime(day: 1, month: 12, year: 2023), 3), true) -#test(("a", 23, 40, "b") > ("a", 23, 40), true) -#test(() <= (), true) -#test(() >= (), true) -#test(() <= (1,), true) -#test((1,) <= (), false) - ---- -// Test assignment operators. - -#let x = 0 -#(x = 10) #test(x, 10) -#(x -= 5) #test(x, 5) -#(x += 1) #test(x, 6) -#(x *= x) #test(x, 36) -#(x /= 2.0) #test(x, 18.0) -#(x = "some") #test(x, "some") -#(x += "thing") #test(x, "something") - ---- -// Test destructuring assignments. - -#let a = none -#let b = none -#let c = none -#((a,) = (1,)) -#test(a, 1) - -#((_, a, b, _) = (1, 2, 3, 4)) -#test(a, 2) -#test(b, 3) - -#((a, b, ..c) = (1, 2, 3, 4, 5, 6)) -#test(a, 1) -#test(b, 2) -#test(c, (3, 4, 5, 6)) - -#((a: a, b, x: c) = (a: 1, b: 2, x: 3)) -#test(a, 1) -#test(b, 2) -#test(c, 3) - -#let a = (1, 2) -#((a: a.at(0), b) = (a: 3, b: 4)) -#test(a, (3, 2)) -#test(b, 4) - -#let a = (1, 2) -#((a.at(0), b) = (3, 4)) -#test(a, (3, 2)) -#test(b, 4) - -#((a, ..b) = (1, 2, 3, 4)) -#test(a, 1) -#test(b, (2, 3, 4)) - -#let a = (1, 2) -#((b, ..a.at(0)) = (1, 2, 3, 4)) -#test(a, ((2, 3, 4), 2)) -#test(b, 1) - ---- -// Test comma placement in destructuring assignment. -#let array = (1, 2, 3) -#((key: array.at(1)) = (key: "hi")) -#test(array, (1, "hi", 3)) - -#let array = (1, 2, 3) -#((array.at(1)) = ("hi")) -#test(array, (1, "hi", 3)) - -#let array = (1, 2, 3) -#((array.at(1),) = ("hi",)) -#test(array, (1, "hi", 3)) - -#let array = (1, 2, 3) -#((array.at(1)) = ("hi",)) -#test(array, (1, ("hi",), 3)) - ---- -// Test nested destructuring assignment. -#let a -#let b -#let c -#(((a, b), (key: c)) = ((1, 2), (key: 3))) -#test((a, b, c), (1, 2, 3)) - ---- -#let array = (1, 2, 3) -// Error: 3-17 cannot destructure string -#((array.at(1),) = ("hi")) -#test(array, (1, ("hi",), 3)) - ---- -// Error: 3-6 cannot mutate a constant: box -#(box = 1) - ---- -// Test `in` operator. -#test("hi" in "worship", true) -#test("hi" in ("we", "hi", "bye"), true) -#test("Hey" in "abHeyCd", true) -#test("Hey" in "abheyCd", false) -#test(5 in range(10), true) -#test(12 in range(10), false) -#test("" in (), false) -#test("key" in (key: "value"), true) -#test("value" in (key: "value"), false) -#test("Hey" not in "abheyCd", true) -#test("a" not -/* fun comment? */ in "abc", false) - ---- -// Error: 10 expected keyword `in` -#("a" not) - ---- -// Test `with` method. - -// Apply positional arguments. -#let add(x, y) = x + y -#test(add.with(2)(3), 5) -#test(add.with(2, 3)(), 5) -#test(add.with(2).with(3)(), 5) -#test((add.with(2))(4), 6) -#test((add.with(2).with(3))(), 5) - -// Make sure that named arguments are overridable. -#let inc(x, y: 1) = x + y -#test(inc(1), 2) - -#let inc2 = inc.with(y: 2) -#test(inc2(2), 4) -#test(inc2(2, y: 4), 6) - -// Apply arguments to an argument sink. -#let times(..sink) = { - let res = sink.pos().product() - if sink.named().at("negate", default: false) { res *= -1 } - res -} -#test((times.with(2, negate: true).with(5))(), -10) -#test((times.with(2).with(5).with(negate: true))(), -10) -#test((times.with(2).with(5, negate: true))(), -10) -#test((times.with(2).with(negate: true))(5), -10) diff --git a/tests/typ/compiler/packages.typ b/tests/typ/compiler/packages.typ deleted file mode 100644 index 0d3fda58..00000000 --- a/tests/typ/compiler/packages.typ +++ /dev/null @@ -1,69 +0,0 @@ -// Test package imports -// Ref: false - ---- -// Test import without items. -#import "@test/adder:0.1.0" -#test(adder.add(2, 8), 10) - ---- -// Test import with items. -#import "@test/adder:0.1.0": add -#test(add(2, 8), 10) - ---- -// Test too high required compiler version. -// Error: 9-29 package requires typst 1.0.0 or newer (current version is VERSION) -#import "@test/future:0.1.0": future - ---- -// Error: 9-13 `@` is not a valid package namespace -#import "@@": * - ---- -// Error: 9-16 package specification is missing name -#import "@heya": * - ---- -// Error: 9-15 `123` is not a valid package namespace -#import "@123": * - ---- -// Error: 9-17 package specification is missing name -#import "@test/": * - ---- -// Error: 9-22 package specification is missing version -#import "@test/mypkg": * - ---- -// Error: 9-20 `$$$` is not a valid package name -#import "@test/$$$": * - ---- -// Error: 9-23 package specification is missing version -#import "@test/mypkg:": * - ---- -// Error: 9-24 version number is missing minor version -#import "@test/mypkg:0": * - ---- -// Error: 9-29 `latest` is not a valid major version -#import "@test/mypkg:latest": * - ---- -// Error: 9-29 `-3` is not a valid major version -#import "@test/mypkg:-3.0.0": * - ---- -// Error: 9-26 version number is missing patch version -#import "@test/mypkg:0.3": * - ---- -// Error: 9-27 version number is missing patch version -#import "@test/mypkg:0.3.": * - ---- -// Error: 9-28 file not found (searched at typ/compiler/#test/mypkg:1.0.0) -#import "#test/mypkg:1.0.0": * diff --git a/tests/typ/compiler/plugin-oob.typ b/tests/typ/compiler/plugin-oob.typ deleted file mode 100644 index 4d1ba205..00000000 --- a/tests/typ/compiler/plugin-oob.typ +++ /dev/null @@ -1,14 +0,0 @@ -// Test Out Of Bound read/write in WebAssembly plugins communication. -// Ref: false - ---- -#let p = plugin("/assets/plugins/plugin-oob.wasm") - -// Error: 2-14 plugin tried to read out of bounds: pointer 0x40000000 is out of bounds for read of length 1 -#p.read_oob() - ---- -#let p = plugin("/assets/plugins/plugin-oob.wasm") - -// Error: 2-27 plugin tried to write out of bounds: pointer 0x40000000 is out of bounds for write of length 3 -#p.write_oob(bytes("xyz")) diff --git a/tests/typ/compiler/plugin.typ b/tests/typ/compiler/plugin.typ deleted file mode 100644 index e727355f..00000000 --- a/tests/typ/compiler/plugin.typ +++ /dev/null @@ -1,36 +0,0 @@ -// Test WebAssembly plugins. -// Ref: false - ---- -#let p = plugin("/assets/plugins/hello.wasm") -#test(p.hello(), bytes("Hello from wasm!!!")) -#test(p.double_it(bytes("hey!")), bytes("hey!.hey!")) -#test( - p.shuffle(bytes("value1"), bytes("value2"), bytes("value3")), - bytes("value3-value1-value2"), -) - ---- -#let p = plugin("/assets/plugins/hello.wasm") - -// Error: 2-20 plugin function takes 0 arguments, but 1 was given -#p.hello(bytes("")) - ---- -#let p = plugin("/assets/plugins/hello.wasm") - -// Error: 10-14 expected bytes, found boolean -// Error: 27-29 expected bytes, found integer -#p.hello(true, bytes(()), 10) - ---- -#let p = plugin("/assets/plugins/hello.wasm") - -// Error: 2-17 plugin errored with: This is an `Err` -#p.returns_err() - ---- -#let p = plugin("/assets/plugins/hello.wasm") - -// Error: 2-16 plugin panicked: wasm `unreachable` instruction executed -#p.will_panic() diff --git a/tests/typ/compiler/raw.typ b/tests/typ/compiler/raw.typ deleted file mode 100644 index 3084146d..00000000 --- a/tests/typ/compiler/raw.typ +++ /dev/null @@ -1,170 +0,0 @@ -// Test new raw parser -// Ref: false - ---- -#let empty = ( - name: "empty", - input: ``, - text: "", -) - -#let backtick = ( - name: "backtick", - input: ``` ` ```, - text: "`", - block: false, -) - -#let lang-backtick = ( - name: "lang-backtick", - input: ```js ` ```, - lang: "js", - text: "`", - block: false, -) - -// The language tag stops on space -#let lang-space = ( - name: "lang-space", - input: ```js test ```, - lang: "js", - text: "test ", - block: false, -) - -// The language tag stops on newline -#let lang-newline = ( - name: "lang-newline", - input: ```js -test -```, - lang: "js", - text: "test", - block: true, -) - -// The first line and the last line are ignored -#let blocky = ( - name: "blocky", - input: { -``` -test -``` -}, - text: "test", - block: true, -) - -// A blocky raw should handle dedents -#let blocky-dedent = ( - name: "blocky-dedent", - input: { -``` - test - ``` - }, - text: "test", - block: true, -) - -// When there is content in the first line, it should exactly eat a whitespace char. -#let blocky-dedent-firstline = ( - name: "blocky-dedent-firstline", - input: ``` test - ```, - text: "test", - block: true, -) - -// When there is content in the first line, it should exactly eat a whitespace char. -#let blocky-dedent-firstline2 = ( - name: "blocky-dedent-firstline2", - input: ``` test -```, - text: "test", - block: true, -) - -// The first line is not affected by dedent, and the middle lines don't consider the whitespace prefix of the first line. -#let blocky-dedent-firstline3 = ( - name: "blocky-dedent-firstline3", - input: ``` test - test2 - ```, - text: "test\n test2", - block: true, -) - -// The first line is not affected by dedent, and the middle lines don't consider the whitespace prefix of the first line. -#let blocky-dedent-firstline4 = ( - name: "blocky-dedent-firstline4", - input: ``` test - test2 - ```, - text: " test\ntest2", - block: true, -) - -#let blocky-dedent-lastline = ( - name: "blocky-dedent-lastline", - input: ``` - test - ```, - text: " test", - block: true, -) - -#let blocky-dedent-lastline2 = ( - name: "blocky-dedent-lastline2", - input: ``` - test - ```, - text: "test", - block: true, -) - -#let blocky-tab = ( - name: "blocky-tab", - input: { -``` - test -``` -}, - text: "\ttest", - block: true, -) - -#let blocky-tab-dedent = ( - name: "blocky-tab-dedent", - input: { -``` - test - - ``` -}, - text: "test\n ", - block: true, -) - -#let cases = ( - empty, - backtick, - lang-backtick, - lang-space, - lang-newline, - blocky, - blocky-dedent, - blocky-dedent-firstline, - blocky-dedent-firstline2, - blocky-dedent-firstline3, - blocky-dedent-lastline, - blocky-dedent-lastline2, - blocky-tab, - blocky-tab-dedent, -) - -#for c in cases { - assert.eq(c.text, c.input.text, message: "in point " + c.name + ", expect " + repr(c.text) + ", got " + repr(c.input.text) + "") - let block = c.at("block", default: false) - assert.eq(block, c.input.block, message: "in point " + c.name + ", expect " + repr(block) + ", got " + repr(c.input.block) + "") -} diff --git a/tests/typ/compiler/recursion.typ b/tests/typ/compiler/recursion.typ deleted file mode 100644 index 421b638b..00000000 --- a/tests/typ/compiler/recursion.typ +++ /dev/null @@ -1,56 +0,0 @@ -// Test recursive function calls. -// Ref: false - ---- -// Test with named function. -#let fib(n) = { - if n <= 2 { - 1 - } else { - fib(n - 1) + fib(n - 2) - } -} - -#test(fib(10), 55) - ---- -// Test with unnamed function. -// Error: 17-18 unknown variable: f -#let f = (n) => f(n - 1) -#f(10) - ---- -// Test capturing with named function. -#let f = 10 -#let f() = f -#test(type(f()), function) - ---- -// Test capturing with unnamed function. -#let f = 10 -#let f = () => f -#test(type(f()), int) - ---- -// Test redefinition. -#let f(x) = "hello" -#let f(x) = if x != none { f(none) } else { "world" } -#test(f(1), "world") - ---- -// Error: 15-21 maximum function call depth exceeded -#let rec(n) = rec(n) + 1 -#rec(1) - ---- -// Test cyclic imports during layout. -// Error: 2-38 maximum show rule depth exceeded -// Hint: 2-38 check whether the show rule matches its own output -#layout(_ => include "recursion.typ") - ---- -// Test recursive show rules. -// Error: 22-25 maximum show rule depth exceeded -// Hint: 22-25 check whether the show rule matches its own output -#show math.equation: $x$ -$ x $ diff --git a/tests/typ/compiler/repr-color-gradient.typ b/tests/typ/compiler/repr-color-gradient.typ deleted file mode 100644 index ef158974..00000000 --- a/tests/typ/compiler/repr-color-gradient.typ +++ /dev/null @@ -1,23 +0,0 @@ -// Test representation of values in the document. - ---- -// Colors -#set page(width: 400pt) -#set text(0.8em) -#blue \ -#color.linear-rgb(blue) \ -#oklab(blue) \ -#oklch(blue) \ -#cmyk(blue) \ -#color.hsl(blue) \ -#color.hsv(blue) \ -#luma(blue) - ---- -// Gradients -#set page(width: 400pt) -#set text(0.8em) -#gradient.linear(blue, red) \ -#gradient.linear(blue, red, dir: ttb) \ -#gradient.linear(blue, red, angle: 45deg, relative: "self") \ -#gradient.linear(blue, red, angle: 45deg, space: rgb) diff --git a/tests/typ/compiler/repr.typ b/tests/typ/compiler/repr.typ deleted file mode 100644 index 5aaf5710..00000000 --- a/tests/typ/compiler/repr.typ +++ /dev/null @@ -1,55 +0,0 @@ -// Test representation of values in the document. - ---- -// Literal values. -#auto \ -#none (empty) \ -#true \ -#false - ---- -// Numerical values. -#1 \ -#1.0e-4 \ -#3.15 \ -#1e-10 \ -#50.368% \ -#0.0000012345pt \ -#4.5cm \ -#12e1pt \ -#2.5rad \ -#45deg \ -#1.7em \ -#(1cm + 0em) \ -#(2em + 10pt) \ -#(100% + (2em + 2pt)) \ -#(100% + 0pt) \ -#(100% - 2em + 2pt) \ -#(100% - 2pt) \ -#2.3fr - ---- -// Colors and strokes. -#set text(0.8em) -#rgb("f7a205") \ -#(2pt + rgb("f7a205")) - -// Strings and escaping. -#raw(repr("hi"), lang: "typc") -#repr("a\n[]\"\u{1F680}string") - -// Content. -#raw(lang: "typc", repr[*Hey*]) \ -#raw(lang: "typc", repr[A _sequence_]) \ -#raw(lang: "typc", repr[A _longer_ *sequence*!]) - -// Functions. -#let f(x) = x -#f \ -#rect \ -#(() => none) - -// Types. -#int \ -#type("hi") \ -#type((a: 1)) diff --git a/tests/typ/compiler/return.typ b/tests/typ/compiler/return.typ deleted file mode 100644 index e709d6a7..00000000 --- a/tests/typ/compiler/return.typ +++ /dev/null @@ -1,89 +0,0 @@ -// Test return out of functions. -// Ref: false - ---- -// Test return with value. -#let f(x) = { - return x + 1 -} - -#test(f(1), 2) - ---- -// Test return with joining. - -#let f(x) = { - "a" - if x == 0 { - return "b" - } else if x == 1 { - "c" - } else { - "d" - return - "e" - } -} - -#test(f(0), "b") -#test(f(1), "ac") -#test(f(2), "ad") - ---- -// Test return with joining and content. -// Ref: true - -#let f(text, caption: none) = { - text - if caption == none [\.#return] - [, ] - emph(caption) - [\.] -} - -#f(caption: [with caption])[My figure] - -#f[My other figure] - ---- -// Test return outside of function. - -#for x in range(5) { - // Error: 3-9 cannot return outside of function - return -} - ---- -// Test that the expression is evaluated to the end. -#let sum(..args) = { - let s = 0 - for v in args.pos() { - s += v - } - s -} - -#let f() = { - sum(..return, 1, 2, 3) - "nope" -} - -#test(f(), 6) - ---- -// Test value return from content. -#let x = 3 -#let f() = [ - Hello π - #return "nope" - World -] - -#test(f(), "nope") - ---- -// Test rejection of extra value -#let f() = [ - // Error: 16-16 expected semicolon or line break - #return a + b Hello World -] diff --git a/tests/typ/compiler/select-where-styles.typ b/tests/typ/compiler/select-where-styles.typ deleted file mode 100644 index 028be2e9..00000000 --- a/tests/typ/compiler/select-where-styles.typ +++ /dev/null @@ -1,91 +0,0 @@ -// Test that where selectors also work with settable fields. - ---- -// 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. - ---- -// 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! - ---- -// 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 -] - ---- -// 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() -} - ---- -// 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() -} - - ---- -// 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/typ/compiler/selector-logical.typ b/tests/typ/compiler/selector-logical.typ deleted file mode 100644 index 5369e4c7..00000000 --- a/tests/typ/compiler/selector-logical.typ +++ /dev/null @@ -1,126 +0,0 @@ -//Tests for logical (and/or) selectors - ---- -= A -== B -#figure([Cat], kind: "cat", supplement: [Other]) -=== D -= E <first> -#figure([Frog], kind: "frog", supplement: none) -#figure([Giraffe], kind: "giraffe", supplement: none) <second> -#figure([GiraffeCat], kind: "cat", supplement: [Other]) <second> -= H -#figure([Iguana], kind: "iguana", supplement: none) -== I - -#let test-selector(selector, ref) = context { - test(query(selector).map(e => e.body), ref) -} - -// Test `or`. -#test-selector( - heading.where(level: 1).or(heading.where(level: 3)), - ([A], [D], [E], [H]), -) - -#test-selector( - heading.where(level: 1).or( - heading.where(level: 3), - figure.where(kind: "frog"), - ), - ([A], [D], [E], [Frog], [H]), -) - -#test-selector( - heading.where(level: 1).or( - heading.where(level: 2), - figure.where(kind: "frog"), - figure.where(kind: "cat"), - ), - ([A], [B], [Cat], [E], [Frog], [GiraffeCat], [H], [I]), -) - -#test-selector( - figure.where(kind: "dog").or(heading.where(level: 3)), - ([D],), -) - -#test-selector( - figure.where(kind: "dog").or(figure.where(kind: "fish")), - (), -) - -// Test `or` duplicates removal. -#test-selector( - heading.where(level: 1).or(heading.where(level: 1)), - ([A], [E], [H]), -) - -// Test `and`. -#test-selector( - figure.where(kind: "cat").and(figure.where(kind: "frog")), - (), -) - -// Test `or` with `before`/`after` -#test-selector( - selector(heading) - .before(<first>) - .or(selector(figure).before(<first>)), - ([A], [B], [Cat], [D], [E]), -) - -#test-selector( - heading.where(level: 2) - .after(<first>) - .or(selector(figure).after(<first>)), - ([Frog], [Giraffe], [GiraffeCat], [Iguana], [I]), -) - -// Test `and` with `after` -#test-selector( - figure.where(kind: "cat") - .and(figure.where(supplement: [Other])) - .after(<first>), - ([GiraffeCat],), -) - -// Test `and` (with nested `or`) -#test-selector( - heading.where(level: 2) - .or(heading.where(level: 3)) - .and(heading.where(level: 2).or(heading.where(level: 1))), - ([B], [I]), -) - -#test-selector( - heading.where(level: 2) - .or(heading.where(level: 3), heading.where(level:1)) - .and( - heading.where(level: 2).or(heading.where(level: 1)), - heading.where(level: 3).or(heading.where(level: 1)), - ), - ([A], [E], [H]), -) - -// Test `and` with `or` and `before`/`after` -#test-selector( - heading.where(level: 1).before(<first>) - .or(heading.where(level: 3).before(<first>)) - .and( - heading.where(level: 1).before(<first>) - .or(heading.where(level: 2).before(<first>)) - ), - ([A], [E]), -) - -#test-selector( - heading.where(level: 1).before(<first>, inclusive: false) - .or(selector(figure).after(<first>)) - .and(figure.where(kind: "iguana").or( - figure.where(kind: "frog"), - figure.where(kind: "cat"), - heading.where(level: 1).after(<first>), - )), - ([Frog], [GiraffeCat], [Iguana]) -) diff --git a/tests/typ/compiler/set.typ b/tests/typ/compiler/set.typ deleted file mode 100644 index 23b3a7c6..00000000 --- a/tests/typ/compiler/set.typ +++ /dev/null @@ -1,66 +0,0 @@ -// General tests for set. - ---- -// Test that text is affected by instantiation-site bold. -#let x = [World] -Hello *#x* - ---- -// 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 - ---- -// 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) - ---- -// Test that scoping works as expected. -#{ - if true { - set text(blue) - [Blue ] - } - [Not blue] -} - ---- -// 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 - ---- -// Test conditional set. -#show ref: it => { - set text(red) if it.target == <unknown> - "@" + str(it.target) -} - -@hello from the @unknown - ---- -// Error: 19-24 expected boolean, found integer -#set text(red) if 1 + 2 - ---- -// Error: 12-26 set is only allowed directly in code and content blocks -#{ let x = set text(blue) } diff --git a/tests/typ/compiler/shorthand.typ b/tests/typ/compiler/shorthand.typ deleted file mode 100644 index 54ae7473..00000000 --- a/tests/typ/compiler/shorthand.typ +++ /dev/null @@ -1,61 +0,0 @@ -// Test shorthands for unicode codepoints. - ---- -The non-breaking space~does work, soft-?hyphen also does. - ---- -// Make sure non-breaking and normal space always -// have the same width. Even if the font decided -// differently. -#set text(font: "New Computer Modern") -a b \ -a~b - ---- -- En dash: -- -- Em dash: --- - ---- -#set text(font: "Roboto") -A... vs #"A..." - ---- -// Check all math shorthands -$...$\ -$-$\ -$'$\ -$*$\ -$!=$\ -$:=$\ -$::=$\ -$=:$\ -$<<$\ -$<<<$\ -$>>$\ -$>>>$\ -$<=$\ -$>=$\ -$->$\ -$-->$\ -$|->$\ -$>->$\ -$->>$\ -$<-$\ -$<--$\ -$<-<$\ -$<<-$\ -$<->$\ -$<-->$\ -$~>$\ -$~~>$\ -$<~$\ -$<~~$\ -$=>$\ -$|=>$\ -$==>$\ -$<==$\ -$<=>$\ -$<==>$\ -$[|$\ -$|]$\ -$||$ diff --git a/tests/typ/compiler/show-bare.typ b/tests/typ/compiler/show-bare.typ deleted file mode 100644 index 210f072d..00000000 --- a/tests/typ/compiler/show-bare.typ +++ /dev/null @@ -1,41 +0,0 @@ -// Test bare show without selector. - ---- -#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. - ---- -// Test bare show in content block. -A #[_B #show: c => [*#c*]; C_] D - ---- -// Test style precedence. -#set text(fill: eastern, size: 1.5em) -#show: text.with(fill: forest) -Forest - ---- -#show: [Shown] -Ignored - ---- -// Error: 4-19 show is only allowed directly in code and content blocks -#((show: body => 2) * body) - ---- -// Error: 6 expected colon -#show it => {} - ---- -// Error: 6 expected colon -#show it diff --git a/tests/typ/compiler/show-node.typ b/tests/typ/compiler/show-node.typ deleted file mode 100644 index ff2bdb5a..00000000 --- a/tests/typ/compiler/show-node.typ +++ /dev/null @@ -1,104 +0,0 @@ -// Test show rules. - ---- -// Override lists. -#show list: it => "(" + it.children.map(v => v.body).join(", ") + ")" - -- A - - B - - C -- D -- E - ---- -// Test full reset. -#show heading: [B] -#show heading: set text(size: 10pt, weight: 400) -A #[= Heading] C - ---- -// Test full removal. -#show heading: none - -Where is -= There are no headings around here! -my heading? - ---- -// 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. - ---- -// Test set and show in code blocks. -#show heading: it => { - set text(red) - show "ding": [π] - it.body -} - -= Heading - ---- -// Test that scoping works as expected. -#{ - let world = [ World ] - show "W": strong - world - { - set text(blue) - show: it => { - show "o": "Γ" - it - } - world - } - world -} - ---- -#show heading: [1234] -= Heading - ---- -// Error: 25-29 content does not contain field "page" -#show heading: it => it.page -= Heading - ---- -#show text: none -Hey - ---- -// Error: 7-12 only element functions can be used as selectors -#show upper: it => {} - ---- -// Error: 16-20 expected content or function, found integer -#show heading: 1234 -= Heading - ---- -// Error: 7-10 expected symbol, string, label, function, regex, or selector, found color -#show red: [] - ---- -// Error: 7-25 show is only allowed directly in code and content blocks -#(1 + show heading: none) diff --git a/tests/typ/compiler/show-recursive.typ b/tests/typ/compiler/show-recursive.typ deleted file mode 100644 index 91a295f2..00000000 --- a/tests/typ/compiler/show-recursive.typ +++ /dev/null @@ -1,51 +0,0 @@ -// Test recursive show rules. - ---- -// Test basic identity. -#show heading: it => it -= Heading - ---- -// Test more recipes down the chain. -#show list: scale.with(origin: left, x: 80%) -#show heading: [] -#show enum: [] -- Actual -- Tight -- List -= Nope - ---- -// 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 - ---- -// 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! diff --git a/tests/typ/compiler/show-selector-logical.typ b/tests/typ/compiler/show-selector-logical.typ deleted file mode 100644 index a11e20b6..00000000 --- a/tests/typ/compiler/show-selector-logical.typ +++ /dev/null @@ -1,21 +0,0 @@ -// Test and/or selectors in show rules. - ---- -// 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 - ---- -// Test element selector combined with label selector. -#show selector(strong).or(<special>): highlight -I am *strong*, I am _emphasized_, and I am #[special<special>]. - ---- -// 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) diff --git a/tests/typ/compiler/show-selector.typ b/tests/typ/compiler/show-selector.typ deleted file mode 100644 index db6db40f..00000000 --- a/tests/typ/compiler/show-selector.typ +++ /dev/null @@ -1,39 +0,0 @@ -// Test show rule patterns. - ---- -// 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 heading: set text(green) -#show heading.where(level: 1): set text(red) -#show heading.where(level: 2): set text(blue) -= Red -== Blue -=== Green diff --git a/tests/typ/compiler/show-set-func.typ b/tests/typ/compiler/show-set-func.typ deleted file mode 100644 index 0447d946..00000000 --- a/tests/typ/compiler/show-set-func.typ +++ /dev/null @@ -1,16 +0,0 @@ -// Test set rules on an element in show rules for said element. - ---- -// 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* - ---- -// 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/typ/compiler/show-set-text.typ b/tests/typ/compiler/show-set-text.typ deleted file mode 100644 index 464cad90..00000000 --- a/tests/typ/compiler/show-set-text.typ +++ /dev/null @@ -1,41 +0,0 @@ -// Text show-set rules are weird. - ---- -#show "He": set text(red) -#show "ya": set text(blue) -Heya - ---- -#show "Heya": set text(red) -#show "ya": set text(blue) -Heya - ---- -#show "He": set text(red) -#show "Heya": set text(blue) -Heya - ---- -#show "Heya": set text(red) -#show "yaho": set text(blue) -Heyaho - ---- -#show "He": set text(red) -#show "ya": set text(weight: "bold") -Heya - ---- -#show "Heya": set text(red) -#show "ya": set text(weight: "bold") -Heya - ---- -#show "He": set text(red) -#show "Heya": set text(weight: "bold") -Heya - ---- -#show "Heya": set text(red) -#show "yaho": set text(weight: "bold") -Heyaho diff --git a/tests/typ/compiler/show-set.typ b/tests/typ/compiler/show-set.typ deleted file mode 100644 index e336f517..00000000 --- a/tests/typ/compiler/show-set.typ +++ /dev/null @@ -1,55 +0,0 @@ -// Test show-set rules. - ---- -// Test overriding show-set rules. -#show strong: set text(red) -Hello *World* - -#show strong: set text(blue) -Hello *World* - ---- -// 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], -) - ---- -// 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 - ---- -// 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 - ---- -// Same thing, but even more cursed, because `kind` is synthesized. -#show figure.where(kind: table): set figure(kind: raw) -#figure(table[A], caption: [Code]) - ---- -// 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 - ---- -// 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]) diff --git a/tests/typ/compiler/show-text.typ b/tests/typ/compiler/show-text.typ deleted file mode 100644 index a42abfb2..00000000 --- a/tests/typ/compiler/show-text.typ +++ /dev/null @@ -1,93 +0,0 @@ -// Test text replacement show rules. - ---- -// Test classic example. -#set text(font: "Roboto") -#show "Der Spiegel": smallcaps -Die Zeitung Der Spiegel existiert. - ---- -// 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! - ---- -// Test direct cycle. -#show "Hello": text(red)[Hello] -Hello World! - ---- -// Test replacing text with raw text. -#show "rax": `rax` -The register rax. - ---- -// Test indirect cycle. -#show "Good": [Typst!] -#show "Typst": [Fun!] -#show "Fun": [Good!] - -#set text(ligatures: false) -Good \ -Fun \ -Typst \ - ---- -// Test that replacements happen exactly once. -#show "A": [BB] -#show "B": [CC] -AA (8) - ---- -// Test caseless match and word boundaries. -#show regex("(?i)\bworld\b"): [π] - -Treeworld, the World of worlds, is a world. - ---- -// Test there is no crashing on empty strings -// Error: 1:7-1:9 text selector is empty -#show "": [] - ---- -// Error: 1:7-1:16 regex selector is empty -#show regex(""): [AA] - ---- -// Error: 1:7-1:42 regex matches empty text -#show regex("(VAR_GLOBAL|END_VAR||BOOL)") : [] - ---- -// This is a fun one. -#set par(justify: true) -#show regex("\S"): letter => box(stroke: 1pt, inset: 2pt, upper(letter)) -#lorem(5) - ---- -// 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. - ---- -// Test accessing the string itself. -#show "hello": it => it.text.split("").map(upper).join("|") -Oh, hello there! - ---- -// Replace worlds but only in lists. -#show list: it => [ - #show "World": [π] - #it -] - -World -- World - ---- -// Test absolute path in layout phase. - -#show "GRAPH": image("/assets/images/graph.png") - -The GRAPH has nodes. diff --git a/tests/typ/compiler/spread.typ b/tests/typ/compiler/spread.typ deleted file mode 100644 index db658453..00000000 --- a/tests/typ/compiler/spread.typ +++ /dev/null @@ -1,133 +0,0 @@ -// Test argument sinks and spreading. -// Ref: false - ---- -// Test standard argument overriding. -#{ - let f(style: "normal", weight: "regular") = { - "(style: " + style + ", weight: " + weight + ")" - } - - let myf(..args) = f(weight: "bold", ..args) - test(myf(), "(style: normal, weight: bold)") - test(myf(weight: "black"), "(style: normal, weight: black)") - test(myf(style: "italic"), "(style: italic, weight: bold)") -} - ---- -// Test multiple calls. -#{ - let f(b, c: "!") = b + c - let g(a, ..sink) = a + f(..sink) - test(g("a", "b", c: "c"), "abc") -} - ---- -// Test doing things with arguments. -#{ - let save(..args) = { - test(type(args), arguments) - test(repr(args), "(three: true, 1, 2)") - } - - save(1, 2, three: true) -} - ---- -// Test spreading array and dictionary. -#{ - let more = (3, -3, 6, 10) - test(calc.min(1, 2, ..more), -3) - test(calc.max(..more, 9), 10) - test(calc.max(..more, 11), 11) -} - -#{ - let more = (c: 3, d: 4) - let tostr(..args) = repr(args) - test(tostr(a: 1, ..more, b: 2), "(a: 1, c: 3, d: 4, b: 2)") -} - ---- -// None is spreadable. -#let f() = none -#f(..none) -#f(..if false {}) -#f(..for x in () []) - ---- -// unnamed spread -#let f(.., a) = a -#test(f(1, 2, 3), 3) - ---- -// Error: 11-19 cannot spread string -#calc.min(.."nope") - ---- -// Error: 10-14 expected pattern, found boolean -#let f(..true) = none - ---- -// Error: 13-16 only one argument sink is allowed -#let f(..a, ..b) = none - ---- -// Test spreading into array and dictionary. -#{ - let l = (1, 2, 3) - let r = (5, 6, 7) - test((..l, 4, ..r), range(1, 8)) - test((..none), ()) -} - -#{ - let x = (a: 1) - let y = (b: 2) - let z = (a: 3) - test((:..x, ..y, ..z), (a: 3, b: 2)) - test((..(a: 1), b: 2), (a: 1, b: 2)) -} - ---- -// Error: 9-17 cannot spread dictionary into array -#(1, 2, ..(a: 1)) - ---- -// Error: 3-11 cannot spread array into dictionary -#(..(1, 2), a: 1) - ---- -// Spread at beginning. -#{ - let f(..a, b) = (a, b) - test(repr(f(1)), "((), 1)") - test(repr(f(1, 2, 3)), "((1, 2), 3)") - test(repr(f(1, 2, 3, 4, 5)), "((1, 2, 3, 4), 5)") -} - ---- -// Spread in the middle. -#{ - let f(a, ..b, c) = (a, b, c) - test(repr(f(1, 2)), "(1, (), 2)") - test(repr(f(1, 2, 3, 4, 5)), "(1, (2, 3, 4), 5)") -} - ---- -// Unnamed sink should just ignore any extra arguments. -#{ - let f(a, b: 5, ..) = (a, b) - test(f(4), (4, 5)) - test(f(10, b: 11), (10, 11)) - test(f(13, 20, b: 12), (13, 12)) - test(f(15, b: 16, c: 13), (15, 16)) -} - ---- -#{ - let f(..a, b, c, d) = none - - // Error: 3-10 missing argument: d - f(1, 2) -} diff --git a/tests/typ/compiler/string.typ b/tests/typ/compiler/string.typ deleted file mode 100644 index 949a2154..00000000 --- a/tests/typ/compiler/string.typ +++ /dev/null @@ -1,247 +0,0 @@ -// Test the string methods. -// Ref: false - ---- -// Test the `len` method. -#test("Hello World!".len(), 12) - ---- -// Test the `first` and `last` methods. -#test("Hello".first(), "H") -#test("Hello".last(), "o") -#test("π³οΈβπAπ³οΈββ§οΈ".first(), "π³οΈβπ") -#test("π³οΈβπAπ³οΈββ§οΈ".last(), "π³οΈββ§οΈ") - ---- -// Error: 2-12 string is empty -#"".first() - ---- -// Error: 2-11 string is empty -#"".last() - ---- -// Test the `at` method. -#test("Hello".at(1), "e") -#test("Hello".at(4), "o") -#test("Hello".at(-1), "o") -#test("Hello".at(-2), "l") -#test("Hey: π³οΈβπ there!".at(5), "π³οΈβπ") - ---- -// Test `at`'s 'default' parameter. -#test("z", "Hello".at(5, default: "z")) - ---- -// Error: 2-14 string index 2 is not a character boundary -#"π³οΈβπ".at(2) - ---- -// Error: 2-15 no default value was specified and string index out of bounds (index: 5, len: 5) -#"Hello".at(5) - ---- -#test("Hello".at(5, default: (a: 10)), (a: 10)) - ---- -// Test the `slice` method. -#test("abc".slice(1, 2), "b") -#test("abcπ‘def".slice(2, 7), "cπ‘") -#test("abcπ‘def".slice(2, -2), "cπ‘d") -#test("abcπ‘def".slice(-3, -1), "de") - ---- -// Error: 2-21 string index -1 is not a character boundary -#"π³οΈβπ".slice(0, -1) - ---- -// Test the `clusters` and `codepoints` methods. -#test("abc".clusters(), ("a", "b", "c")) -#test("abc".clusters(), ("a", "b", "c")) -#test("π³οΈβπ!".clusters(), ("π³οΈβπ", "!")) -#test("π³οΈβπ!".codepoints(), ("π³", "\u{fe0f}", "\u{200d}", "π", "!")) - ---- -// Test the `contains` method. -#test("abc".contains("b"), true) -#test("b" in "abc", true) -#test("1234f".contains(regex("\d")), true) -#test(regex("\d") in "1234f", true) -#test("abc".contains("d"), false) -#test("1234g" in "1234f", false) -#test("abc".contains(regex("^[abc]$")), false) -#test("abc".contains(regex("^[abc]+$")), true) - ---- -// Test the `starts-with` and `ends-with` methods. -#test("Typst".starts-with("Ty"), true) -#test("Typst".starts-with(regex("[Tt]ys")), false) -#test("Typst".starts-with("st"), false) -#test("Typst".ends-with("st"), true) -#test("Typst".ends-with(regex("\d*")), true) -#test("Typst".ends-with(regex("\d+")), false) -#test("Typ12".ends-with(regex("\d+")), true) -#test("typst13".ends-with(regex("1[0-9]")), true) -#test("typst113".ends-with(regex("1[0-9]")), true) -#test("typst23".ends-with(regex("1[0-9]")), false) - ---- -// Test the `find` and `position` methods. -#let date = regex("\d{2}:\d{2}") -#test("Hello World".find("World"), "World") -#test("Hello World".position("World"), 6) -#test("It's 12:13 now".find(date), "12:13") -#test("It's 12:13 now".position(date), 5) - ---- -// Test the `match` method. -#test("Is there a".match("for this?"), none) -#test( - "The time of my life.".match(regex("[mit]+e")), - (start: 4, end: 8, text: "time", captures: ()), -) - -// Test the `matches` method. -#test("Hello there".matches("\d"), ()) -#test("Day by Day.".matches("Day"), ( - (start: 0, end: 3, text: "Day", captures: ()), - (start: 7, end: 10, text: "Day", captures: ()), -)) - -// Compute the sum of all timestamps in the text. -#let timesum(text) = { - let time = 0 - for match in text.matches(regex("(\d+):(\d+)")) { - let caps = match.captures - time += 60 * int(caps.at(0)) + int(caps.at(1)) - } - str(int(time / 60)) + ":" + str(calc.rem(time, 60)) -} - -#test(timesum(""), "0:0") -#test(timesum("2:70"), "3:10") -#test(timesum("1:20, 2:10, 0:40"), "4:10") - ---- -// Test the `replace` method with `Str` replacements. -#test("ABC".replace("", "-"), "-A-B-C-") -#test("Ok".replace("Ok", "Nope", count: 0), "Ok") -#test("to add?".replace("", "How ", count: 1), "How to add?") -#test("AB C DEF GH J".replace(" ", ",", count: 2), "AB,C,DEF GH J") -#test("Walcemo" - .replace("o", "k") - .replace("e", "o") - .replace("k", "e") - .replace("a", "e"), - "Welcome" -) -#test("123".replace(regex("\d$"), "_"), "12_") -#test("123".replace(regex("\d{1,2}$"), "__"), "1__") - ---- -// Test the `replace` method with `Func` replacements. - -#test("abc".replace(regex("[a-z]"), m => { - str(m.start) + m.text + str(m.end) -}), "0a11b22c3") -#test("abcd, efgh".replace(regex("\w+"), m => { - upper(m.text) -}), "ABCD, EFGH") -#test("hello : world".replace(regex("^(.+)\s*(:)\s*(.+)$"), m => { - upper(m.captures.at(0)) + m.captures.at(1) + " " + upper(m.captures.at(2)) -}), "HELLO : WORLD") -#test("hello world, lorem ipsum".replace(regex("(\w+) (\w+)"), m => { - m.captures.at(1) + " " + m.captures.at(0) -}), "world hello, ipsum lorem") -#test("hello world, lorem ipsum".replace(regex("(\w+) (\w+)"), count: 1, m => { - m.captures.at(1) + " " + m.captures.at(0) -}), "world hello, lorem ipsum") -#test("123 456".replace(regex("[a-z]+"), "a"), "123 456") - -#test("abc".replace("", m => "-"), "-a-b-c-") -#test("abc".replace("", m => "-", count: 1), "-abc") -#test("123".replace("abc", m => ""), "123") -#test("123".replace("abc", m => "", count: 2), "123") -#test("a123b123c".replace("123", m => { - str(m.start) + "-" + str(m.end) -}), "a1-4b5-8c") -#test("halla warld".replace("a", m => { - if m.start == 1 { "e" } - else if m.start == 4 or m.start == 7 { "o" } -}), "hello world") -#test("aaa".replace("a", m => str(m.captures.len())), "000") - ---- -// Error: 23-24 expected string, found integer -#"123".replace("123", m => 1) - ---- -// Error: 23-32 expected string or function, found array -#"123".replace("123", (1, 2, 3)) - ---- -// Test the `trim` method; the pattern is not provided. -#let str = "Typst, LaTeX, Word, InDesign" -#let array = ("Typst", "LaTeX", "Word", "InDesign") -#test(str.split(",").map(s => s.trim()), array) -#test("".trim(), "") -#test(" ".trim(), "") -#test("\t".trim(), "") -#test("\n".trim(), "") -#test("\t \n".trim(), "") -#test(" abc ".trim(at: start), "abc ") -#test("\tabc ".trim(at: start), "abc ") -#test("abc\n".trim(at: end), "abc") -#test(" abc ".trim(at: end, repeat: true), " abc") -#test(" abc".trim(at: start, repeat: false), "abc") - ---- -// Test the `trim` method; the pattern is a string. -#test("aabcaa".trim("a", repeat: false), "abca") -#test("aabca".trim("a", at: start), "bca") -#test("aabcaa".trim("a", at: end, repeat: false), "aabca") -#test(" abc\n".trim("\n"), " abc") -#test("whole".trim("whole", at: start), "") - ---- -// Test the `trim` method; the pattern is a regex. -#test("".trim(regex(".")), "") -#test("123abc456".trim(regex("\d")), "abc") -#test("123abc456".trim(regex("\d"), repeat: false), "23abc45") -#test("123a4b5c678".trim(regex("\d"), repeat: true), "a4b5c") -#test("123a4b5c678".trim(regex("\d"), repeat: false), "23a4b5c67") -#test("123abc456".trim(regex("\d"), at: start), "abc456") -#test("123abc456".trim(regex("\d"), at: end), "123abc") -#test("123abc456".trim(regex("\d+"), at: end, repeat: false), "123abc") -#test("123abc456".trim(regex("\d{1,2}$"), repeat: false), "123abc4") -#test("hello world".trim(regex(".")), "") -#test("12306".trim(regex("\d"), at: start), "") -#test("12306abc".trim(regex("\d"), at: start), "abc") -#test("whole".trim(regex("whole"), at: start), "") -#test("12306".trim(regex("\d"), at: end), "") -#test("abc12306".trim(regex("\d"), at: end), "abc") -#test("whole".trim(regex("whole"), at: end), "") - ---- -// Error: 17-21 expected either `start` or `end` -#"abc".trim(at: left) - ---- -// Test the `split` method. -#test("abc".split(""), ("", "a", "b", "c", "")) -#test("abc".split("b"), ("a", "c")) -#test("a123c".split(regex("\d")), ("a", "", "", "c")) -#test("a123c".split(regex("\d+")), ("a", "c")) - ---- -// Test the `rev` method. -#test("abc".rev(), "cba") -#test("axΜe".rev(), "exΜa") - ---- -// Error: 12-15 unknown variable: arg -#"abc".rev(arg) - ---- -// Error: 2-2:1 unclosed string -#"hello\" diff --git a/tests/typ/compiler/type-compatibility.typ b/tests/typ/compiler/type-compatibility.typ deleted file mode 100644 index 664981f4..00000000 --- a/tests/typ/compiler/type-compatibility.typ +++ /dev/null @@ -1,10 +0,0 @@ -// Test compatibility between types and strings. -// Ref: false - ---- -#test(type(10), int) -#test(type(10), "integer") -#test("is " + type(10), "is integer") -#test(int in ("integer", "string"), true) -#test(int in "integers or strings", true) -#test(str in "integers or strings", true) diff --git a/tests/typ/compiler/while.typ b/tests/typ/compiler/while.typ deleted file mode 100644 index 56409c6e..00000000 --- a/tests/typ/compiler/while.typ +++ /dev/null @@ -1,60 +0,0 @@ -// Test while expressions. - ---- -// Should output `2 4 6 8 10`. -#let i = 0 -#while i < 10 [ - #(i += 2) - #i -] - -// Should output `Hi`. -#let iter = true -#while iter { - iter = false - "Hi." -} - -#while false { - dont-care -} - ---- -// Value of while loops. -// Ref: false - -#test(while false {}, none) - -#let i = 0 -#test(type(while i < 1 [#(i += 1)]), content) - ---- -// Condition must be boolean. -// Error: 8-14 expected boolean, found content -#while [nope] [nope] - ---- -// Error: 8-25 condition is always true -#while 2 < "hello".len() {} - ---- -// Error: 2:2-2:24 loop seems to be infinite -#let i = 1 -#while i > 0 { i += 1 } - ---- -// Error: 7 expected expression -#while - -// Error: 8 expected expression -#{while} - -// Error: 9 expected block -#while x - -// Error: 7 expected expression -#while -x {} - -// Error: 9 expected block -#while x something |
