mirror of
https://github.com/typst/typst
synced 2025-07-27 14:27:56 +08:00
Compare commits
13 Commits
221e3d97a2
...
15b105d6dd
Author | SHA1 | Date | |
---|---|---|---|
|
15b105d6dd | ||
|
8c811110f3 | ||
|
5738c98ff5 | ||
|
24bac30c84 | ||
|
78355421ad | ||
|
af2253ba16 | ||
|
b036fd97ab | ||
|
e81a5a6ef2 | ||
|
c9c2315ad3 | ||
|
4bbd4e195b | ||
|
eed75ca4d6 | ||
|
a43b7e785c | ||
|
55dad02887 |
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
@ -40,7 +40,7 @@ jobs:
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt update
|
||||
sudo apt install -y gcc-multilib libssl-dev:i386 pkg-config:i386
|
||||
- uses: dtolnay/rust-toolchain@1.87.0
|
||||
- uses: dtolnay/rust-toolchain@1.88.0
|
||||
with:
|
||||
targets: ${{ matrix.bits == 32 && 'i686-unknown-linux-gnu' || '' }}
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
@ -73,7 +73,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@1.87.0
|
||||
- uses: dtolnay/rust-toolchain@1.88.0
|
||||
with:
|
||||
components: clippy, rustfmt
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
@ -88,7 +88,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@1.83.0
|
||||
- uses: dtolnay/rust-toolchain@1.88.0
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo check --workspace
|
||||
|
||||
@ -99,7 +99,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: nightly-2024-10-29
|
||||
toolchain: nightly-2025-05-10
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo install --locked cargo-fuzz@0.12.0
|
||||
- run: cd tests/fuzz && cargo fuzz build --dev
|
||||
@ -112,6 +112,6 @@ jobs:
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
components: miri
|
||||
toolchain: nightly-2024-10-29
|
||||
toolchain: nightly-2025-05-10
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo miri test -p typst-library test_miri
|
||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -44,7 +44,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@1.87.0
|
||||
- uses: dtolnay/rust-toolchain@1.88.0
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
|
132
Cargo.lock
generated
132
Cargo.lock
generated
@ -181,9 +181,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.8.0"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@ -214,9 +214,9 @@ checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.21.0"
|
||||
version = "1.23.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"
|
||||
checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422"
|
||||
dependencies = [
|
||||
"bytemuck_derive",
|
||||
]
|
||||
@ -964,6 +964,69 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hayro"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/LaurenzV/hayro?rev=e701f95#e701f9569157a2fe4ade68930dc9e9283782dcca"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"hayro-interpret",
|
||||
"image",
|
||||
"kurbo",
|
||||
"rustc-hash",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hayro-font"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/LaurenzV/hayro?rev=e701f95#e701f9569157a2fe4ade68930dc9e9283782dcca"
|
||||
dependencies = [
|
||||
"log",
|
||||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hayro-interpret"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/LaurenzV/hayro?rev=e701f95#e701f9569157a2fe4ade68930dc9e9283782dcca"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"hayro-font",
|
||||
"hayro-syntax",
|
||||
"kurbo",
|
||||
"log",
|
||||
"phf",
|
||||
"qcms",
|
||||
"skrifa",
|
||||
"smallvec",
|
||||
"yoke 0.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hayro-syntax"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/LaurenzV/hayro?rev=e701f95#e701f9569157a2fe4ade68930dc9e9283782dcca"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"kurbo",
|
||||
"log",
|
||||
"rustc-hash",
|
||||
"smallvec",
|
||||
"zune-jpeg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hayro-write"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/LaurenzV/hayro?rev=e701f95#e701f9569157a2fe4ade68930dc9e9283782dcca"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"hayro-syntax",
|
||||
"log",
|
||||
"pdf-writer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
@ -1198,17 +1261,11 @@ dependencies = [
|
||||
"icu_properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "if_chain"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.25.5"
|
||||
version = "0.25.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b"
|
||||
checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder-lite",
|
||||
@ -1271,7 +1328,7 @@ version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
@ -1367,7 +1424,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "krilla"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/LaurenzV/krilla?rev=20c14fe#20c14fefee5002566b3d6668b338bbe2168784e7"
|
||||
source = "git+https://github.com/LaurenzV/krilla?rev=37b9a00#37b9a00bfac87ed0b347b7cf8e9d37a6f68fcccd"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bumpalo",
|
||||
@ -1376,6 +1433,7 @@ dependencies = [
|
||||
"float-cmp 0.10.0",
|
||||
"fxhash",
|
||||
"gif",
|
||||
"hayro-write",
|
||||
"image-webp",
|
||||
"imagesize",
|
||||
"once_cell",
|
||||
@ -1385,6 +1443,7 @@ dependencies = [
|
||||
"rustybuzz",
|
||||
"siphasher",
|
||||
"skrifa",
|
||||
"smallvec",
|
||||
"subsetter",
|
||||
"tiny-skia-path",
|
||||
"xmp-writer",
|
||||
@ -1395,7 +1454,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "krilla-svg"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/LaurenzV/krilla?rev=20c14fe#20c14fefee5002566b3d6668b338bbe2168784e7"
|
||||
source = "git+https://github.com/LaurenzV/krilla?rev=37b9a00#37b9a00bfac87ed0b347b7cf8e9d37a6f68fcccd"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"fontdb",
|
||||
@ -1408,9 +1467,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kurbo"
|
||||
version = "0.11.1"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f"
|
||||
checksum = "1077d333efea6170d9ccb96d3c3026f300ca0773da4938cc4c811daa6df68b0c"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"smallvec",
|
||||
@ -1462,7 +1521,7 @@ version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
@ -1628,7 +1687,7 @@ version = "8.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
"filetime",
|
||||
"fsevent-sys",
|
||||
"inotify",
|
||||
@ -1710,7 +1769,7 @@ version = "0.10.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
@ -1847,7 +1906,7 @@ version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ea27c5015ab81753fc61e49f8cde74999346605ee148bb20008ef3d3150e0dc"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
@ -2005,7 +2064,7 @@ version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
"getopts",
|
||||
"memchr",
|
||||
"unicase",
|
||||
@ -2118,7 +2177,7 @@ version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2221,7 +2280,7 @@ version = "0.38.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
@ -2240,7 +2299,7 @@ version = "0.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
"bytemuck",
|
||||
"core_maths",
|
||||
"log",
|
||||
@ -2288,7 +2347,7 @@ version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
@ -2451,9 +2510,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.13.2"
|
||||
version = "1.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
@ -2861,7 +2920,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "typst-assets"
|
||||
version = "0.13.1"
|
||||
source = "git+https://github.com/typst/typst-assets?rev=edf0d64#edf0d648376e29738a05a933af9ea99bb81557b1"
|
||||
source = "git+https://github.com/typst/typst-assets?rev=fbf00f9#fbf00f9539fdb0825bef4d39fb57d5986c51b756"
|
||||
|
||||
[[package]]
|
||||
name = "typst-cli"
|
||||
@ -2911,7 +2970,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "typst-dev-assets"
|
||||
version = "0.13.1"
|
||||
source = "git+https://github.com/typst/typst-dev-assets?rev=bfa947f#bfa947f3433d7d13a995168c40ae788a2ebfe648"
|
||||
source = "git+https://github.com/typst/typst-dev-assets?rev=c6c2acf#c6c2acf6cdc31f99a23a478d3d614f8bf806a4f5"
|
||||
|
||||
[[package]]
|
||||
name = "typst-docs"
|
||||
@ -2943,7 +3002,6 @@ version = "0.13.1"
|
||||
dependencies = [
|
||||
"comemo",
|
||||
"ecow",
|
||||
"if_chain",
|
||||
"indexmap 2.7.1",
|
||||
"stacker",
|
||||
"toml",
|
||||
@ -2991,7 +3049,6 @@ version = "0.13.1"
|
||||
dependencies = [
|
||||
"comemo",
|
||||
"ecow",
|
||||
"if_chain",
|
||||
"once_cell",
|
||||
"pathdiff",
|
||||
"serde",
|
||||
@ -3063,7 +3120,7 @@ name = "typst-library"
|
||||
version = "0.13.1"
|
||||
dependencies = [
|
||||
"az",
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
"bumpalo",
|
||||
"chinese-number",
|
||||
"ciborium",
|
||||
@ -3075,6 +3132,7 @@ dependencies = [
|
||||
"fontdb",
|
||||
"glidesort",
|
||||
"hayagriva",
|
||||
"hayro-syntax",
|
||||
"icu_properties",
|
||||
"icu_provider",
|
||||
"icu_provider_blob",
|
||||
@ -3173,11 +3231,13 @@ version = "0.13.1"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"comemo",
|
||||
"hayro",
|
||||
"image",
|
||||
"pixglyph",
|
||||
"resvg",
|
||||
"tiny-skia",
|
||||
"ttf-parser",
|
||||
"typst-assets",
|
||||
"typst-library",
|
||||
"typst-macros",
|
||||
"typst-timing",
|
||||
@ -3191,8 +3251,10 @@ dependencies = [
|
||||
"comemo",
|
||||
"ecow",
|
||||
"flate2",
|
||||
"hayro",
|
||||
"image",
|
||||
"ttf-parser",
|
||||
"typst-assets",
|
||||
"typst-library",
|
||||
"typst-macros",
|
||||
"typst-timing",
|
||||
@ -3589,7 +3651,7 @@ version = "0.221.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9845c470a2e10b61dd42c385839cdd6496363ed63b5c9e420b5488b77bd22083"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
"indexmap 2.7.1",
|
||||
]
|
||||
|
||||
@ -3724,7 +3786,7 @@ version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
15
Cargo.toml
15
Cargo.toml
@ -5,9 +5,9 @@ resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
version = "0.13.1"
|
||||
rust-version = "1.83" # also change in ci.yml
|
||||
rust-version = "1.88" # also change in ci.yml
|
||||
authors = ["The Typst Project Developers"]
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
homepage = "https://typst.app"
|
||||
repository = "https://github.com/typst/typst"
|
||||
license = "Apache-2.0"
|
||||
@ -32,8 +32,8 @@ typst-svg = { path = "crates/typst-svg", version = "0.13.1" }
|
||||
typst-syntax = { path = "crates/typst-syntax", version = "0.13.1" }
|
||||
typst-timing = { path = "crates/typst-timing", version = "0.13.1" }
|
||||
typst-utils = { path = "crates/typst-utils", version = "0.13.1" }
|
||||
typst-assets = { git = "https://github.com/typst/typst-assets", rev = "edf0d64" }
|
||||
typst-dev-assets = { git = "https://github.com/typst/typst-dev-assets", rev = "bfa947f" }
|
||||
typst-assets = { git = "https://github.com/typst/typst-assets", rev = "fbf00f9" }
|
||||
typst-dev-assets = { git = "https://github.com/typst/typst-dev-assets", rev = "c6c2acf" }
|
||||
arrayvec = "0.7.4"
|
||||
az = "1.2"
|
||||
base64 = "0.22"
|
||||
@ -61,6 +61,8 @@ fontdb = { version = "0.23", default-features = false }
|
||||
fs_extra = "1.3"
|
||||
glidesort = "0.1.2"
|
||||
hayagriva = "0.8.1"
|
||||
hayro-syntax = { git = "https://github.com/LaurenzV/hayro", rev = "e701f95" }
|
||||
hayro = { git = "https://github.com/LaurenzV/hayro", rev = "e701f95" }
|
||||
heck = "0.5"
|
||||
hypher = "0.1.4"
|
||||
icu_properties = { version = "1.4", features = ["serde"] }
|
||||
@ -68,13 +70,12 @@ icu_provider = { version = "1.4", features = ["sync"] }
|
||||
icu_provider_adapters = "1.4"
|
||||
icu_provider_blob = "1.4"
|
||||
icu_segmenter = { version = "1.4", features = ["serde"] }
|
||||
if_chain = "1"
|
||||
image = { version = "0.25.5", default-features = false, features = ["png", "jpeg", "gif", "webp"] }
|
||||
indexmap = { version = "2", features = ["serde"] }
|
||||
infer = { version = "0.19.0", default-features = false }
|
||||
kamadak-exif = "0.6"
|
||||
krilla = { git = "https://github.com/LaurenzV/krilla", rev = "20c14fe", default-features = false, features = ["raster-images", "comemo", "rayon"] }
|
||||
krilla-svg = { git = "https://github.com/LaurenzV/krilla", rev = "20c14fe" }
|
||||
krilla = { git = "https://github.com/LaurenzV/krilla", rev = "37b9a00", default-features = false, features = ["raster-images", "comemo", "rayon", "pdf"] }
|
||||
krilla-svg = { git = "https://github.com/LaurenzV/krilla", rev = "37b9a00"}
|
||||
kurbo = "0.11"
|
||||
libfuzzer-sys = "0.4"
|
||||
lipsum = "0.9"
|
||||
|
@ -1,10 +1,10 @@
|
||||
use std::env;
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::fs::{File, create_dir_all};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use clap::{CommandFactory, ValueEnum};
|
||||
use clap_complete::{generate_to, Shell};
|
||||
use clap_complete::{Shell, generate_to};
|
||||
use clap_mangen::Man;
|
||||
|
||||
#[path = "src/args.rs"]
|
||||
|
@ -10,13 +10,13 @@ use ecow::eco_format;
|
||||
use parking_lot::RwLock;
|
||||
use pathdiff::diff_paths;
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||
use typst::WorldExt;
|
||||
use typst::diag::{
|
||||
bail, At, Severity, SourceDiagnostic, SourceResult, StrResult, Warned,
|
||||
At, Severity, SourceDiagnostic, SourceResult, StrResult, Warned, bail,
|
||||
};
|
||||
use typst::foundations::{Datetime, Smart};
|
||||
use typst::layout::{Frame, Page, PageRanges, PagedDocument};
|
||||
use typst::syntax::{FileId, Lines, Span};
|
||||
use typst::WorldExt;
|
||||
use typst_html::HtmlDocument;
|
||||
use typst_pdf::{PdfOptions, PdfStandards, Timestamp};
|
||||
|
||||
@ -513,7 +513,9 @@ fn write_make_deps(
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
else {
|
||||
bail!("failed to create make dependencies file because output path was not valid unicode")
|
||||
bail!(
|
||||
"failed to create make dependencies file because output path was not valid unicode"
|
||||
)
|
||||
};
|
||||
if output_paths.is_empty() {
|
||||
bail!("failed to create make dependencies file because output was stdout")
|
||||
|
@ -8,8 +8,8 @@ use codespan_reporting::term::termcolor::WriteColor;
|
||||
use typst::utils::format_duration;
|
||||
use typst_kit::download::{DownloadState, Downloader, Progress};
|
||||
|
||||
use crate::terminal::{self, TermOut};
|
||||
use crate::ARGS;
|
||||
use crate::terminal::{self, TermOut};
|
||||
|
||||
/// Prints download progress by writing `downloading {0}` followed by repeatedly
|
||||
/// updating the last terminal line.
|
||||
|
@ -4,7 +4,7 @@ use std::path::Path;
|
||||
use codespan_reporting::term::termcolor::{Color, ColorSpec, WriteColor};
|
||||
use ecow::eco_format;
|
||||
use fs_extra::dir::CopyOptions;
|
||||
use typst::diag::{bail, FileError, StrResult};
|
||||
use typst::diag::{FileError, StrResult, bail};
|
||||
use typst::syntax::package::{
|
||||
PackageManifest, PackageSpec, TemplateInfo, VersionlessPackageSpec,
|
||||
};
|
||||
|
@ -21,8 +21,8 @@ use std::io::{self, Write};
|
||||
use std::process::ExitCode;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use clap::error::ErrorKind;
|
||||
use clap::Parser;
|
||||
use clap::error::ErrorKind;
|
||||
use codespan_reporting::term;
|
||||
use codespan_reporting::term::termcolor::WriteColor;
|
||||
use typst::diag::HintedStrResult;
|
||||
@ -102,7 +102,7 @@ fn print_error(msg: &str) -> io::Result<()> {
|
||||
|
||||
#[cfg(not(feature = "self-update"))]
|
||||
mod update {
|
||||
use typst::diag::{bail, StrResult};
|
||||
use typst::diag::{StrResult, bail};
|
||||
|
||||
use crate::args::UpdateCommand;
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
use comemo::Track;
|
||||
use ecow::{eco_format, EcoString};
|
||||
use ecow::{EcoString, eco_format};
|
||||
use serde::Serialize;
|
||||
use typst::diag::{bail, HintedStrResult, StrResult, Warned};
|
||||
use typst::World;
|
||||
use typst::diag::{HintedStrResult, StrResult, Warned, bail};
|
||||
use typst::engine::Sink;
|
||||
use typst::foundations::{Content, IntoValue, LocatableSelector, Scope};
|
||||
use typst::layout::PagedDocument;
|
||||
use typst::syntax::{Span, SyntaxMode};
|
||||
use typst::World;
|
||||
use typst_eval::eval_string;
|
||||
|
||||
use crate::args::{QueryCommand, SerializationFormat};
|
||||
|
@ -5,7 +5,7 @@ use std::sync::Arc;
|
||||
use ecow::eco_format;
|
||||
use parking_lot::{Condvar, Mutex, MutexGuard};
|
||||
use tiny_http::{Header, Request, Response, StatusCode};
|
||||
use typst::diag::{bail, StrResult};
|
||||
use typst::diag::{StrResult, bail};
|
||||
|
||||
use crate::args::{Input, ServerArgs};
|
||||
|
||||
@ -162,7 +162,7 @@ impl<T> Bucket<T> {
|
||||
}
|
||||
|
||||
/// Retrieves the current data in the bucket.
|
||||
fn get(&self) -> MutexGuard<T> {
|
||||
fn get(&self) -> MutexGuard<'_, T> {
|
||||
self.mutex.lock()
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,9 @@ use std::fs::File;
|
||||
use std::io::BufWriter;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use typst::diag::{bail, StrResult};
|
||||
use typst::syntax::Span;
|
||||
use typst::World;
|
||||
use typst::diag::{StrResult, bail};
|
||||
use typst::syntax::Span;
|
||||
|
||||
use crate::args::{CliArguments, Command};
|
||||
use crate::world::SystemWorld;
|
||||
|
@ -6,7 +6,7 @@ use ecow::eco_format;
|
||||
use semver::Version;
|
||||
use serde::Deserialize;
|
||||
use tempfile::NamedTempFile;
|
||||
use typst::diag::{bail, StrResult};
|
||||
use typst::diag::{StrResult, bail};
|
||||
use typst_kit::download::Downloader;
|
||||
use xz2::bufread::XzDecoder;
|
||||
use zip::ZipArchive;
|
||||
|
@ -10,12 +10,12 @@ use codespan_reporting::term::{self, termcolor};
|
||||
use ecow::eco_format;
|
||||
use notify::{Event, RecommendedWatcher, RecursiveMode, Watcher as _};
|
||||
use same_file::is_same_file;
|
||||
use typst::diag::{bail, warning, StrResult};
|
||||
use typst::diag::{StrResult, bail, warning};
|
||||
use typst::syntax::Span;
|
||||
use typst::utils::format_duration;
|
||||
|
||||
use crate::args::{Input, Output, WatchCommand};
|
||||
use crate::compile::{compile_once, print_diagnostics, CompileConfig};
|
||||
use crate::compile::{CompileConfig, compile_once, print_diagnostics};
|
||||
use crate::timings::Timer;
|
||||
use crate::world::{SystemWorld, WorldCreationError};
|
||||
use crate::{print_error, terminal};
|
||||
|
@ -5,7 +5,7 @@ use std::sync::{LazyLock, OnceLock};
|
||||
use std::{fmt, fs, io, mem};
|
||||
|
||||
use chrono::{DateTime, Datelike, FixedOffset, Local, Utc};
|
||||
use ecow::{eco_format, EcoString};
|
||||
use ecow::{EcoString, eco_format};
|
||||
use parking_lot::Mutex;
|
||||
use typst::diag::{FileError, FileResult};
|
||||
use typst::foundations::{Bytes, Datetime, Dict, IntoValue};
|
||||
@ -361,10 +361,10 @@ impl<T: Clone> SlotCell<T> {
|
||||
f: impl FnOnce(Vec<u8>, Option<T>) -> FileResult<T>,
|
||||
) -> FileResult<T> {
|
||||
// If we accessed the file already in this compilation, retrieve it.
|
||||
if mem::replace(&mut self.accessed, true) {
|
||||
if let Some(data) = &self.data {
|
||||
return data.clone();
|
||||
}
|
||||
if mem::replace(&mut self.accessed, true)
|
||||
&& let Some(data) = &self.data
|
||||
{
|
||||
return data.clone();
|
||||
}
|
||||
|
||||
// Read and hash the file.
|
||||
@ -372,10 +372,10 @@ impl<T: Clone> SlotCell<T> {
|
||||
let fingerprint = timed!("hashing file", typst::utils::hash128(&result));
|
||||
|
||||
// If the file contents didn't change, yield the old processed data.
|
||||
if mem::replace(&mut self.fingerprint, fingerprint) == fingerprint {
|
||||
if let Some(data) = &self.data {
|
||||
return data.clone();
|
||||
}
|
||||
if mem::replace(&mut self.fingerprint, fingerprint) == fingerprint
|
||||
&& let Some(data) = &self.data
|
||||
{
|
||||
return data.clone();
|
||||
}
|
||||
|
||||
let prev = self.data.take().and_then(Result::ok);
|
||||
|
@ -20,7 +20,6 @@ typst-timing = { workspace = true }
|
||||
typst-utils = { workspace = true }
|
||||
comemo = { workspace = true }
|
||||
ecow = { workspace = true }
|
||||
if_chain = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
toml = { workspace = true }
|
||||
unicode-segmentation = { workspace = true }
|
||||
|
@ -1,9 +1,9 @@
|
||||
use ecow::eco_format;
|
||||
use typst_library::diag::{bail, At, Hint, SourceResult, Trace, Tracepoint};
|
||||
use typst_library::diag::{At, Hint, SourceResult, Trace, Tracepoint, bail};
|
||||
use typst_library::foundations::{Dict, Value};
|
||||
use typst_syntax::ast::{self, AstNode};
|
||||
|
||||
use crate::{call_method_access, is_accessor_method, Eval, Vm};
|
||||
use crate::{Eval, Vm, call_method_access, is_accessor_method};
|
||||
|
||||
/// Access an expression mutably.
|
||||
pub(crate) trait Access {
|
||||
@ -29,10 +29,10 @@ impl Access for ast::Expr<'_> {
|
||||
impl Access for ast::Ident<'_> {
|
||||
fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
|
||||
let span = self.span();
|
||||
if vm.inspected == Some(span) {
|
||||
if let Ok(binding) = vm.scopes.get(&self) {
|
||||
vm.trace(binding.read().clone());
|
||||
}
|
||||
if vm.inspected == Some(span)
|
||||
&& let Ok(binding) = vm.scopes.get(&self)
|
||||
{
|
||||
vm.trace(binding.read().clone());
|
||||
}
|
||||
vm.scopes
|
||||
.get_mut(&self)
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use ecow::eco_format;
|
||||
use typst_library::diag::{bail, error, At, SourceDiagnostic, SourceResult};
|
||||
use typst_library::diag::{At, SourceDiagnostic, SourceResult, bail, error};
|
||||
use typst_library::foundations::{Array, Dict, Value};
|
||||
use typst_syntax::ast::{self, AstNode};
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
use comemo::{Tracked, TrackedMut};
|
||||
use ecow::{eco_format, EcoString, EcoVec};
|
||||
use ecow::{EcoString, EcoVec, eco_format};
|
||||
use typst_library::World;
|
||||
use typst_library::diag::{
|
||||
bail, error, At, HintedStrResult, HintedString, SourceDiagnostic, SourceResult,
|
||||
Trace, Tracepoint,
|
||||
At, HintedStrResult, HintedString, SourceDiagnostic, SourceResult, Trace, Tracepoint,
|
||||
bail, error,
|
||||
};
|
||||
use typst_library::engine::{Engine, Sink, Traced};
|
||||
use typst_library::foundations::{
|
||||
@ -12,12 +13,11 @@ use typst_library::foundations::{
|
||||
use typst_library::introspection::Introspector;
|
||||
use typst_library::math::LrElem;
|
||||
use typst_library::routines::Routines;
|
||||
use typst_library::World;
|
||||
use typst_syntax::ast::{self, AstNode, Ident};
|
||||
use typst_syntax::{Span, Spanned, SyntaxNode};
|
||||
use typst_utils::LazyHash;
|
||||
|
||||
use crate::{call_method_mut, is_mutating_method, Access, Eval, FlowEvent, Route, Vm};
|
||||
use crate::{Access, Eval, FlowEvent, Route, Vm, call_method_mut, is_mutating_method};
|
||||
|
||||
impl Eval for ast::FuncCall<'_> {
|
||||
type Output = Value;
|
||||
|
@ -1,9 +1,9 @@
|
||||
use ecow::{eco_vec, EcoVec};
|
||||
use typst_library::diag::{bail, error, warning, At, SourceResult};
|
||||
use ecow::{EcoVec, eco_vec};
|
||||
use typst_library::diag::{At, SourceResult, bail, error, warning};
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{
|
||||
ops, Array, Capturer, Closure, Content, ContextElem, Dict, Func, NativeElement,
|
||||
Selector, Str, Value,
|
||||
Array, Capturer, Closure, Content, ContextElem, Dict, Func, NativeElement, Selector,
|
||||
Str, Value, ops,
|
||||
};
|
||||
use typst_library::introspection::{Counter, State};
|
||||
use typst_syntax::ast::{self, AstNode};
|
||||
@ -324,21 +324,17 @@ impl Eval for ast::FieldAccess<'_> {
|
||||
};
|
||||
|
||||
// Check whether this is a get rule field access.
|
||||
if_chain::if_chain! {
|
||||
if let Value::Func(func) = &value;
|
||||
if let Some(element) = func.element();
|
||||
if let Some(id) = element.field_id(&field);
|
||||
let styles = vm.context.styles().at(field.span());
|
||||
if let Ok(value) = element.field_from_styles(
|
||||
id,
|
||||
styles.as_ref().map(|&s| s).unwrap_or_default(),
|
||||
);
|
||||
then {
|
||||
// Only validate the context once we know that this is indeed
|
||||
// a field from the style chain.
|
||||
let _ = styles?;
|
||||
return Ok(value);
|
||||
}
|
||||
if let Value::Func(func) = &value
|
||||
&& let Some(element) = func.element()
|
||||
&& let Some(id) = element.field_id(&field)
|
||||
&& let styles = vm.context.styles().at(field.span())
|
||||
&& let Ok(value) = element
|
||||
.field_from_styles(id, styles.as_ref().map(|&s| s).unwrap_or_default())
|
||||
{
|
||||
// Only validate the context once we know that this is indeed
|
||||
// a field from the style chain.
|
||||
let _ = styles?;
|
||||
return Ok(value);
|
||||
}
|
||||
|
||||
Err(err)
|
||||
|
@ -1,10 +1,10 @@
|
||||
use typst_library::diag::{bail, error, At, SourceDiagnostic, SourceResult};
|
||||
use typst_library::foundations::{ops, IntoValue, Value};
|
||||
use typst_library::diag::{At, SourceDiagnostic, SourceResult, bail, error};
|
||||
use typst_library::foundations::{IntoValue, Value, ops};
|
||||
use typst_syntax::ast::{self, AstNode};
|
||||
use typst_syntax::{Span, SyntaxKind, SyntaxNode};
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use crate::{destructure, Eval, Vm};
|
||||
use crate::{Eval, Vm, destructure};
|
||||
|
||||
/// The maximum number of loop iterations.
|
||||
const MAX_ITERATIONS: usize = 10_000;
|
||||
|
@ -1,16 +1,16 @@
|
||||
use comemo::TrackedMut;
|
||||
use ecow::{eco_format, eco_vec, EcoString};
|
||||
use ecow::{EcoString, eco_format, eco_vec};
|
||||
use typst_library::World;
|
||||
use typst_library::diag::{
|
||||
bail, error, warning, At, FileError, SourceResult, Trace, Tracepoint,
|
||||
At, FileError, SourceResult, Trace, Tracepoint, bail, error, warning,
|
||||
};
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{Binding, Content, Module, Value};
|
||||
use typst_library::World;
|
||||
use typst_syntax::ast::{self, AstNode, BareImportError};
|
||||
use typst_syntax::package::{PackageManifest, PackageSpec};
|
||||
use typst_syntax::{FileId, Span, VirtualPath};
|
||||
|
||||
use crate::{eval, Eval, Vm};
|
||||
use crate::{Eval, Vm, eval};
|
||||
|
||||
impl Eval for ast::ModuleImport<'_> {
|
||||
type Output = Value;
|
||||
@ -46,14 +46,14 @@ impl Eval for ast::ModuleImport<'_> {
|
||||
// If there is a rename, import the source itself under that name.
|
||||
let new_name = self.new_name();
|
||||
if let Some(new_name) = new_name {
|
||||
if let ast::Expr::Ident(ident) = self.source() {
|
||||
if ident.as_str() == new_name.as_str() {
|
||||
// Warn on `import x as x`
|
||||
vm.engine.sink.warn(warning!(
|
||||
new_name.span(),
|
||||
"unnecessary import rename to same name",
|
||||
));
|
||||
}
|
||||
if let ast::Expr::Ident(ident) = self.source()
|
||||
&& ident.as_str() == new_name.as_str()
|
||||
{
|
||||
// Warn on `import x as x`
|
||||
vm.engine.sink.warn(warning!(
|
||||
new_name.span(),
|
||||
"unnecessary import rename to same name",
|
||||
));
|
||||
}
|
||||
|
||||
// Define renamed module on the scope.
|
||||
@ -142,15 +142,14 @@ impl Eval for ast::ModuleImport<'_> {
|
||||
// it.
|
||||
|
||||
// Warn on `import ...: x as x`
|
||||
if let ast::ImportItem::Renamed(renamed_item) = &item {
|
||||
if renamed_item.original_name().as_str()
|
||||
if let ast::ImportItem::Renamed(renamed_item) = &item
|
||||
&& renamed_item.original_name().as_str()
|
||||
== renamed_item.new_name().as_str()
|
||||
{
|
||||
vm.engine.sink.warn(warning!(
|
||||
renamed_item.new_name().span(),
|
||||
"unnecessary import rename to same name",
|
||||
));
|
||||
}
|
||||
{
|
||||
vm.engine.sink.warn(warning!(
|
||||
renamed_item.new_name().span(),
|
||||
"unnecessary import rename to same name",
|
||||
));
|
||||
}
|
||||
|
||||
vm.bind(item.bound_name(), binding.clone());
|
||||
|
@ -14,7 +14,7 @@ mod methods;
|
||||
mod rules;
|
||||
mod vm;
|
||||
|
||||
pub use self::call::{eval_closure, CapturesVisitor};
|
||||
pub use self::call::{CapturesVisitor, eval_closure};
|
||||
pub use self::flow::FlowEvent;
|
||||
pub use self::import::import;
|
||||
pub use self::vm::Vm;
|
||||
@ -24,14 +24,14 @@ use self::binding::*;
|
||||
use self::methods::*;
|
||||
|
||||
use comemo::{Track, Tracked, TrackedMut};
|
||||
use typst_library::diag::{bail, SourceResult};
|
||||
use typst_library::World;
|
||||
use typst_library::diag::{SourceResult, bail};
|
||||
use typst_library::engine::{Engine, Route, Sink, Traced};
|
||||
use typst_library::foundations::{Context, Module, NativeElement, Scope, Scopes, Value};
|
||||
use typst_library::introspection::Introspector;
|
||||
use typst_library::math::EquationElem;
|
||||
use typst_library::routines::Routines;
|
||||
use typst_library::World;
|
||||
use typst_syntax::{ast, parse, parse_code, parse_math, Source, Span, SyntaxMode};
|
||||
use typst_syntax::{Source, Span, SyntaxMode, ast, parse, parse_code, parse_math};
|
||||
|
||||
/// Evaluate a source file and return the resulting module.
|
||||
#[comemo::memoize]
|
||||
|
@ -1,4 +1,4 @@
|
||||
use typst_library::diag::{warning, At, SourceResult};
|
||||
use typst_library::diag::{At, SourceResult, warning};
|
||||
use typst_library::foundations::{
|
||||
Content, Label, NativeElement, Repr, Smart, Symbol, Unlabellable, Value,
|
||||
};
|
||||
|
@ -1,8 +1,8 @@
|
||||
use typst_library::diag::{At, HintedStrResult, SourceResult};
|
||||
use typst_library::foundations::{ops, IntoValue, Value};
|
||||
use typst_library::foundations::{IntoValue, Value, ops};
|
||||
use typst_syntax::ast::{self, AstNode};
|
||||
|
||||
use crate::{access_dict, Access, Eval, Vm};
|
||||
use crate::{Access, Eval, Vm, access_dict};
|
||||
|
||||
impl Eval for ast::Unary<'_> {
|
||||
type Output = Value;
|
||||
@ -76,12 +76,12 @@ fn apply_assignment(
|
||||
|
||||
// An assignment to a dictionary field is different from a normal access
|
||||
// since it can create the field instead of just modifying it.
|
||||
if binary.op() == ast::BinOp::Assign {
|
||||
if let ast::Expr::FieldAccess(access) = lhs {
|
||||
let dict = access_dict(vm, access)?;
|
||||
dict.insert(access.field().get().clone().into(), rhs);
|
||||
return Ok(Value::None);
|
||||
}
|
||||
if binary.op() == ast::BinOp::Assign
|
||||
&& let ast::Expr::FieldAccess(access) = lhs
|
||||
{
|
||||
let dict = access_dict(vm, access)?;
|
||||
dict.insert(access.field().get().clone().into(), rhs);
|
||||
return Ok(Value::None);
|
||||
}
|
||||
|
||||
let location = binary.lhs().access(vm)?;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use typst_library::diag::{warning, At, SourceResult};
|
||||
use typst_library::diag::{At, SourceResult, warning};
|
||||
use typst_library::foundations::{
|
||||
Element, Func, Recipe, Selector, ShowableSelector, Styles, Transformation,
|
||||
};
|
||||
@ -12,10 +12,10 @@ impl Eval for ast::SetRule<'_> {
|
||||
type Output = Styles;
|
||||
|
||||
fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
||||
if let Some(condition) = self.condition() {
|
||||
if !condition.eval(vm)?.cast::<bool>().at(condition.span())? {
|
||||
return Ok(Styles::new());
|
||||
}
|
||||
if let Some(condition) = self.condition()
|
||||
&& !condition.eval(vm)?.cast::<bool>().at(condition.span())?
|
||||
{
|
||||
return Ok(Styles::new());
|
||||
}
|
||||
|
||||
let target = self.target();
|
||||
@ -58,18 +58,16 @@ impl Eval for ast::ShowRule<'_> {
|
||||
|
||||
/// Migration hint for `show par: set block(spacing: ..)`.
|
||||
fn check_show_par_set_block(vm: &mut Vm, recipe: &Recipe) {
|
||||
if_chain::if_chain! {
|
||||
if let Some(Selector::Elem(elem, _)) = recipe.selector();
|
||||
if *elem == Element::of::<ParElem>();
|
||||
if let Transformation::Style(styles) = recipe.transform();
|
||||
if styles.has(BlockElem::above) || styles.has(BlockElem::below);
|
||||
then {
|
||||
vm.engine.sink.warn(warning!(
|
||||
if let Some(Selector::Elem(elem, _)) = recipe.selector()
|
||||
&& *elem == Element::of::<ParElem>()
|
||||
&& let Transformation::Style(styles) = recipe.transform()
|
||||
&& (styles.has(BlockElem::above) || styles.has(BlockElem::below))
|
||||
{
|
||||
vm.engine.sink.warn(warning!(
|
||||
recipe.span(),
|
||||
"`show par: set block(spacing: ..)` has no effect anymore";
|
||||
hint: "write `set par(spacing: ..)` instead";
|
||||
hint: "this is specific to paragraphs as they are not considered blocks anymore"
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
use comemo::Tracked;
|
||||
use typst_library::World;
|
||||
use typst_library::diag::warning;
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{Binding, Context, IntoValue, Scopes, Value};
|
||||
use typst_library::World;
|
||||
use typst_syntax::ast::{self, AstNode};
|
||||
use typst_syntax::Span;
|
||||
use typst_syntax::ast::{self, AstNode};
|
||||
|
||||
use crate::FlowEvent;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use typst_library::diag::{warning, SourceResult};
|
||||
use typst_library::diag::{SourceResult, warning};
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{Content, StyleChain, Target, TargetElem};
|
||||
use typst_library::introspection::{SplitLocator, TagElem};
|
||||
@ -8,7 +8,7 @@ use typst_library::routines::Pair;
|
||||
use typst_library::text::{LinebreakElem, SmartQuoteElem, SpaceElem, TextElem};
|
||||
|
||||
use crate::fragment::html_fragment;
|
||||
use crate::{attr, tag, FrameElem, HtmlElem, HtmlElement, HtmlFrame, HtmlNode};
|
||||
use crate::{FrameElem, HtmlElem, HtmlElement, HtmlFrame, HtmlNode, attr, tag};
|
||||
|
||||
/// Converts realized content into HTML nodes.
|
||||
pub fn convert_to_nodes<'a>(
|
||||
|
@ -2,7 +2,8 @@ use std::collections::HashSet;
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use comemo::{Tracked, TrackedMut};
|
||||
use typst_library::diag::{bail, SourceResult};
|
||||
use typst_library::World;
|
||||
use typst_library::diag::{SourceResult, bail};
|
||||
use typst_library::engine::{Engine, Route, Sink, Traced};
|
||||
use typst_library::foundations::{Content, StyleChain};
|
||||
use typst_library::introspection::{
|
||||
@ -11,11 +12,10 @@ use typst_library::introspection::{
|
||||
use typst_library::layout::{Point, Position, Transform};
|
||||
use typst_library::model::DocumentInfo;
|
||||
use typst_library::routines::{Arenas, RealizationKind, Routines};
|
||||
use typst_library::World;
|
||||
use typst_syntax::Span;
|
||||
use typst_utils::NonZeroExt;
|
||||
|
||||
use crate::{attr, tag, HtmlDocument, HtmlElement, HtmlNode};
|
||||
use crate::{HtmlDocument, HtmlElement, HtmlNode, attr, tag};
|
||||
|
||||
/// Produce an HTML document from content.
|
||||
///
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
|
||||
use ecow::{EcoString, EcoVec};
|
||||
use typst_library::diag::{bail, HintedStrResult, StrResult};
|
||||
use typst_library::foundations::{cast, Dict, Repr, Str, StyleChain};
|
||||
use typst_library::diag::{HintedStrResult, StrResult, bail};
|
||||
use typst_library::foundations::{Dict, Repr, Str, StyleChain, cast};
|
||||
use typst_library::introspection::{Introspector, Tag};
|
||||
use typst_library::layout::{Abs, Frame, Point};
|
||||
use typst_library::model::DocumentInfo;
|
||||
|
@ -1,12 +1,12 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use typst_library::diag::{bail, At, SourceResult, StrResult};
|
||||
use typst_library::diag::{At, SourceResult, StrResult, bail};
|
||||
use typst_library::foundations::Repr;
|
||||
use typst_library::introspection::Introspector;
|
||||
use typst_syntax::Span;
|
||||
|
||||
use crate::{
|
||||
attr, charsets, tag, HtmlDocument, HtmlElement, HtmlFrame, HtmlNode, HtmlTag,
|
||||
HtmlDocument, HtmlElement, HtmlFrame, HtmlNode, HtmlTag, attr, charsets, tag,
|
||||
};
|
||||
|
||||
/// Encodes an HTML document into a string.
|
||||
@ -262,11 +262,7 @@ impl RawMode {
|
||||
{
|
||||
// Template literals can be multi-line, so indent may change
|
||||
// the semantics of the JavaScript.
|
||||
if text.contains('`') {
|
||||
Self::Wrap
|
||||
} else {
|
||||
Self::Indent
|
||||
}
|
||||
if text.contains('`') { Self::Wrap } else { Self::Indent }
|
||||
}
|
||||
tag::style => Self::Indent,
|
||||
_ => Self::Keep,
|
||||
|
@ -4,8 +4,8 @@ use typst_library::engine::{Engine, Route, Sink, Traced};
|
||||
use typst_library::foundations::{Content, StyleChain};
|
||||
use typst_library::introspection::{Introspector, Locator, LocatorLink};
|
||||
|
||||
use typst_library::routines::{Arenas, FragmentKind, RealizationKind, Routines};
|
||||
use typst_library::World;
|
||||
use typst_library::routines::{Arenas, FragmentKind, RealizationKind, Routines};
|
||||
|
||||
use crate::HtmlNode;
|
||||
|
||||
|
@ -19,8 +19,8 @@ pub use self::encode::html;
|
||||
pub use self::rules::register;
|
||||
|
||||
use ecow::EcoString;
|
||||
use typst_library::foundations::{Content, Module, Scope};
|
||||
use typst_library::Category;
|
||||
use typst_library::foundations::{Content, Module, Scope};
|
||||
use typst_macros::elem;
|
||||
|
||||
/// Creates the module with all HTML definitions.
|
||||
@ -86,11 +86,7 @@ impl HtmlElem {
|
||||
attr: HtmlAttr,
|
||||
value: Option<impl Into<EcoString>>,
|
||||
) -> Self {
|
||||
if let Some(value) = value {
|
||||
self.with_attr(attr, value)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
if let Some(value) = value { self.with_attr(attr, value) } else { self }
|
||||
}
|
||||
|
||||
/// Adds CSS styles to an element.
|
||||
|
@ -1,14 +1,14 @@
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
|
||||
use comemo::Track;
|
||||
use ecow::{eco_format, EcoString};
|
||||
use ecow::{EcoString, eco_format};
|
||||
use typst_library::foundations::{Label, NativeElement};
|
||||
use typst_library::introspection::{Introspector, Location, Tag};
|
||||
use typst_library::layout::{Frame, FrameItem, Point};
|
||||
use typst_library::model::{Destination, LinkElem};
|
||||
use typst_utils::PicoStr;
|
||||
|
||||
use crate::{attr, tag, HtmlElement, HtmlNode};
|
||||
use crate::{HtmlElement, HtmlNode, attr, tag};
|
||||
|
||||
/// Searches for links within a frame.
|
||||
///
|
||||
|
@ -1,12 +1,12 @@
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use ecow::{eco_format, EcoVec};
|
||||
use typst_library::diag::{warning, At};
|
||||
use ecow::{EcoVec, eco_format};
|
||||
use typst_library::diag::{At, warning};
|
||||
use typst_library::foundations::{
|
||||
Content, NativeElement, NativeRuleMap, ShowFn, Smart, StyleChain, Target,
|
||||
};
|
||||
use typst_library::introspection::{Counter, Locator};
|
||||
use typst_library::layout::resolve::{table_to_cellgrid, Cell, CellGrid, Entry};
|
||||
use typst_library::layout::resolve::{Cell, CellGrid, Entry, table_to_cellgrid};
|
||||
use typst_library::layout::{OuterVAlignment, Sizing};
|
||||
use typst_library::model::{
|
||||
Attribution, CiteElem, CiteGroup, Destination, EmphElem, EnumElem, FigureCaption,
|
||||
@ -19,7 +19,7 @@ use typst_library::text::{
|
||||
};
|
||||
use typst_library::visualize::ImageElem;
|
||||
|
||||
use crate::{attr, css, tag, FrameElem, HtmlAttrs, HtmlElem, HtmlTag};
|
||||
use crate::{FrameElem, HtmlAttrs, HtmlElem, HtmlTag, attr, css, tag};
|
||||
|
||||
/// Registers show rules for the [HTML target](Target::Html).
|
||||
pub fn register(rules: &mut NativeRuleMap) {
|
||||
@ -238,13 +238,11 @@ const QUOTE_RULE: ShowFn<QuoteElem> = |elem, _, styles| {
|
||||
|
||||
if block {
|
||||
let mut blockquote = HtmlElem::new(tag::blockquote).with_body(Some(realized));
|
||||
if let Some(Attribution::Content(attribution)) = attribution {
|
||||
if let Some(link) = attribution.to_packed::<LinkElem>() {
|
||||
if let LinkTarget::Dest(Destination::Url(url)) = &link.dest {
|
||||
blockquote =
|
||||
blockquote.with_attr(attr::cite, url.clone().into_inner());
|
||||
}
|
||||
}
|
||||
if let Some(Attribution::Content(attribution)) = attribution
|
||||
&& let Some(link) = attribution.to_packed::<LinkElem>()
|
||||
&& let LinkTarget::Dest(Destination::Url(url)) = &link.dest
|
||||
{
|
||||
blockquote = blockquote.with_attr(attr::cite, url.clone().into_inner());
|
||||
}
|
||||
|
||||
realized = blockquote.pack().spanned(span);
|
||||
|
@ -9,9 +9,9 @@ use std::sync::LazyLock;
|
||||
|
||||
use bumpalo::Bump;
|
||||
use comemo::Tracked;
|
||||
use ecow::{eco_format, eco_vec, EcoString};
|
||||
use ecow::{EcoString, eco_format, eco_vec};
|
||||
use typst_assets::html as data;
|
||||
use typst_library::diag::{bail, At, Hint, HintedStrResult, SourceResult};
|
||||
use typst_library::diag::{At, Hint, HintedStrResult, SourceResult, bail};
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{
|
||||
Args, Array, AutoValue, CastInfo, Content, Context, Datetime, Dict, Duration,
|
||||
@ -22,7 +22,7 @@ use typst_library::layout::{Axes, Axis, Dir, Length};
|
||||
use typst_library::visualize::Color;
|
||||
use typst_macros::cast;
|
||||
|
||||
use crate::{css, tag, HtmlAttr, HtmlAttrs, HtmlElem, HtmlTag};
|
||||
use crate::{HtmlAttr, HtmlAttrs, HtmlElem, HtmlTag, css, tag};
|
||||
|
||||
/// Hook up all typed HTML definitions.
|
||||
pub(super) fn define(html: &mut Scope) {
|
||||
|
@ -17,7 +17,6 @@ typst = { workspace = true }
|
||||
typst-eval = { workspace = true }
|
||||
comemo = { workspace = true }
|
||||
ecow = { workspace = true }
|
||||
if_chain = { workspace = true }
|
||||
pathdiff = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
unscanny = { workspace = true }
|
||||
|
@ -1,11 +1,11 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use comemo::Track;
|
||||
use ecow::{eco_vec, EcoString, EcoVec};
|
||||
use ecow::{EcoString, EcoVec, eco_vec};
|
||||
use typst::foundations::{Label, Styles, Value};
|
||||
use typst::layout::PagedDocument;
|
||||
use typst::model::{BibliographyElem, FigureElem};
|
||||
use typst::syntax::{ast, LinkedNode, SyntaxKind};
|
||||
use typst::syntax::{LinkedNode, SyntaxKind, ast};
|
||||
|
||||
use crate::IdeWorld;
|
||||
|
||||
@ -27,16 +27,17 @@ pub fn analyze_expr(
|
||||
ast::Expr::Numeric(v) => Value::numeric(v.get()),
|
||||
ast::Expr::Str(v) => Value::Str(v.get().into()),
|
||||
_ => {
|
||||
if node.kind() == SyntaxKind::Contextual {
|
||||
if let Some(child) = node.children().next_back() {
|
||||
return analyze_expr(world, &child);
|
||||
}
|
||||
if node.kind() == SyntaxKind::Contextual
|
||||
&& let Some(child) = node.children().next_back()
|
||||
{
|
||||
return analyze_expr(world, &child);
|
||||
}
|
||||
|
||||
if let Some(parent) = node.parent() {
|
||||
if parent.kind() == SyntaxKind::FieldAccess && node.index() > 0 {
|
||||
return analyze_expr(world, parent);
|
||||
}
|
||||
if let Some(parent) = node.parent()
|
||||
&& parent.kind() == SyntaxKind::FieldAccess
|
||||
&& node.index() > 0
|
||||
{
|
||||
return analyze_expr(world, parent);
|
||||
}
|
||||
|
||||
return typst::trace::<PagedDocument>(world.upcast(), node.span());
|
||||
|
@ -2,18 +2,17 @@ use std::cmp::Reverse;
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::ffi::OsStr;
|
||||
|
||||
use ecow::{eco_format, EcoString};
|
||||
use if_chain::if_chain;
|
||||
use ecow::{EcoString, eco_format};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typst::foundations::{
|
||||
fields_on, repr, AutoValue, CastInfo, Func, Label, NoneValue, ParamInfo, Repr,
|
||||
StyleChain, Styles, Type, Value,
|
||||
AutoValue, CastInfo, Func, Label, NoneValue, ParamInfo, Repr, StyleChain, Styles,
|
||||
Type, Value, fields_on, repr,
|
||||
};
|
||||
use typst::layout::{Alignment, Dir, PagedDocument};
|
||||
use typst::syntax::ast::AstNode;
|
||||
use typst::syntax::{
|
||||
ast, is_id_continue, is_id_start, is_ident, FileId, LinkedNode, Side, Source,
|
||||
SyntaxKind,
|
||||
FileId, LinkedNode, Side, Source, SyntaxKind, ast, is_id_continue, is_id_start,
|
||||
is_ident,
|
||||
};
|
||||
use typst::text::{FontFlags, RawElem};
|
||||
use typst::visualize::Color;
|
||||
@ -22,7 +21,7 @@ use unscanny::Scanner;
|
||||
use crate::utils::{
|
||||
check_value_recursively, globals, plain_docs_sentence, summarize_font_family,
|
||||
};
|
||||
use crate::{analyze_expr, analyze_import, analyze_labels, named_items, IdeWorld};
|
||||
use crate::{IdeWorld, analyze_expr, analyze_import, analyze_labels, named_items};
|
||||
|
||||
/// Autocomplete a cursor position in a source file.
|
||||
///
|
||||
@ -145,26 +144,22 @@ fn complete_markup(ctx: &mut CompletionContext) -> bool {
|
||||
}
|
||||
|
||||
// Behind a half-completed binding: "#let x = |".
|
||||
if_chain! {
|
||||
if let Some(prev) = ctx.leaf.prev_leaf();
|
||||
if prev.kind() == SyntaxKind::Eq;
|
||||
if prev.parent_kind() == Some(SyntaxKind::LetBinding);
|
||||
then {
|
||||
ctx.from = ctx.cursor;
|
||||
code_completions(ctx, false);
|
||||
return true;
|
||||
}
|
||||
if let Some(prev) = ctx.leaf.prev_leaf()
|
||||
&& prev.kind() == SyntaxKind::Eq
|
||||
&& prev.parent_kind() == Some(SyntaxKind::LetBinding)
|
||||
{
|
||||
ctx.from = ctx.cursor;
|
||||
code_completions(ctx, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Behind a half-completed context block: "#context |".
|
||||
if_chain! {
|
||||
if let Some(prev) = ctx.leaf.prev_leaf();
|
||||
if prev.kind() == SyntaxKind::Context;
|
||||
then {
|
||||
ctx.from = ctx.cursor;
|
||||
code_completions(ctx, false);
|
||||
return true;
|
||||
}
|
||||
if let Some(prev) = ctx.leaf.prev_leaf()
|
||||
&& prev.kind() == SyntaxKind::Context
|
||||
{
|
||||
ctx.from = ctx.cursor;
|
||||
code_completions(ctx, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Directly after a raw block.
|
||||
@ -373,37 +368,34 @@ fn complete_field_accesses(ctx: &mut CompletionContext) -> bool {
|
||||
);
|
||||
|
||||
// Behind an expression plus dot: "emoji.|".
|
||||
if_chain! {
|
||||
if ctx.leaf.kind() == SyntaxKind::Dot
|
||||
|| (matches!(ctx.leaf.kind(), SyntaxKind::Text | SyntaxKind::MathText)
|
||||
&& ctx.leaf.text() == ".");
|
||||
if ctx.leaf.range().end == ctx.cursor;
|
||||
if let Some(prev) = ctx.leaf.prev_sibling();
|
||||
if !in_markup || prev.range().end == ctx.leaf.range().start;
|
||||
if prev.is::<ast::Expr>();
|
||||
if prev.parent_kind() != Some(SyntaxKind::Markup) ||
|
||||
prev.prev_sibling_kind() == Some(SyntaxKind::Hash);
|
||||
if let Some((value, styles)) = analyze_expr(ctx.world, &prev).into_iter().next();
|
||||
then {
|
||||
ctx.from = ctx.cursor;
|
||||
field_access_completions(ctx, &value, &styles);
|
||||
return true;
|
||||
}
|
||||
if (ctx.leaf.kind() == SyntaxKind::Dot
|
||||
|| (matches!(ctx.leaf.kind(), SyntaxKind::Text | SyntaxKind::MathText)
|
||||
&& ctx.leaf.text() == "."))
|
||||
&& ctx.leaf.range().end == ctx.cursor
|
||||
&& let Some(prev) = ctx.leaf.prev_sibling()
|
||||
&& (!in_markup || prev.range().end == ctx.leaf.range().start)
|
||||
&& prev.is::<ast::Expr>()
|
||||
&& (prev.parent_kind() != Some(SyntaxKind::Markup)
|
||||
|| prev.prev_sibling_kind() == Some(SyntaxKind::Hash))
|
||||
&& let Some((value, styles)) = analyze_expr(ctx.world, &prev).into_iter().next()
|
||||
{
|
||||
ctx.from = ctx.cursor;
|
||||
field_access_completions(ctx, &value, &styles);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Behind a started field access: "emoji.fa|".
|
||||
if_chain! {
|
||||
if ctx.leaf.kind() == SyntaxKind::Ident;
|
||||
if let Some(prev) = ctx.leaf.prev_sibling();
|
||||
if prev.kind() == SyntaxKind::Dot;
|
||||
if let Some(prev_prev) = prev.prev_sibling();
|
||||
if prev_prev.is::<ast::Expr>();
|
||||
if let Some((value, styles)) = analyze_expr(ctx.world, &prev_prev).into_iter().next();
|
||||
then {
|
||||
ctx.from = ctx.leaf.offset();
|
||||
field_access_completions(ctx, &value, &styles);
|
||||
return true;
|
||||
}
|
||||
if ctx.leaf.kind() == SyntaxKind::Ident
|
||||
&& let Some(prev) = ctx.leaf.prev_sibling()
|
||||
&& prev.kind() == SyntaxKind::Dot
|
||||
&& let Some(prev_prev) = prev.prev_sibling()
|
||||
&& prev_prev.is::<ast::Expr>()
|
||||
&& let Some((value, styles)) =
|
||||
analyze_expr(ctx.world, &prev_prev).into_iter().next()
|
||||
{
|
||||
ctx.from = ctx.leaf.offset();
|
||||
field_access_completions(ctx, &value, &styles);
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
@ -507,57 +499,49 @@ fn complete_open_labels(ctx: &mut CompletionContext) -> bool {
|
||||
fn complete_imports(ctx: &mut CompletionContext) -> bool {
|
||||
// In an import path for a file or package:
|
||||
// "#import "|",
|
||||
if_chain! {
|
||||
if matches!(
|
||||
ctx.leaf.parent_kind(),
|
||||
Some(SyntaxKind::ModuleImport | SyntaxKind::ModuleInclude)
|
||||
);
|
||||
if let Some(ast::Expr::Str(str)) = ctx.leaf.cast();
|
||||
if let Some(SyntaxKind::ModuleImport | SyntaxKind::ModuleInclude) =
|
||||
ctx.leaf.parent_kind()
|
||||
&& let Some(ast::Expr::Str(str)) = ctx.leaf.cast()
|
||||
{
|
||||
let value = str.get();
|
||||
then {
|
||||
ctx.from = ctx.leaf.offset();
|
||||
if value.starts_with('@') {
|
||||
let all_versions = value.contains(':');
|
||||
ctx.package_completions(all_versions);
|
||||
} else {
|
||||
ctx.file_completions_with_extensions(&["typ"]);
|
||||
}
|
||||
return true;
|
||||
ctx.from = ctx.leaf.offset();
|
||||
if value.starts_with('@') {
|
||||
let all_versions = value.contains(':');
|
||||
ctx.package_completions(all_versions);
|
||||
} else {
|
||||
ctx.file_completions_with_extensions(&["typ"]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Behind an import list:
|
||||
// "#import "path.typ": |",
|
||||
// "#import "path.typ": a, b, |".
|
||||
if_chain! {
|
||||
if let Some(prev) = ctx.leaf.prev_sibling();
|
||||
if let Some(ast::Expr::ModuleImport(import)) = prev.get().cast();
|
||||
if let Some(ast::Imports::Items(items)) = import.imports();
|
||||
if let Some(source) = prev.children().find(|child| child.is::<ast::Expr>());
|
||||
then {
|
||||
ctx.from = ctx.cursor;
|
||||
import_item_completions(ctx, items, &source);
|
||||
return true;
|
||||
}
|
||||
if let Some(prev) = ctx.leaf.prev_sibling()
|
||||
&& let Some(ast::Expr::ModuleImport(import)) = prev.get().cast()
|
||||
&& let Some(ast::Imports::Items(items)) = import.imports()
|
||||
&& let Some(source) = prev.children().find(|child| child.is::<ast::Expr>())
|
||||
{
|
||||
ctx.from = ctx.cursor;
|
||||
import_item_completions(ctx, items, &source);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Behind a half-started identifier in an import list:
|
||||
// "#import "path.typ": thi|",
|
||||
if_chain! {
|
||||
if ctx.leaf.kind() == SyntaxKind::Ident;
|
||||
if let Some(parent) = ctx.leaf.parent();
|
||||
if parent.kind() == SyntaxKind::ImportItemPath;
|
||||
if let Some(grand) = parent.parent();
|
||||
if grand.kind() == SyntaxKind::ImportItems;
|
||||
if let Some(great) = grand.parent();
|
||||
if let Some(ast::Expr::ModuleImport(import)) = great.get().cast();
|
||||
if let Some(ast::Imports::Items(items)) = import.imports();
|
||||
if let Some(source) = great.children().find(|child| child.is::<ast::Expr>());
|
||||
then {
|
||||
ctx.from = ctx.leaf.offset();
|
||||
import_item_completions(ctx, items, &source);
|
||||
return true;
|
||||
}
|
||||
if ctx.leaf.kind() == SyntaxKind::Ident
|
||||
&& let Some(parent) = ctx.leaf.parent()
|
||||
&& parent.kind() == SyntaxKind::ImportItemPath
|
||||
&& let Some(grand) = parent.parent()
|
||||
&& grand.kind() == SyntaxKind::ImportItems
|
||||
&& let Some(great) = grand.parent()
|
||||
&& let Some(ast::Expr::ModuleImport(import)) = great.get().cast()
|
||||
&& let Some(ast::Imports::Items(items)) = import.imports()
|
||||
&& let Some(source) = great.children().find(|child| child.is::<ast::Expr>())
|
||||
{
|
||||
ctx.from = ctx.leaf.offset();
|
||||
import_item_completions(ctx, items, &source);
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
@ -607,15 +591,13 @@ fn complete_rules(ctx: &mut CompletionContext) -> bool {
|
||||
}
|
||||
|
||||
// Behind a half-completed show rule: "show strong: |".
|
||||
if_chain! {
|
||||
if let Some(prev) = ctx.leaf.prev_leaf();
|
||||
if matches!(prev.kind(), SyntaxKind::Colon);
|
||||
if matches!(prev.parent_kind(), Some(SyntaxKind::ShowRule));
|
||||
then {
|
||||
ctx.from = ctx.cursor;
|
||||
show_rule_recipe_completions(ctx);
|
||||
return true;
|
||||
}
|
||||
if let Some(prev) = ctx.leaf.prev_leaf()
|
||||
&& matches!(prev.kind(), SyntaxKind::Colon)
|
||||
&& matches!(prev.parent_kind(), Some(SyntaxKind::ShowRule))
|
||||
{
|
||||
ctx.from = ctx.cursor;
|
||||
show_rule_recipe_completions(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
@ -682,26 +664,23 @@ fn show_rule_recipe_completions(ctx: &mut CompletionContext) {
|
||||
/// Complete call and set rule parameters.
|
||||
fn complete_params(ctx: &mut CompletionContext) -> bool {
|
||||
// Ensure that we are in a function call or set rule's argument list.
|
||||
let (callee, set, args, args_linked) = if_chain! {
|
||||
if let Some(parent) = ctx.leaf.parent();
|
||||
if let Some(parent) = match parent.kind() {
|
||||
let (callee, set, args, args_linked) = if let Some(parent) = ctx.leaf.parent()
|
||||
&& let Some(parent) = match parent.kind() {
|
||||
SyntaxKind::Named => parent.parent(),
|
||||
_ => Some(parent),
|
||||
};
|
||||
if let Some(args) = parent.get().cast::<ast::Args>();
|
||||
if let Some(grand) = parent.parent();
|
||||
if let Some(expr) = grand.get().cast::<ast::Expr>();
|
||||
let set = matches!(expr, ast::Expr::SetRule(_));
|
||||
if let Some(callee) = match expr {
|
||||
}
|
||||
&& let Some(args) = parent.get().cast::<ast::Args>()
|
||||
&& let Some(grand) = parent.parent()
|
||||
&& let Some(expr) = grand.get().cast::<ast::Expr>()
|
||||
&& let set = matches!(expr, ast::Expr::SetRule(_))
|
||||
&& let Some(callee) = match expr {
|
||||
ast::Expr::FuncCall(call) => Some(call.callee()),
|
||||
ast::Expr::SetRule(set) => Some(set.target()),
|
||||
_ => None,
|
||||
};
|
||||
then {
|
||||
(callee, set, args, parent)
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} {
|
||||
(callee, set, args, parent)
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Find the piece of syntax that decides what we're completing.
|
||||
@ -718,32 +697,28 @@ fn complete_params(ctx: &mut CompletionContext) -> bool {
|
||||
}
|
||||
|
||||
// Parameter values: "func(param:|)", "func(param: |)".
|
||||
if_chain! {
|
||||
if deciding.kind() == SyntaxKind::Colon;
|
||||
if let Some(prev) = deciding.prev_leaf();
|
||||
if let Some(param) = prev.get().cast::<ast::Ident>();
|
||||
then {
|
||||
if let Some(next) = deciding.next_leaf() {
|
||||
ctx.from = ctx.cursor.min(next.offset());
|
||||
}
|
||||
|
||||
named_param_value_completions(ctx, callee, ¶m);
|
||||
return true;
|
||||
if let SyntaxKind::Colon = deciding.kind()
|
||||
&& let Some(prev) = deciding.prev_leaf()
|
||||
&& let Some(param) = prev.get().cast::<ast::Ident>()
|
||||
{
|
||||
if let Some(next) = deciding.next_leaf() {
|
||||
ctx.from = ctx.cursor.min(next.offset());
|
||||
}
|
||||
|
||||
named_param_value_completions(ctx, callee, ¶m);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parameters: "func(|)", "func(hi|)", "func(12,|)".
|
||||
if_chain! {
|
||||
if matches!(deciding.kind(), SyntaxKind::LeftParen | SyntaxKind::Comma);
|
||||
if deciding.kind() != SyntaxKind::Comma || deciding.range().end < ctx.cursor;
|
||||
then {
|
||||
if let Some(next) = deciding.next_leaf() {
|
||||
ctx.from = ctx.cursor.min(next.offset());
|
||||
}
|
||||
|
||||
param_completions(ctx, callee, set, args, args_linked);
|
||||
return true;
|
||||
if let SyntaxKind::LeftParen | SyntaxKind::Comma = deciding.kind()
|
||||
&& (deciding.kind() != SyntaxKind::Comma || deciding.range().end < ctx.cursor)
|
||||
{
|
||||
if let Some(next) = deciding.next_leaf() {
|
||||
ctx.from = ctx.cursor.min(next.offset());
|
||||
}
|
||||
|
||||
param_completions(ctx, callee, set, args, args_linked);
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
@ -859,7 +834,7 @@ fn param_value_completions<'a>(
|
||||
fn path_completion(func: &Func, param: &ParamInfo) -> Option<&'static [&'static str]> {
|
||||
Some(match (func.name(), param.name) {
|
||||
(Some("image"), "source") => {
|
||||
&["png", "jpg", "jpeg", "gif", "svg", "svgz", "webp"]
|
||||
&["png", "jpg", "jpeg", "gif", "svg", "svgz", "webp", "pdf"]
|
||||
}
|
||||
(Some("csv"), "source") => &["csv"],
|
||||
(Some("plugin"), "source") => &["wasm"],
|
||||
@ -1104,14 +1079,12 @@ fn code_completions(ctx: &mut CompletionContext, hash: bool) {
|
||||
fn is_in_equation_show_rule(leaf: &LinkedNode<'_>) -> bool {
|
||||
let mut node = leaf;
|
||||
while let Some(parent) = node.parent() {
|
||||
if_chain! {
|
||||
if let Some(expr) = parent.get().cast::<ast::Expr>();
|
||||
if let ast::Expr::ShowRule(show) = expr;
|
||||
if let Some(ast::Expr::FieldAccess(field)) = show.selector();
|
||||
if field.field().as_str() == "equation";
|
||||
then {
|
||||
return true;
|
||||
}
|
||||
if let Some(expr) = parent.get().cast::<ast::Expr>()
|
||||
&& let ast::Expr::ShowRule(show) = expr
|
||||
&& let Some(ast::Expr::FieldAccess(field)) = show.selector()
|
||||
&& field.field().as_str() == "equation"
|
||||
{
|
||||
return true;
|
||||
}
|
||||
node = parent;
|
||||
}
|
||||
@ -1382,10 +1355,11 @@ impl<'a> CompletionContext<'a> {
|
||||
}
|
||||
} else if at {
|
||||
apply = Some(eco_format!("at(\"{label}\")"));
|
||||
} else if label.starts_with('"') && self.after.starts_with('"') {
|
||||
if let Some(trimmed) = label.strip_suffix('"') {
|
||||
apply = Some(trimmed.into());
|
||||
}
|
||||
} else if label.starts_with('"')
|
||||
&& self.after.starts_with('"')
|
||||
&& let Some(trimmed) = label.strip_suffix('"')
|
||||
{
|
||||
apply = Some(trimmed.into());
|
||||
}
|
||||
|
||||
self.completions.push(Completion {
|
||||
@ -1571,7 +1545,7 @@ mod tests {
|
||||
|
||||
use typst::layout::PagedDocument;
|
||||
|
||||
use super::{autocomplete, Completion, CompletionKind};
|
||||
use super::{Completion, CompletionKind, autocomplete};
|
||||
use crate::tests::{FilePos, TestWorld, WorldLike};
|
||||
|
||||
/// Quote a string.
|
||||
@ -1589,7 +1563,7 @@ mod tests {
|
||||
fn must_include<'a>(&self, includes: impl IntoIterator<Item = &'a str>) -> &Self;
|
||||
fn must_exclude<'a>(&self, excludes: impl IntoIterator<Item = &'a str>) -> &Self;
|
||||
fn must_apply<'a>(&self, label: &str, apply: impl Into<Option<&'a str>>)
|
||||
-> &Self;
|
||||
-> &Self;
|
||||
}
|
||||
|
||||
impl ResponseExt for Response {
|
||||
|
@ -1,12 +1,12 @@
|
||||
use typst::foundations::{Label, Selector, Value};
|
||||
use typst::layout::PagedDocument;
|
||||
use typst::syntax::{ast, LinkedNode, Side, Source, Span};
|
||||
use typst::syntax::{LinkedNode, Side, Source, Span, ast};
|
||||
use typst::utils::PicoStr;
|
||||
|
||||
use crate::utils::globals;
|
||||
use crate::{
|
||||
analyze_expr, analyze_import, deref_target, named_items, DerefTarget, IdeWorld,
|
||||
NamedItem,
|
||||
DerefTarget, IdeWorld, NamedItem, analyze_expr, analyze_import, deref_target,
|
||||
named_items,
|
||||
};
|
||||
|
||||
/// A definition of some item.
|
||||
@ -90,11 +90,11 @@ mod tests {
|
||||
use std::borrow::Borrow;
|
||||
use std::ops::Range;
|
||||
|
||||
use typst::WorldExt;
|
||||
use typst::foundations::{IntoValue, NativeElement};
|
||||
use typst::syntax::Side;
|
||||
use typst::WorldExt;
|
||||
|
||||
use super::{definition, Definition};
|
||||
use super::{Definition, definition};
|
||||
use crate::tests::{FilePos, TestWorld, WorldLike};
|
||||
|
||||
type Response = (TestWorld, Option<Definition>);
|
||||
|
@ -1,10 +1,10 @@
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use typst::WorldExt;
|
||||
use typst::layout::{Frame, FrameItem, PagedDocument, Point, Position, Size};
|
||||
use typst::model::{Destination, Url};
|
||||
use typst::syntax::{FileId, LinkedNode, Side, Source, Span, SyntaxKind};
|
||||
use typst::visualize::{Curve, CurveItem, FillRule, Geometry};
|
||||
use typst::WorldExt;
|
||||
|
||||
use crate::IdeWorld;
|
||||
|
||||
@ -36,28 +36,28 @@ pub fn jump_from_click(
|
||||
) -> Option<Jump> {
|
||||
// Try to find a link first.
|
||||
for (pos, item) in frame.items() {
|
||||
if let FrameItem::Link(dest, size) = item {
|
||||
if is_in_rect(*pos, *size, click) {
|
||||
return Some(match dest {
|
||||
Destination::Url(url) => Jump::Url(url.clone()),
|
||||
Destination::Position(pos) => Jump::Position(*pos),
|
||||
Destination::Location(loc) => {
|
||||
Jump::Position(document.introspector.position(*loc))
|
||||
}
|
||||
});
|
||||
}
|
||||
if let FrameItem::Link(dest, size) = item
|
||||
&& is_in_rect(*pos, *size, click)
|
||||
{
|
||||
return Some(match dest {
|
||||
Destination::Url(url) => Jump::Url(url.clone()),
|
||||
Destination::Position(pos) => Jump::Position(*pos),
|
||||
Destination::Location(loc) => {
|
||||
Jump::Position(document.introspector.position(*loc))
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// If there's no link, search for a jump target.
|
||||
for (mut pos, item) in frame.items().rev() {
|
||||
for &(mut pos, ref item) in frame.items().rev() {
|
||||
match item {
|
||||
FrameItem::Group(group) => {
|
||||
let pos = click - pos;
|
||||
if let Some(clip) = &group.clip {
|
||||
if !clip.contains(FillRule::NonZero, pos) {
|
||||
continue;
|
||||
}
|
||||
if let Some(clip) = &group.clip
|
||||
&& !clip.contains(FillRule::NonZero, pos)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Realistic transforms should always be invertible.
|
||||
// An example of one that isn't is a scale of 0, which would
|
||||
@ -177,11 +177,11 @@ pub fn jump_from_cursor(
|
||||
|
||||
/// Find the position of a span in a frame.
|
||||
fn find_in_frame(frame: &Frame, span: Span) -> Option<Point> {
|
||||
for (mut pos, item) in frame.items() {
|
||||
if let FrameItem::Group(group) = item {
|
||||
if let Some(point) = find_in_frame(&group.frame, span) {
|
||||
return Some(pos + point.transform(group.transform));
|
||||
}
|
||||
for &(mut pos, ref item) in frame.items() {
|
||||
if let FrameItem::Group(group) = item
|
||||
&& let Some(point) = find_in_frame(&group.frame, span)
|
||||
{
|
||||
return Some(pos + point.transform(group.transform));
|
||||
}
|
||||
|
||||
if let FrameItem::Text(text) = item {
|
||||
@ -222,7 +222,7 @@ mod tests {
|
||||
|
||||
use typst::layout::{Abs, Point, Position};
|
||||
|
||||
use super::{jump_from_click, jump_from_cursor, Jump};
|
||||
use super::{Jump, jump_from_click, jump_from_cursor};
|
||||
use crate::tests::{FilePos, TestWorld, WorldLike};
|
||||
|
||||
fn point(x: f64, y: f64) -> Point {
|
||||
|
@ -9,16 +9,16 @@ mod tooltip;
|
||||
mod utils;
|
||||
|
||||
pub use self::analyze::{analyze_expr, analyze_import, analyze_labels};
|
||||
pub use self::complete::{autocomplete, Completion, CompletionKind};
|
||||
pub use self::definition::{definition, Definition};
|
||||
pub use self::jump::{jump_from_click, jump_from_cursor, Jump};
|
||||
pub use self::matchers::{deref_target, named_items, DerefTarget, NamedItem};
|
||||
pub use self::tooltip::{tooltip, Tooltip};
|
||||
pub use self::complete::{Completion, CompletionKind, autocomplete};
|
||||
pub use self::definition::{Definition, definition};
|
||||
pub use self::jump::{Jump, jump_from_click, jump_from_cursor};
|
||||
pub use self::matchers::{DerefTarget, NamedItem, deref_target, named_items};
|
||||
pub use self::tooltip::{Tooltip, tooltip};
|
||||
|
||||
use ecow::EcoString;
|
||||
use typst::syntax::package::PackageSpec;
|
||||
use typst::syntax::FileId;
|
||||
use typst::World;
|
||||
use typst::syntax::FileId;
|
||||
use typst::syntax::package::PackageSpec;
|
||||
|
||||
/// Extends the `World` for IDE functionality.
|
||||
pub trait IdeWorld: World {
|
||||
|
@ -1,9 +1,9 @@
|
||||
use ecow::EcoString;
|
||||
use typst::foundations::{Module, Value};
|
||||
use typst::syntax::ast::AstNode;
|
||||
use typst::syntax::{ast, LinkedNode, Span, SyntaxKind};
|
||||
use typst::syntax::{LinkedNode, Span, SyntaxKind, ast};
|
||||
|
||||
use crate::{analyze_import, IdeWorld};
|
||||
use crate::{IdeWorld, analyze_import};
|
||||
|
||||
/// Find the named items starting from the given position.
|
||||
pub fn named_items<T>(
|
||||
@ -59,10 +59,10 @@ pub fn named_items<T>(
|
||||
};
|
||||
|
||||
// Seeing the module itself.
|
||||
if let Some((name, span)) = name_and_span {
|
||||
if let Some(res) = recv(NamedItem::Module(&name, span, module)) {
|
||||
return Some(res);
|
||||
}
|
||||
if let Some((name, span)) = name_and_span
|
||||
&& let Some(res) = recv(NamedItem::Module(&name, span, module))
|
||||
{
|
||||
return Some(res);
|
||||
}
|
||||
|
||||
// Seeing the imported items.
|
||||
@ -124,13 +124,13 @@ pub fn named_items<T>(
|
||||
}
|
||||
|
||||
if let Some(parent) = node.parent() {
|
||||
if let Some(v) = parent.cast::<ast::ForLoop>() {
|
||||
if node.prev_sibling_kind() != Some(SyntaxKind::In) {
|
||||
let pattern = v.pattern();
|
||||
for ident in pattern.bindings() {
|
||||
if let Some(res) = recv(NamedItem::Var(ident)) {
|
||||
return Some(res);
|
||||
}
|
||||
if let Some(v) = parent.cast::<ast::ForLoop>()
|
||||
&& node.prev_sibling_kind() != Some(SyntaxKind::In)
|
||||
{
|
||||
let pattern = v.pattern();
|
||||
for ident in pattern.bindings() {
|
||||
if let Some(res) = recv(NamedItem::Var(ident)) {
|
||||
return Some(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,10 +155,10 @@ pub fn named_items<T>(
|
||||
}
|
||||
}
|
||||
ast::Param::Spread(s) => {
|
||||
if let Some(sink_ident) = s.sink_ident() {
|
||||
if let Some(t) = recv(NamedItem::Var(sink_ident)) {
|
||||
return Some(t);
|
||||
}
|
||||
if let Some(sink_ident) = s.sink_ident()
|
||||
&& let Some(t) = recv(NamedItem::Var(sink_ident))
|
||||
{
|
||||
return Some(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -216,7 +216,7 @@ impl<'a> NamedItem<'a> {
|
||||
|
||||
/// Categorize an expression into common classes IDE functionality can operate
|
||||
/// on.
|
||||
pub fn deref_target(node: LinkedNode) -> Option<DerefTarget<'_>> {
|
||||
pub fn deref_target(node: LinkedNode<'_>) -> Option<DerefTarget<'_>> {
|
||||
// Move to the first ancestor that is an expression.
|
||||
let mut ancestor = node;
|
||||
while !ancestor.is::<ast::Expr>() {
|
||||
|
@ -9,7 +9,7 @@ use typst::layout::{Abs, Margin, PageElem};
|
||||
use typst::syntax::package::{PackageSpec, PackageVersion};
|
||||
use typst::syntax::{FileId, Source, VirtualPath};
|
||||
use typst::text::{Font, FontBook, TextElem, TextSize};
|
||||
use typst::utils::{singleton, LazyHash};
|
||||
use typst::utils::{LazyHash, singleton};
|
||||
use typst::{Feature, Library, LibraryExt, World};
|
||||
|
||||
use crate::IdeWorld;
|
||||
|
@ -1,17 +1,16 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use ecow::{eco_format, EcoString};
|
||||
use if_chain::if_chain;
|
||||
use ecow::{EcoString, eco_format};
|
||||
use typst::engine::Sink;
|
||||
use typst::foundations::{repr, Binding, Capturer, CastInfo, Repr, Value};
|
||||
use typst::foundations::{Binding, Capturer, CastInfo, Repr, Value, repr};
|
||||
use typst::layout::{Length, PagedDocument};
|
||||
use typst::syntax::ast::AstNode;
|
||||
use typst::syntax::{ast, LinkedNode, Side, Source, SyntaxKind};
|
||||
use typst::utils::{round_with_precision, Numeric};
|
||||
use typst::syntax::{LinkedNode, Side, Source, SyntaxKind, ast};
|
||||
use typst::utils::{Numeric, round_with_precision};
|
||||
use typst_eval::CapturesVisitor;
|
||||
|
||||
use crate::utils::{plain_docs_sentence, summarize_font_family};
|
||||
use crate::{analyze_expr, analyze_import, analyze_labels, IdeWorld};
|
||||
use crate::{IdeWorld, analyze_expr, analyze_import, analyze_labels};
|
||||
|
||||
/// Describe the item under the cursor.
|
||||
///
|
||||
@ -66,10 +65,10 @@ fn expr_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||
return Some(Tooltip::Text(plain_docs_sentence(docs)));
|
||||
}
|
||||
|
||||
if let &Value::Length(length) = value {
|
||||
if let Some(tooltip) = length_tooltip(length) {
|
||||
return Some(tooltip);
|
||||
}
|
||||
if let &Value::Length(length) = value
|
||||
&& let Some(tooltip) = length_tooltip(length)
|
||||
{
|
||||
return Some(tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,10 +92,10 @@ fn expr_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||
last = Some((value, 1));
|
||||
}
|
||||
|
||||
if let Some((_, count)) = last {
|
||||
if count > 1 {
|
||||
write!(pieces.last_mut().unwrap(), " (×{count})").unwrap();
|
||||
}
|
||||
if let Some((_, count)) = last
|
||||
&& count > 1
|
||||
{
|
||||
write!(pieces.last_mut().unwrap(), " (×{count})").unwrap();
|
||||
}
|
||||
|
||||
if iter.next().is_some() {
|
||||
@ -109,19 +108,17 @@ fn expr_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||
|
||||
/// Tooltips for imports.
|
||||
fn import_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||
if_chain! {
|
||||
if leaf.kind() == SyntaxKind::Star;
|
||||
if let Some(parent) = leaf.parent();
|
||||
if let Some(import) = parent.cast::<ast::ModuleImport>();
|
||||
if let Some(node) = parent.find(import.source().span());
|
||||
if let Some(value) = analyze_import(world, &node);
|
||||
if let Some(scope) = value.scope();
|
||||
then {
|
||||
let names: Vec<_> =
|
||||
scope.iter().map(|(name, ..)| eco_format!("`{name}`")).collect();
|
||||
let list = repr::separated_list(&names, "and");
|
||||
return Some(Tooltip::Text(eco_format!("This star imports {list}")));
|
||||
}
|
||||
if leaf.kind() == SyntaxKind::Star
|
||||
&& let Some(parent) = leaf.parent()
|
||||
&& let Some(import) = parent.cast::<ast::ModuleImport>()
|
||||
&& let Some(node) = parent.find(import.source().span())
|
||||
&& let Some(value) = analyze_import(world, &node)
|
||||
&& let Some(scope) = value.scope()
|
||||
{
|
||||
let names: Vec<_> =
|
||||
scope.iter().map(|(name, ..)| eco_format!("`{name}`")).collect();
|
||||
let list = repr::separated_list(&names, "and");
|
||||
return Some(Tooltip::Text(eco_format!("This star imports {list}")));
|
||||
}
|
||||
|
||||
None
|
||||
@ -190,50 +187,45 @@ fn label_tooltip(document: &PagedDocument, leaf: &LinkedNode) -> Option<Tooltip>
|
||||
|
||||
/// Tooltips for components of a named parameter.
|
||||
fn named_param_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||
let (func, named) = if_chain! {
|
||||
let (func, named) =
|
||||
// Ensure that we are in a named pair in the arguments to a function
|
||||
// call or set rule.
|
||||
if let Some(parent) = leaf.parent();
|
||||
if let Some(named) = parent.cast::<ast::Named>();
|
||||
if let Some(grand) = parent.parent();
|
||||
if matches!(grand.kind(), SyntaxKind::Args);
|
||||
if let Some(grand_grand) = grand.parent();
|
||||
if let Some(expr) = grand_grand.cast::<ast::Expr>();
|
||||
if let Some(ast::Expr::Ident(callee)) = match expr {
|
||||
if let Some(parent) = leaf.parent()
|
||||
&& let Some(named) = parent.cast::<ast::Named>()
|
||||
&& let Some(grand) = parent.parent()
|
||||
&& matches!(grand.kind(), SyntaxKind::Args)
|
||||
&& let Some(grand_grand) = grand.parent()
|
||||
&& let Some(expr) = grand_grand.cast::<ast::Expr>()
|
||||
&& let Some(ast::Expr::Ident(callee)) = match expr {
|
||||
ast::Expr::FuncCall(call) => Some(call.callee()),
|
||||
ast::Expr::SetRule(set) => Some(set.target()),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
// Find metadata about the function.
|
||||
if let Some(Value::Func(func)) = world
|
||||
&& let Some(Value::Func(func)) = world
|
||||
.library()
|
||||
.global
|
||||
.scope()
|
||||
.get(&callee)
|
||||
.map(Binding::read);
|
||||
then { (func, named) }
|
||||
else { return None; }
|
||||
};
|
||||
.map(Binding::read)
|
||||
{ (func, named) }
|
||||
else { return None; };
|
||||
|
||||
// Hovering over the parameter name.
|
||||
if_chain! {
|
||||
if leaf.index() == 0;
|
||||
if let Some(ident) = leaf.cast::<ast::Ident>();
|
||||
if let Some(param) = func.param(&ident);
|
||||
then {
|
||||
return Some(Tooltip::Text(plain_docs_sentence(param.docs)));
|
||||
}
|
||||
if leaf.index() == 0
|
||||
&& let Some(ident) = leaf.cast::<ast::Ident>()
|
||||
&& let Some(param) = func.param(&ident)
|
||||
{
|
||||
return Some(Tooltip::Text(plain_docs_sentence(param.docs)));
|
||||
}
|
||||
|
||||
// Hovering over a string parameter value.
|
||||
if_chain! {
|
||||
if let Some(string) = leaf.cast::<ast::Str>();
|
||||
if let Some(param) = func.param(&named.name());
|
||||
if let Some(docs) = find_string_doc(¶m.input, &string.get());
|
||||
then {
|
||||
return Some(Tooltip::Text(docs.into()));
|
||||
}
|
||||
if let Some(string) = leaf.cast::<ast::Str>()
|
||||
&& let Some(param) = func.param(&named.name())
|
||||
&& let Some(docs) = find_string_doc(¶m.input, &string.get())
|
||||
{
|
||||
return Some(Tooltip::Text(docs.into()));
|
||||
}
|
||||
|
||||
None
|
||||
@ -252,27 +244,24 @@ fn find_string_doc(info: &CastInfo, string: &str) -> Option<&'static str> {
|
||||
|
||||
/// Tooltip for font.
|
||||
fn font_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||
if_chain! {
|
||||
// Ensure that we are on top of a string.
|
||||
if let Some(string) = leaf.cast::<ast::Str>();
|
||||
let lower = string.get().to_lowercase();
|
||||
// Ensure that we are on top of a string.
|
||||
if let Some(string) = leaf.cast::<ast::Str>()
|
||||
&& let lower = string.get().to_lowercase()
|
||||
|
||||
// Ensure that we are in the arguments to the text function.
|
||||
if let Some(parent) = leaf.parent();
|
||||
if let Some(named) = parent.cast::<ast::Named>();
|
||||
if named.name().as_str() == "font";
|
||||
&& let Some(parent) = leaf.parent()
|
||||
&& let Some(named) = parent.cast::<ast::Named>()
|
||||
&& named.name().as_str() == "font"
|
||||
|
||||
// Find the font family.
|
||||
if let Some((_, iter)) = world
|
||||
&& let Some((_, iter)) = world
|
||||
.book()
|
||||
.families()
|
||||
.find(|&(family, _)| family.to_lowercase().as_str() == lower.as_str());
|
||||
|
||||
then {
|
||||
let detail = summarize_font_family(iter.collect());
|
||||
return Some(Tooltip::Text(detail));
|
||||
}
|
||||
};
|
||||
.find(|&(family, _)| family.to_lowercase().as_str() == lower.as_str())
|
||||
{
|
||||
let detail = summarize_font_family(iter.collect());
|
||||
return Some(Tooltip::Text(detail));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
@ -283,7 +272,7 @@ mod tests {
|
||||
|
||||
use typst::syntax::Side;
|
||||
|
||||
use super::{tooltip, Tooltip};
|
||||
use super::{Tooltip, tooltip};
|
||||
use crate::tests::{FilePos, TestWorld, WorldLike};
|
||||
|
||||
type Response = Option<Tooltip>;
|
||||
|
@ -2,7 +2,7 @@ use std::fmt::Write;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use comemo::Track;
|
||||
use ecow::{eco_format, EcoString};
|
||||
use ecow::{EcoString, eco_format};
|
||||
use typst::engine::{Engine, Route, Sink, Traced};
|
||||
use typst::foundations::{Scope, Value};
|
||||
use typst::introspection::Introspector;
|
||||
@ -119,11 +119,7 @@ pub fn globals<'a>(world: &'a dyn IdeWorld, leaf: &LinkedNode) -> &'a Scope {
|
||||
.is_none_or(|prev| !matches!(prev.kind(), SyntaxKind::Hash));
|
||||
|
||||
let library = world.library();
|
||||
if in_math {
|
||||
library.math.scope()
|
||||
} else {
|
||||
library.global.scope()
|
||||
}
|
||||
if in_math { library.math.scope() } else { library.global.scope() }
|
||||
}
|
||||
|
||||
/// Checks whether the given value or any of its constituent parts satisfy the
|
||||
|
@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
|
||||
use ecow::eco_format;
|
||||
use once_cell::sync::OnceCell;
|
||||
use serde::Deserialize;
|
||||
use typst_library::diag::{bail, PackageError, PackageResult, StrResult};
|
||||
use typst_library::diag::{PackageError, PackageResult, StrResult, bail};
|
||||
use typst_syntax::package::{PackageSpec, PackageVersion, VersionlessPackageSpec};
|
||||
|
||||
use crate::download::{Downloader, Progress};
|
||||
@ -189,7 +189,7 @@ impl PackageStorage {
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
return Err(PackageError::NetworkFailed(Some(eco_format!("{err}"))))
|
||||
return Err(PackageError::NetworkFailed(Some(eco_format!("{err}"))));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -407,10 +407,10 @@ fn distribute<'a>(
|
||||
// If there is still something remaining, apply it to the
|
||||
// last region (it will overflow, but there's nothing else
|
||||
// we can do).
|
||||
if !remaining.approx_empty() {
|
||||
if let Some(last) = buf.last_mut() {
|
||||
*last += remaining;
|
||||
}
|
||||
if !remaining.approx_empty()
|
||||
&& let Some(last) = buf.last_mut()
|
||||
{
|
||||
*last += remaining;
|
||||
}
|
||||
|
||||
// Distribute the heights to the first region and the
|
||||
|
@ -2,10 +2,11 @@ use std::cell::{LazyCell, RefCell};
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::hash::Hash;
|
||||
|
||||
use bumpalo::boxed::Box as BumpBox;
|
||||
use bumpalo::Bump;
|
||||
use bumpalo::boxed::Box as BumpBox;
|
||||
use comemo::{Track, Tracked, TrackedMut};
|
||||
use typst_library::diag::{bail, warning, SourceResult};
|
||||
use typst_library::World;
|
||||
use typst_library::diag::{SourceResult, bail, warning};
|
||||
use typst_library::engine::{Engine, Route, Sink, Traced};
|
||||
use typst_library::foundations::{Packed, Resolve, Smart, StyleChain};
|
||||
use typst_library::introspection::{
|
||||
@ -19,10 +20,9 @@ use typst_library::layout::{
|
||||
use typst_library::model::ParElem;
|
||||
use typst_library::routines::{Pair, Routines};
|
||||
use typst_library::text::TextElem;
|
||||
use typst_library::World;
|
||||
use typst_utils::SliceExt;
|
||||
|
||||
use super::{layout_multi_block, layout_single_block, FlowMode};
|
||||
use super::{FlowMode, layout_multi_block, layout_single_block};
|
||||
use crate::inline::ParSituation;
|
||||
use crate::modifiers::layout_and_modify;
|
||||
|
||||
@ -684,10 +684,10 @@ impl<T> CachedCell<T> {
|
||||
let input_hash = typst_utils::hash128(&input);
|
||||
|
||||
let mut slot = self.0.borrow_mut();
|
||||
if let Some((hash, output)) = &*slot {
|
||||
if *hash == input_hash {
|
||||
return output.clone();
|
||||
}
|
||||
if let Some((hash, output)) = &*slot
|
||||
&& *hash == input_hash
|
||||
{
|
||||
return output.clone();
|
||||
}
|
||||
|
||||
let output = f(input);
|
||||
|
@ -18,7 +18,7 @@ use typst_syntax::Span;
|
||||
use typst_utils::{NonZeroExt, Numeric};
|
||||
|
||||
use super::{
|
||||
distribute, Config, FlowMode, FlowResult, LineNumberConfig, PlacedChild, Stop, Work,
|
||||
Config, FlowMode, FlowResult, LineNumberConfig, PlacedChild, Stop, Work, distribute,
|
||||
};
|
||||
|
||||
/// Composes the contents of a single page/region. A region can have multiple
|
||||
@ -319,11 +319,7 @@ impl<'a, 'b> Composer<'a, 'b, '_, '_> {
|
||||
let used = base.y - remaining;
|
||||
let half = need / 2.0;
|
||||
let ratio = (used + half) / base.y;
|
||||
if ratio <= 0.5 {
|
||||
FixedAlignment::Start
|
||||
} else {
|
||||
FixedAlignment::End
|
||||
}
|
||||
if ratio <= 0.5 { FixedAlignment::Start } else { FixedAlignment::End }
|
||||
});
|
||||
|
||||
// Select the insertion area where we'll put this float.
|
||||
|
@ -14,7 +14,8 @@ use std::rc::Rc;
|
||||
use bumpalo::Bump;
|
||||
use comemo::{Track, Tracked, TrackedMut};
|
||||
use ecow::EcoVec;
|
||||
use typst_library::diag::{bail, At, SourceDiagnostic, SourceResult};
|
||||
use typst_library::World;
|
||||
use typst_library::diag::{At, SourceDiagnostic, SourceResult, bail};
|
||||
use typst_library::engine::{Engine, Route, Sink, Traced};
|
||||
use typst_library::foundations::{Content, Packed, Resolve, StyleChain};
|
||||
use typst_library::introspection::{
|
||||
@ -27,14 +28,13 @@ use typst_library::layout::{
|
||||
use typst_library::model::{FootnoteElem, FootnoteEntry, LineNumberingScope, ParLine};
|
||||
use typst_library::routines::{Arenas, FragmentKind, Pair, RealizationKind, Routines};
|
||||
use typst_library::text::TextElem;
|
||||
use typst_library::World;
|
||||
use typst_utils::{NonZeroExt, Numeric};
|
||||
|
||||
use self::block::{layout_multi_block, layout_single_block};
|
||||
use self::collect::{
|
||||
collect, Child, LineChild, MultiChild, MultiSpill, PlacedChild, SingleChild,
|
||||
Child, LineChild, MultiChild, MultiSpill, PlacedChild, SingleChild, collect,
|
||||
};
|
||||
use self::compose::{compose, Composer};
|
||||
use self::compose::{Composer, compose};
|
||||
use self::distribute::distribute;
|
||||
|
||||
/// Lays out content into a single region, producing a single frame.
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use typst_library::diag::{bail, SourceResult};
|
||||
use typst_library::diag::{SourceResult, bail};
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{Resolve, StyleChain};
|
||||
use typst_library::layout::grid::resolve::{
|
||||
@ -16,8 +16,8 @@ use typst_syntax::Span;
|
||||
use typst_utils::Numeric;
|
||||
|
||||
use super::{
|
||||
generate_line_segments, hline_stroke_at_column, layout_cell, vline_stroke_at_row,
|
||||
LineSegment, Rowspan, UnbreakableRowGroup,
|
||||
LineSegment, Rowspan, UnbreakableRowGroup, generate_line_segments,
|
||||
hline_stroke_at_column, layout_cell, vline_stroke_at_row,
|
||||
};
|
||||
|
||||
/// Performs grid layout.
|
||||
@ -274,39 +274,39 @@ impl<'a> GridLayouter<'a> {
|
||||
pub fn layout(mut self, engine: &mut Engine) -> SourceResult<Fragment> {
|
||||
self.measure_columns(engine)?;
|
||||
|
||||
if let Some(footer) = &self.grid.footer {
|
||||
if footer.repeated {
|
||||
// Ensure rows in the first region will be aware of the
|
||||
// possible presence of the footer.
|
||||
self.prepare_footer(footer, engine, 0)?;
|
||||
self.regions.size.y -= self.current.footer_height;
|
||||
self.current.initial_after_repeats = self.regions.size.y;
|
||||
}
|
||||
if let Some(footer) = &self.grid.footer
|
||||
&& footer.repeated
|
||||
{
|
||||
// Ensure rows in the first region will be aware of the
|
||||
// possible presence of the footer.
|
||||
self.prepare_footer(footer, engine, 0)?;
|
||||
self.regions.size.y -= self.current.footer_height;
|
||||
self.current.initial_after_repeats = self.regions.size.y;
|
||||
}
|
||||
|
||||
let mut y = 0;
|
||||
let mut consecutive_header_count = 0;
|
||||
while y < self.grid.rows.len() {
|
||||
if let Some(next_header) = self.upcoming_headers.get(consecutive_header_count)
|
||||
&& next_header.range.contains(&y)
|
||||
{
|
||||
if next_header.range.contains(&y) {
|
||||
self.place_new_headers(&mut consecutive_header_count, engine)?;
|
||||
y = next_header.range.end;
|
||||
self.place_new_headers(&mut consecutive_header_count, engine)?;
|
||||
y = next_header.range.end;
|
||||
|
||||
// Skip header rows during normal layout.
|
||||
continue;
|
||||
}
|
||||
// Skip header rows during normal layout.
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(footer) = &self.grid.footer {
|
||||
if footer.repeated && y >= footer.start {
|
||||
if y == footer.start {
|
||||
self.layout_footer(footer, engine, self.finished.len())?;
|
||||
self.flush_orphans();
|
||||
}
|
||||
y = footer.end;
|
||||
continue;
|
||||
if let Some(footer) = &self.grid.footer
|
||||
&& footer.repeated
|
||||
&& y >= footer.start
|
||||
{
|
||||
if y == footer.start {
|
||||
self.layout_footer(footer, engine, self.finished.len())?;
|
||||
self.flush_orphans();
|
||||
}
|
||||
y = footer.end;
|
||||
continue;
|
||||
}
|
||||
|
||||
self.layout_row(y, engine, 0)?;
|
||||
@ -1228,7 +1228,7 @@ impl<'a> GridLayouter<'a> {
|
||||
.skip(parent.y)
|
||||
.take(rowspan)
|
||||
.rev()
|
||||
.find(|(_, &row)| row == Sizing::Auto)
|
||||
.find(|&(_, &row)| row == Sizing::Auto)
|
||||
.map(|(y, _)| y);
|
||||
|
||||
if last_spanned_auto_row != Some(y) {
|
||||
@ -1283,14 +1283,12 @@ impl<'a> GridLayouter<'a> {
|
||||
// remeasure.
|
||||
if let Some([first, rest @ ..]) =
|
||||
frames.get(measurement_data.frames_in_previous_regions..)
|
||||
&& can_skip
|
||||
&& breakable
|
||||
&& first.is_empty()
|
||||
&& rest.iter().any(|frame| !frame.is_empty())
|
||||
{
|
||||
if can_skip
|
||||
&& breakable
|
||||
&& first.is_empty()
|
||||
&& rest.iter().any(|frame| !frame.is_empty())
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
// Skip frames from previous regions if applicable.
|
||||
@ -1529,16 +1527,16 @@ impl<'a> GridLayouter<'a> {
|
||||
// The latest rows have orphan prevention (headers) and no other rows
|
||||
// were placed, so remove those rows and try again in a new region,
|
||||
// unless this is the last region.
|
||||
if let Some(orphan_snapshot) = self.current.lrows_orphan_snapshot.take() {
|
||||
if !last {
|
||||
self.current.lrows.truncate(orphan_snapshot);
|
||||
self.current.repeated_header_rows =
|
||||
self.current.repeated_header_rows.min(orphan_snapshot);
|
||||
if let Some(orphan_snapshot) = self.current.lrows_orphan_snapshot.take()
|
||||
&& !last
|
||||
{
|
||||
self.current.lrows.truncate(orphan_snapshot);
|
||||
self.current.repeated_header_rows =
|
||||
self.current.repeated_header_rows.min(orphan_snapshot);
|
||||
|
||||
if orphan_snapshot == 0 {
|
||||
// Removed all repeated headers.
|
||||
self.current.last_repeated_header_end = 0;
|
||||
}
|
||||
if orphan_snapshot == 0 {
|
||||
// Removed all repeated headers.
|
||||
self.current.last_repeated_header_end = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1571,21 +1569,19 @@ impl<'a> GridLayouter<'a> {
|
||||
&& self.current.could_progress_at_top;
|
||||
|
||||
let mut laid_out_footer_start = None;
|
||||
if !footer_would_be_widow {
|
||||
if let Some(footer) = &self.grid.footer {
|
||||
// Don't layout the footer if it would be alone with the header
|
||||
// in the page (hence the widow check), and don't layout it
|
||||
// twice (check below).
|
||||
//
|
||||
// TODO(subfooters): this check can be replaced by a vector of
|
||||
// repeating footers in the future, and/or some "pending
|
||||
// footers" vector for footers we're about to place.
|
||||
if footer.repeated
|
||||
&& self.current.lrows.iter().all(|row| row.index() < footer.start)
|
||||
{
|
||||
laid_out_footer_start = Some(footer.start);
|
||||
self.layout_footer(footer, engine, self.finished.len())?;
|
||||
}
|
||||
if !footer_would_be_widow && let Some(footer) = &self.grid.footer {
|
||||
// Don't layout the footer if it would be alone with the header
|
||||
// in the page (hence the widow check), and don't layout it
|
||||
// twice (check below).
|
||||
//
|
||||
// TODO(subfooters): this check can be replaced by a vector of
|
||||
// repeating footers in the future, and/or some "pending
|
||||
// footers" vector for footers we're about to place.
|
||||
if footer.repeated
|
||||
&& self.current.lrows.iter().all(|row| row.index() < footer.start)
|
||||
{
|
||||
laid_out_footer_start = Some(footer.start);
|
||||
self.layout_footer(footer, engine, self.finished.len())?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use typst_library::foundations::{AlternativeFold, Fold};
|
||||
use typst_library::layout::grid::resolve::{CellGrid, Line, Repeatable};
|
||||
use typst_library::layout::Abs;
|
||||
use typst_library::layout::grid::resolve::{CellGrid, Line, Repeatable};
|
||||
use typst_library::visualize::Stroke;
|
||||
|
||||
use super::RowPiece;
|
||||
@ -291,12 +291,12 @@ pub fn vline_stroke_at_row(
|
||||
// We would then analyze the cell one column after (if at a gutter
|
||||
// column), and/or one row below (if at a gutter row), in order to
|
||||
// check if it would be merged with a cell before the vline.
|
||||
if let Some(parent) = grid.effective_parent_cell_position(x, y) {
|
||||
if parent.x < x {
|
||||
// There is a colspan cell going through this vline's position,
|
||||
// so don't draw it here.
|
||||
return None;
|
||||
}
|
||||
if let Some(parent) = grid.effective_parent_cell_position(x, y)
|
||||
&& parent.x < x
|
||||
{
|
||||
// There is a colspan cell going through this vline's position,
|
||||
// so don't draw it here.
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
@ -416,26 +416,26 @@ pub fn hline_stroke_at_column(
|
||||
// We would then analyze the cell one column after (if at a gutter
|
||||
// column), and/or one row below (if at a gutter row), in order to
|
||||
// check if it would be merged with a cell before the hline.
|
||||
if let Some(parent) = grid.effective_parent_cell_position(x, y) {
|
||||
if parent.y < y {
|
||||
// Get the first 'y' spanned by the possible rowspan in this region.
|
||||
// The 'parent.y' row and any other spanned rows above 'y' could be
|
||||
// missing from this region, which could have lead the check above
|
||||
// to be triggered, even though there is no spanned row above the
|
||||
// hline in the final layout of this region, and thus no overlap
|
||||
// with the hline, allowing it to be drawn regardless of the
|
||||
// theoretical presence of a rowspan going across its position.
|
||||
let local_parent_y = rows
|
||||
.iter()
|
||||
.find(|row| row.y >= parent.y)
|
||||
.map(|row| row.y)
|
||||
.unwrap_or(y);
|
||||
if let Some(parent) = grid.effective_parent_cell_position(x, y)
|
||||
&& parent.y < y
|
||||
{
|
||||
// Get the first 'y' spanned by the possible rowspan in this region.
|
||||
// The 'parent.y' row and any other spanned rows above 'y' could be
|
||||
// missing from this region, which could have lead the check above
|
||||
// to be triggered, even though there is no spanned row above the
|
||||
// hline in the final layout of this region, and thus no overlap
|
||||
// with the hline, allowing it to be drawn regardless of the
|
||||
// theoretical presence of a rowspan going across its position.
|
||||
let local_parent_y = rows
|
||||
.iter()
|
||||
.find(|row| row.y >= parent.y)
|
||||
.map(|row| row.y)
|
||||
.unwrap_or(y);
|
||||
|
||||
if local_parent_y < y {
|
||||
// There is a rowspan cell going through this hline's
|
||||
// position, so don't draw it here.
|
||||
return None;
|
||||
}
|
||||
if local_parent_y < y {
|
||||
// There is a rowspan cell going through this hline's
|
||||
// position, so don't draw it here.
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,13 @@ use typst_library::diag::SourceResult;
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{Packed, StyleChain};
|
||||
use typst_library::introspection::Locator;
|
||||
use typst_library::layout::grid::resolve::{grid_to_cellgrid, table_to_cellgrid, Cell};
|
||||
use typst_library::layout::grid::resolve::{Cell, grid_to_cellgrid, table_to_cellgrid};
|
||||
use typst_library::layout::{Fragment, GridElem, Regions};
|
||||
use typst_library::model::TableElem;
|
||||
|
||||
use self::layouter::RowPiece;
|
||||
use self::lines::{
|
||||
generate_line_segments, hline_stroke_at_column, vline_stroke_at_row, LineSegment,
|
||||
LineSegment, generate_line_segments, hline_stroke_at_column, vline_stroke_at_row,
|
||||
};
|
||||
use self::rowspans::{Rowspan, UnbreakableRowGroup};
|
||||
|
||||
|
@ -240,16 +240,17 @@ impl<'a> GridLayouter<'a> {
|
||||
self.current.initial_after_repeats = self.regions.size.y;
|
||||
}
|
||||
|
||||
if let Some(footer) = &self.grid.footer {
|
||||
if footer.repeated && skipped_region {
|
||||
// Simulate the footer again; the region's 'full' might have
|
||||
// changed.
|
||||
self.regions.size.y += self.current.footer_height;
|
||||
self.current.footer_height = self
|
||||
.simulate_footer(footer, &self.regions, engine, disambiguator)?
|
||||
.height;
|
||||
self.regions.size.y -= self.current.footer_height;
|
||||
}
|
||||
if let Some(footer) = &self.grid.footer
|
||||
&& footer.repeated
|
||||
&& skipped_region
|
||||
{
|
||||
// Simulate the footer again; the region's 'full' might have
|
||||
// changed.
|
||||
self.regions.size.y += self.current.footer_height;
|
||||
self.current.footer_height = self
|
||||
.simulate_footer(footer, &self.regions, engine, disambiguator)?
|
||||
.height;
|
||||
self.regions.size.y -= self.current.footer_height;
|
||||
}
|
||||
|
||||
let repeating_header_rows =
|
||||
|
@ -4,8 +4,8 @@ use typst_library::foundations::Resolve;
|
||||
use typst_library::layout::grid::resolve::Repeatable;
|
||||
use typst_library::layout::{Abs, Axes, Frame, Point, Region, Regions, Size, Sizing};
|
||||
|
||||
use super::layouter::{points, Row};
|
||||
use super::{layout_cell, Cell, GridLayouter};
|
||||
use super::layouter::{Row, points};
|
||||
use super::{Cell, GridLayouter, layout_cell};
|
||||
|
||||
/// All information needed to layout a single rowspan.
|
||||
pub struct Rowspan {
|
||||
@ -238,15 +238,16 @@ impl GridLayouter<'_> {
|
||||
// current row is dynamic and depends on the amount of upcoming
|
||||
// unbreakable cells (with or without a rowspan setting).
|
||||
let mut amount_unbreakable_rows = None;
|
||||
if let Some(footer) = &self.grid.footer {
|
||||
if !footer.repeated && current_row >= footer.start {
|
||||
// Non-repeated footer, so keep it unbreakable.
|
||||
//
|
||||
// TODO(subfooters): This will become unnecessary
|
||||
// once non-repeated footers are treated differently and
|
||||
// have widow prevention.
|
||||
amount_unbreakable_rows = Some(self.grid.rows.len() - footer.start);
|
||||
}
|
||||
if let Some(footer) = &self.grid.footer
|
||||
&& !footer.repeated
|
||||
&& current_row >= footer.start
|
||||
{
|
||||
// Non-repeated footer, so keep it unbreakable.
|
||||
//
|
||||
// TODO(subfooters): This will become unnecessary
|
||||
// once non-repeated footers are treated differently and
|
||||
// have widow prevention.
|
||||
amount_unbreakable_rows = Some(self.grid.rows.len() - footer.start);
|
||||
}
|
||||
|
||||
let row_group = self.simulate_unbreakable_row_group(
|
||||
@ -1268,9 +1269,9 @@ fn subtract_end_sizes(sizes: &mut Vec<Abs>, mut subtract: Abs) {
|
||||
while subtract > Abs::zero() && sizes.last().is_some_and(|&size| size <= subtract) {
|
||||
subtract -= sizes.pop().unwrap();
|
||||
}
|
||||
if subtract > Abs::zero() {
|
||||
if let Some(last_size) = sizes.last_mut() {
|
||||
*last_size -= subtract;
|
||||
}
|
||||
if subtract > Abs::zero()
|
||||
&& let Some(last_size) = sizes.last_mut()
|
||||
{
|
||||
*last_size -= subtract;
|
||||
}
|
||||
}
|
||||
|
@ -6,14 +6,14 @@ use typst_library::layout::{
|
||||
};
|
||||
use typst_library::routines::Pair;
|
||||
use typst_library::text::{
|
||||
is_default_ignorable, LinebreakElem, SmartQuoteElem, SmartQuoter, SmartQuotes,
|
||||
SpaceElem, TextElem,
|
||||
LinebreakElem, SmartQuoteElem, SmartQuoter, SmartQuotes, SpaceElem, TextElem,
|
||||
is_default_ignorable,
|
||||
};
|
||||
use typst_syntax::Span;
|
||||
use typst_utils::Numeric;
|
||||
|
||||
use super::*;
|
||||
use crate::modifiers::{layout_and_modify, FrameModifiers, FrameModify};
|
||||
use crate::modifiers::{FrameModifiers, FrameModify, layout_and_modify};
|
||||
|
||||
// The characters by which spacing, inline content and pins are replaced in the
|
||||
// full text.
|
||||
@ -274,11 +274,11 @@ impl<'a> Collector<'a> {
|
||||
let segment_len = self.full.len() - prev;
|
||||
|
||||
// Merge adjacent text segments with the same styles.
|
||||
if let Some(Segment::Text(last_len, last_styles)) = self.segments.last_mut() {
|
||||
if *last_styles == styles {
|
||||
*last_len += segment_len;
|
||||
return;
|
||||
}
|
||||
if let Some(Segment::Text(last_len, last_styles)) = self.segments.last_mut()
|
||||
&& *last_styles == styles
|
||||
{
|
||||
*last_len += segment_len;
|
||||
return;
|
||||
}
|
||||
|
||||
self.segments.push(Segment::Text(segment_len, styles));
|
||||
|
@ -6,7 +6,7 @@ use typst_library::foundations::Resolve;
|
||||
use typst_library::introspection::{SplitLocator, Tag};
|
||||
use typst_library::layout::{Abs, Dir, Em, Fr, Frame, FrameItem, Point};
|
||||
use typst_library::model::ParLineMarker;
|
||||
use typst_library::text::{variant, Lang, TextElem};
|
||||
use typst_library::text::{Lang, TextElem, variant};
|
||||
use typst_utils::Numeric;
|
||||
|
||||
use super::*;
|
||||
@ -155,17 +155,17 @@ pub fn line<'a>(
|
||||
let mut items = collect_items(engine, p, range, trim);
|
||||
|
||||
// Add a hyphen at the line start, if a previous dash should be repeated.
|
||||
if pred.is_some_and(|pred| should_repeat_hyphen(pred, full)) {
|
||||
if let Some(shaped) = items.first_text_mut() {
|
||||
shaped.prepend_hyphen(engine, p.config.fallback);
|
||||
}
|
||||
if pred.is_some_and(|pred| should_repeat_hyphen(pred, full))
|
||||
&& let Some(shaped) = items.first_text_mut()
|
||||
{
|
||||
shaped.prepend_hyphen(engine, p.config.fallback);
|
||||
}
|
||||
|
||||
// Add a hyphen at the line end, if we ended on a soft hyphen.
|
||||
if dash == Some(Dash::Soft) {
|
||||
if let Some(shaped) = items.last_text_mut() {
|
||||
shaped.push_hyphen(engine, p.config.fallback);
|
||||
}
|
||||
if dash == Some(Dash::Soft)
|
||||
&& let Some(shaped) = items.last_text_mut()
|
||||
{
|
||||
shaped.push_hyphen(engine, p.config.fallback);
|
||||
}
|
||||
|
||||
// Deal with CJ characters at line boundaries.
|
||||
@ -218,10 +218,10 @@ fn collect_items<'a>(
|
||||
}
|
||||
|
||||
// Add fallback text to expand the line height, if necessary.
|
||||
if !items.iter().any(|item| matches!(item, Item::Text(_))) {
|
||||
if let Some(fallback) = fallback {
|
||||
items.push(fallback, usize::MAX);
|
||||
}
|
||||
if !items.iter().any(|item| matches!(item, Item::Text(_)))
|
||||
&& let Some(fallback) = fallback
|
||||
{
|
||||
items.push(fallback, usize::MAX);
|
||||
}
|
||||
|
||||
items
|
||||
@ -461,30 +461,26 @@ pub fn commit(
|
||||
}
|
||||
|
||||
// Handle hanging punctuation to the left.
|
||||
if let Some(Item::Text(text)) = line.items.first() {
|
||||
if let Some(glyph) = text.glyphs.first() {
|
||||
if !text.dir.is_positive()
|
||||
&& text.styles.get(TextElem::overhang)
|
||||
&& (line.items.len() > 1 || text.glyphs.len() > 1)
|
||||
{
|
||||
let amount = overhang(glyph.c) * glyph.x_advance.at(glyph.size);
|
||||
offset -= amount;
|
||||
remaining += amount;
|
||||
}
|
||||
}
|
||||
if let Some(Item::Text(text)) = line.items.first()
|
||||
&& let Some(glyph) = text.glyphs.first()
|
||||
&& !text.dir.is_positive()
|
||||
&& text.styles.get(TextElem::overhang)
|
||||
&& (line.items.len() > 1 || text.glyphs.len() > 1)
|
||||
{
|
||||
let amount = overhang(glyph.c) * glyph.x_advance.at(glyph.size);
|
||||
offset -= amount;
|
||||
remaining += amount;
|
||||
}
|
||||
|
||||
// Handle hanging punctuation to the right.
|
||||
if let Some(Item::Text(text)) = line.items.last() {
|
||||
if let Some(glyph) = text.glyphs.last() {
|
||||
if text.dir.is_positive()
|
||||
&& text.styles.get(TextElem::overhang)
|
||||
&& (line.items.len() > 1 || text.glyphs.len() > 1)
|
||||
{
|
||||
let amount = overhang(glyph.c) * glyph.x_advance.at(glyph.size);
|
||||
remaining += amount;
|
||||
}
|
||||
}
|
||||
if let Some(Item::Text(text)) = line.items.last()
|
||||
&& let Some(glyph) = text.glyphs.last()
|
||||
&& text.dir.is_positive()
|
||||
&& text.styles.get(TextElem::overhang)
|
||||
&& (line.items.len() > 1 || text.glyphs.len() > 1)
|
||||
{
|
||||
let amount = overhang(glyph.c) * glyph.x_advance.at(glyph.size);
|
||||
remaining += amount;
|
||||
}
|
||||
|
||||
// Determine how much additional space is needed. The justification_ratio is
|
||||
|
@ -2,8 +2,8 @@ use std::ops::{Add, Sub};
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use az::SaturatingAs;
|
||||
use icu_properties::maps::{CodePointMapData, CodePointMapDataBorrowed};
|
||||
use icu_properties::LineBreak;
|
||||
use icu_properties::maps::{CodePointMapData, CodePointMapDataBorrowed};
|
||||
use icu_provider::AsDeserializingBufferProvider;
|
||||
use icu_provider_adapters::fork::ForkByKeyProvider;
|
||||
use icu_provider_blob::BlobDataProvider;
|
||||
@ -11,7 +11,7 @@ use icu_segmenter::LineSegmenter;
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::layout::{Abs, Em};
|
||||
use typst_library::model::Linebreaks;
|
||||
use typst_library::text::{is_default_ignorable, Lang, TextElem};
|
||||
use typst_library::text::{Lang, TextElem, is_default_ignorable};
|
||||
use typst_syntax::link_prefix;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
@ -136,12 +136,12 @@ fn linebreak_simple<'a>(
|
||||
// If the line doesn't fit anymore, we push the last fitting attempt
|
||||
// into the stack and rebuild the line from the attempt's end. The
|
||||
// resulting line cannot be broken up further.
|
||||
if !width.fits(attempt.width) {
|
||||
if let Some((last_attempt, last_end)) = last.take() {
|
||||
lines.push(last_attempt);
|
||||
start = last_end;
|
||||
attempt = line(engine, p, start..end, breakpoint, lines.last());
|
||||
}
|
||||
if !width.fits(attempt.width)
|
||||
&& let Some((last_attempt, last_end)) = last.take()
|
||||
{
|
||||
lines.push(last_attempt);
|
||||
start = last_end;
|
||||
attempt = line(engine, p, start..end, breakpoint, lines.last());
|
||||
}
|
||||
|
||||
// Finish the current line if there is a mandatory line break (i.e. due
|
||||
@ -894,11 +894,7 @@ impl CostMetrics {
|
||||
/// we allow less because otherwise we get an invalid layout fairly often,
|
||||
/// which makes our bound useless.
|
||||
fn min_ratio(&self, approx: bool) -> f64 {
|
||||
if approx {
|
||||
self.min_approx_ratio
|
||||
} else {
|
||||
self.min_ratio
|
||||
}
|
||||
if approx { self.min_approx_ratio } else { self.min_ratio }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ pub use self::box_::layout_box;
|
||||
pub use self::shaping::create_shape_plan;
|
||||
|
||||
use comemo::{Track, Tracked, TrackedMut};
|
||||
use typst_library::World;
|
||||
use typst_library::diag::SourceResult;
|
||||
use typst_library::engine::{Engine, Route, Sink, Traced};
|
||||
use typst_library::foundations::{Packed, Smart, StyleChain};
|
||||
@ -23,18 +24,17 @@ use typst_library::model::{
|
||||
};
|
||||
use typst_library::routines::{Arenas, Pair, RealizationKind, Routines};
|
||||
use typst_library::text::{Costs, Lang, TextElem};
|
||||
use typst_library::World;
|
||||
use typst_utils::{Numeric, SliceExt};
|
||||
|
||||
use self::collect::{collect, Item, Segment, SpanMapper};
|
||||
use self::collect::{Item, Segment, SpanMapper, collect};
|
||||
use self::deco::decorate;
|
||||
use self::finalize::finalize;
|
||||
use self::line::{apply_shift, commit, line, Line};
|
||||
use self::linebreak::{linebreak, Breakpoint};
|
||||
use self::prepare::{prepare, Preparation};
|
||||
use self::line::{Line, apply_shift, commit, line};
|
||||
use self::linebreak::{Breakpoint, linebreak};
|
||||
use self::prepare::{Preparation, prepare};
|
||||
use self::shaping::{
|
||||
cjk_punct_style, is_of_cj_script, shape_range, ShapedGlyph, ShapedText,
|
||||
BEGIN_PUNCT_PAT, END_PUNCT_PAT,
|
||||
BEGIN_PUNCT_PAT, END_PUNCT_PAT, ShapedGlyph, ShapedText, cjk_punct_style,
|
||||
is_of_cj_script, shape_range,
|
||||
};
|
||||
|
||||
/// Range of a substring of text.
|
||||
@ -190,11 +190,7 @@ fn configuration(
|
||||
Config {
|
||||
justify,
|
||||
linebreaks: base.linebreaks.unwrap_or_else(|| {
|
||||
if justify {
|
||||
Linebreaks::Optimized
|
||||
} else {
|
||||
Linebreaks::Simple
|
||||
}
|
||||
if justify { Linebreaks::Optimized } else { Linebreaks::Simple }
|
||||
}),
|
||||
first_line_indent: {
|
||||
let FirstLineIndent { amount, all } = base.first_line_indent;
|
||||
|
@ -4,21 +4,21 @@ use std::sync::Arc;
|
||||
|
||||
use az::SaturatingAs;
|
||||
use rustybuzz::{BufferFlags, Feature, ShapePlan, UnicodeBuffer};
|
||||
use ttf_parser::gsub::SubstitutionSubtable;
|
||||
use ttf_parser::Tag;
|
||||
use ttf_parser::gsub::SubstitutionSubtable;
|
||||
use typst_library::World;
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{Smart, StyleChain};
|
||||
use typst_library::layout::{Abs, Dir, Em, Frame, FrameItem, Point, Size};
|
||||
use typst_library::text::{
|
||||
families, features, is_default_ignorable, language, variant, Font, FontFamily,
|
||||
FontVariant, Glyph, Lang, Region, ShiftSettings, TextEdgeBounds, TextElem, TextItem,
|
||||
Font, FontFamily, FontVariant, Glyph, Lang, Region, ShiftSettings, TextEdgeBounds,
|
||||
TextElem, TextItem, families, features, is_default_ignorable, language, variant,
|
||||
};
|
||||
use typst_library::World;
|
||||
use typst_utils::SliceExt;
|
||||
use unicode_bidi::{BidiInfo, Level as BidiLevel};
|
||||
use unicode_script::{Script, UnicodeScript};
|
||||
|
||||
use super::{decorate, Item, Range, SpanMapper};
|
||||
use super::{Item, Range, SpanMapper, decorate};
|
||||
use crate::modifiers::FrameModifyText;
|
||||
|
||||
/// The result of shaping text.
|
||||
@ -539,11 +539,7 @@ impl<'a> ShapedText<'a> {
|
||||
// Find any glyph with the text index.
|
||||
let found = self.glyphs.binary_search_by(|g: &ShapedGlyph| {
|
||||
let ordering = g.range.start.cmp(&text_index);
|
||||
if ltr {
|
||||
ordering
|
||||
} else {
|
||||
ordering.reverse()
|
||||
}
|
||||
if ltr { ordering } else { ordering.reverse() }
|
||||
});
|
||||
|
||||
let mut idx = match found {
|
||||
|
@ -24,11 +24,7 @@ pub fn layout_list(
|
||||
let body_indent = elem.body_indent.get(styles);
|
||||
let tight = elem.tight.get(styles);
|
||||
let gutter = elem.spacing.get(styles).unwrap_or_else(|| {
|
||||
if tight {
|
||||
styles.get(ParElem::leading)
|
||||
} else {
|
||||
styles.get(ParElem::spacing)
|
||||
}
|
||||
if tight { styles.get(ParElem::leading) } else { styles.get(ParElem::spacing) }
|
||||
});
|
||||
|
||||
let Depth(depth) = styles.get(ListElem::depth);
|
||||
@ -88,22 +84,15 @@ pub fn layout_enum(
|
||||
let body_indent = elem.body_indent.get(styles);
|
||||
let tight = elem.tight.get(styles);
|
||||
let gutter = elem.spacing.get(styles).unwrap_or_else(|| {
|
||||
if tight {
|
||||
styles.get(ParElem::leading)
|
||||
} else {
|
||||
styles.get(ParElem::spacing)
|
||||
}
|
||||
if tight { styles.get(ParElem::leading) } else { styles.get(ParElem::spacing) }
|
||||
});
|
||||
|
||||
let mut cells = vec![];
|
||||
let mut locator = locator.split();
|
||||
let mut number = elem.start.get(styles).unwrap_or_else(|| {
|
||||
if reversed {
|
||||
elem.children.len() as u64
|
||||
} else {
|
||||
1
|
||||
}
|
||||
});
|
||||
let mut number = elem
|
||||
.start
|
||||
.get(styles)
|
||||
.unwrap_or_else(|| if reversed { elem.children.len() as u64 } else { 1 });
|
||||
let mut parents = styles.get_cloned(EnumElem::parents);
|
||||
|
||||
let full = elem.full.get(styles);
|
||||
|
@ -4,8 +4,8 @@ use typst_library::layout::{Frame, Point, Size};
|
||||
use typst_library::math::AccentElem;
|
||||
|
||||
use super::{
|
||||
style_cramped, style_dtls, style_flac, FrameFragment, GlyphFragment, MathContext,
|
||||
MathFragment,
|
||||
FrameFragment, GlyphFragment, MathContext, MathFragment, style_cramped, style_dtls,
|
||||
style_flac,
|
||||
};
|
||||
|
||||
/// Lays out an [`AccentElem`].
|
||||
|
@ -8,8 +8,8 @@ use typst_library::math::{
|
||||
use typst_utils::OptionExt;
|
||||
|
||||
use super::{
|
||||
stretch_fragment, style_for_subscript, style_for_superscript, FrameFragment, Limits,
|
||||
MathContext, MathFragment,
|
||||
FrameFragment, Limits, MathContext, MathFragment, stretch_fragment,
|
||||
style_for_subscript, style_for_superscript,
|
||||
};
|
||||
|
||||
macro_rules! measure {
|
||||
|
@ -1,13 +1,13 @@
|
||||
use typst_library::diag::SourceResult;
|
||||
use typst_library::foundations::{Content, Packed, Resolve, StyleChain, SymbolElem};
|
||||
use typst_library::layout::{Em, Frame, FrameItem, Point, Size};
|
||||
use typst_library::math::{BinomElem, FracElem, DELIM_SHORT_FALL};
|
||||
use typst_library::math::{BinomElem, DELIM_SHORT_FALL, FracElem};
|
||||
use typst_library::text::TextElem;
|
||||
use typst_library::visualize::{FixedStroke, Geometry};
|
||||
use typst_syntax::Span;
|
||||
|
||||
use super::{
|
||||
style_for_denominator, style_for_numerator, FrameFragment, GlyphFragment, MathContext,
|
||||
FrameFragment, GlyphFragment, MathContext, style_for_denominator, style_for_numerator,
|
||||
};
|
||||
|
||||
const FRAC_AROUND: Em = Em::new(0.1);
|
||||
|
@ -2,18 +2,18 @@ use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
use az::SaturatingAs;
|
||||
use rustybuzz::{BufferFlags, UnicodeBuffer};
|
||||
use ttf_parser::math::{GlyphAssembly, GlyphConstruction, GlyphPart};
|
||||
use ttf_parser::GlyphId;
|
||||
use typst_library::diag::{bail, warning, SourceResult};
|
||||
use ttf_parser::math::{GlyphAssembly, GlyphConstruction, GlyphPart};
|
||||
use typst_library::diag::{SourceResult, bail, warning};
|
||||
use typst_library::foundations::StyleChain;
|
||||
use typst_library::introspection::Tag;
|
||||
use typst_library::layout::{
|
||||
Abs, Axes, Axis, Corner, Em, Frame, FrameItem, Point, Size, VAlignment,
|
||||
};
|
||||
use typst_library::math::{EquationElem, MathSize};
|
||||
use typst_library::text::{features, language, Font, Glyph, TextElem, TextItem};
|
||||
use typst_library::text::{Font, Glyph, TextElem, TextItem, features, language};
|
||||
use typst_syntax::Span;
|
||||
use typst_utils::{default_math_class, Get};
|
||||
use typst_utils::{Get, default_math_class};
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use super::MathContext;
|
||||
@ -681,7 +681,11 @@ fn min_connector_overlap(font: &Font) -> Option<Em> {
|
||||
.map(|variants| font.to_em(variants.min_connector_overlap))
|
||||
}
|
||||
|
||||
fn glyph_construction(font: &Font, id: GlyphId, axis: Axis) -> Option<GlyphConstruction> {
|
||||
fn glyph_construction(
|
||||
font: &Font,
|
||||
id: GlyphId,
|
||||
axis: Axis,
|
||||
) -> Option<GlyphConstruction<'_>> {
|
||||
font.ttf()
|
||||
.tables()
|
||||
.math?
|
||||
@ -810,7 +814,10 @@ fn assemble(
|
||||
|
||||
/// Return an iterator over the assembly's parts with extenders repeated the
|
||||
/// specified number of times.
|
||||
fn parts(assembly: GlyphAssembly, repeat: usize) -> impl Iterator<Item = GlyphPart> + '_ {
|
||||
fn parts(
|
||||
assembly: GlyphAssembly<'_>,
|
||||
repeat: usize,
|
||||
) -> impl Iterator<Item = GlyphPart> + '_ {
|
||||
assembly.parts.into_iter().flat_map(move |part| {
|
||||
let count = if part.part_flags.extender() { repeat } else { 1 };
|
||||
std::iter::repeat_n(part, count)
|
||||
|
@ -5,7 +5,7 @@ use typst_library::math::{EquationElem, LrElem, MidElem, StretchSize};
|
||||
use typst_utils::SliceExt;
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use super::{stretch_fragment, MathContext, MathFragment};
|
||||
use super::{MathContext, MathFragment, stretch_fragment};
|
||||
|
||||
/// Lays out an [`LrElem`].
|
||||
#[typst_macros::time(name = "math.lr", span = elem.span())]
|
||||
@ -21,10 +21,10 @@ pub fn layout_lr(
|
||||
}
|
||||
|
||||
// Extract implicit LrElem.
|
||||
if let Some(lr) = body.to_packed::<LrElem>() {
|
||||
if lr.size.get_ref(styles).is_lr_default() {
|
||||
body = &lr.body;
|
||||
}
|
||||
if let Some(lr) = body.to_packed::<LrElem>()
|
||||
&& lr.size.get_ref(styles).is_lr_default()
|
||||
{
|
||||
body = &lr.body;
|
||||
}
|
||||
|
||||
let mut fragments = ctx.layout_into_fragments(body, styles)?;
|
||||
@ -69,11 +69,11 @@ pub fn layout_lr(
|
||||
|
||||
// Handle MathFragment::Glyph fragments that should be scaled up.
|
||||
for fragment in inner_fragments.iter_mut() {
|
||||
if let MathFragment::Glyph(ref mut glyph) = fragment {
|
||||
if glyph.mid_stretched == Some(false) {
|
||||
glyph.mid_stretched = Some(true);
|
||||
scale(ctx, styles, fragment, relative_to, height)?;
|
||||
}
|
||||
if let MathFragment::Glyph(glyph) = fragment
|
||||
&& glyph.mid_stretched == Some(false)
|
||||
{
|
||||
glyph.mid_stretched = Some(true);
|
||||
scale(ctx, styles, fragment, relative_to, height)?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ pub fn layout_mid(
|
||||
let mut fragments = ctx.layout_into_fragments(&elem.body, styles)?;
|
||||
|
||||
for fragment in &mut fragments {
|
||||
if let MathFragment::Glyph(ref mut glyph) = fragment {
|
||||
if let MathFragment::Glyph(glyph) = fragment {
|
||||
glyph.mid_stretched = Some(false);
|
||||
glyph.class = MathClass::Relation;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use typst_library::diag::{bail, warning, SourceResult};
|
||||
use typst_library::diag::{SourceResult, bail, warning};
|
||||
use typst_library::foundations::{Content, Packed, Resolve, StyleChain};
|
||||
use typst_library::layout::{
|
||||
Abs, Axes, Em, FixedAlignment, Frame, FrameItem, Point, Rel, Size,
|
||||
@ -11,8 +11,8 @@ use typst_library::visualize::{FillRule, FixedStroke, Geometry, LineCap, Shape};
|
||||
use typst_syntax::Span;
|
||||
|
||||
use super::{
|
||||
alignments, style_for_denominator, AlignmentResult, FrameFragment, GlyphFragment,
|
||||
LeftRightAlternator, MathContext,
|
||||
AlignmentResult, FrameFragment, GlyphFragment, LeftRightAlternator, MathContext,
|
||||
alignments, style_for_denominator,
|
||||
};
|
||||
|
||||
const DEFAULT_STROKE_THICKNESS: Em = Em::new(0.05);
|
||||
|
@ -13,7 +13,8 @@ mod stretch;
|
||||
mod text;
|
||||
mod underover;
|
||||
|
||||
use typst_library::diag::{bail, SourceResult};
|
||||
use typst_library::World;
|
||||
use typst_library::diag::{SourceResult, bail};
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{
|
||||
Content, NativeElement, Packed, Resolve, StyleChain, SymbolElem,
|
||||
@ -28,15 +29,14 @@ use typst_library::math::*;
|
||||
use typst_library::model::ParElem;
|
||||
use typst_library::routines::{Arenas, RealizationKind};
|
||||
use typst_library::text::{
|
||||
families, variant, Font, LinebreakElem, SpaceElem, TextEdgeBounds, TextElem,
|
||||
Font, LinebreakElem, SpaceElem, TextEdgeBounds, TextElem, families, variant,
|
||||
};
|
||||
use typst_library::World;
|
||||
use typst_syntax::Span;
|
||||
use typst_utils::Numeric;
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use self::fragment::{
|
||||
has_dtls_feat, stretch_axes, FrameFragment, GlyphFragment, Limits, MathFragment,
|
||||
FrameFragment, GlyphFragment, Limits, MathFragment, has_dtls_feat, stretch_axes,
|
||||
};
|
||||
use self::run::{LeftRightAlternator, MathRun, MathRunFrameBuilder};
|
||||
use self::shared::*;
|
||||
@ -603,13 +603,10 @@ fn layout_h(
|
||||
ctx: &mut MathContext,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<()> {
|
||||
if let Spacing::Rel(rel) = elem.amount {
|
||||
if rel.rel.is_zero() {
|
||||
ctx.push(MathFragment::Spacing(
|
||||
rel.abs.resolve(styles),
|
||||
elem.weak.get(styles),
|
||||
));
|
||||
}
|
||||
if let Spacing::Rel(rel) = elem.amount
|
||||
&& rel.rel.is_zero()
|
||||
{
|
||||
ctx.push(MathFragment::Spacing(rel.abs.resolve(styles), elem.weak.get(styles)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use typst_library::math::{EquationElem, MathSize, RootElem};
|
||||
use typst_library::text::TextElem;
|
||||
use typst_library::visualize::{FixedStroke, Geometry};
|
||||
|
||||
use super::{style_cramped, FrameFragment, GlyphFragment, MathContext};
|
||||
use super::{FrameFragment, GlyphFragment, MathContext, style_cramped};
|
||||
|
||||
/// Lays out a [`RootElem`].
|
||||
///
|
||||
|
@ -2,11 +2,11 @@ use std::iter::once;
|
||||
|
||||
use typst_library::foundations::{Resolve, StyleChain};
|
||||
use typst_library::layout::{Abs, AlignElem, Em, Frame, InlineItem, Point, Size};
|
||||
use typst_library::math::{EquationElem, MathSize, MEDIUM, THICK, THIN};
|
||||
use typst_library::math::{EquationElem, MEDIUM, MathSize, THICK, THIN};
|
||||
use typst_library::model::ParElem;
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use super::{alignments, FrameFragment, MathFragment};
|
||||
use super::{FrameFragment, MathFragment, alignments};
|
||||
|
||||
const TIGHT_LEADING: Em = Em::new(0.25);
|
||||
|
||||
@ -87,10 +87,10 @@ impl MathRun {
|
||||
|
||||
// Insert spacing between the last and this non-ignorant item.
|
||||
if !fragment.is_ignorant() {
|
||||
if let Some(i) = last {
|
||||
if let Some(s) = spacing(&resolved[i], space.take(), &fragment) {
|
||||
resolved.insert(i + 1, s);
|
||||
}
|
||||
if let Some(i) = last
|
||||
&& let Some(s) = spacing(&resolved[i], space.take(), &fragment)
|
||||
{
|
||||
resolved.insert(i + 1, s);
|
||||
}
|
||||
|
||||
last = Some(resolved.len());
|
||||
@ -123,10 +123,10 @@ impl MathRun {
|
||||
1 + self.0.iter().filter(|f| matches!(f, MathFragment::Linebreak)).count();
|
||||
|
||||
// A linebreak at the very end does not introduce an extra row.
|
||||
if let Some(f) = self.0.last() {
|
||||
if matches!(f, MathFragment::Linebreak) {
|
||||
count -= 1
|
||||
}
|
||||
if let Some(f) = self.0.last()
|
||||
&& matches!(f, MathFragment::Linebreak)
|
||||
{
|
||||
count -= 1
|
||||
}
|
||||
count
|
||||
}
|
||||
@ -344,10 +344,10 @@ impl MathRun {
|
||||
descent = Abs::zero();
|
||||
|
||||
space_is_visible = true;
|
||||
if let Some(f_next) = iter.peek() {
|
||||
if !is_space(f_next) {
|
||||
items.push(InlineItem::Space(Abs::zero(), true));
|
||||
}
|
||||
if let Some(f_next) = iter.peek()
|
||||
&& !is_space(f_next)
|
||||
{
|
||||
items.push(InlineItem::Space(Abs::zero(), true));
|
||||
}
|
||||
} else {
|
||||
space_is_visible = false;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use ttf_parser::math::MathValue;
|
||||
use ttf_parser::Tag;
|
||||
use ttf_parser::math::MathValue;
|
||||
use typst_library::foundations::{Style, StyleChain};
|
||||
use typst_library::layout::{Abs, FixedAlignment, Frame, Point, Size};
|
||||
use typst_library::math::{EquationElem, MathSize};
|
||||
|
@ -1,10 +1,10 @@
|
||||
use typst_library::diag::{warning, SourceResult};
|
||||
use typst_library::diag::{SourceResult, warning};
|
||||
use typst_library::foundations::{Packed, StyleChain};
|
||||
use typst_library::layout::{Abs, Axis};
|
||||
use typst_library::math::{StretchElem, StretchSize};
|
||||
use typst_utils::Get;
|
||||
|
||||
use super::{stretch_axes, MathContext, MathFragment};
|
||||
use super::{MathContext, MathFragment, stretch_axes};
|
||||
|
||||
/// Lays out a [`StretchElem`].
|
||||
#[typst_macros::time(name = "math.stretch", span = elem.span())]
|
||||
@ -30,7 +30,7 @@ pub fn stretch_fragment(
|
||||
) -> SourceResult<()> {
|
||||
let size = fragment.size();
|
||||
|
||||
let MathFragment::Glyph(ref mut glyph) = fragment else { return Ok(()) };
|
||||
let MathFragment::Glyph(glyph) = fragment else { return Ok(()) };
|
||||
|
||||
// Return if we attempt to stretch along an axis which isn't stretchable,
|
||||
// so that the original fragment isn't modified.
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::f64::consts::SQRT_2;
|
||||
|
||||
use codex::styling::{to_style, MathStyle};
|
||||
use codex::styling::{MathStyle, to_style};
|
||||
use ecow::EcoString;
|
||||
use typst_library::diag::SourceResult;
|
||||
use typst_library::foundations::{Packed, StyleChain, SymbolElem};
|
||||
@ -9,13 +9,13 @@ use typst_library::math::{EquationElem, MathSize};
|
||||
use typst_library::text::{
|
||||
BottomEdge, BottomEdgeMetric, TextElem, TopEdge, TopEdgeMetric,
|
||||
};
|
||||
use typst_syntax::{is_newline, Span};
|
||||
use typst_syntax::{Span, is_newline};
|
||||
use unicode_math_class::MathClass;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use super::{
|
||||
has_dtls_feat, style_dtls, FrameFragment, GlyphFragment, MathContext, MathFragment,
|
||||
MathRun,
|
||||
FrameFragment, GlyphFragment, MathContext, MathFragment, MathRun, has_dtls_feat,
|
||||
style_dtls,
|
||||
};
|
||||
|
||||
/// Lays out a [`TextElem`].
|
||||
|
@ -10,8 +10,8 @@ use typst_library::visualize::{FixedStroke, Geometry};
|
||||
use typst_syntax::Span;
|
||||
|
||||
use super::{
|
||||
stack, style_cramped, style_for_subscript, style_for_superscript, FrameFragment,
|
||||
GlyphFragment, LeftRightAlternator, MathContext, MathRun,
|
||||
FrameFragment, GlyphFragment, LeftRightAlternator, MathContext, MathRun, stack,
|
||||
style_cramped, style_for_subscript, style_for_superscript,
|
||||
};
|
||||
|
||||
const BRACE_GAP: Em = Em::new(0.25);
|
||||
|
@ -7,6 +7,7 @@ mod run;
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use comemo::{Tracked, TrackedMut};
|
||||
use typst_library::World;
|
||||
use typst_library::diag::SourceResult;
|
||||
use typst_library::engine::{Engine, Route, Sink, Traced};
|
||||
use typst_library::foundations::{Content, StyleChain};
|
||||
@ -16,11 +17,10 @@ use typst_library::introspection::{
|
||||
use typst_library::layout::{FrameItem, Page, PagedDocument, Point, Transform};
|
||||
use typst_library::model::DocumentInfo;
|
||||
use typst_library::routines::{Arenas, Pair, RealizationKind, Routines};
|
||||
use typst_library::World;
|
||||
|
||||
use self::collect::{collect, Item};
|
||||
use self::collect::{Item, collect};
|
||||
use self::finalize::finalize;
|
||||
use self::run::{layout_blank_page, layout_page_run, LayoutedPage};
|
||||
use self::run::{LayoutedPage, layout_blank_page, layout_page_run};
|
||||
|
||||
/// Layout content into a document.
|
||||
///
|
||||
|
@ -1,4 +1,5 @@
|
||||
use comemo::{Track, Tracked, TrackedMut};
|
||||
use typst_library::World;
|
||||
use typst_library::diag::SourceResult;
|
||||
use typst_library::engine::{Engine, Route, Sink, Traced};
|
||||
use typst_library::foundations::{
|
||||
@ -16,10 +17,9 @@ use typst_library::model::Numbering;
|
||||
use typst_library::routines::{Pair, Routines};
|
||||
use typst_library::text::{LocalName, TextElem};
|
||||
use typst_library::visualize::Paint;
|
||||
use typst_library::World;
|
||||
use typst_utils::Numeric;
|
||||
|
||||
use crate::flow::{layout_flow, FlowMode};
|
||||
use crate::flow::{FlowMode, layout_flow};
|
||||
|
||||
/// A mostly finished layout for one page. Needs only knowledge of its exact
|
||||
/// page number to be finalized into a `Page`. (Because the margins can depend
|
||||
|
@ -1,4 +1,4 @@
|
||||
use typst_library::diag::{bail, SourceResult};
|
||||
use typst_library::diag::{SourceResult, bail};
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{Packed, Resolve, StyleChain};
|
||||
use typst_library::introspection::Locator;
|
||||
|
@ -1,12 +1,12 @@
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use comemo::Track;
|
||||
use ecow::{eco_format, EcoVec};
|
||||
use ecow::{EcoVec, eco_format};
|
||||
use smallvec::smallvec;
|
||||
use typst_library::diag::{bail, At, SourceResult};
|
||||
use typst_library::diag::{At, SourceResult, bail};
|
||||
use typst_library::foundations::{
|
||||
dict, Content, Context, NativeElement, NativeRuleMap, Packed, Resolve, ShowFn, Smart,
|
||||
StyleChain, Target,
|
||||
Content, Context, NativeElement, NativeRuleMap, Packed, Resolve, ShowFn, Smart,
|
||||
StyleChain, Target, dict,
|
||||
};
|
||||
use typst_library::introspection::{Counter, Locator, LocatorLink};
|
||||
use typst_library::layout::{
|
||||
@ -161,11 +161,7 @@ const TERMS_RULE: ShowFn<TermsElem> = |elem, _, styles| {
|
||||
let indent = elem.indent.get(styles);
|
||||
let hanging_indent = elem.hanging_indent.get(styles);
|
||||
let gutter = elem.spacing.get(styles).unwrap_or_else(|| {
|
||||
if tight {
|
||||
styles.get(ParElem::leading)
|
||||
} else {
|
||||
styles.get(ParElem::spacing)
|
||||
}
|
||||
if tight { styles.get(ParElem::leading) } else { styles.get(ParElem::spacing) }
|
||||
});
|
||||
|
||||
let pad = hanging_indent + indent;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::f64::consts::SQRT_2;
|
||||
|
||||
use kurbo::{CubicBez, ParamCurveExtrema};
|
||||
use typst_library::diag::{bail, SourceResult};
|
||||
use typst_library::diag::{SourceResult, bail};
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{Content, Packed, Resolve, Smart, StyleChain};
|
||||
use typst_library::introspection::Locator;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use typst_library::diag::{bail, SourceResult};
|
||||
use typst_library::diag::{SourceResult, bail};
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{Content, Packed, Resolve, StyleChain, StyledElem};
|
||||
use typst_library::introspection::{Locator, SplitLocator};
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::cell::LazyCell;
|
||||
|
||||
use typst_library::diag::{bail, SourceResult};
|
||||
use typst_library::diag::{SourceResult, bail};
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{Content, Packed, Resolve, Smart, StyleChain};
|
||||
use typst_library::introspection::Locator;
|
||||
|
@ -31,6 +31,7 @@ flate2 = { workspace = true }
|
||||
fontdb = { workspace = true }
|
||||
glidesort = { workspace = true }
|
||||
hayagriva = { workspace = true }
|
||||
hayro-syntax = { workspace = true }
|
||||
icu_properties = { workspace = true }
|
||||
icu_provider = { workspace = true }
|
||||
icu_provider_blob = { workspace = true }
|
||||
|
@ -8,7 +8,7 @@ use std::string::FromUtf8Error;
|
||||
|
||||
use az::SaturatingAs;
|
||||
use comemo::Tracked;
|
||||
use ecow::{eco_vec, EcoVec};
|
||||
use ecow::{EcoVec, eco_vec};
|
||||
use typst_syntax::package::{PackageSpec, PackageVersion};
|
||||
use typst_syntax::{Lines, Span, Spanned, SyntaxError};
|
||||
use utf8_iter::ErrorReportingUtf8Chars;
|
||||
@ -296,13 +296,12 @@ impl<T> Trace<T> for SourceResult<T> {
|
||||
let Some(trace_range) = world.range(span) else { return errors };
|
||||
for error in errors.make_mut().iter_mut() {
|
||||
// Skip traces that surround the error.
|
||||
if let Some(error_range) = world.range(error.span) {
|
||||
if error.span.id() == span.id()
|
||||
&& trace_range.start <= error_range.start
|
||||
&& trace_range.end >= error_range.end
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if let Some(error_range) = world.range(error.span)
|
||||
&& error.span.id() == span.id()
|
||||
&& trace_range.start <= error_range.start
|
||||
&& trace_range.end >= error_range.end
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
error.trace.push(Spanned::new(make_point(), span));
|
||||
@ -839,7 +838,9 @@ pub fn format_xml_like_error(format: &str, error: roxmltree::Error) -> LoadError
|
||||
let pos = LineCol::one_based(error.pos().row as usize, error.pos().col as usize);
|
||||
let message = match error {
|
||||
roxmltree::Error::UnexpectedCloseTag(expected, actual, _) => {
|
||||
eco_format!("failed to parse {format} (found closing tag '{actual}' instead of '{expected}')")
|
||||
eco_format!(
|
||||
"failed to parse {format} (found closing tag '{actual}' instead of '{expected}')"
|
||||
)
|
||||
}
|
||||
roxmltree::Error::UnknownEntityReference(entity, _) => {
|
||||
eco_format!("failed to parse {format} (unknown entity '{entity}')")
|
||||
|
@ -8,11 +8,11 @@ use ecow::EcoVec;
|
||||
use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
|
||||
use typst_syntax::{FileId, Span};
|
||||
|
||||
use crate::diag::{bail, HintedStrResult, SourceDiagnostic, SourceResult, StrResult};
|
||||
use crate::World;
|
||||
use crate::diag::{HintedStrResult, SourceDiagnostic, SourceResult, StrResult, bail};
|
||||
use crate::foundations::{Styles, Value};
|
||||
use crate::introspection::Introspector;
|
||||
use crate::routines::Routines;
|
||||
use crate::World;
|
||||
|
||||
/// Holds all data needed during compilation.
|
||||
pub struct Engine<'a> {
|
||||
@ -47,7 +47,11 @@ impl Engine<'_> {
|
||||
}
|
||||
|
||||
/// Runs tasks on the engine in parallel.
|
||||
pub fn parallelize<P, I, T, U, F>(&mut self, iter: P, f: F) -> impl Iterator<Item = U>
|
||||
pub fn parallelize<P, I, T, U, F>(
|
||||
&mut self,
|
||||
iter: P,
|
||||
f: F,
|
||||
) -> impl Iterator<Item = U> + use<P, I, T, U, F>
|
||||
where
|
||||
P: IntoIterator<IntoIter = I>,
|
||||
I: Iterator<Item = T>,
|
||||
@ -111,11 +115,7 @@ impl Traced {
|
||||
/// We hide the span if it isn't in the given file so that only results for
|
||||
/// the file with the traced span are invalidated.
|
||||
pub fn get(&self, id: FileId) -> Option<Span> {
|
||||
if self.0.and_then(Span::id) == Some(id) {
|
||||
self.0
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if self.0.and_then(Span::id) == Some(id) { self.0 } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::ops::Add;
|
||||
|
||||
use ecow::{eco_format, eco_vec, EcoString, EcoVec};
|
||||
use ecow::{EcoString, EcoVec, eco_format, eco_vec};
|
||||
use typst_syntax::{Span, Spanned};
|
||||
|
||||
use crate::diag::{bail, error, At, SourceDiagnostic, SourceResult, StrResult};
|
||||
use crate::diag::{At, SourceDiagnostic, SourceResult, StrResult, bail, error};
|
||||
use crate::foundations::{
|
||||
cast, func, repr, scope, ty, Array, Dict, FromValue, IntoValue, Repr, Str, Value,
|
||||
Array, Dict, FromValue, IntoValue, Repr, Str, Value, cast, func, repr, scope, ty,
|
||||
};
|
||||
|
||||
/// Captured arguments to a function.
|
||||
|
@ -4,16 +4,16 @@ use std::num::{NonZeroI64, NonZeroUsize};
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
use comemo::Tracked;
|
||||
use ecow::{eco_format, EcoString, EcoVec};
|
||||
use ecow::{EcoString, EcoVec, eco_format};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smallvec::SmallVec;
|
||||
use typst_syntax::{Span, Spanned};
|
||||
|
||||
use crate::diag::{bail, At, HintedStrResult, SourceDiagnostic, SourceResult, StrResult};
|
||||
use crate::diag::{At, HintedStrResult, SourceDiagnostic, SourceResult, StrResult, bail};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, func, ops, repr, scope, ty, Args, Bytes, CastInfo, Context, Dict, FromValue,
|
||||
Func, IntoValue, Reflect, Repr, Str, Value, Version,
|
||||
Args, Bytes, CastInfo, Context, Dict, FromValue, Func, IntoValue, Reflect, Repr, Str,
|
||||
Value, Version, cast, func, ops, repr, scope, ty,
|
||||
};
|
||||
|
||||
/// Create a new [`Array`] from values.
|
||||
|
@ -4,8 +4,8 @@ use ecow::EcoString;
|
||||
|
||||
use crate::diag::HintedStrResult;
|
||||
use crate::foundations::{
|
||||
ty, CastInfo, Fold, FromValue, IntoValue, Reflect, Repr, Resolve, StyleChain, Type,
|
||||
Value,
|
||||
CastInfo, Fold, FromValue, IntoValue, Reflect, Repr, Resolve, StyleChain, Type,
|
||||
Value, ty,
|
||||
};
|
||||
|
||||
/// A value that indicates a smart default.
|
||||
|
@ -1,6 +1,6 @@
|
||||
use ecow::EcoString;
|
||||
|
||||
use crate::foundations::{ty, Repr};
|
||||
use crate::foundations::{Repr, ty};
|
||||
|
||||
/// A type with two states.
|
||||
///
|
||||
|
@ -5,13 +5,13 @@ use std::ops::{Add, AddAssign, Deref};
|
||||
use std::str::Utf8Error;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ecow::{eco_format, EcoString};
|
||||
use ecow::{EcoString, eco_format};
|
||||
use serde::{Serialize, Serializer};
|
||||
use typst_syntax::Lines;
|
||||
use typst_utils::LazyHash;
|
||||
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::foundations::{cast, func, scope, ty, Array, Reflect, Repr, Str, Value};
|
||||
use crate::diag::{StrResult, bail};
|
||||
use crate::foundations::{Array, Reflect, Repr, Str, Value, cast, func, scope, ty};
|
||||
|
||||
/// A sequence of bytes.
|
||||
///
|
||||
|
@ -7,8 +7,8 @@ use az::SaturatingAs;
|
||||
use typst_syntax::{Span, Spanned};
|
||||
use typst_utils::{round_int_with_precision, round_with_precision};
|
||||
|
||||
use crate::diag::{bail, At, HintedString, SourceResult, StrResult};
|
||||
use crate::foundations::{cast, func, ops, Decimal, IntoValue, Module, Scope, Value};
|
||||
use crate::diag::{At, HintedString, SourceResult, StrResult, bail};
|
||||
use crate::foundations::{Decimal, IntoValue, Module, Scope, Value, cast, func, ops};
|
||||
use crate::layout::{Angle, Fr, Length, Ratio};
|
||||
|
||||
/// A module with calculation definitions.
|
||||
|
@ -14,7 +14,7 @@ use unicode_math_class::MathClass;
|
||||
|
||||
use crate::diag::{At, HintedStrResult, HintedString, SourceResult, StrResult};
|
||||
use crate::foundations::{
|
||||
array, repr, Fold, NativeElement, Packed, Repr, Str, Type, Value,
|
||||
Fold, NativeElement, Packed, Repr, Str, Type, Value, array, repr,
|
||||
};
|
||||
|
||||
/// Determine details of a type.
|
||||
@ -347,13 +347,14 @@ impl CastInfo {
|
||||
msg.hint(eco_format!("use `label({})` to create a label", s.repr()));
|
||||
}
|
||||
}
|
||||
} else if let Value::Decimal(_) = found {
|
||||
if !matching_type && parts.iter().any(|p| p == "float") {
|
||||
msg.hint(eco_format!(
|
||||
"if loss of precision is acceptable, explicitly cast the \
|
||||
} else if let Value::Decimal(_) = found
|
||||
&& !matching_type
|
||||
&& parts.iter().any(|p| p == "float")
|
||||
{
|
||||
msg.hint(eco_format!(
|
||||
"if loss of precision is acceptable, explicitly cast the \
|
||||
decimal to a float with `float(value)`"
|
||||
));
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
msg
|
||||
|
@ -11,8 +11,8 @@ use typst_utils::Static;
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, Args, Content, ContentVtable, FieldAccessError, Func, ParamInfo, Repr, Scope,
|
||||
Selector, StyleChain, Styles, Value,
|
||||
Args, Content, ContentVtable, FieldAccessError, Func, ParamInfo, Repr, Scope,
|
||||
Selector, StyleChain, Styles, Value, cast,
|
||||
};
|
||||
use crate::text::{Lang, Region};
|
||||
|
||||
@ -243,7 +243,7 @@ pub trait Set {
|
||||
pub trait Synthesize {
|
||||
/// Prepare the element for show rule application.
|
||||
fn synthesize(&mut self, engine: &mut Engine, styles: StyleChain)
|
||||
-> SourceResult<()>;
|
||||
-> SourceResult<()>;
|
||||
}
|
||||
|
||||
/// Defines built-in show set rules for an element.
|
||||
|
@ -3,7 +3,7 @@ use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use ecow::{eco_format, EcoString};
|
||||
use ecow::{EcoString, eco_format};
|
||||
|
||||
use crate::foundations::{
|
||||
Container, Content, FieldVtable, Fold, FoldFn, IntoValue, NativeElement, Packed,
|
||||
|
@ -17,7 +17,7 @@ use std::iter::{self, Sum};
|
||||
use std::ops::{Add, AddAssign, ControlFlow};
|
||||
|
||||
use comemo::Tracked;
|
||||
use ecow::{eco_format, EcoString};
|
||||
use ecow::{EcoString, eco_format};
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
use typst_syntax::Span;
|
||||
@ -26,8 +26,8 @@ use typst_utils::singleton;
|
||||
use crate::diag::{SourceResult, StrResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
func, repr, scope, ty, Context, Dict, IntoValue, Label, Property, Recipe,
|
||||
RecipeIndex, Repr, Selector, Str, Style, StyleChain, Styles, Value,
|
||||
Context, Dict, IntoValue, Label, Property, Recipe, RecipeIndex, Repr, Selector, Str,
|
||||
Style, StyleChain, Styles, Value, func, repr, scope, ty,
|
||||
};
|
||||
use crate::introspection::Location;
|
||||
use crate::layout::{AlignElem, Alignment, Axes, Length, MoveElem, PadElem, Rel, Sides};
|
||||
@ -174,10 +174,10 @@ impl Content {
|
||||
id: u8,
|
||||
styles: Option<StyleChain>,
|
||||
) -> Result<Value, FieldAccessError> {
|
||||
if id == 255 {
|
||||
if let Some(label) = self.label() {
|
||||
return Ok(label.into_value());
|
||||
}
|
||||
if id == 255
|
||||
&& let Some(label) = self.label()
|
||||
{
|
||||
return Ok(label.into_value());
|
||||
}
|
||||
|
||||
match self.0.handle().field(id) {
|
||||
|
@ -5,7 +5,7 @@ use std::ptr::NonNull;
|
||||
use std::sync::atomic::{self, AtomicUsize, Ordering};
|
||||
|
||||
use typst_syntax::Span;
|
||||
use typst_utils::{fat, HashLock, SmallBitSet};
|
||||
use typst_utils::{HashLock, SmallBitSet, fat};
|
||||
|
||||
use super::vtable;
|
||||
use crate::foundations::{Element, Label, NativeElement, Packed};
|
||||
|
@ -1,9 +1,9 @@
|
||||
use comemo::Track;
|
||||
|
||||
use crate::diag::{bail, Hint, HintedStrResult, SourceResult};
|
||||
use crate::diag::{Hint, HintedStrResult, SourceResult, bail};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
elem, Args, Construct, Content, Func, ShowFn, StyleChain, Value,
|
||||
Args, Construct, Content, Func, ShowFn, StyleChain, Value, elem,
|
||||
};
|
||||
use crate::introspection::{Locatable, Location};
|
||||
|
||||
|
@ -2,17 +2,17 @@ use std::cmp::Ordering;
|
||||
use std::hash::Hash;
|
||||
use std::ops::{Add, Sub};
|
||||
|
||||
use ecow::{eco_format, EcoString, EcoVec};
|
||||
use ecow::{EcoString, EcoVec, eco_format};
|
||||
use time::error::{Format, InvalidFormatDescription};
|
||||
use time::macros::format_description;
|
||||
use time::{format_description, Month, PrimitiveDateTime};
|
||||
use time::{Month, PrimitiveDateTime, format_description};
|
||||
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::World;
|
||||
use crate::diag::{StrResult, bail};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, func, repr, scope, ty, Dict, Duration, Repr, Smart, Str, Value,
|
||||
Dict, Duration, Repr, Smart, Str, Value, cast, func, repr, scope, ty,
|
||||
};
|
||||
use crate::World;
|
||||
|
||||
/// Represents a date, a time, or a combination of both.
|
||||
///
|
||||
|
@ -3,14 +3,14 @@ use std::hash::{Hash, Hasher};
|
||||
use std::ops::Neg;
|
||||
use std::str::FromStr;
|
||||
|
||||
use ecow::{eco_format, EcoString};
|
||||
use ecow::{EcoString, eco_format};
|
||||
use rust_decimal::MathematicalOps;
|
||||
use typst_syntax::{ast, Span, Spanned};
|
||||
use typst_syntax::{Span, Spanned, ast};
|
||||
|
||||
use crate::diag::{warning, At, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{cast, func, repr, scope, ty, Repr, Str};
|
||||
use crate::World;
|
||||
use crate::diag::{At, SourceResult, warning};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{Repr, Str, cast, func, repr, scope, ty};
|
||||
|
||||
/// A fixed-point decimal number type.
|
||||
///
|
||||
|
@ -3,7 +3,7 @@ use std::hash::{Hash, Hasher};
|
||||
use std::ops::{Add, AddAssign};
|
||||
use std::sync::Arc;
|
||||
|
||||
use ecow::{eco_format, EcoString};
|
||||
use ecow::{EcoString, eco_format};
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use typst_syntax::is_ident;
|
||||
@ -11,7 +11,7 @@ use typst_utils::ArcExt;
|
||||
|
||||
use crate::diag::{Hint, HintedStrResult, StrResult};
|
||||
use crate::foundations::{
|
||||
array, cast, func, repr, scope, ty, Array, Module, Repr, Str, Value,
|
||||
Array, Module, Repr, Str, Value, array, cast, func, repr, scope, ty,
|
||||
};
|
||||
|
||||
/// Create a new [`Dict`] from key-value pairs.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user