mirror of
https://github.com/typst/typst
synced 2025-07-27 22:37:54 +08:00
Fix 2024 clippy warnings
This commit is contained in:
parent
4bbd4e195b
commit
c9c2315ad3
@ -162,7 +162,7 @@ impl<T> Bucket<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the current data in the bucket.
|
/// Retrieves the current data in the bucket.
|
||||||
fn get(&self) -> MutexGuard<T> {
|
fn get(&self) -> MutexGuard<'_, T> {
|
||||||
self.mutex.lock()
|
self.mutex.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,22 +361,20 @@ impl<T: Clone> SlotCell<T> {
|
|||||||
f: impl FnOnce(Vec<u8>, Option<T>) -> FileResult<T>,
|
f: impl FnOnce(Vec<u8>, Option<T>) -> FileResult<T>,
|
||||||
) -> FileResult<T> {
|
) -> FileResult<T> {
|
||||||
// If we accessed the file already in this compilation, retrieve it.
|
// If we accessed the file already in this compilation, retrieve it.
|
||||||
if mem::replace(&mut self.accessed, true) {
|
if mem::replace(&mut self.accessed, true)
|
||||||
if let Some(data) = &self.data {
|
&& let Some(data) = &self.data {
|
||||||
return data.clone();
|
return data.clone();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Read and hash the file.
|
// Read and hash the file.
|
||||||
let result = timed!("loading file", load());
|
let result = timed!("loading file", load());
|
||||||
let fingerprint = timed!("hashing file", typst::utils::hash128(&result));
|
let fingerprint = timed!("hashing file", typst::utils::hash128(&result));
|
||||||
|
|
||||||
// If the file contents didn't change, yield the old processed data.
|
// If the file contents didn't change, yield the old processed data.
|
||||||
if mem::replace(&mut self.fingerprint, fingerprint) == fingerprint {
|
if mem::replace(&mut self.fingerprint, fingerprint) == fingerprint
|
||||||
if let Some(data) = &self.data {
|
&& let Some(data) = &self.data {
|
||||||
return data.clone();
|
return data.clone();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let prev = self.data.take().and_then(Result::ok);
|
let prev = self.data.take().and_then(Result::ok);
|
||||||
let value = result.and_then(|data| f(data, prev));
|
let value = result.and_then(|data| f(data, prev));
|
||||||
|
@ -29,11 +29,10 @@ impl Access for ast::Expr<'_> {
|
|||||||
impl Access for ast::Ident<'_> {
|
impl Access for ast::Ident<'_> {
|
||||||
fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
|
fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
|
||||||
let span = self.span();
|
let span = self.span();
|
||||||
if vm.inspected == Some(span) {
|
if vm.inspected == Some(span)
|
||||||
if let Ok(binding) = vm.scopes.get(&self) {
|
&& let Ok(binding) = vm.scopes.get(&self) {
|
||||||
vm.trace(binding.read().clone());
|
vm.trace(binding.read().clone());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
vm.scopes
|
vm.scopes
|
||||||
.get_mut(&self)
|
.get_mut(&self)
|
||||||
.and_then(|b| b.write().map_err(Into::into))
|
.and_then(|b| b.write().map_err(Into::into))
|
||||||
|
@ -46,15 +46,14 @@ impl Eval for ast::ModuleImport<'_> {
|
|||||||
// If there is a rename, import the source itself under that name.
|
// If there is a rename, import the source itself under that name.
|
||||||
let new_name = self.new_name();
|
let new_name = self.new_name();
|
||||||
if let Some(new_name) = new_name {
|
if let Some(new_name) = new_name {
|
||||||
if let ast::Expr::Ident(ident) = self.source() {
|
if let ast::Expr::Ident(ident) = self.source()
|
||||||
if ident.as_str() == new_name.as_str() {
|
&& ident.as_str() == new_name.as_str() {
|
||||||
// Warn on `import x as x`
|
// Warn on `import x as x`
|
||||||
vm.engine.sink.warn(warning!(
|
vm.engine.sink.warn(warning!(
|
||||||
new_name.span(),
|
new_name.span(),
|
||||||
"unnecessary import rename to same name",
|
"unnecessary import rename to same name",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Define renamed module on the scope.
|
// Define renamed module on the scope.
|
||||||
vm.define(new_name, source.clone());
|
vm.define(new_name, source.clone());
|
||||||
@ -142,8 +141,8 @@ impl Eval for ast::ModuleImport<'_> {
|
|||||||
// it.
|
// it.
|
||||||
|
|
||||||
// Warn on `import ...: x as x`
|
// Warn on `import ...: x as x`
|
||||||
if let ast::ImportItem::Renamed(renamed_item) = &item {
|
if let ast::ImportItem::Renamed(renamed_item) = &item
|
||||||
if renamed_item.original_name().as_str()
|
&& renamed_item.original_name().as_str()
|
||||||
== renamed_item.new_name().as_str()
|
== renamed_item.new_name().as_str()
|
||||||
{
|
{
|
||||||
vm.engine.sink.warn(warning!(
|
vm.engine.sink.warn(warning!(
|
||||||
@ -151,7 +150,6 @@ impl Eval for ast::ModuleImport<'_> {
|
|||||||
"unnecessary import rename to same name",
|
"unnecessary import rename to same name",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
vm.bind(item.bound_name(), binding.clone());
|
vm.bind(item.bound_name(), binding.clone());
|
||||||
}
|
}
|
||||||
|
@ -76,13 +76,12 @@ fn apply_assignment(
|
|||||||
|
|
||||||
// An assignment to a dictionary field is different from a normal access
|
// An assignment to a dictionary field is different from a normal access
|
||||||
// since it can create the field instead of just modifying it.
|
// since it can create the field instead of just modifying it.
|
||||||
if binary.op() == ast::BinOp::Assign {
|
if binary.op() == ast::BinOp::Assign
|
||||||
if let ast::Expr::FieldAccess(access) = lhs {
|
&& let ast::Expr::FieldAccess(access) = lhs {
|
||||||
let dict = access_dict(vm, access)?;
|
let dict = access_dict(vm, access)?;
|
||||||
dict.insert(access.field().get().clone().into(), rhs);
|
dict.insert(access.field().get().clone().into(), rhs);
|
||||||
return Ok(Value::None);
|
return Ok(Value::None);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let location = binary.lhs().access(vm)?;
|
let location = binary.lhs().access(vm)?;
|
||||||
let lhs = std::mem::take(&mut *location);
|
let lhs = std::mem::take(&mut *location);
|
||||||
|
@ -12,11 +12,10 @@ impl Eval for ast::SetRule<'_> {
|
|||||||
type Output = Styles;
|
type Output = Styles;
|
||||||
|
|
||||||
fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
if let Some(condition) = self.condition() {
|
if let Some(condition) = self.condition()
|
||||||
if !condition.eval(vm)?.cast::<bool>().at(condition.span())? {
|
&& !condition.eval(vm)?.cast::<bool>().at(condition.span())? {
|
||||||
return Ok(Styles::new());
|
return Ok(Styles::new());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let target = self.target();
|
let target = self.target();
|
||||||
let target = target
|
let target = target
|
||||||
|
@ -238,14 +238,12 @@ const QUOTE_RULE: ShowFn<QuoteElem> = |elem, _, styles| {
|
|||||||
|
|
||||||
if block {
|
if block {
|
||||||
let mut blockquote = HtmlElem::new(tag::blockquote).with_body(Some(realized));
|
let mut blockquote = HtmlElem::new(tag::blockquote).with_body(Some(realized));
|
||||||
if let Some(Attribution::Content(attribution)) = attribution {
|
if let Some(Attribution::Content(attribution)) = attribution
|
||||||
if let Some(link) = attribution.to_packed::<LinkElem>() {
|
&& let Some(link) = attribution.to_packed::<LinkElem>()
|
||||||
if let LinkTarget::Dest(Destination::Url(url)) = &link.dest {
|
&& let LinkTarget::Dest(Destination::Url(url)) = &link.dest {
|
||||||
blockquote =
|
blockquote =
|
||||||
blockquote.with_attr(attr::cite, url.clone().into_inner());
|
blockquote.with_attr(attr::cite, url.clone().into_inner());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
realized = blockquote.pack().spanned(span);
|
realized = blockquote.pack().spanned(span);
|
||||||
|
|
||||||
|
@ -27,17 +27,15 @@ pub fn analyze_expr(
|
|||||||
ast::Expr::Numeric(v) => Value::numeric(v.get()),
|
ast::Expr::Numeric(v) => Value::numeric(v.get()),
|
||||||
ast::Expr::Str(v) => Value::Str(v.get().into()),
|
ast::Expr::Str(v) => Value::Str(v.get().into()),
|
||||||
_ => {
|
_ => {
|
||||||
if node.kind() == SyntaxKind::Contextual {
|
if node.kind() == SyntaxKind::Contextual
|
||||||
if let Some(child) = node.children().next_back() {
|
&& let Some(child) = node.children().next_back() {
|
||||||
return analyze_expr(world, &child);
|
return analyze_expr(world, &child);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(parent) = node.parent() {
|
if let Some(parent) = node.parent()
|
||||||
if parent.kind() == SyntaxKind::FieldAccess && node.index() > 0 {
|
&& parent.kind() == SyntaxKind::FieldAccess && node.index() > 0 {
|
||||||
return analyze_expr(world, parent);
|
return analyze_expr(world, parent);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return typst::trace::<PagedDocument>(world.upcast(), node.span());
|
return typst::trace::<PagedDocument>(world.upcast(), node.span());
|
||||||
}
|
}
|
||||||
|
@ -1382,11 +1382,10 @@ impl<'a> CompletionContext<'a> {
|
|||||||
}
|
}
|
||||||
} else if at {
|
} else if at {
|
||||||
apply = Some(eco_format!("at(\"{label}\")"));
|
apply = Some(eco_format!("at(\"{label}\")"));
|
||||||
} else if label.starts_with('"') && self.after.starts_with('"') {
|
} else if label.starts_with('"') && self.after.starts_with('"')
|
||||||
if let Some(trimmed) = label.strip_suffix('"') {
|
&& let Some(trimmed) = label.strip_suffix('"') {
|
||||||
apply = Some(trimmed.into());
|
apply = Some(trimmed.into());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.completions.push(Completion {
|
self.completions.push(Completion {
|
||||||
kind: kind.unwrap_or_else(|| match value {
|
kind: kind.unwrap_or_else(|| match value {
|
||||||
|
@ -36,8 +36,8 @@ pub fn jump_from_click(
|
|||||||
) -> Option<Jump> {
|
) -> Option<Jump> {
|
||||||
// Try to find a link first.
|
// Try to find a link first.
|
||||||
for (pos, item) in frame.items() {
|
for (pos, item) in frame.items() {
|
||||||
if let FrameItem::Link(dest, size) = item {
|
if let FrameItem::Link(dest, size) = item
|
||||||
if is_in_rect(*pos, *size, click) {
|
&& is_in_rect(*pos, *size, click) {
|
||||||
return Some(match dest {
|
return Some(match dest {
|
||||||
Destination::Url(url) => Jump::Url(url.clone()),
|
Destination::Url(url) => Jump::Url(url.clone()),
|
||||||
Destination::Position(pos) => Jump::Position(*pos),
|
Destination::Position(pos) => Jump::Position(*pos),
|
||||||
@ -47,18 +47,16 @@ pub fn jump_from_click(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If there's no link, search for a jump target.
|
// If there's no link, search for a jump target.
|
||||||
for &(mut pos, ref item) in frame.items().rev() {
|
for &(mut pos, ref item) in frame.items().rev() {
|
||||||
match item {
|
match item {
|
||||||
FrameItem::Group(group) => {
|
FrameItem::Group(group) => {
|
||||||
let pos = click - pos;
|
let pos = click - pos;
|
||||||
if let Some(clip) = &group.clip {
|
if let Some(clip) = &group.clip
|
||||||
if !clip.contains(FillRule::NonZero, pos) {
|
&& !clip.contains(FillRule::NonZero, pos) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Realistic transforms should always be invertible.
|
// Realistic transforms should always be invertible.
|
||||||
// An example of one that isn't is a scale of 0, which would
|
// An example of one that isn't is a scale of 0, which would
|
||||||
// not be clickable anyway.
|
// not be clickable anyway.
|
||||||
@ -178,11 +176,10 @@ pub fn jump_from_cursor(
|
|||||||
/// Find the position of a span in a frame.
|
/// Find the position of a span in a frame.
|
||||||
fn find_in_frame(frame: &Frame, span: Span) -> Option<Point> {
|
fn find_in_frame(frame: &Frame, span: Span) -> Option<Point> {
|
||||||
for &(mut pos, ref item) in frame.items() {
|
for &(mut pos, ref item) in frame.items() {
|
||||||
if let FrameItem::Group(group) = item {
|
if let FrameItem::Group(group) = item
|
||||||
if let Some(point) = find_in_frame(&group.frame, span) {
|
&& let Some(point) = find_in_frame(&group.frame, span) {
|
||||||
return Some(pos + point.transform(group.transform));
|
return Some(pos + point.transform(group.transform));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let FrameItem::Text(text) = item {
|
if let FrameItem::Text(text) = item {
|
||||||
for glyph in &text.glyphs {
|
for glyph in &text.glyphs {
|
||||||
|
@ -59,11 +59,10 @@ pub fn named_items<T>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Seeing the module itself.
|
// Seeing the module itself.
|
||||||
if let Some((name, span)) = name_and_span {
|
if let Some((name, span)) = name_and_span
|
||||||
if let Some(res) = recv(NamedItem::Module(&name, span, module)) {
|
&& let Some(res) = recv(NamedItem::Module(&name, span, module)) {
|
||||||
return Some(res);
|
return Some(res);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Seeing the imported items.
|
// Seeing the imported items.
|
||||||
match imports {
|
match imports {
|
||||||
@ -124,8 +123,8 @@ pub fn named_items<T>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(parent) = node.parent() {
|
if let Some(parent) = node.parent() {
|
||||||
if let Some(v) = parent.cast::<ast::ForLoop>() {
|
if let Some(v) = parent.cast::<ast::ForLoop>()
|
||||||
if node.prev_sibling_kind() != Some(SyntaxKind::In) {
|
&& node.prev_sibling_kind() != Some(SyntaxKind::In) {
|
||||||
let pattern = v.pattern();
|
let pattern = v.pattern();
|
||||||
for ident in pattern.bindings() {
|
for ident in pattern.bindings() {
|
||||||
if let Some(res) = recv(NamedItem::Var(ident)) {
|
if let Some(res) = recv(NamedItem::Var(ident)) {
|
||||||
@ -133,7 +132,6 @@ pub fn named_items<T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(v) = parent.cast::<ast::Closure>().filter(|v| {
|
if let Some(v) = parent.cast::<ast::Closure>().filter(|v| {
|
||||||
// Check if the node is in the body of the closure.
|
// Check if the node is in the body of the closure.
|
||||||
@ -155,15 +153,14 @@ pub fn named_items<T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::Param::Spread(s) => {
|
ast::Param::Spread(s) => {
|
||||||
if let Some(sink_ident) = s.sink_ident() {
|
if let Some(sink_ident) = s.sink_ident()
|
||||||
if let Some(t) = recv(NamedItem::Var(sink_ident)) {
|
&& let Some(t) = recv(NamedItem::Var(sink_ident)) {
|
||||||
return Some(t);
|
return Some(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ancestor = Some(parent.clone());
|
ancestor = Some(parent.clone());
|
||||||
continue;
|
continue;
|
||||||
@ -216,7 +213,7 @@ impl<'a> NamedItem<'a> {
|
|||||||
|
|
||||||
/// Categorize an expression into common classes IDE functionality can operate
|
/// Categorize an expression into common classes IDE functionality can operate
|
||||||
/// on.
|
/// 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.
|
// Move to the first ancestor that is an expression.
|
||||||
let mut ancestor = node;
|
let mut ancestor = node;
|
||||||
while !ancestor.is::<ast::Expr>() {
|
while !ancestor.is::<ast::Expr>() {
|
||||||
|
@ -66,12 +66,11 @@ fn expr_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
|||||||
return Some(Tooltip::Text(plain_docs_sentence(docs)));
|
return Some(Tooltip::Text(plain_docs_sentence(docs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let &Value::Length(length) = value {
|
if let &Value::Length(length) = value
|
||||||
if let Some(tooltip) = length_tooltip(length) {
|
&& let Some(tooltip) = length_tooltip(length) {
|
||||||
return Some(tooltip);
|
return Some(tooltip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if expr.is_literal() {
|
if expr.is_literal() {
|
||||||
return None;
|
return None;
|
||||||
@ -93,11 +92,10 @@ fn expr_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
|||||||
last = Some((value, 1));
|
last = Some((value, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((_, count)) = last {
|
if let Some((_, count)) = last
|
||||||
if count > 1 {
|
&& count > 1 {
|
||||||
write!(pieces.last_mut().unwrap(), " (×{count})").unwrap();
|
write!(pieces.last_mut().unwrap(), " (×{count})").unwrap();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if iter.next().is_some() {
|
if iter.next().is_some() {
|
||||||
pieces.push("...".into());
|
pieces.push("...".into());
|
||||||
|
@ -407,11 +407,10 @@ fn distribute<'a>(
|
|||||||
// If there is still something remaining, apply it to the
|
// If there is still something remaining, apply it to the
|
||||||
// last region (it will overflow, but there's nothing else
|
// last region (it will overflow, but there's nothing else
|
||||||
// we can do).
|
// we can do).
|
||||||
if !remaining.approx_empty() {
|
if !remaining.approx_empty()
|
||||||
if let Some(last) = buf.last_mut() {
|
&& let Some(last) = buf.last_mut() {
|
||||||
*last += remaining;
|
*last += remaining;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Distribute the heights to the first region and the
|
// Distribute the heights to the first region and the
|
||||||
// backlog. There is no last region, since the height is
|
// backlog. There is no last region, since the height is
|
||||||
|
@ -684,11 +684,10 @@ impl<T> CachedCell<T> {
|
|||||||
let input_hash = typst_utils::hash128(&input);
|
let input_hash = typst_utils::hash128(&input);
|
||||||
|
|
||||||
let mut slot = self.0.borrow_mut();
|
let mut slot = self.0.borrow_mut();
|
||||||
if let Some((hash, output)) = &*slot {
|
if let Some((hash, output)) = &*slot
|
||||||
if *hash == input_hash {
|
&& *hash == input_hash {
|
||||||
return output.clone();
|
return output.clone();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let output = f(input);
|
let output = f(input);
|
||||||
*slot = Some((input_hash, output.clone()));
|
*slot = Some((input_hash, output.clone()));
|
||||||
|
@ -274,32 +274,29 @@ impl<'a> GridLayouter<'a> {
|
|||||||
pub fn layout(mut self, engine: &mut Engine) -> SourceResult<Fragment> {
|
pub fn layout(mut self, engine: &mut Engine) -> SourceResult<Fragment> {
|
||||||
self.measure_columns(engine)?;
|
self.measure_columns(engine)?;
|
||||||
|
|
||||||
if let Some(footer) = &self.grid.footer {
|
if let Some(footer) = &self.grid.footer
|
||||||
if footer.repeated {
|
&& footer.repeated {
|
||||||
// Ensure rows in the first region will be aware of the
|
// Ensure rows in the first region will be aware of the
|
||||||
// possible presence of the footer.
|
// possible presence of the footer.
|
||||||
self.prepare_footer(footer, engine, 0)?;
|
self.prepare_footer(footer, engine, 0)?;
|
||||||
self.regions.size.y -= self.current.footer_height;
|
self.regions.size.y -= self.current.footer_height;
|
||||||
self.current.initial_after_repeats = self.regions.size.y;
|
self.current.initial_after_repeats = self.regions.size.y;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut y = 0;
|
let mut y = 0;
|
||||||
let mut consecutive_header_count = 0;
|
let mut consecutive_header_count = 0;
|
||||||
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)
|
||||||
{
|
&& next_header.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.range.end;
|
y = next_header.range.end;
|
||||||
|
|
||||||
// Skip header rows during normal layout.
|
// Skip header rows during normal layout.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(footer) = &self.grid.footer {
|
if let Some(footer) = &self.grid.footer
|
||||||
if footer.repeated && y >= footer.start {
|
&& footer.repeated && y >= footer.start {
|
||||||
if y == footer.start {
|
if y == footer.start {
|
||||||
self.layout_footer(footer, engine, self.finished.len())?;
|
self.layout_footer(footer, engine, self.finished.len())?;
|
||||||
self.flush_orphans();
|
self.flush_orphans();
|
||||||
@ -307,7 +304,6 @@ impl<'a> GridLayouter<'a> {
|
|||||||
y = footer.end;
|
y = footer.end;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.layout_row(y, engine, 0)?;
|
self.layout_row(y, engine, 0)?;
|
||||||
|
|
||||||
@ -1283,15 +1279,13 @@ impl<'a> GridLayouter<'a> {
|
|||||||
// remeasure.
|
// remeasure.
|
||||||
if let Some([first, rest @ ..]) =
|
if let Some([first, rest @ ..]) =
|
||||||
frames.get(measurement_data.frames_in_previous_regions..)
|
frames.get(measurement_data.frames_in_previous_regions..)
|
||||||
{
|
&& can_skip
|
||||||
if can_skip
|
|
||||||
&& breakable
|
&& breakable
|
||||||
&& first.is_empty()
|
&& first.is_empty()
|
||||||
&& rest.iter().any(|frame| !frame.is_empty())
|
&& rest.iter().any(|frame| !frame.is_empty())
|
||||||
{
|
{
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Skip frames from previous regions if applicable.
|
// Skip frames from previous regions if applicable.
|
||||||
let mut sizes = frames
|
let mut sizes = frames
|
||||||
@ -1529,8 +1523,8 @@ impl<'a> GridLayouter<'a> {
|
|||||||
// The latest rows have orphan prevention (headers) and no other rows
|
// The latest rows have orphan prevention (headers) and no other rows
|
||||||
// were placed, so remove those rows and try again in a new region,
|
// were placed, so remove those rows and try again in a new region,
|
||||||
// unless this is the last region.
|
// unless this is the last region.
|
||||||
if let Some(orphan_snapshot) = self.current.lrows_orphan_snapshot.take() {
|
if let Some(orphan_snapshot) = self.current.lrows_orphan_snapshot.take()
|
||||||
if !last {
|
&& !last {
|
||||||
self.current.lrows.truncate(orphan_snapshot);
|
self.current.lrows.truncate(orphan_snapshot);
|
||||||
self.current.repeated_header_rows =
|
self.current.repeated_header_rows =
|
||||||
self.current.repeated_header_rows.min(orphan_snapshot);
|
self.current.repeated_header_rows.min(orphan_snapshot);
|
||||||
@ -1540,7 +1534,6 @@ impl<'a> GridLayouter<'a> {
|
|||||||
self.current.last_repeated_header_end = 0;
|
self.current.last_repeated_header_end = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.current
|
.current
|
||||||
@ -1571,8 +1564,8 @@ impl<'a> GridLayouter<'a> {
|
|||||||
&& self.current.could_progress_at_top;
|
&& self.current.could_progress_at_top;
|
||||||
|
|
||||||
let mut laid_out_footer_start = None;
|
let mut laid_out_footer_start = None;
|
||||||
if !footer_would_be_widow {
|
if !footer_would_be_widow
|
||||||
if let Some(footer) = &self.grid.footer {
|
&& let Some(footer) = &self.grid.footer {
|
||||||
// Don't layout the footer if it would be alone with the header
|
// 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
|
// in the page (hence the widow check), and don't layout it
|
||||||
// twice (check below).
|
// twice (check below).
|
||||||
@ -1587,7 +1580,6 @@ impl<'a> GridLayouter<'a> {
|
|||||||
self.layout_footer(footer, engine, self.finished.len())?;
|
self.layout_footer(footer, engine, self.finished.len())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the height of existing rows in the region.
|
// Determine the height of existing rows in the region.
|
||||||
let mut used = Abs::zero();
|
let mut used = Abs::zero();
|
||||||
|
@ -291,14 +291,13 @@ pub fn vline_stroke_at_row(
|
|||||||
// We would then analyze the cell one column after (if at a gutter
|
// 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
|
// 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.
|
// check if it would be merged with a cell before the vline.
|
||||||
if let Some(parent) = grid.effective_parent_cell_position(x, y) {
|
if let Some(parent) = grid.effective_parent_cell_position(x, y)
|
||||||
if parent.x < x {
|
&& parent.x < x {
|
||||||
// There is a colspan cell going through this vline's position,
|
// There is a colspan cell going through this vline's position,
|
||||||
// so don't draw it here.
|
// so don't draw it here.
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let (left_cell_stroke, left_cell_prioritized) = x
|
let (left_cell_stroke, left_cell_prioritized) = x
|
||||||
.checked_sub(1)
|
.checked_sub(1)
|
||||||
@ -416,8 +415,8 @@ pub fn hline_stroke_at_column(
|
|||||||
// We would then analyze the cell one column after (if at a gutter
|
// 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
|
// 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.
|
// check if it would be merged with a cell before the hline.
|
||||||
if let Some(parent) = grid.effective_parent_cell_position(x, y) {
|
if let Some(parent) = grid.effective_parent_cell_position(x, y)
|
||||||
if parent.y < y {
|
&& parent.y < y {
|
||||||
// Get the first 'y' spanned by the possible rowspan in this region.
|
// 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
|
// The 'parent.y' row and any other spanned rows above 'y' could be
|
||||||
// missing from this region, which could have lead the check above
|
// missing from this region, which could have lead the check above
|
||||||
@ -438,7 +437,6 @@ pub fn hline_stroke_at_column(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// When the hline is at the top of the region and this isn't the first
|
// When the hline is at the top of the region and this isn't the first
|
||||||
// region, fold with the top stroke of the topmost cell at this column,
|
// region, fold with the top stroke of the topmost cell at this column,
|
||||||
|
@ -240,8 +240,8 @@ impl<'a> GridLayouter<'a> {
|
|||||||
self.current.initial_after_repeats = self.regions.size.y;
|
self.current.initial_after_repeats = self.regions.size.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(footer) = &self.grid.footer {
|
if let Some(footer) = &self.grid.footer
|
||||||
if footer.repeated && skipped_region {
|
&& footer.repeated && skipped_region {
|
||||||
// Simulate the footer again; the region's 'full' might have
|
// Simulate the footer again; the region's 'full' might have
|
||||||
// changed.
|
// changed.
|
||||||
self.regions.size.y += self.current.footer_height;
|
self.regions.size.y += self.current.footer_height;
|
||||||
@ -250,7 +250,6 @@ impl<'a> GridLayouter<'a> {
|
|||||||
.height;
|
.height;
|
||||||
self.regions.size.y -= self.current.footer_height;
|
self.regions.size.y -= self.current.footer_height;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let repeating_header_rows =
|
let repeating_header_rows =
|
||||||
total_header_row_count(self.repeating_headers.iter().copied());
|
total_header_row_count(self.repeating_headers.iter().copied());
|
||||||
|
@ -238,8 +238,8 @@ impl GridLayouter<'_> {
|
|||||||
// current row is dynamic and depends on the amount of upcoming
|
// current row is dynamic and depends on the amount of upcoming
|
||||||
// unbreakable cells (with or without a rowspan setting).
|
// unbreakable cells (with or without a rowspan setting).
|
||||||
let mut amount_unbreakable_rows = None;
|
let mut amount_unbreakable_rows = None;
|
||||||
if let Some(footer) = &self.grid.footer {
|
if let Some(footer) = &self.grid.footer
|
||||||
if !footer.repeated && current_row >= footer.start {
|
&& !footer.repeated && current_row >= footer.start {
|
||||||
// Non-repeated footer, so keep it unbreakable.
|
// Non-repeated footer, so keep it unbreakable.
|
||||||
//
|
//
|
||||||
// TODO(subfooters): This will become unnecessary
|
// TODO(subfooters): This will become unnecessary
|
||||||
@ -247,7 +247,6 @@ impl GridLayouter<'_> {
|
|||||||
// have widow prevention.
|
// have widow prevention.
|
||||||
amount_unbreakable_rows = Some(self.grid.rows.len() - footer.start);
|
amount_unbreakable_rows = Some(self.grid.rows.len() - footer.start);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let row_group = self.simulate_unbreakable_row_group(
|
let row_group = self.simulate_unbreakable_row_group(
|
||||||
current_row,
|
current_row,
|
||||||
@ -1268,9 +1267,8 @@ fn subtract_end_sizes(sizes: &mut Vec<Abs>, mut subtract: Abs) {
|
|||||||
while subtract > Abs::zero() && sizes.last().is_some_and(|&size| size <= subtract) {
|
while subtract > Abs::zero() && sizes.last().is_some_and(|&size| size <= subtract) {
|
||||||
subtract -= sizes.pop().unwrap();
|
subtract -= sizes.pop().unwrap();
|
||||||
}
|
}
|
||||||
if subtract > Abs::zero() {
|
if subtract > Abs::zero()
|
||||||
if let Some(last_size) = sizes.last_mut() {
|
&& let Some(last_size) = sizes.last_mut() {
|
||||||
*last_size -= subtract;
|
*last_size -= subtract;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -274,12 +274,11 @@ impl<'a> Collector<'a> {
|
|||||||
let segment_len = self.full.len() - prev;
|
let segment_len = self.full.len() - prev;
|
||||||
|
|
||||||
// Merge adjacent text segments with the same styles.
|
// Merge adjacent text segments with the same styles.
|
||||||
if let Some(Segment::Text(last_len, last_styles)) = self.segments.last_mut() {
|
if let Some(Segment::Text(last_len, last_styles)) = self.segments.last_mut()
|
||||||
if *last_styles == styles {
|
&& *last_styles == styles {
|
||||||
*last_len += segment_len;
|
*last_len += segment_len;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.segments.push(Segment::Text(segment_len, styles));
|
self.segments.push(Segment::Text(segment_len, styles));
|
||||||
}
|
}
|
||||||
|
@ -155,18 +155,16 @@ pub fn line<'a>(
|
|||||||
let mut items = collect_items(engine, p, range, trim);
|
let mut items = collect_items(engine, p, range, trim);
|
||||||
|
|
||||||
// Add a hyphen at the line start, if a previous dash should be repeated.
|
// 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 pred.is_some_and(|pred| should_repeat_hyphen(pred, full))
|
||||||
if let Some(shaped) = items.first_text_mut() {
|
&& let Some(shaped) = items.first_text_mut() {
|
||||||
shaped.prepend_hyphen(engine, p.config.fallback);
|
shaped.prepend_hyphen(engine, p.config.fallback);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Add a hyphen at the line end, if we ended on a soft hyphen.
|
// Add a hyphen at the line end, if we ended on a soft hyphen.
|
||||||
if dash == Some(Dash::Soft) {
|
if dash == Some(Dash::Soft)
|
||||||
if let Some(shaped) = items.last_text_mut() {
|
&& let Some(shaped) = items.last_text_mut() {
|
||||||
shaped.push_hyphen(engine, p.config.fallback);
|
shaped.push_hyphen(engine, p.config.fallback);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Deal with CJ characters at line boundaries.
|
// Deal with CJ characters at line boundaries.
|
||||||
adjust_cj_at_line_boundaries(p, full, &mut items);
|
adjust_cj_at_line_boundaries(p, full, &mut items);
|
||||||
@ -218,11 +216,10 @@ fn collect_items<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add fallback text to expand the line height, if necessary.
|
// Add fallback text to expand the line height, if necessary.
|
||||||
if !items.iter().any(|item| matches!(item, Item::Text(_))) {
|
if !items.iter().any(|item| matches!(item, Item::Text(_)))
|
||||||
if let Some(fallback) = fallback {
|
&& let Some(fallback) = fallback {
|
||||||
items.push(fallback, usize::MAX);
|
items.push(fallback, usize::MAX);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
items
|
items
|
||||||
}
|
}
|
||||||
@ -461,9 +458,9 @@ pub fn commit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle hanging punctuation to the left.
|
// Handle hanging punctuation to the left.
|
||||||
if let Some(Item::Text(text)) = line.items.first() {
|
if let Some(Item::Text(text)) = line.items.first()
|
||||||
if let Some(glyph) = text.glyphs.first() {
|
&& let Some(glyph) = text.glyphs.first()
|
||||||
if !text.dir.is_positive()
|
&& !text.dir.is_positive()
|
||||||
&& text.styles.get(TextElem::overhang)
|
&& text.styles.get(TextElem::overhang)
|
||||||
&& (line.items.len() > 1 || text.glyphs.len() > 1)
|
&& (line.items.len() > 1 || text.glyphs.len() > 1)
|
||||||
{
|
{
|
||||||
@ -471,21 +468,17 @@ pub fn commit(
|
|||||||
offset -= amount;
|
offset -= amount;
|
||||||
remaining += amount;
|
remaining += amount;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle hanging punctuation to the right.
|
// Handle hanging punctuation to the right.
|
||||||
if let Some(Item::Text(text)) = line.items.last() {
|
if let Some(Item::Text(text)) = line.items.last()
|
||||||
if let Some(glyph) = text.glyphs.last() {
|
&& let Some(glyph) = text.glyphs.last()
|
||||||
if text.dir.is_positive()
|
&& text.dir.is_positive()
|
||||||
&& text.styles.get(TextElem::overhang)
|
&& text.styles.get(TextElem::overhang)
|
||||||
&& (line.items.len() > 1 || text.glyphs.len() > 1)
|
&& (line.items.len() > 1 || text.glyphs.len() > 1)
|
||||||
{
|
{
|
||||||
let amount = overhang(glyph.c) * glyph.x_advance.at(glyph.size);
|
let amount = overhang(glyph.c) * glyph.x_advance.at(glyph.size);
|
||||||
remaining += amount;
|
remaining += amount;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine how much additional space is needed. The justification_ratio is
|
// Determine how much additional space is needed. The justification_ratio is
|
||||||
// for the first step justification, extra_justification is for the last
|
// for the first step justification, extra_justification is for the last
|
||||||
|
@ -136,13 +136,12 @@ fn linebreak_simple<'a>(
|
|||||||
// If the line doesn't fit anymore, we push the last fitting attempt
|
// 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
|
// into the stack and rebuild the line from the attempt's end. The
|
||||||
// resulting line cannot be broken up further.
|
// resulting line cannot be broken up further.
|
||||||
if !width.fits(attempt.width) {
|
if !width.fits(attempt.width)
|
||||||
if let Some((last_attempt, last_end)) = last.take() {
|
&& let Some((last_attempt, last_end)) = last.take() {
|
||||||
lines.push(last_attempt);
|
lines.push(last_attempt);
|
||||||
start = last_end;
|
start = last_end;
|
||||||
attempt = line(engine, p, start..end, breakpoint, lines.last());
|
attempt = line(engine, p, start..end, breakpoint, lines.last());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Finish the current line if there is a mandatory line break (i.e. due
|
// Finish the current line if there is a mandatory line break (i.e. due
|
||||||
// to "\n") or if the line doesn't fit horizontally already since then
|
// to "\n") or if the line doesn't fit horizontally already since then
|
||||||
|
@ -681,7 +681,7 @@ fn min_connector_overlap(font: &Font) -> Option<Em> {
|
|||||||
.map(|variants| font.to_em(variants.min_connector_overlap))
|
.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()
|
font.ttf()
|
||||||
.tables()
|
.tables()
|
||||||
.math?
|
.math?
|
||||||
@ -810,7 +810,7 @@ fn assemble(
|
|||||||
|
|
||||||
/// Return an iterator over the assembly's parts with extenders repeated the
|
/// Return an iterator over the assembly's parts with extenders repeated the
|
||||||
/// specified number of times.
|
/// 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| {
|
assembly.parts.into_iter().flat_map(move |part| {
|
||||||
let count = if part.part_flags.extender() { repeat } else { 1 };
|
let count = if part.part_flags.extender() { repeat } else { 1 };
|
||||||
std::iter::repeat_n(part, count)
|
std::iter::repeat_n(part, count)
|
||||||
|
@ -21,11 +21,10 @@ pub fn layout_lr(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract implicit LrElem.
|
// Extract implicit LrElem.
|
||||||
if let Some(lr) = body.to_packed::<LrElem>() {
|
if let Some(lr) = body.to_packed::<LrElem>()
|
||||||
if lr.size.get(styles).is_one() {
|
&& lr.size.get(styles).is_one() {
|
||||||
body = &lr.body;
|
body = &lr.body;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut fragments = ctx.layout_into_fragments(body, styles)?;
|
let mut fragments = ctx.layout_into_fragments(body, styles)?;
|
||||||
|
|
||||||
@ -55,13 +54,12 @@ pub fn layout_lr(
|
|||||||
|
|
||||||
// Handle MathFragment::Glyph fragments that should be scaled up.
|
// Handle MathFragment::Glyph fragments that should be scaled up.
|
||||||
for fragment in inner_fragments.iter_mut() {
|
for fragment in inner_fragments.iter_mut() {
|
||||||
if let MathFragment::Glyph(glyph) = fragment {
|
if let MathFragment::Glyph(glyph) = fragment
|
||||||
if glyph.mid_stretched == Some(false) {
|
&& glyph.mid_stretched == Some(false) {
|
||||||
glyph.mid_stretched = Some(true);
|
glyph.mid_stretched = Some(true);
|
||||||
scale(ctx, fragment, relative_to, height);
|
scale(ctx, fragment, relative_to, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Remove weak SpacingFragment immediately after the opening or immediately
|
// Remove weak SpacingFragment immediately after the opening or immediately
|
||||||
// before the closing.
|
// before the closing.
|
||||||
|
@ -603,14 +603,13 @@ fn layout_h(
|
|||||||
ctx: &mut MathContext,
|
ctx: &mut MathContext,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> SourceResult<()> {
|
) -> SourceResult<()> {
|
||||||
if let Spacing::Rel(rel) = elem.amount {
|
if let Spacing::Rel(rel) = elem.amount
|
||||||
if rel.rel.is_zero() {
|
&& rel.rel.is_zero() {
|
||||||
ctx.push(MathFragment::Spacing(
|
ctx.push(MathFragment::Spacing(
|
||||||
rel.abs.resolve(styles),
|
rel.abs.resolve(styles),
|
||||||
elem.weak.get(styles),
|
elem.weak.get(styles),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,11 +87,10 @@ impl MathRun {
|
|||||||
|
|
||||||
// Insert spacing between the last and this non-ignorant item.
|
// Insert spacing between the last and this non-ignorant item.
|
||||||
if !fragment.is_ignorant() {
|
if !fragment.is_ignorant() {
|
||||||
if let Some(i) = last {
|
if let Some(i) = last
|
||||||
if let Some(s) = spacing(&resolved[i], space.take(), &fragment) {
|
&& let Some(s) = spacing(&resolved[i], space.take(), &fragment) {
|
||||||
resolved.insert(i + 1, s);
|
resolved.insert(i + 1, s);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
last = Some(resolved.len());
|
last = Some(resolved.len());
|
||||||
}
|
}
|
||||||
@ -123,11 +122,10 @@ impl MathRun {
|
|||||||
1 + self.0.iter().filter(|f| matches!(f, MathFragment::Linebreak)).count();
|
1 + self.0.iter().filter(|f| matches!(f, MathFragment::Linebreak)).count();
|
||||||
|
|
||||||
// A linebreak at the very end does not introduce an extra row.
|
// A linebreak at the very end does not introduce an extra row.
|
||||||
if let Some(f) = self.0.last() {
|
if let Some(f) = self.0.last()
|
||||||
if matches!(f, MathFragment::Linebreak) {
|
&& matches!(f, MathFragment::Linebreak) {
|
||||||
count -= 1
|
count -= 1
|
||||||
}
|
}
|
||||||
}
|
|
||||||
count
|
count
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,11 +342,10 @@ impl MathRun {
|
|||||||
descent = Abs::zero();
|
descent = Abs::zero();
|
||||||
|
|
||||||
space_is_visible = true;
|
space_is_visible = true;
|
||||||
if let Some(f_next) = iter.peek() {
|
if let Some(f_next) = iter.peek()
|
||||||
if !is_space(f_next) {
|
&& !is_space(f_next) {
|
||||||
items.push(InlineItem::Space(Abs::zero(), true));
|
items.push(InlineItem::Space(Abs::zero(), true));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
space_is_visible = false;
|
space_is_visible = false;
|
||||||
}
|
}
|
||||||
|
@ -296,14 +296,13 @@ impl<T> Trace<T> for SourceResult<T> {
|
|||||||
let Some(trace_range) = world.range(span) else { return errors };
|
let Some(trace_range) = world.range(span) else { return errors };
|
||||||
for error in errors.make_mut().iter_mut() {
|
for error in errors.make_mut().iter_mut() {
|
||||||
// Skip traces that surround the error.
|
// Skip traces that surround the error.
|
||||||
if let Some(error_range) = world.range(error.span) {
|
if let Some(error_range) = world.range(error.span)
|
||||||
if error.span.id() == span.id()
|
&& error.span.id() == span.id()
|
||||||
&& trace_range.start <= error_range.start
|
&& trace_range.start <= error_range.start
|
||||||
&& trace_range.end >= error_range.end
|
&& trace_range.end >= error_range.end
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
error.trace.push(Spanned::new(make_point(), span));
|
error.trace.push(Spanned::new(make_point(), span));
|
||||||
}
|
}
|
||||||
|
@ -347,14 +347,13 @@ impl CastInfo {
|
|||||||
msg.hint(eco_format!("use `label({})` to create a label", s.repr()));
|
msg.hint(eco_format!("use `label({})` to create a label", s.repr()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Value::Decimal(_) = found {
|
} else if let Value::Decimal(_) = found
|
||||||
if !matching_type && parts.iter().any(|p| p == "float") {
|
&& !matching_type && parts.iter().any(|p| p == "float") {
|
||||||
msg.hint(eco_format!(
|
msg.hint(eco_format!(
|
||||||
"if loss of precision is acceptable, explicitly cast the \
|
"if loss of precision is acceptable, explicitly cast the \
|
||||||
decimal to a float with `float(value)`"
|
decimal to a float with `float(value)`"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
msg
|
msg
|
||||||
}
|
}
|
||||||
|
@ -174,11 +174,10 @@ impl Content {
|
|||||||
id: u8,
|
id: u8,
|
||||||
styles: Option<StyleChain>,
|
styles: Option<StyleChain>,
|
||||||
) -> Result<Value, FieldAccessError> {
|
) -> Result<Value, FieldAccessError> {
|
||||||
if id == 255 {
|
if id == 255
|
||||||
if let Some(label) = self.label() {
|
&& let Some(label) = self.label() {
|
||||||
return Ok(label.into_value());
|
return Ok(label.into_value());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
match self.0.handle().field(id) {
|
match self.0.handle().field(id) {
|
||||||
Some(handle) => match styles {
|
Some(handle) => match styles {
|
||||||
|
@ -150,11 +150,10 @@ where
|
|||||||
T: PartialEq + IntoValue,
|
T: PartialEq + IntoValue,
|
||||||
{
|
{
|
||||||
fn into_value(self) -> Value {
|
fn into_value(self) -> Value {
|
||||||
if self.is_uniform() {
|
if self.is_uniform()
|
||||||
if let Some(top_left) = self.top_left {
|
&& let Some(top_left) = self.top_left {
|
||||||
return top_left.into_value();
|
return top_left.into_value();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut dict = Dict::new();
|
let mut dict = Dict::new();
|
||||||
let mut handle = |key: &str, component: Option<T>| {
|
let mut handle = |key: &str, component: Option<T>| {
|
||||||
|
@ -2098,14 +2098,13 @@ fn check_for_conflicting_cell_row(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((_, _, footer)) = footer {
|
if let Some((_, _, footer)) = footer
|
||||||
if cell_y < footer.end && cell_y + rowspan > footer.start {
|
&& cell_y < footer.end && cell_y + rowspan > footer.start {
|
||||||
bail!(
|
bail!(
|
||||||
"cell would conflict with footer spanning the same position";
|
"cell would conflict with footer spanning the same position";
|
||||||
hint: "try reducing the cell's rowspan or moving the footer"
|
hint: "try reducing the cell's rowspan or moving the footer"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -530,11 +530,10 @@ cast! {
|
|||||||
Margin,
|
Margin,
|
||||||
self => {
|
self => {
|
||||||
let two_sided = self.two_sided.unwrap_or(false);
|
let two_sided = self.two_sided.unwrap_or(false);
|
||||||
if !two_sided && self.sides.is_uniform() {
|
if !two_sided && self.sides.is_uniform()
|
||||||
if let Some(left) = self.sides.left {
|
&& let Some(left) = self.sides.left {
|
||||||
return left.into_value();
|
return left.into_value();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut dict = Dict::new();
|
let mut dict = Dict::new();
|
||||||
let mut handle = |key: &str, component: Option<Smart<Rel<Length>>>| {
|
let mut handle = |key: &str, component: Option<Smart<Rel<Length>>>| {
|
||||||
|
@ -184,11 +184,10 @@ where
|
|||||||
T: PartialEq + IntoValue,
|
T: PartialEq + IntoValue,
|
||||||
{
|
{
|
||||||
fn into_value(self) -> Value {
|
fn into_value(self) -> Value {
|
||||||
if self.is_uniform() {
|
if self.is_uniform()
|
||||||
if let Some(left) = self.left {
|
&& let Some(left) = self.left {
|
||||||
return left.into_value();
|
return left.into_value();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut dict = Dict::new();
|
let mut dict = Dict::new();
|
||||||
let mut handle = |key: &str, component: Option<T>| {
|
let mut handle = |key: &str, component: Option<T>| {
|
||||||
|
@ -927,12 +927,11 @@ impl ElemRenderer<'_> {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(hayagriva::ElemMeta::Entry(i)) = elem.meta {
|
if let Some(hayagriva::ElemMeta::Entry(i)) = elem.meta
|
||||||
if let Some(location) = (self.link)(i) {
|
&& let Some(location) = (self.link)(i) {
|
||||||
let dest = Destination::Location(location);
|
let dest = Destination::Location(location);
|
||||||
content = content.linked(dest);
|
content = content.linked(dest);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(content)
|
Ok(content)
|
||||||
}
|
}
|
||||||
|
@ -210,12 +210,11 @@ impl Synthesize for Packed<RefElem> {
|
|||||||
elem.citation = Some(Some(citation));
|
elem.citation = Some(Some(citation));
|
||||||
elem.element = Some(None);
|
elem.element = Some(None);
|
||||||
|
|
||||||
if !BibliographyElem::has(engine, elem.target) {
|
if !BibliographyElem::has(engine, elem.target)
|
||||||
if let Ok(found) = engine.introspector.query_label(elem.target).cloned() {
|
&& let Ok(found) = engine.introspector.query_label(elem.target).cloned() {
|
||||||
elem.element = Some(Some(found));
|
elem.element = Some(Some(found));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -284,11 +284,9 @@ impl FontInfo {
|
|||||||
.raw_face()
|
.raw_face()
|
||||||
.table(Tag::from_bytes(b"OS/2"))
|
.table(Tag::from_bytes(b"OS/2"))
|
||||||
.and_then(|os2| os2.get(32..45))
|
.and_then(|os2| os2.get(32..45))
|
||||||
{
|
&& matches!(panose, [2, 2..=10, ..]) {
|
||||||
if matches!(panose, [2, 2..=10, ..]) {
|
|
||||||
flags.insert(FontFlags::SERIF);
|
flags.insert(FontFlags::SERIF);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Some(FontInfo {
|
Some(FontInfo {
|
||||||
family,
|
family,
|
||||||
@ -397,12 +395,11 @@ fn typographic_family(mut family: &str) -> &str {
|
|||||||
|
|
||||||
// Also allow an extra modifier, but apply it only if it is separated it
|
// Also allow an extra modifier, but apply it only if it is separated it
|
||||||
// from the text before it (to prevent false positives).
|
// from the text before it (to prevent false positives).
|
||||||
if let Some(t) = MODIFIERS.iter().find_map(|s| t.strip_suffix(s)) {
|
if let Some(t) = MODIFIERS.iter().find_map(|s| t.strip_suffix(s))
|
||||||
if let Some(stripped) = t.strip_suffix(SEPARATORS) {
|
&& let Some(stripped) = t.strip_suffix(SEPARATORS) {
|
||||||
trimmed = stripped;
|
trimmed = stripped;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Apply style suffix trimming.
|
// Apply style suffix trimming.
|
||||||
family = &family[..len];
|
family = &family[..len];
|
||||||
|
@ -144,17 +144,15 @@ cast! {
|
|||||||
self => self.as_str().into_value(),
|
self => self.as_str().into_value(),
|
||||||
string: EcoString => {
|
string: EcoString => {
|
||||||
let result = Self::from_str(&string);
|
let result = Self::from_str(&string);
|
||||||
if result.is_err() {
|
if result.is_err()
|
||||||
if let Some((lang, region)) = string.split_once('-') {
|
&& let Some((lang, region)) = string.split_once('-')
|
||||||
if Lang::from_str(lang).is_ok() && Region::from_str(region).is_ok() {
|
&& Lang::from_str(lang).is_ok() && Region::from_str(region).is_ok() {
|
||||||
return result
|
return result
|
||||||
.hint(eco_format!(
|
.hint(eco_format!(
|
||||||
"you should leave only \"{}\" in the `lang` parameter and specify \"{}\" in the `region` parameter",
|
"you should leave only \"{}\" in the `lang` parameter and specify \"{}\" in the `region` parameter",
|
||||||
lang, region,
|
lang, region,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result?
|
result?
|
||||||
}
|
}
|
||||||
|
@ -270,15 +270,14 @@ pub struct TextElem {
|
|||||||
/// ```
|
/// ```
|
||||||
#[parse({
|
#[parse({
|
||||||
let paint: Option<Spanned<Paint>> = args.named_or_find("fill")?;
|
let paint: Option<Spanned<Paint>> = args.named_or_find("fill")?;
|
||||||
if let Some(paint) = &paint {
|
if let Some(paint) = &paint
|
||||||
if paint.v.relative() == Smart::Custom(RelativeTo::Self_) {
|
&& paint.v.relative() == Smart::Custom(RelativeTo::Self_) {
|
||||||
bail!(
|
bail!(
|
||||||
paint.span,
|
paint.span,
|
||||||
"gradients and tilings on text must be relative to the parent";
|
"gradients and tilings on text must be relative to the parent";
|
||||||
hint: "make sure to set `relative: auto` on your text fill"
|
hint: "make sure to set `relative: auto` on your text fill"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
paint.map(|paint| paint.v)
|
paint.map(|paint| paint.v)
|
||||||
})]
|
})]
|
||||||
#[default(Color::BLACK.into())]
|
#[default(Color::BLACK.into())]
|
||||||
|
@ -750,11 +750,10 @@ fn preprocess(
|
|||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> EcoVec<(EcoString, Span)> {
|
) -> EcoVec<(EcoString, Span)> {
|
||||||
if let RawContent::Lines(lines) = text {
|
if let RawContent::Lines(lines) = text
|
||||||
if lines.iter().all(|(s, _)| !s.contains('\t')) {
|
&& lines.iter().all(|(s, _)| !s.contains('\t')) {
|
||||||
return lines.clone();
|
return lines.clone();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut text = text.get();
|
let mut text = text.get();
|
||||||
if text.contains('\t') {
|
if text.contains('\t') {
|
||||||
|
@ -1123,8 +1123,8 @@ impl Color {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the hue circle is traversed in the short direction.
|
// Ensure that the hue circle is traversed in the short direction.
|
||||||
if let Some(index) = space.hue_index() {
|
if let Some(index) = space.hue_index()
|
||||||
if (c0[index] - c1[index]).abs() > 180.0 {
|
&& (c0[index] - c1[index]).abs() > 180.0 {
|
||||||
let (h0, h1) = if c0[index] < c1[index] {
|
let (h0, h1) = if c0[index] < c1[index] {
|
||||||
(c0[index] + 360.0, c1[index])
|
(c0[index] + 360.0, c1[index])
|
||||||
} else {
|
} else {
|
||||||
@ -1132,7 +1132,6 @@ impl Color {
|
|||||||
};
|
};
|
||||||
m[index] = (w0 * h0 + w1 * h1) / (w0 + w1);
|
m[index] = (w0 * h0 + w1 * h1) / (w0 + w1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
m
|
m
|
||||||
} else {
|
} else {
|
||||||
|
@ -14,14 +14,12 @@ pub fn scope(_: TokenStream, item: syn::Item) -> Result<TokenStream> {
|
|||||||
let self_ty = &item.self_ty;
|
let self_ty = &item.self_ty;
|
||||||
|
|
||||||
let mut primitive_ident_ext = None;
|
let mut primitive_ident_ext = None;
|
||||||
if let syn::Type::Path(syn::TypePath { path, .. }) = self_ty.as_ref() {
|
if let syn::Type::Path(syn::TypePath { path, .. }) = self_ty.as_ref()
|
||||||
if let Some(ident) = path.get_ident() {
|
&& let Some(ident) = path.get_ident()
|
||||||
if is_primitive(ident) {
|
&& is_primitive(ident) {
|
||||||
let ident_ext = quote::format_ident!("{ident}Ext");
|
let ident_ext = quote::format_ident!("{ident}Ext");
|
||||||
primitive_ident_ext = Some(ident_ext);
|
primitive_ident_ext = Some(ident_ext);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let self_ty_expr = match &primitive_ident_ext {
|
let self_ty_expr = match &primitive_ident_ext {
|
||||||
None => quote! { #self_ty },
|
None => quote! { #self_ty },
|
||||||
|
@ -27,19 +27,16 @@ pub fn documentation(attrs: &[syn::Attribute]) -> String {
|
|||||||
|
|
||||||
// Parse doc comments.
|
// Parse doc comments.
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if let syn::Meta::NameValue(meta) = &attr.meta {
|
if let syn::Meta::NameValue(meta) = &attr.meta
|
||||||
if meta.path.is_ident("doc") {
|
&& meta.path.is_ident("doc")
|
||||||
if let syn::Expr::Lit(lit) = &meta.value {
|
&& let syn::Expr::Lit(lit) = &meta.value
|
||||||
if let syn::Lit::Str(string) = &lit.lit {
|
&& let syn::Lit::Str(string) = &lit.lit {
|
||||||
let full = string.value();
|
let full = string.value();
|
||||||
let line = full.strip_prefix(' ').unwrap_or(&full);
|
let line = full.strip_prefix(' ').unwrap_or(&full);
|
||||||
doc.push_str(line);
|
doc.push_str(line);
|
||||||
doc.push('\n');
|
doc.push('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doc.trim().into()
|
doc.trim().into()
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,13 @@ pub(crate) fn build_outline(gc: &GlobalContext) -> Outline {
|
|||||||
let elements = &gc.document.introspector.query(&HeadingElem::ELEM.select());
|
let elements = &gc.document.introspector.query(&HeadingElem::ELEM.select());
|
||||||
|
|
||||||
for elem in elements.iter() {
|
for elem in elements.iter() {
|
||||||
if let Some(page_ranges) = &gc.options.page_ranges {
|
if let Some(page_ranges) = &gc.options.page_ranges
|
||||||
if !page_ranges
|
&& !page_ranges
|
||||||
.includes_page(gc.document.introspector.page(elem.location().unwrap()))
|
.includes_page(gc.document.introspector.page(elem.location().unwrap()))
|
||||||
{
|
{
|
||||||
// Don't bookmark headings in non-exported pages.
|
// Don't bookmark headings in non-exported pages.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let heading = elem.to_packed::<HeadingElem>().unwrap();
|
let heading = elem.to_packed::<HeadingElem>().unwrap();
|
||||||
let leaf = HeadingNode::leaf(heading);
|
let leaf = HeadingNode::leaf(heading);
|
||||||
|
@ -307,12 +307,11 @@ fn visit_kind_rules<'a>(
|
|||||||
visit_regex_match(s, &[(content, styles)], m)?;
|
visit_regex_match(s, &[(content, styles)], m)?;
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
} else if let Some(elem) = content.to_packed::<TextElem>() {
|
} else if let Some(elem) = content.to_packed::<TextElem>()
|
||||||
if let Some(m) = find_regex_match_in_str(&elem.text, styles) {
|
&& let Some(m) = find_regex_match_in_str(&elem.text, styles) {
|
||||||
visit_regex_match(s, &[(content, styles)], m)?;
|
visit_regex_match(s, &[(content, styles)], m)?;
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Transparently wrap mathy content into equations.
|
// Transparently wrap mathy content into equations.
|
||||||
if content.can::<dyn Mathy>() && !content.is::<EquationElem>() {
|
if content.can::<dyn Mathy>() && !content.is::<EquationElem>() {
|
||||||
@ -1092,11 +1091,10 @@ fn find_regex_match_in_elems<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let linebreak = content.is::<LinebreakElem>();
|
let linebreak = content.is::<LinebreakElem>();
|
||||||
if linebreak {
|
if linebreak
|
||||||
if let SpaceState::Space(_) = space {
|
&& let SpaceState::Space(_) = space {
|
||||||
buf.pop();
|
buf.pop();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if styles != current && !buf.is_empty() {
|
if styles != current && !buf.is_empty() {
|
||||||
leftmost = find_regex_match_in_str(&buf, current);
|
leftmost = find_regex_match_in_str(&buf, current);
|
||||||
|
@ -193,8 +193,8 @@ fn render_group(canvas: &mut sk::Pixmap, state: State, pos: Point, group: &Group
|
|||||||
|
|
||||||
let mut mask = state.mask;
|
let mut mask = state.mask;
|
||||||
let storage;
|
let storage;
|
||||||
if let Some(clip_curve) = group.clip.as_ref() {
|
if let Some(clip_curve) = group.clip.as_ref()
|
||||||
if let Some(path) = shape::convert_curve(clip_curve)
|
&& let Some(path) = shape::convert_curve(clip_curve)
|
||||||
.and_then(|path| path.transform(state.transform))
|
.and_then(|path| path.transform(state.transform))
|
||||||
{
|
{
|
||||||
if let Some(mask) = mask {
|
if let Some(mask) = mask {
|
||||||
@ -226,7 +226,6 @@ fn render_group(canvas: &mut sk::Pixmap, state: State, pos: Point, group: &Group
|
|||||||
|
|
||||||
mask = Some(&storage);
|
mask = Some(&storage);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
render_frame(canvas, state.with_mask(mask), &group.frame);
|
render_frame(canvas, state.with_mask(mask), &group.frame);
|
||||||
}
|
}
|
||||||
|
@ -87,8 +87,7 @@ fn render_outline_glyph(
|
|||||||
|
|
||||||
if let Some(FixedStroke { paint, thickness, cap, join, dash, miter_limit }) =
|
if let Some(FixedStroke { paint, thickness, cap, join, dash, miter_limit }) =
|
||||||
&text.stroke
|
&text.stroke
|
||||||
{
|
&& thickness.to_f32() > 0.0 {
|
||||||
if thickness.to_f32() > 0.0 {
|
|
||||||
let dash = dash.as_ref().and_then(shape::to_sk_dash_pattern);
|
let dash = dash.as_ref().and_then(shape::to_sk_dash_pattern);
|
||||||
|
|
||||||
let paint = paint::to_sk_paint(
|
let paint = paint::to_sk_paint(
|
||||||
@ -110,7 +109,6 @@ fn render_outline_glyph(
|
|||||||
|
|
||||||
canvas.stroke_path(&path, &paint, &stroke, ts, state.mask);
|
canvas.stroke_path(&path, &paint, &stroke, ts, state.mask);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,13 +340,12 @@ impl<'a> SVGRenderer<'a> {
|
|||||||
Destination::Location(loc) => {
|
Destination::Location(loc) => {
|
||||||
// TODO: Location links on the same page could also be supported
|
// TODO: Location links on the same page could also be supported
|
||||||
// outside of HTML.
|
// outside of HTML.
|
||||||
if let Some(introspector) = self.introspector {
|
if let Some(introspector) = self.introspector
|
||||||
if let Some(id) = introspector.html_id(*loc) {
|
&& let Some(id) = introspector.html_id(*loc) {
|
||||||
self.xml.write_attribute_fmt("href", format_args!("#{id}"));
|
self.xml.write_attribute_fmt("href", format_args!("#{id}"));
|
||||||
self.xml.write_attribute_fmt("xlink:href", format_args!("#{id}"));
|
self.xml.write_attribute_fmt("xlink:href", format_args!("#{id}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Destination::Position(_) => {
|
Destination::Position(_) => {
|
||||||
// TODO: Links on the same page could be supported.
|
// TODO: Links on the same page could be supported.
|
||||||
}
|
}
|
||||||
|
@ -300,8 +300,8 @@ pub fn highlight(node: &LinkedNode) -> Option<Tag> {
|
|||||||
fn highlight_ident(node: &LinkedNode) -> Option<Tag> {
|
fn highlight_ident(node: &LinkedNode) -> Option<Tag> {
|
||||||
// Are we directly before an argument list?
|
// Are we directly before an argument list?
|
||||||
let next_leaf = node.next_leaf();
|
let next_leaf = node.next_leaf();
|
||||||
if let Some(next) = &next_leaf {
|
if let Some(next) = &next_leaf
|
||||||
if node.range().end == next.offset()
|
&& node.range().end == next.offset()
|
||||||
&& ((next.kind() == SyntaxKind::LeftParen
|
&& ((next.kind() == SyntaxKind::LeftParen
|
||||||
&& matches!(
|
&& matches!(
|
||||||
next.parent_kind(),
|
next.parent_kind(),
|
||||||
@ -312,7 +312,6 @@ fn highlight_ident(node: &LinkedNode) -> Option<Tag> {
|
|||||||
{
|
{
|
||||||
return Some(Tag::Function);
|
return Some(Tag::Function);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Are we in math?
|
// Are we in math?
|
||||||
if node.kind() == SyntaxKind::MathIdent {
|
if node.kind() == SyntaxKind::MathIdent {
|
||||||
@ -379,14 +378,13 @@ pub fn highlight_html(root: &SyntaxNode) -> String {
|
|||||||
/// Highlight one source node, emitting HTML.
|
/// Highlight one source node, emitting HTML.
|
||||||
fn highlight_html_impl(html: &mut String, node: &LinkedNode) {
|
fn highlight_html_impl(html: &mut String, node: &LinkedNode) {
|
||||||
let mut span = false;
|
let mut span = false;
|
||||||
if let Some(tag) = highlight(node) {
|
if let Some(tag) = highlight(node)
|
||||||
if tag != Tag::Error {
|
&& tag != Tag::Error {
|
||||||
span = true;
|
span = true;
|
||||||
html.push_str("<span class=\"");
|
html.push_str("<span class=\"");
|
||||||
html.push_str(tag.css_class());
|
html.push_str(tag.css_class());
|
||||||
html.push_str("\">");
|
html.push_str("\">");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let text = node.text();
|
let text = node.text();
|
||||||
if !text.is_empty() {
|
if !text.is_empty() {
|
||||||
|
@ -783,11 +783,10 @@ impl Lexer<'_> {
|
|||||||
let ident = self.s.from(start);
|
let ident = self.s.from(start);
|
||||||
|
|
||||||
let prev = self.s.get(0..start);
|
let prev = self.s.get(0..start);
|
||||||
if !prev.ends_with(['.', '@']) || prev.ends_with("..") {
|
if (!prev.ends_with(['.', '@']) || prev.ends_with(".."))
|
||||||
if let Some(keyword) = keyword(ident) {
|
&& let Some(keyword) = keyword(ident) {
|
||||||
return keyword;
|
return keyword;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ident == "_" {
|
if ident == "_" {
|
||||||
SyntaxKind::Underscore
|
SyntaxKind::Underscore
|
||||||
|
@ -733,13 +733,11 @@ impl<'a> LinkedNode<'a> {
|
|||||||
if children
|
if children
|
||||||
.peek()
|
.peek()
|
||||||
.is_none_or(|next| next.span().number() > span.number())
|
.is_none_or(|next| next.span().number() > span.number())
|
||||||
{
|
&& let Some(found) = child.find(span) {
|
||||||
if let Some(found) = child.find(span) {
|
|
||||||
return Some(found);
|
return Some(found);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -442,14 +442,13 @@ fn math_unparen(p: &mut Parser, m: Marker) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let [first, .., last] = node.children_mut() {
|
if let [first, .., last] = node.children_mut()
|
||||||
if first.text() == "(" && last.text() == ")" {
|
&& first.text() == "(" && last.text() == ")" {
|
||||||
first.convert_to_kind(SyntaxKind::LeftParen);
|
first.convert_to_kind(SyntaxKind::LeftParen);
|
||||||
last.convert_to_kind(SyntaxKind::RightParen);
|
last.convert_to_kind(SyntaxKind::RightParen);
|
||||||
// Only convert if we did have regular parens.
|
// Only convert if we did have regular parens.
|
||||||
node.convert_to_kind(SyntaxKind::Math);
|
node.convert_to_kind(SyntaxKind::Math);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The unicode math class of a string. Only returns `Some` if `text` has
|
/// The unicode math class of a string. Only returns `Some` if `text` has
|
||||||
@ -1199,10 +1198,9 @@ fn array_or_dict_item(p: &mut Parser, state: &mut GroupState) {
|
|||||||
Some(ast::Expr::Ident(ident)) => Some(ident.get().clone()),
|
Some(ast::Expr::Ident(ident)) => Some(ident.get().clone()),
|
||||||
Some(ast::Expr::Str(s)) => Some(s.get()),
|
Some(ast::Expr::Str(s)) => Some(s.get()),
|
||||||
_ => None,
|
_ => None,
|
||||||
} {
|
|
||||||
if !state.seen.insert(key.clone()) {
|
|
||||||
node.convert_to_error(eco_format!("duplicate key: {key}"));
|
|
||||||
}
|
}
|
||||||
|
&& !state.seen.insert(key.clone()) {
|
||||||
|
node.convert_to_error(eco_format!("duplicate key: {key}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
p.wrap(m, pair_kind);
|
p.wrap(m, pair_kind);
|
||||||
@ -1855,8 +1853,8 @@ impl<'s> Parser<'s> {
|
|||||||
self.nl_mode = mode;
|
self.nl_mode = mode;
|
||||||
func(self);
|
func(self);
|
||||||
self.nl_mode = previous;
|
self.nl_mode = previous;
|
||||||
if let Some(newline) = self.token.newline {
|
if let Some(newline) = self.token.newline
|
||||||
if mode != previous {
|
&& mode != previous {
|
||||||
// Restore our actual token's kind or insert a fake end.
|
// Restore our actual token's kind or insert a fake end.
|
||||||
let actual_kind = self.token.node.kind();
|
let actual_kind = self.token.node.kind();
|
||||||
if self.nl_mode.stop_at(newline, actual_kind) {
|
if self.nl_mode.stop_at(newline, actual_kind) {
|
||||||
@ -1866,7 +1864,6 @@ impl<'s> Parser<'s> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Move the lexer forward and prepare the current token. In Code, this
|
/// Move the lexer forward and prepare the current token. In Code, this
|
||||||
/// might insert a temporary [`SyntaxKind::End`] based on our newline mode.
|
/// might insert a temporary [`SyntaxKind::End`] based on our newline mode.
|
||||||
|
@ -70,15 +70,14 @@ fn try_reparse(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the child is a block, try to reparse the block.
|
// If the child is a block, try to reparse the block.
|
||||||
if child.kind().is_block() {
|
if child.kind().is_block()
|
||||||
if let Some(newborn) = reparse_block(text, new_range.clone()) {
|
&& let Some(newborn) = reparse_block(text, new_range.clone()) {
|
||||||
return node
|
return node
|
||||||
.replace_children(i..i + 1, vec![newborn])
|
.replace_children(i..i + 1, vec![newborn])
|
||||||
.is_ok()
|
.is_ok()
|
||||||
.then_some(new_range);
|
.then_some(new_range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Does the child overlap with the edit?
|
// Does the child overlap with the edit?
|
||||||
if overlaps(&prev_range, &replaced) {
|
if overlaps(&prev_range, &replaced) {
|
||||||
|
@ -96,12 +96,11 @@ fn resolve_definition(head: &str, base: &str) -> StrResult<String> {
|
|||||||
if let Ok(field) = value.field(next, ()) {
|
if let Ok(field) = value.field(next, ()) {
|
||||||
route.push_str("/#definitions-");
|
route.push_str("/#definitions-");
|
||||||
route.push_str(next);
|
route.push_str(next);
|
||||||
if let Some(next) = parts.next() {
|
if let Some(next) = parts.next()
|
||||||
if field.cast::<Func>().is_ok_and(|func| func.param(next).is_some()) {
|
&& field.cast::<Func>().is_ok_and(|func| func.param(next).is_some()) {
|
||||||
route.push('-');
|
route.push('-');
|
||||||
route.push_str(next);
|
route.push_str(next);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else if value
|
} else if value
|
||||||
.clone()
|
.clone()
|
||||||
.cast::<Func>()
|
.cast::<Func>()
|
||||||
|
@ -66,10 +66,9 @@ impl World for FuzzWorld {
|
|||||||
|
|
||||||
fuzz_target!(|text: &str| {
|
fuzz_target!(|text: &str| {
|
||||||
let world = FuzzWorld::new(text);
|
let world = FuzzWorld::new(text);
|
||||||
if let Ok(document) = typst::compile::<PagedDocument>(&world).output {
|
if let Ok(document) = typst::compile::<PagedDocument>(&world).output
|
||||||
if let Some(page) = document.pages.first() {
|
&& let Some(page) = document.pages.first() {
|
||||||
std::hint::black_box(typst_render::render(page, 1.0));
|
std::hint::black_box(typst_render::render(page, 1.0));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
comemo::evict(10);
|
comemo::evict(10);
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user