Shrink tests (#4967)
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 963 B |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1022 B |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 295 B |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
tests/ref/image-jpg.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
tests/ref/image-png.png
Normal file
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 495 B |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 944 B |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 704 B |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 456 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 372 B |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 2.9 KiB |
BIN
tests/ref/outline-bookmark.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 10 KiB |
BIN
tests/ref/outline-styled-text.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 5.1 KiB |
BIN
tests/ref/place-float-align-auto.png
Normal file
After Width: | Height: | Size: 570 B |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 34 KiB |
BIN
tests/ref/place-float-flow-around.png
Normal file
After Width: | Height: | Size: 397 B |
Before Width: | Height: | Size: 2.6 KiB |
BIN
tests/ref/place-float-in-column-align-auto.png
Normal file
After Width: | Height: | Size: 843 B |
BIN
tests/ref/place-float-in-column-queued.png
Normal file
After Width: | Height: | Size: 638 B |
BIN
tests/ref/place-float-queued.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.3 KiB |
BIN
tests/ref/place-flush-figure.png
Normal file
After Width: | Height: | Size: 905 B |
BIN
tests/ref/place-flush.png
Normal file
After Width: | Height: | Size: 347 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 460 B |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
tests/ref/raw-highlight-cpp.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
tests/ref/raw-highlight-html.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
tests/ref/raw-highlight-py.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
tests/ref/raw-highlight-rust.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 3.3 KiB |
BIN
tests/ref/raw-highlight-typc.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
tests/ref/raw-highlight-typm.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
tests/ref/smartquote-de-ch.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
tests/ref/smartquote-de.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
tests/ref/smartquote-es-mx.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
tests/ref/smartquote-es.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
tests/ref/smartquote-fi.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
tests/ref/smartquote-fr.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
tests/ref/smartquote-gr.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
tests/ref/smartquote-he.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
tests/ref/smartquote-it.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
tests/ref/smartquote-la.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
tests/ref/smartquote-ro.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
tests/ref/smartquote-ru.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 1.7 KiB |
@ -75,4 +75,6 @@ impl CliArguments {
|
|||||||
pub enum Command {
|
pub enum Command {
|
||||||
/// Clears the on-disk test artifact store.
|
/// Clears the on-disk test artifact store.
|
||||||
Clean,
|
Clean,
|
||||||
|
/// Deletes all dangling reference images.
|
||||||
|
Undangle,
|
||||||
}
|
}
|
||||||
|
@ -408,8 +408,8 @@ fn selected(name: &str, abs: PathBuf) -> bool {
|
|||||||
|
|
||||||
/// An error in a test file.
|
/// An error in a test file.
|
||||||
pub struct TestParseError {
|
pub struct TestParseError {
|
||||||
pos: FilePos,
|
pub pos: FilePos,
|
||||||
message: String,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for TestParseError {
|
impl Display for TestParseError {
|
||||||
|
@ -431,7 +431,7 @@ fn skippable_frame(frame: &Frame) -> bool {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether to pixel images are approximately equal.
|
/// Whether two pixel images are approximately equal.
|
||||||
fn approx_equal(a: &sk::Pixmap, b: &sk::Pixmap) -> bool {
|
fn approx_equal(a: &sk::Pixmap, b: &sk::Pixmap) -> bool {
|
||||||
a.width() == b.width()
|
a.width() == b.width()
|
||||||
&& a.height() == b.height()
|
&& a.height() == b.height()
|
||||||
|
@ -38,7 +38,8 @@ fn main() {
|
|||||||
|
|
||||||
match &ARGS.command {
|
match &ARGS.command {
|
||||||
None => test(),
|
None => test(),
|
||||||
Some(Command::Clean) => std::fs::remove_dir_all(STORE_PATH).unwrap(),
|
Some(Command::Clean) => clean(),
|
||||||
|
Some(Command::Undangle) => undangle(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,3 +121,21 @@ fn test() {
|
|||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clean() {
|
||||||
|
std::fs::remove_dir_all(STORE_PATH).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn undangle() {
|
||||||
|
match crate::collect::collect() {
|
||||||
|
Ok(_) => eprintln!("no danging reference images"),
|
||||||
|
Err(errors) => {
|
||||||
|
for error in errors {
|
||||||
|
if error.message == "dangling reference image" {
|
||||||
|
std::fs::remove_file(&error.pos.path).unwrap();
|
||||||
|
eprintln!("✅ deleted {}", error.pos.path.display());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,13 +3,19 @@ use std::collections::HashMap;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::str::FromStr;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
use comemo::Tracked;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use typst::diag::{bail, FileError, FileResult, StrResult};
|
use typst::diag::{bail, At, FileError, FileResult, SourceResult, StrResult};
|
||||||
use typst::foundations::{func, Bytes, Datetime, NoneValue, Repr, Smart, Value};
|
use typst::engine::Engine;
|
||||||
|
use typst::foundations::{
|
||||||
|
func, Array, Bytes, Context, Datetime, IntoValue, NoneValue, Repr, Smart, Value,
|
||||||
|
};
|
||||||
use typst::layout::{Abs, Margin, PageElem};
|
use typst::layout::{Abs, Margin, PageElem};
|
||||||
use typst::syntax::{FileId, Source};
|
use typst::model::{Numbering, NumberingPattern};
|
||||||
|
use typst::syntax::{FileId, Source, Span};
|
||||||
use typst::text::{Font, FontBook, TextElem, TextSize};
|
use typst::text::{Font, FontBook, TextElem, TextSize};
|
||||||
use typst::utils::{singleton, LazyHash};
|
use typst::utils::{singleton, LazyHash};
|
||||||
use typst::visualize::Color;
|
use typst::visualize::Color;
|
||||||
@ -176,40 +182,11 @@ fn library() -> Library {
|
|||||||
// that it multiplies to nice round numbers.
|
// that it multiplies to nice round numbers.
|
||||||
let mut lib = Library::default();
|
let mut lib = Library::default();
|
||||||
|
|
||||||
#[func]
|
|
||||||
fn test(lhs: Value, rhs: Value) -> StrResult<NoneValue> {
|
|
||||||
if lhs != rhs {
|
|
||||||
bail!("Assertion failed: {} != {}", lhs.repr(), rhs.repr());
|
|
||||||
}
|
|
||||||
Ok(NoneValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[func]
|
|
||||||
fn test_repr(lhs: Value, rhs: Value) -> StrResult<NoneValue> {
|
|
||||||
if lhs.repr() != rhs.repr() {
|
|
||||||
bail!("Assertion failed: {} != {}", lhs.repr(), rhs.repr());
|
|
||||||
}
|
|
||||||
Ok(NoneValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[func]
|
|
||||||
fn print(#[variadic] values: Vec<Value>) -> NoneValue {
|
|
||||||
let mut out = std::io::stdout().lock();
|
|
||||||
write!(out, "> ").unwrap();
|
|
||||||
for (i, value) in values.into_iter().enumerate() {
|
|
||||||
if i > 0 {
|
|
||||||
write!(out, ", ").unwrap();
|
|
||||||
}
|
|
||||||
write!(out, "{value:?}").unwrap();
|
|
||||||
}
|
|
||||||
writeln!(out).unwrap();
|
|
||||||
NoneValue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hook up helpers into the global scope.
|
// Hook up helpers into the global scope.
|
||||||
lib.global.scope_mut().define_func::<test>();
|
lib.global.scope_mut().define_func::<test>();
|
||||||
lib.global.scope_mut().define_func::<test_repr>();
|
lib.global.scope_mut().define_func::<test_repr>();
|
||||||
lib.global.scope_mut().define_func::<print>();
|
lib.global.scope_mut().define_func::<print>();
|
||||||
|
lib.global.scope_mut().define_func::<lines>();
|
||||||
lib.global
|
lib.global
|
||||||
.scope_mut()
|
.scope_mut()
|
||||||
.define("conifer", Color::from_u8(0x9f, 0xEB, 0x52, 0xFF));
|
.define("conifer", Color::from_u8(0x9f, 0xEB, 0x52, 0xFF));
|
||||||
@ -228,3 +205,50 @@ fn library() -> Library {
|
|||||||
|
|
||||||
lib
|
lib
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
fn test(lhs: Value, rhs: Value) -> StrResult<NoneValue> {
|
||||||
|
if lhs != rhs {
|
||||||
|
bail!("Assertion failed: {} != {}", lhs.repr(), rhs.repr());
|
||||||
|
}
|
||||||
|
Ok(NoneValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
fn test_repr(lhs: Value, rhs: Value) -> StrResult<NoneValue> {
|
||||||
|
if lhs.repr() != rhs.repr() {
|
||||||
|
bail!("Assertion failed: {} != {}", lhs.repr(), rhs.repr());
|
||||||
|
}
|
||||||
|
Ok(NoneValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
fn print(#[variadic] values: Vec<Value>) -> NoneValue {
|
||||||
|
let mut out = std::io::stdout().lock();
|
||||||
|
write!(out, "> ").unwrap();
|
||||||
|
for (i, value) in values.into_iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
write!(out, ", ").unwrap();
|
||||||
|
}
|
||||||
|
write!(out, "{value:?}").unwrap();
|
||||||
|
}
|
||||||
|
writeln!(out).unwrap();
|
||||||
|
NoneValue
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates `count` lines of text based on the numbering.
|
||||||
|
#[func]
|
||||||
|
fn lines(
|
||||||
|
engine: &mut Engine,
|
||||||
|
context: Tracked<Context>,
|
||||||
|
span: Span,
|
||||||
|
count: usize,
|
||||||
|
#[default(Numbering::Pattern(NumberingPattern::from_str("A").unwrap()))]
|
||||||
|
numbering: Numbering,
|
||||||
|
) -> SourceResult<Value> {
|
||||||
|
(1..=count)
|
||||||
|
.map(|n| numbering.apply(engine, context, &[n]))
|
||||||
|
.collect::<SourceResult<Array>>()?
|
||||||
|
.join(Some('\n'.into_value()), None)
|
||||||
|
.at(span)
|
||||||
|
}
|
||||||
|
@ -176,10 +176,10 @@
|
|||||||
#let c = "value"
|
#let c = "value"
|
||||||
#let d = "conflict"
|
#let d = "conflict"
|
||||||
|
|
||||||
#assert.eq(((a): b), ("hello": "world"))
|
#test(((a): b), ("hello": "world"))
|
||||||
#assert.eq(((a): 1, (a): 2), ("hello": 2))
|
#test(((a): 1, (a): 2), ("hello": 2))
|
||||||
#assert.eq((hello: 1, (a): 2), ("hello": 2))
|
#test((hello: 1, (a): 2), ("hello": 2))
|
||||||
#assert.eq((a + b: c, (a + b): d, (a): "value2", a: "value3"), ("helloworld": "conflict", "hello": "value2", "a": "value3"))
|
#test((a + b: c, (a + b): d, (a): "value2", a: "value3"), ("helloworld": "conflict", "hello": "value2", "a": "value3"))
|
||||||
|
|
||||||
--- issue-1338-dictionary-underscore ---
|
--- issue-1338-dictionary-underscore ---
|
||||||
#let foo = "foo"
|
#let foo = "foo"
|
||||||
|
@ -1,57 +1,90 @@
|
|||||||
--- repr ---
|
--- repr ---
|
||||||
#test(repr(ltr), "ltr")
|
#let t(a, b) = test(repr(a), b.text)
|
||||||
#test(repr((1, 2, false, )), "(1, 2, false)")
|
|
||||||
|
|
||||||
--- repr-literals ---
|
|
||||||
// Literal values.
|
// Literal values.
|
||||||
#auto \
|
#t(auto, `auto`)
|
||||||
#none (empty) \
|
#t(true, `true`)
|
||||||
#true \
|
#t(false, `false`)
|
||||||
#false
|
|
||||||
|
|
||||||
--- repr-numerical ---
|
|
||||||
// Numerical values.
|
// Numerical values.
|
||||||
#1 \
|
#t(12.0, `12.0`)
|
||||||
#1.0e-4 \
|
#t(3.14, `3.14`)
|
||||||
#3.15 \
|
#t(1234567890.0, `1234567890.0`)
|
||||||
#1e-10 \
|
#t(0123456789.0, `123456789.0`)
|
||||||
#50.368% \
|
#t(0.0, `0.0`)
|
||||||
#0.0000012345pt \
|
#t(-0.0, `-0.0`)
|
||||||
#4.5cm \
|
#t(-1.0, `-1.0`)
|
||||||
#12e1pt \
|
#t(-9876543210.0, `-9876543210.0`)
|
||||||
#2.5rad \
|
#t(-0987654321.0, `-987654321.0`)
|
||||||
#45deg \
|
#t(-3.14, `-3.14`)
|
||||||
#1.7em \
|
#t(4.0 - 8.0, `-4.0`)
|
||||||
#(1cm + 0em) \
|
#t(float.inf, `float.inf`)
|
||||||
#(2em + 10pt) \
|
#t(-float.inf, `-float.inf`)
|
||||||
#(100% + (2em + 2pt)) \
|
#t(float.nan, `float.nan`)
|
||||||
#(100% + 0pt) \
|
|
||||||
#(100% - 2em + 2pt) \
|
|
||||||
#(100% - 2pt) \
|
|
||||||
#2.3fr
|
|
||||||
|
|
||||||
--- repr-misc ---
|
|
||||||
// Colors and strokes.
|
|
||||||
#set text(0.8em)
|
|
||||||
#rgb("f7a205") \
|
|
||||||
#(2pt + rgb("f7a205"))
|
|
||||||
|
|
||||||
// Strings and escaping.
|
// Strings and escaping.
|
||||||
#raw(repr("hi"), lang: "typc")
|
#t("hi", `"hi"`)
|
||||||
#repr("a\n[]\"\u{1F680}string")
|
#t("a\n[]\"\u{1F680}string", `"a\n[]\"🚀string"`)
|
||||||
|
|
||||||
// Content.
|
// Array and dictionary.
|
||||||
#raw(lang: "typc", repr[*Hey*]) \
|
#t((1, 2, false, ), `(1, 2, false)`)
|
||||||
#raw(lang: "typc", repr[A _sequence_]) \
|
#t((a: 1, b: "2"), `(a: 1, b: "2")`)
|
||||||
#raw(lang: "typc", repr[A _longer_ *sequence*!])
|
|
||||||
|
|
||||||
// Functions.
|
// Functions.
|
||||||
#let f(x) = x
|
#let f(x) = x
|
||||||
#f \
|
#t(f, `f`)
|
||||||
#rect \
|
#t(rect , `rect`)
|
||||||
#(() => none)
|
#t(() => none, `(..) => ..`)
|
||||||
|
|
||||||
// Types.
|
// Types.
|
||||||
#int \
|
#t(int, `integer`)
|
||||||
#type("hi") \
|
#t(type("hi"), `string`)
|
||||||
#type((a: 1))
|
#t(type((a: 1)), `dictionary`)
|
||||||
|
|
||||||
|
// Constants.
|
||||||
|
#t(ltr, `ltr`)
|
||||||
|
#t(left, `left`)
|
||||||
|
|
||||||
|
// Content.
|
||||||
|
#t([*Hey*], `strong(body: [Hey])`)
|
||||||
|
#t([A _sequence_], `sequence([A], [ ], emph(body: [sequence]))`)
|
||||||
|
#t([A _longer_ *sequence*!], ```
|
||||||
|
sequence(
|
||||||
|
[A],
|
||||||
|
[ ],
|
||||||
|
emph(body: [longer]),
|
||||||
|
[ ],
|
||||||
|
strong(body: [sequence]),
|
||||||
|
[!],
|
||||||
|
)
|
||||||
|
```)
|
||||||
|
|
||||||
|
// Colors and strokes.
|
||||||
|
#t(rgb("f7a205"), `rgb("#f7a205")`)
|
||||||
|
#t(2pt + rgb("f7a205"), `2pt + rgb("#f7a205")`)
|
||||||
|
#t(blue, `rgb("#0074d9")`)
|
||||||
|
#t(color.linear-rgb(blue), `color.linear-rgb(0%, 17.46%, 69.39%)`)
|
||||||
|
#t(oklab(blue), `oklab(56.22%, -0.05, -0.17)`)
|
||||||
|
#t(oklch(blue), `oklch(56.22%, 0.177, 253.71deg)`)
|
||||||
|
#t(cmyk(blue), `cmyk(100%, 46.54%, 0%, 14.9%)`)
|
||||||
|
#t(color.hsl(blue), `color.hsl(207.93deg, 100%, 42.55%)`)
|
||||||
|
#t(color.hsv(blue), `color.hsv(207.93deg, 100%, 85.1%)`)
|
||||||
|
#t(luma(blue), `luma(45.53%)`)
|
||||||
|
|
||||||
|
// Gradients.
|
||||||
|
#t(
|
||||||
|
gradient.linear(blue, red),
|
||||||
|
`gradient.linear((rgb("#0074d9"), 0%), (rgb("#ff4136"), 100%))`,
|
||||||
|
)
|
||||||
|
#t(
|
||||||
|
gradient.linear(blue, red, dir: ttb),
|
||||||
|
`gradient.linear(dir: rtl, (rgb("#0074d9"), 0%), (rgb("#ff4136"), 100%))`,
|
||||||
|
)
|
||||||
|
#t(
|
||||||
|
gradient.linear(blue, red, relative: "self", angle: 45deg),
|
||||||
|
`gradient.linear(angle: 45deg, relative: "self", (rgb("#0074d9"), 0%), (rgb("#ff4136"), 100%))`,
|
||||||
|
)
|
||||||
|
#t(
|
||||||
|
gradient.linear(blue, red, space: rgb, angle: 45deg),
|
||||||
|
`gradient.linear(angle: 45deg, space: rgb, (rgb("#0074d9"), 0%), (rgb("#ff4136"), 100%))`,
|
||||||
|
)
|
||||||
|
@ -54,13 +54,13 @@ At Beta, it was #context {
|
|||||||
|
|
||||||
--- counter-page ---
|
--- counter-page ---
|
||||||
#set page(height: 50pt, margin: (bottom: 20pt, rest: 10pt))
|
#set page(height: 50pt, margin: (bottom: 20pt, rest: 10pt))
|
||||||
#lorem(12)
|
#lines(4)
|
||||||
#set page(numbering: "(i)")
|
#set page(numbering: "(i)")
|
||||||
#lorem(6)
|
#lines(2)
|
||||||
#pagebreak()
|
#pagebreak()
|
||||||
#set page(numbering: "1 / 1")
|
#set page(numbering: "1 / 1")
|
||||||
#counter(page).update(1)
|
#counter(page).update(1)
|
||||||
#lorem(20)
|
#lines(7)
|
||||||
|
|
||||||
--- counter-page-footer-before-set-page ---
|
--- counter-page-footer-before-set-page ---
|
||||||
#set page(numbering: "1", margin: (bottom: 20pt))
|
#set page(numbering: "1", margin: (bottom: 20pt))
|
||||||
|
@ -72,80 +72,11 @@
|
|||||||
caption: [Tetrahedron],
|
caption: [Tetrahedron],
|
||||||
)
|
)
|
||||||
|
|
||||||
--- query-before-after ---
|
|
||||||
// LARGE
|
|
||||||
#set page(
|
|
||||||
paper: "a7",
|
|
||||||
numbering: "1 / 1",
|
|
||||||
margin: (bottom: 1cm, rest: 0.5cm),
|
|
||||||
)
|
|
||||||
|
|
||||||
#show heading.where(level: 1, outlined: true): it => [
|
|
||||||
#it
|
|
||||||
|
|
||||||
#set text(size: 12pt, weight: "regular")
|
|
||||||
#outline(
|
|
||||||
title: none,
|
|
||||||
indent: true,
|
|
||||||
target: heading
|
|
||||||
.where(level: 1)
|
|
||||||
.or(heading.where(level: 2))
|
|
||||||
.after(it.location(), inclusive: true)
|
|
||||||
.before(
|
|
||||||
heading
|
|
||||||
.where(level: 1, outlined: true)
|
|
||||||
.after(it.location(), inclusive: false),
|
|
||||||
inclusive: false,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
#set heading(outlined: true, numbering: "1.")
|
|
||||||
|
|
||||||
= Section 1
|
|
||||||
== Subsection 1
|
|
||||||
== Subsection 2
|
|
||||||
=== Subsubsection 1
|
|
||||||
=== Subsubsection 2
|
|
||||||
== Subsection 3
|
|
||||||
|
|
||||||
= Section 2
|
|
||||||
== Subsection 1
|
|
||||||
== Subsection 2
|
|
||||||
|
|
||||||
= Section 3
|
|
||||||
== Subsection 1
|
|
||||||
== Subsection 2
|
|
||||||
=== Subsubsection 1
|
|
||||||
=== Subsubsection 2
|
|
||||||
=== Subsubsection 3
|
|
||||||
== Subsection 3
|
|
||||||
|
|
||||||
--- query-and-or ---
|
|
||||||
#set page(
|
|
||||||
paper: "a7",
|
|
||||||
numbering: "1 / 1",
|
|
||||||
margin: (bottom: 1cm, rest: 0.5cm),
|
|
||||||
)
|
|
||||||
|
|
||||||
#set heading(outlined: true, numbering: "1.")
|
|
||||||
|
|
||||||
#context [
|
|
||||||
Non-outlined elements:
|
|
||||||
#(query(selector(heading).and(heading.where(outlined: false)))
|
|
||||||
.map(it => it.body).join(", "))
|
|
||||||
]
|
|
||||||
|
|
||||||
#heading("A", outlined: false)
|
|
||||||
#heading("B", outlined: true)
|
|
||||||
#heading("C", outlined: true)
|
|
||||||
#heading("D", outlined: false)
|
|
||||||
|
|
||||||
--- query-complex ---
|
--- query-complex ---
|
||||||
= A
|
= A
|
||||||
== B
|
== B
|
||||||
#figure([Cat], kind: "cat", supplement: [Other])
|
#figure([Cat], kind: "cat", supplement: [Other])
|
||||||
=== D
|
#heading(level: 3, outlined: false)[D]
|
||||||
= E <first>
|
= E <first>
|
||||||
#figure([Frog], kind: "frog", supplement: none)
|
#figure([Frog], kind: "frog", supplement: none)
|
||||||
#figure([Giraffe], kind: "giraffe", supplement: none) <second>
|
#figure([Giraffe], kind: "giraffe", supplement: none) <second>
|
||||||
@ -164,6 +95,11 @@
|
|||||||
([A], [D], [E], [H]),
|
([A], [D], [E], [H]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#test-selector(
|
||||||
|
selector(heading).and(heading.where(outlined: false)),
|
||||||
|
([D],)
|
||||||
|
)
|
||||||
|
|
||||||
#test-selector(
|
#test-selector(
|
||||||
heading.where(level: 1).or(
|
heading.where(level: 1).or(
|
||||||
heading.where(level: 3),
|
heading.where(level: 3),
|
||||||
|
@ -28,7 +28,7 @@ Was: #context {
|
|||||||
#set page(width: 200pt)
|
#set page(width: 200pt)
|
||||||
#set text(8pt)
|
#set text(8pt)
|
||||||
|
|
||||||
#let ls = state("lorem", lorem(1000).split("."))
|
#let ls = state("lorem", lorem(30).split(" "))
|
||||||
#let loremum(count) = {
|
#let loremum(count) = {
|
||||||
context ls.get().slice(0, count).join(".").trim() + "."
|
context ls.get().slice(0, count).join(".").trim() + "."
|
||||||
ls.update(list => list.slice(count))
|
ls.update(list => list.slice(count))
|
||||||
|
@ -98,15 +98,15 @@ Paragraph
|
|||||||
#set page(height: 100pt)
|
#set page(height: 100pt)
|
||||||
#set align(center)
|
#set align(center)
|
||||||
|
|
||||||
#lorem(10)
|
#lines(3)
|
||||||
#block(width: 80%, height: 60pt, fill: aqua)
|
#block(width: 80%, height: 60pt, fill: aqua)
|
||||||
#lorem(6)
|
#lines(2)
|
||||||
#block(
|
#block(
|
||||||
breakable: false,
|
breakable: false,
|
||||||
width: 100%,
|
width: 100%,
|
||||||
inset: 4pt,
|
inset: 4pt,
|
||||||
fill: aqua,
|
fill: aqua,
|
||||||
lorem(8) + colbreak(),
|
lines(3) + colbreak(),
|
||||||
)
|
)
|
||||||
|
|
||||||
--- block-consistent-width ---
|
--- block-consistent-width ---
|
||||||
|
@ -11,11 +11,8 @@
|
|||||||
// the rest moved down. The reason was that the second block resulted in
|
// the rest moved down. The reason was that the second block resulted in
|
||||||
// overlarge frames because the region wasn't finished properly.
|
// overlarge frames because the region wasn't finished properly.
|
||||||
#set page(height: 70pt)
|
#set page(height: 70pt)
|
||||||
#block[This file tests a bug where an almost empty page occurs.]
|
#block(lines(3))
|
||||||
#block[
|
#block(lines(5))
|
||||||
The text in this second block was torn apart and split up for
|
|
||||||
some reason beyond my knowledge.
|
|
||||||
]
|
|
||||||
|
|
||||||
--- issue-flow-trailing-leading ---
|
--- issue-flow-trailing-leading ---
|
||||||
// In this bug, the first part of the paragraph moved down to the second page
|
// In this bug, the first part of the paragraph moved down to the second page
|
||||||
@ -48,13 +45,13 @@
|
|||||||
// This bug caused an index-out-of-bounds panic when layouting paragraphs needed
|
// This bug caused an index-out-of-bounds panic when layouting paragraphs needed
|
||||||
// multiple reorderings.
|
// multiple reorderings.
|
||||||
#set page(height: 200pt)
|
#set page(height: 200pt)
|
||||||
#lorem(30)
|
#lines(10)
|
||||||
|
|
||||||
#figure(placement: auto, block(height: 100%))
|
#figure(placement: auto, block(height: 100%))
|
||||||
|
|
||||||
#lorem(10)
|
#lines(3)
|
||||||
|
|
||||||
#lorem(10)
|
#lines(3)
|
||||||
|
|
||||||
--- issue-3641-float-loop ---
|
--- issue-3641-float-loop ---
|
||||||
// Flow layout should terminate!
|
// Flow layout should terminate!
|
||||||
@ -64,7 +61,7 @@
|
|||||||
#set page(height: 40pt)
|
#set page(height: 40pt)
|
||||||
|
|
||||||
= Heading
|
= Heading
|
||||||
#lorem(6)
|
#lines(2)
|
||||||
|
|
||||||
--- issue-3355-metadata-weak-spacing ---
|
--- issue-3355-metadata-weak-spacing ---
|
||||||
#set page(height: 50pt)
|
#set page(height: 50pt)
|
||||||
|
@ -2,38 +2,37 @@
|
|||||||
|
|
||||||
--- flow-heading-no-orphan ---
|
--- flow-heading-no-orphan ---
|
||||||
#set page(height: 100pt)
|
#set page(height: 100pt)
|
||||||
#lorem(12)
|
#lines(4)
|
||||||
|
|
||||||
= Introduction
|
= Introduction
|
||||||
This is the start and it goes on.
|
A
|
||||||
|
|
||||||
--- flow-par-no-orphan-and-widow-lines ---
|
--- flow-par-no-orphan-and-widow-lines ---
|
||||||
// LARGE
|
#set page(width: 60pt, height: 140pt)
|
||||||
#set page("a8", height: 140pt)
|
|
||||||
#set text(weight: 700)
|
#set text(weight: 700)
|
||||||
|
|
||||||
// Fits fully onto the first page.
|
// Fits fully onto the first page.
|
||||||
#set text(blue)
|
#set text(blue)
|
||||||
#lorem(27)
|
#lines(8)
|
||||||
|
|
||||||
// The first line would fit, but is moved to the second page.
|
// The first line would fit, but is moved to the second page.
|
||||||
#lorem(20)
|
#lines(6, "1")
|
||||||
|
|
||||||
// The second-to-last line is moved to the third page so that the last is isn't
|
// The second-to-last line is moved to the third page so that the last is isn't
|
||||||
// as lonely.
|
// as lonely.
|
||||||
#set text(maroon)
|
#set text(maroon)
|
||||||
#lorem(11)
|
#lines(4)
|
||||||
|
|
||||||
#lorem(13)
|
#lines(4, "1")
|
||||||
|
|
||||||
// All three lines go to the next page.
|
// All three lines go to the next page.
|
||||||
#set text(olive)
|
#set text(olive)
|
||||||
#lorem(10)
|
#lines(3)
|
||||||
|
|
||||||
--- flow-widow-forced ---
|
--- flow-widow-forced ---
|
||||||
// Ensure that a widow is allowed when the three lines don't all fit.
|
// Ensure that a widow is allowed when the three lines don't all fit.
|
||||||
#set page(height: 50pt)
|
#set page(height: 50pt)
|
||||||
#lorem(10)
|
#lines(3)
|
||||||
|
|
||||||
--- issue-1445-widow-orphan-unnecessary-skip ---
|
--- issue-1445-widow-orphan-unnecessary-skip ---
|
||||||
// Ensure that widow/orphan prevention doesn't unnecessarily move things
|
// Ensure that widow/orphan prevention doesn't unnecessarily move things
|
||||||
|
83
tests/suite/layout/flow/place-float.typ
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
--- place-float-flow-around ---
|
||||||
|
#set page(height: 80pt)
|
||||||
|
#set place(float: true)
|
||||||
|
#place(bottom + center, rect(height: 20pt))
|
||||||
|
#lines(4)
|
||||||
|
|
||||||
|
--- place-float-queued ---
|
||||||
|
#set page(height: 180pt)
|
||||||
|
#set figure(placement: auto)
|
||||||
|
|
||||||
|
#figure(rect(height: 60pt), caption: [I])
|
||||||
|
#figure(rect(height: 40pt), caption: [II])
|
||||||
|
#figure(rect(), caption: [III])
|
||||||
|
#figure(rect(), caption: [IV])
|
||||||
|
A
|
||||||
|
|
||||||
|
--- place-float-align-auto ---
|
||||||
|
#set page(height: 140pt)
|
||||||
|
#set place(clearance: 5pt)
|
||||||
|
#set place(auto, float: true)
|
||||||
|
|
||||||
|
#place(rect[A])
|
||||||
|
#place(rect[B])
|
||||||
|
1 \ 2
|
||||||
|
#place(rect[C])
|
||||||
|
#place(rect[D])
|
||||||
|
|
||||||
|
--- place-float-in-column-align-auto ---
|
||||||
|
#set page(height: 150pt, columns: 2)
|
||||||
|
#set place(auto, float: true, clearance: 10pt)
|
||||||
|
#set rect(width: 75%)
|
||||||
|
|
||||||
|
#place(rect[I])
|
||||||
|
#place(rect[II])
|
||||||
|
#place(rect[III])
|
||||||
|
#place(rect[IV])
|
||||||
|
|
||||||
|
#lines(6)
|
||||||
|
|
||||||
|
#place(rect[V])
|
||||||
|
|
||||||
|
--- place-float-in-column-queued ---
|
||||||
|
#set page(height: 100pt, columns: 2)
|
||||||
|
#set place(float: true, clearance: 10pt)
|
||||||
|
#set rect(width: 75%)
|
||||||
|
#set text(costs: (widow: 0%, orphan: 0%))
|
||||||
|
|
||||||
|
#lines(3)
|
||||||
|
|
||||||
|
#place(top, rect[I])
|
||||||
|
#place(top, rect[II])
|
||||||
|
#place(bottom, rect[III])
|
||||||
|
|
||||||
|
#lines(3)
|
||||||
|
|
||||||
|
--- place-float-missing ---
|
||||||
|
// Error: 2-20 automatic positioning is only available for floating placement
|
||||||
|
// Hint: 2-20 you can enable floating placement with `place(float: true, ..)`
|
||||||
|
#place(auto)[Hello]
|
||||||
|
|
||||||
|
--- place-float-center-horizon ---
|
||||||
|
// Error: 2-45 floating placement must be `auto`, `top`, or `bottom`
|
||||||
|
#place(center + horizon, float: true)[Hello]
|
||||||
|
|
||||||
|
--- place-float-horizon ---
|
||||||
|
// Error: 2-36 floating placement must be `auto`, `top`, or `bottom`
|
||||||
|
#place(horizon, float: true)[Hello]
|
||||||
|
|
||||||
|
--- place-float-default ---
|
||||||
|
// Error: 2-27 floating placement must be `auto`, `top`, or `bottom`
|
||||||
|
#place(float: true)[Hello]
|
||||||
|
|
||||||
|
--- place-float-right ---
|
||||||
|
// Error: 2-34 floating placement must be `auto`, `top`, or `bottom`
|
||||||
|
#place(right, float: true)[Hello]
|
||||||
|
|
||||||
|
--- issue-2595-float-overlap ---
|
||||||
|
#set page(height: 80pt)
|
||||||
|
|
||||||
|
1
|
||||||
|
#place(auto, float: true, block(height: 100%, width: 100%, fill: aqua))
|
||||||
|
#place(auto, float: true, block(height: 100%, width: 100%, fill: red))
|
||||||
|
#lines(7)
|
29
tests/suite/layout/flow/place-flush.typ
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
--- place-flush ---
|
||||||
|
#set page(height: 120pt)
|
||||||
|
#let floater(align, height) = place(
|
||||||
|
align,
|
||||||
|
float: true,
|
||||||
|
rect(width: 100%, height: height),
|
||||||
|
)
|
||||||
|
|
||||||
|
#floater(top, 30pt)
|
||||||
|
A
|
||||||
|
|
||||||
|
#floater(bottom, 50pt)
|
||||||
|
#place.flush()
|
||||||
|
B // Should be on the second page.
|
||||||
|
|
||||||
|
--- place-flush-figure ---
|
||||||
|
#set page(height: 120pt)
|
||||||
|
#let floater(align, height, caption) = figure(
|
||||||
|
placement: align,
|
||||||
|
caption: caption,
|
||||||
|
rect(width: 100%, height: height),
|
||||||
|
)
|
||||||
|
|
||||||
|
#floater(top, 30pt)[I]
|
||||||
|
A
|
||||||
|
|
||||||
|
#floater(bottom, 50pt)[II]
|
||||||
|
#place.flush()
|
||||||
|
B // Should be on the second page.
|