mirror of
https://github.com/typst/typst
synced 2025-07-01 17:52:52 +08:00
add Deref to Repeatable
honestly, all the unwrapping was just generating noise.
This commit is contained in:
parent
9a01b9bfe8
commit
71ae276071
@ -238,9 +238,9 @@ impl<'a> GridLayouter<'a> {
|
|||||||
while y < self.grid.rows.len() {
|
while y < self.grid.rows.len() {
|
||||||
if let Some(next_header) = self.upcoming_headers.get(consecutive_header_count)
|
if let Some(next_header) = self.upcoming_headers.get(consecutive_header_count)
|
||||||
{
|
{
|
||||||
if next_header.unwrap().range().contains(&y) {
|
if next_header.range().contains(&y) {
|
||||||
self.place_new_headers(&mut consecutive_header_count, engine)?;
|
self.place_new_headers(&mut consecutive_header_count, engine)?;
|
||||||
y = next_header.unwrap().end;
|
y = next_header.end;
|
||||||
|
|
||||||
// Skip header rows during normal layout.
|
// Skip header rows during normal layout.
|
||||||
continue;
|
continue;
|
||||||
|
@ -18,9 +18,8 @@ impl<'a> GridLayouter<'a> {
|
|||||||
|
|
||||||
if new_upcoming_headers.first().is_some_and(|next_header| {
|
if new_upcoming_headers.first().is_some_and(|next_header| {
|
||||||
consecutive_headers.last().is_none_or(|latest_header| {
|
consecutive_headers.last().is_none_or(|latest_header| {
|
||||||
!latest_header.unwrap().short_lived
|
!latest_header.short_lived && next_header.start == latest_header.end
|
||||||
&& next_header.unwrap().start == latest_header.unwrap().end
|
}) && !next_header.short_lived
|
||||||
}) && !next_header.unwrap().short_lived
|
|
||||||
}) {
|
}) {
|
||||||
// More headers coming, so wait until we reach them.
|
// More headers coming, so wait until we reach them.
|
||||||
// TODO: refactor
|
// TODO: refactor
|
||||||
@ -31,7 +30,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
*consecutive_header_count = 0;
|
*consecutive_header_count = 0;
|
||||||
|
|
||||||
// Layout short-lived headers immediately.
|
// Layout short-lived headers immediately.
|
||||||
if consecutive_headers.last().is_some_and(|h| h.unwrap().short_lived) {
|
if consecutive_headers.last().is_some_and(|h| h.short_lived) {
|
||||||
// No chance of orphans as we're immediately placing conflicting
|
// No chance of orphans as we're immediately placing conflicting
|
||||||
// headers afterwards, which basically are not headers, for all intents
|
// headers afterwards, which basically are not headers, for all intents
|
||||||
// and purposes. It is therefore guaranteed that all new headers have
|
// and purposes. It is therefore guaranteed that all new headers have
|
||||||
@ -104,7 +103,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
|
|
||||||
// Assuming non-conflicting headers sorted by increasing y, this must
|
// Assuming non-conflicting headers sorted by increasing y, this must
|
||||||
// be the header with the lowest level (sorted by increasing levels).
|
// be the header with the lowest level (sorted by increasing levels).
|
||||||
let first_level = first_header.unwrap().level;
|
let first_level = first_header.level;
|
||||||
|
|
||||||
// Stop repeating conflicting headers.
|
// Stop repeating conflicting headers.
|
||||||
// If we go to a new region before the pending headers fit alongside
|
// If we go to a new region before the pending headers fit alongside
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::num::{NonZeroU32, NonZeroUsize};
|
use std::num::{NonZeroU32, NonZeroUsize};
|
||||||
use std::ops::Range;
|
use std::ops::{Deref, Range};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use ecow::eco_format;
|
use ecow::eco_format;
|
||||||
@ -487,6 +487,14 @@ pub enum Repeatable<T> {
|
|||||||
NotRepeated(T),
|
NotRepeated(T),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Deref for Repeatable<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Repeatable<T> {
|
impl<T> Repeatable<T> {
|
||||||
/// Gets the value inside this repeatable, regardless of whether
|
/// Gets the value inside this repeatable, regardless of whether
|
||||||
/// it repeats.
|
/// it repeats.
|
||||||
@ -1562,10 +1570,10 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
let mut consecutive_header_start = data.start;
|
let mut consecutive_header_start = data.start;
|
||||||
for conflicting_header in
|
for conflicting_header in
|
||||||
headers.iter_mut().rev().take_while(move |h| {
|
headers.iter_mut().rev().take_while(move |h| {
|
||||||
let conflicts = h.unwrap().end == consecutive_header_start
|
let conflicts = h.end == consecutive_header_start
|
||||||
&& h.unwrap().level >= data.level;
|
&& h.level >= data.level;
|
||||||
|
|
||||||
consecutive_header_start = h.unwrap().start;
|
consecutive_header_start = h.start;
|
||||||
conflicts
|
conflicts
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
@ -1818,8 +1826,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
|
|
||||||
// TODO: will need a global slice of headers and footers for
|
// TODO: will need a global slice of headers and footers for
|
||||||
// when we have multiple footers
|
// when we have multiple footers
|
||||||
let last_header_end =
|
let last_header_end = headers.last().map(|header| header.end);
|
||||||
headers.last().map(Repeatable::unwrap).map(|header| header.end);
|
|
||||||
|
|
||||||
if has_gutter {
|
if has_gutter {
|
||||||
// Convert the footer's start index to post-gutter coordinates.
|
// Convert the footer's start index to post-gutter coordinates.
|
||||||
@ -1860,11 +1867,11 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
// final footer, as short lived, given that there are no normal rows
|
// final footer, as short lived, given that there are no normal rows
|
||||||
// after them, so repeating them is pointless.
|
// after them, so repeating them is pointless.
|
||||||
let mut consecutive_header_start =
|
let mut consecutive_header_start =
|
||||||
footer.as_ref().map(|f| f.unwrap().start).unwrap_or(row_amount);
|
footer.as_ref().map(|f| f.start).unwrap_or(row_amount);
|
||||||
for header_at_the_end in headers.iter_mut().rev().take_while(move |h| {
|
for header_at_the_end in headers.iter_mut().rev().take_while(move |h| {
|
||||||
let at_the_end = h.unwrap().end == consecutive_header_start;
|
let at_the_end = h.end == consecutive_header_start;
|
||||||
|
|
||||||
consecutive_header_start = h.unwrap().start;
|
consecutive_header_start = h.start;
|
||||||
at_the_end
|
at_the_end
|
||||||
}) {
|
}) {
|
||||||
header_at_the_end.unwrap_mut().short_lived = true;
|
header_at_the_end.unwrap_mut().short_lived = true;
|
||||||
@ -2052,9 +2059,10 @@ fn check_for_conflicting_cell_row(
|
|||||||
// `y + 1 = header.start` holds, that means `y < header.start`, and it
|
// `y + 1 = header.start` holds, that means `y < header.start`, and it
|
||||||
// only occupies one row (`y`), so the cell is actually not in
|
// only occupies one row (`y`), so the cell is actually not in
|
||||||
// conflict.
|
// conflict.
|
||||||
if headers.iter().any(|header| {
|
if headers
|
||||||
cell_y < header.unwrap().end && cell_y + rowspan > header.unwrap().start
|
.iter()
|
||||||
}) {
|
.any(|header| cell_y < header.end && cell_y + rowspan > header.start)
|
||||||
|
{
|
||||||
bail!(
|
bail!(
|
||||||
"cell would conflict with header spanning the same position";
|
"cell would conflict with header spanning the same position";
|
||||||
hint: "try moving the cell or the header"
|
hint: "try moving the cell or the header"
|
||||||
@ -2248,11 +2256,9 @@ fn find_next_available_position<const SKIP_ROWS: bool>(
|
|||||||
}
|
}
|
||||||
// TODO: consider keeping vector of upcoming headers to make this check
|
// TODO: consider keeping vector of upcoming headers to make this check
|
||||||
// non-quadratic (O(cells) instead of O(headers * cells)).
|
// non-quadratic (O(cells) instead of O(headers * cells)).
|
||||||
} else if let Some(header) =
|
} else if let Some(header) = headers.iter().find(|header| {
|
||||||
headers.iter().map(Repeatable::unwrap).find(|header| {
|
(header.start * columns..header.end * columns).contains(&resolved_index)
|
||||||
(header.start * columns..header.end * columns).contains(&resolved_index)
|
}) {
|
||||||
})
|
|
||||||
{
|
|
||||||
// Skip header (can't place a cell inside it from outside it).
|
// Skip header (can't place a cell inside it from outside it).
|
||||||
resolved_index = header.end * columns;
|
resolved_index = header.end * columns;
|
||||||
|
|
||||||
|
@ -293,13 +293,13 @@ fn show_cellgrid_html(grid: CellGrid, styles: StyleChain) -> Content {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let footer = grid.footer.map(|ft| {
|
let footer = grid.footer.map(|ft| {
|
||||||
let rows = rows.drain(ft.unwrap().start..);
|
let rows = rows.drain(ft.start..);
|
||||||
elem(tag::tfoot, Content::sequence(rows.map(|row| tr(tag::td, row))))
|
elem(tag::tfoot, Content::sequence(rows.map(|row| tr(tag::td, row))))
|
||||||
});
|
});
|
||||||
// TODO: Headers and footers in arbitrary positions
|
// TODO: Headers and footers in arbitrary positions
|
||||||
// Right now, only those at either end are accepted
|
// Right now, only those at either end are accepted
|
||||||
let header = grid.headers.first().filter(|h| h.unwrap().start == 0).map(|hd| {
|
let header = grid.headers.first().filter(|h| h.start == 0).map(|hd| {
|
||||||
let rows = rows.drain(..hd.unwrap().end);
|
let rows = rows.drain(..hd.end);
|
||||||
elem(tag::thead, Content::sequence(rows.map(|row| tr(tag::th, row))))
|
elem(tag::thead, Content::sequence(rows.map(|row| tr(tag::th, row))))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user