Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
b5f6801
Add missing Typst 0.14 changelog entry (#7285)
laurmaedje Nov 5, 2025
29e7429
Fix panic in PDF backend due to ambiguous logical parent (#7216)
saecki Oct 27, 2025
dfc7e08
Specify the signature of `layout.func` in documentation (#7199)
YDX-2147483647 Oct 27, 2025
00dbfab
Properly document the default value of `array.join`'s `default` param…
MDLC01 Oct 27, 2025
a764465
Document the OpenType contextual alternates (`calt`) feature (#7169)
YDX-2147483647 Oct 27, 2025
68a41d7
Improve the docs for relative lengths (#6897)
YDX-2147483647 Oct 27, 2025
fa23f93
Do not create empty Make deps file when writing to standard output (#…
tovrstra Oct 28, 2025
0166c2f
Document version type comparison (#7152)
Andrew15-5 Oct 30, 2025
f7fbc8a
Minor fixes to documentation groups (#7242)
MDLC01 Oct 30, 2025
0b71b5c
Always treat `TextElem` fragments as spaced in math (#7276)
isuffix Oct 31, 2025
e8dc6d3
Update link on selector page to point to element functions (#7289)
bountonw Nov 5, 2025
47e5b2b
Fix spacing around mat/vec/cases (#7309)
mkorje Nov 5, 2025
6efb31f
Mention `SOURCE_DATE_EPOCH` in docs for `today` (#7311)
pavelzw Nov 5, 2025
809dc4e
Let examples distinguish ±dx and ±dy in the docs for `place` and `mov…
YDX-2147483647 Nov 7, 2025
525d977
Improve documentation for hide (#7201)
Andrew15-5 Nov 8, 2025
4cb20af
Fix height for horizontal glyph assemblies (#7327)
mkorje Nov 8, 2025
5a918cb
Change `d` to `dif` in the examples in the documentation (#7361)
iwkjosec Nov 12, 2025
a0176ea
Bump MSRV to 1.89 (#7363)
saecki Nov 12, 2025
b299416
Fix parsing of consecutive examples in docs (#7325)
YDX-2147483647 Nov 12, 2025
47be476
Fix table headers and footers with gutter in HTML export (#7332)
PgBiel Nov 12, 2025
84bd738
Update Rust nightly version used in tests (#7366)
laurmaedje Nov 13, 2025
ab330a8
Update krilla (#7369)
saecki Nov 14, 2025
74b7514
Correct a typo in v0.14.0 changelog (#7387)
YDX-2147483647 Nov 17, 2025
7715e88
Add documentation for column breaks in multi-column layout example (#…
Ri-Nai Nov 17, 2025
92d2a35
Improve documentation for `state.update` (#7192)
Andrew15-5 Nov 17, 2025
0d01556
Fix issue with table example (#7409)
fidelity-michael Nov 19, 2025
7b8c830
Fix lack of fallback to float for large integer literals (#7389)
YDX-2147483647 Nov 21, 2025
624de26
Bump krilla (#7458)
laurmaedje Nov 25, 2025
7cc3fdc
Consider all lookups and subtables in `subs` / `sups` coverage checks…
laurmaedje Nov 25, 2025
f820a90
Fix crash in PDF error formatting (#7460)
laurmaedje Nov 25, 2025
6b12b24
Do not propagate errors in numbering resolution during heading synthe…
laurmaedje Nov 25, 2025
faab8a2
Fix crash in PDF tagging with oob grid line end (#7448)
saecki Nov 25, 2025
64d9599
Bump wasmi to v0.51.2 (#7438)
tjjfvi Nov 25, 2025
e31aa60
Clamp PDF page size to 3x3 units (#7454)
saecki Nov 25, 2025
62cc09d
Slightly more accurate path separator replacement in tests (#7465)
saecki Nov 26, 2025
73f40b1
Generate internal compiler errors instead of panicking (#7450)
saecki Nov 27, 2025
9adeaf3
Use original logical index of line fallback text item (#7471)
saecki Nov 27, 2025
e95d580
Fix oblique fonts being classified as italic (#7483)
laurmaedje Dec 1, 2025
cef869f
Fix `arrow.l.r` not working as an accent (#7481)
laurmaedje Dec 1, 2025
f3c1bae
Fix caching of pdf tagging text attribute parameters (#7478)
saecki Dec 1, 2025
c782228
Fix `page.numbering` docs (#7420)
T0mstone Dec 1, 2025
8951558
Fix panic when division overflows in `calc` (#7419)
andylizi Dec 1, 2025
fcda8ce
Explicitly mark block equations in accessibility documentation (#7504)
saecki Dec 1, 2025
1d640ac
Warn instead of erroring for page set rule in HTML export (#7513)
laurmaedje Dec 2, 2025
008ad40
Bump krilla (#7516)
saecki Dec 2, 2025
df5afd3
Fix crash in `array.sorted` (#7520)
laurmaedje Dec 3, 2025
9e68d13
Typst 0.14.1 changelog (#7517)
laurmaedje Dec 3, 2025
eb2027e
Version bump
laurmaedje Dec 3, 2025
a780ba8
Merge upstream changes from v0.14.1
github-actions[bot] Aug 29, 2026
aee1e81
chore: コンフリクトを解消
3w36zj6 Aug 29, 2026
008f498
chore: Rustを1.89.0に更新
3w36zj6 Aug 29, 2026
d736b15
chore: リンクを解決
3w36zj6 Aug 29, 2026
1ba9863
chore: バージョンをv0.14.1に更新
3w36zj6 Aug 30, 2026
82a265c
chore: 翻訳ステータスを更新
3w36zj6 Aug 30, 2026
086b3de
chore: ref画像をv0.14.1に更新
3w36zj6 Aug 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 87 additions & 60 deletions Cargo.lock

Large diffs are not rendered by default.

46 changes: 23 additions & 23 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ default-members = ["crates/typst-cli"]
resolver = "2"

[workspace.package]
version = "0.14.0"
rust-version = "1.88" # also change in ci.yml
version = "0.14.1"
rust-version = "1.89" # also change in ci.yml
authors = ["The Typst Project Developers"]
edition = "2024"
homepage = "https://typst.app"
Expand All @@ -16,24 +16,24 @@ keywords = ["typst"]
readme = "README.md"

[workspace.dependencies]
typst = { path = "crates/typst", version = "0.14.0" }
typst-cli = { path = "crates/typst-cli", version = "0.14.0" }
typst-eval = { path = "crates/typst-eval", version = "0.14.0" }
typst-html = { path = "crates/typst-html", version = "0.14.0" }
typst-ide = { path = "crates/typst-ide", version = "0.14.0" }
typst-kit = { path = "crates/typst-kit", version = "0.14.0" }
typst-layout = { path = "crates/typst-layout", version = "0.14.0" }
typst-library = { path = "crates/typst-library", version = "0.14.0" }
typst-macros = { path = "crates/typst-macros", version = "0.14.0" }
typst-pdf = { path = "crates/typst-pdf", version = "0.14.0" }
typst-realize = { path = "crates/typst-realize", version = "0.14.0" }
typst-render = { path = "crates/typst-render", version = "0.14.0" }
typst-svg = { path = "crates/typst-svg", version = "0.14.0" }
typst-syntax = { path = "crates/typst-syntax", version = "0.14.0" }
typst-timing = { path = "crates/typst-timing", version = "0.14.0" }
typst-utils = { path = "crates/typst-utils", version = "0.14.0" }
typst-assets = "0.14.0"
typst-dev-assets = { git = "https://github.com/typst/typst-dev-assets", tag = "v0.14.0" }
typst = { path = "crates/typst", version = "0.14.1" }
typst-cli = { path = "crates/typst-cli", version = "0.14.1" }
typst-eval = { path = "crates/typst-eval", version = "0.14.1" }
typst-html = { path = "crates/typst-html", version = "0.14.1" }
typst-ide = { path = "crates/typst-ide", version = "0.14.1" }
typst-kit = { path = "crates/typst-kit", version = "0.14.1" }
typst-layout = { path = "crates/typst-layout", version = "0.14.1" }
typst-library = { path = "crates/typst-library", version = "0.14.1" }
typst-macros = { path = "crates/typst-macros", version = "0.14.1" }
typst-pdf = { path = "crates/typst-pdf", version = "0.14.1" }
typst-realize = { path = "crates/typst-realize", version = "0.14.1" }
typst-render = { path = "crates/typst-render", version = "0.14.1" }
typst-svg = { path = "crates/typst-svg", version = "0.14.1" }
typst-syntax = { path = "crates/typst-syntax", version = "0.14.1" }
typst-timing = { path = "crates/typst-timing", version = "0.14.1" }
typst-utils = { path = "crates/typst-utils", version = "0.14.1" }
typst-assets = "0.14.1"
typst-dev-assets = { git = "https://github.com/typst/typst-dev-assets", tag = "v0.14.1" }
arrayvec = "0.7.4"
az = "1.2"
base64 = "0.22"
Expand Down Expand Up @@ -77,8 +77,8 @@ image = { version = "0.25.5", default-features = false, features = ["png", "jpeg
indexmap = { version = "2", features = ["serde"] }
infer = { version = "0.19.0", default-features = false }
kamadak-exif = "0.6"
krilla = { version = "0.5.0", default-features = false, features = ["raster-images", "comemo", "rayon", "pdf"] }
krilla-svg = "0.2"
krilla = { version = "0.6.0", default-features = false, features = ["raster-images", "comemo", "rayon", "pdf"] }
krilla-svg = "0.3.0"
kurbo = "0.12"
libfuzzer-sys = "0.4"
lipsum = "0.9"
Expand Down Expand Up @@ -141,7 +141,7 @@ ureq = { version = "2", default-features = false, features = ["native-tls", "gzi
usvg = { version = "0.45", default-features = false, features = ["text"] }
utf8_iter = "1.0.4"
walkdir = "2"
wasmi = { version = "0.51.0", default-features = false, features = ["simd"] }
wasmi = { version = "0.51.2", default-features = false, features = ["simd"] }
web-sys = "0.3"
xmlparser = "0.13.5"
xmlwriter = "0.1.0"
Expand Down
10 changes: 7 additions & 3 deletions crates/typst-cli/src/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fn write_deps_make(
dest: &Output,
outputs: &[Output],
) -> io::Result<()> {
let mut dest = dest.open()?;
let mut buffer = Vec::new();
for (i, output) in outputs.iter().enumerate() {
let path = match output {
Output::Path(path) => path.as_os_str(),
Expand All @@ -82,10 +82,14 @@ fn write_deps_make(
// processed.
let Some(string) = path.to_str() else { continue };
if i != 0 {
dest.write_all(b" ")?;
buffer.write_all(b" ")?;
}
dest.write_all(munge(string).as_bytes())?;
buffer.write_all(munge(string).as_bytes())?;
}

// Only create the deps file in case of valid output paths.
let mut dest = dest.open()?;
dest.write_all(&buffer)?;
dest.write_all(b":")?;

for dep in relative_dependencies(world)? {
Expand Down
33 changes: 25 additions & 8 deletions crates/typst-html/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use typst_library::foundations::{
Content, Context, NativeElement, NativeRuleMap, ShowFn, Smart, StyleChain, Target,
};
use typst_library::introspection::Counter;
use typst_library::layout::resolve::{Cell, CellGrid, Entry};
use typst_library::layout::resolve::{Cell, CellGrid, Entry, Header};
use typst_library::layout::{
BlockBody, BlockElem, BoxElem, HElem, OuterVAlignment, Sizing,
};
Expand Down Expand Up @@ -563,26 +563,42 @@ fn show_cellgrid(grid: &CellGrid, styles: StyleChain) -> Content {
// TODO(subfooters): similarly to headers, take consecutive footers from
// the end for 'tfoot'.
let footer = grid.footer.as_ref().map(|ft| {
let rows = rows.drain(ft.start..);
// Convert from gutter to non-gutter coordinates. Use ceil as it might
// include the previous gutter row
// (cf. typst-library/layout/grid/resolve.rs).
let footer_start = if grid.has_gutter { ft.start.div_ceil(2) } else { ft.start };
let rows = rows.drain(footer_start..);
elem(tag::tfoot, Content::sequence(rows.map(|row| tr(tag::td, row))))
});

// Header range converting from gutter (doubled) to non-gutter coordinates.
let header_range = |hd: &Header| {
if grid.has_gutter {
// Use ceil as it might be `2 * row_amount - 1` if the header is at
// the end (cf. typst-library/layout/grid/resolve.rs).
hd.range.start / 2..hd.range.end.div_ceil(2)
} else {
hd.range.clone()
}
};

// Store all consecutive headers at the start in 'thead'. All remaining
// headers are just 'th' rows across the table body.
let mut consecutive_header_end = 0;
let first_mid_table_header = grid
.headers
.iter()
.take_while(|hd| {
let is_consecutive = hd.range.start == consecutive_header_end;
consecutive_header_end = hd.range.end;
let range = header_range(hd);
let is_consecutive = range.start == consecutive_header_end;
consecutive_header_end = range.end;
is_consecutive
})
.count();

let (y_offset, header) = if first_mid_table_header > 0 {
let removed_header_rows =
grid.headers.get(first_mid_table_header - 1).unwrap().range.end;
header_range(grid.headers.get(first_mid_table_header - 1).unwrap()).end;
let rows = rows.drain(..removed_header_rows);

(
Expand All @@ -601,10 +617,11 @@ fn show_cellgrid(grid: &CellGrid, styles: StyleChain) -> Content {
let mut body =
Content::sequence(rows.into_iter().enumerate().map(|(relative_y, row)| {
let y = relative_y + y_offset;
if let Some(current_header) =
grid.headers.get(next_header).filter(|h| h.range.contains(&y))
if let Some(current_header_range) =
grid.headers.get(next_header).map(|h| header_range(h))
&& current_header_range.contains(&y)
{
if y + 1 == current_header.range.end {
if y + 1 == current_header_range.end {
next_header += 1;
}

Expand Down
9 changes: 4 additions & 5 deletions crates/typst-layout/src/inline/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ fn collect_items<'a>(

// Add fallback text to expand the line height, if necessary.
if !items.iter().any(|item| matches!(item, Item::Text(_)))
&& let Some(fallback) = fallback
&& let Some((idx, fallback)) = fallback
{
items.push(fallback, LogicalIndex::FALLBACK_TEXT);
items.push(fallback, idx);
}
}

Expand Down Expand Up @@ -287,7 +287,7 @@ fn collect_range<'a>(
range: Range,
trim: &Trim,
items: &mut Items<'a>,
fallback: &mut Option<ItemEntry<'a>>,
fallback: &mut Option<(LogicalIndex, ItemEntry<'a>)>,
) {
for (i, (subrange, item)) in p.slice(range.clone()) {
let idx = LogicalIndex::from_item_index(i);
Expand All @@ -310,7 +310,7 @@ fn collect_range<'a>(
// When there is no text, still keep this as a fallback item, which
// we can use to force a non-zero line-height when the line doesn't
// contain any other text.
*fallback = Some(ItemEntry::from(Item::Text(shaped.empty())));
*fallback = Some((idx, ItemEntry::from(Item::Text(shaped.empty()))));
continue;
}

Expand Down Expand Up @@ -782,7 +782,6 @@ pub struct LogicalIndex(usize);

impl LogicalIndex {
const START_HYPHEN: Self = Self(0);
const FALLBACK_TEXT: Self = Self(usize::MAX - 1);
const END_HYPHEN: Self = Self(usize::MAX);

/// Create a logical index from the index of an item in the [`p.items`](Preparation::items).
Expand Down
18 changes: 9 additions & 9 deletions crates/typst-layout/src/inline/shaping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1100,17 +1100,17 @@ fn determine_shift(
// "subs"/"sups" to the feature list if supported by the font.
// In case of a problem, we just early exit
let gsub = font.rusty().tables().gsub?;
let subtable_index =
gsub.features.find(settings.kind.feature())?.lookup_indices.get(0)?;
let coverage = gsub
.lookups
.get(subtable_index)?
.subtables
.get::<SubstitutionSubtable>(0)?
.coverage();
let lookups = gsub.features.find(settings.kind.feature())?.lookup_indices;
text.chars()
.all(|c| {
font.rusty().glyph_index(c).is_some_and(|i| coverage.contains(i))
let Some(i) = font.rusty().glyph_index(c) else { return false };
lookups
.into_iter()
.flat_map(|i| gsub.lookups.get(i))
.flat_map(|lookup| {
lookup.subtables.into_iter::<SubstitutionSubtable>()
})
.any(|subtable| subtable.coverage().contains(i))
})
.then(|| {
// If we can use the OpenType feature, we can keep the text
Expand Down
11 changes: 10 additions & 1 deletion crates/typst-layout/src/math/fragment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,16 @@ fn assemble(
}

match axis {
Axis::X => base.size.x = full,
Axis::X => {
base.size.x = full;
let (ascent, descent) = glyphs
.iter()
.filter_map(|glyph| ascent_descent(&base.item.font, GlyphId(glyph.id)))
.reduce(|(ma, md), (a, d)| (ma.max(a), md.max(d)))
.unwrap_or((Em::zero(), Em::zero()));
base.baseline = Some(ascent.at(base.item.size));
base.size.y = (ascent + descent).at(base.item.size);
}
Axis::Y => {
base.baseline = None;
base.size.y = full;
Expand Down
3 changes: 3 additions & 0 deletions crates/typst-layout/src/math/mat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use typst_library::math::{Augment, AugmentOffsets, CasesElem, MatElem, VecElem};
use typst_library::text::TextElem;
use typst_library::visualize::{FillRule, FixedStroke, Geometry, LineCap, Shape};
use typst_syntax::Span;
use unicode_math_class::MathClass;

use super::{
AlignmentResult, DELIM_SHORT_FALL, FrameFragment, GlyphFragment, LeftRightAlternator,
Expand Down Expand Up @@ -348,6 +349,7 @@ fn layout_delimiters(
ctx.layout_into_fragment(&SymbolElem::packed(left_c).spanned(span), styles)?;
left.stretch_vertical(ctx, target, short_fall);
left.center_on_axis();
left.set_class(MathClass::Opening);
ctx.push(left);
}

Expand All @@ -358,6 +360,7 @@ fn layout_delimiters(
ctx.layout_into_fragment(&SymbolElem::packed(right_c).spanned(span), styles)?;
right.stretch_vertical(ctx, target, short_fall);
right.center_on_axis();
right.set_class(MathClass::Closing);
ctx.push(right);
}

Expand Down
4 changes: 1 addition & 3 deletions crates/typst-layout/src/math/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ fn layout_inline_text(
.chars()
.flat_map(|c| to_style(c, MathStyle::select(c, variant, bold, italic)))
.collect();

let spaced = styled_text.graphemes(true).nth(1).is_some();
let elem = TextElem::packed(styled_text).spanned(span);

// There isn't a natural width for a paragraph in a math environment;
Expand All @@ -118,7 +116,7 @@ fn layout_inline_text(
Ok(FrameFragment::new(styles, frame)
.with_class(MathClass::Alphabetic)
.with_text_like(true)
.with_spaced(spaced))
.with_spaced(true))
}
}

Expand Down
53 changes: 53 additions & 0 deletions crates/typst-library/src/diag.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Diagnostics.

use std::backtrace::{Backtrace, BacktraceStatus};
use std::fmt::{self, Display, Formatter, Write as _};
use std::io;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -868,3 +869,55 @@ pub fn format_xml_like_error(format: &str, error: roxmltree::Error) -> LoadError

LoadError { pos: pos.into(), message }
}

/// Asserts a condition, generating an internal compiler error with the provided
/// message on failure.
#[track_caller]
pub fn assert_internal(cond: bool, msg: &str) -> HintedStrResult<()> {
if !cond { Err(internal_error(msg)) } else { Ok(()) }
}

/// Generates an internal compiler error with the provided message.
#[track_caller]
pub fn panic_internal(msg: &str) -> HintedStrResult<()> {
Err(internal_error(msg))
}

/// Adds a method analogous to [`Option::expect`] that raises an internal
/// compiler error instead of panicking.
pub trait ExpectInternal<T> {
/// Extracts the value, producing an internal error if `self` is `None`.
fn expect_internal(self, msg: &str) -> HintedStrResult<T>;
}

impl<T> ExpectInternal<T> for Option<T> {
#[track_caller]
fn expect_internal(self, msg: &str) -> HintedStrResult<T> {
match self {
Some(val) => Ok(val),
None => Err(internal_error(msg)),
}
}
}

/// The shared internal implementation of [`assert_internal`] and
/// [`expect_internal`].
#[track_caller]
fn internal_error(msg: &str) -> HintedString {
let loc = std::panic::Location::caller();
let mut error = error!(
"internal error: {msg} (occurred at {loc})";
hint: "please report this as a bug"
);

if cfg!(debug_assertions) {
let backtrace = Backtrace::capture();
if backtrace.status() == BacktraceStatus::Captured {
error.hint(eco_format!("compiler backtrace:\n{backtrace}"));
} else {
error.hint("set `RUST_BACKTRACE` to `1` or `full` to capture a backtrace");
}
}

error
}
Loading
Loading