mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Handle paragraph indent at a later stage
This commit is contained in:
parent
bf59c08a0a
commit
cabd0908e2
@ -1,3 +1,5 @@
|
||||
use typst::model::{Property, StyleEntry};
|
||||
|
||||
use super::{AlignNode, ColbreakNode, PlaceNode, Spacing, VNode};
|
||||
use crate::prelude::*;
|
||||
use crate::text::ParNode;
|
||||
@ -58,6 +60,8 @@ struct FlowLayouter {
|
||||
used: Size,
|
||||
/// The sum of fractions in the current region.
|
||||
fr: Fr,
|
||||
/// Whether the last block was a paragraph.
|
||||
last_block_was_par: bool,
|
||||
/// Spacing and layouted blocks.
|
||||
items: Vec<FlowItem>,
|
||||
/// Finished frames for previous regions.
|
||||
@ -92,6 +96,7 @@ impl FlowLayouter {
|
||||
full,
|
||||
used: Size::zero(),
|
||||
fr: Fr::zero(),
|
||||
last_block_was_par: false,
|
||||
items: vec![],
|
||||
finished: vec![],
|
||||
}
|
||||
@ -150,8 +155,18 @@ impl FlowLayouter {
|
||||
.unwrap_or(Align::Top),
|
||||
);
|
||||
|
||||
// Disable paragraph indent if this is not a consecutive paragraph.
|
||||
let reset;
|
||||
let is_par = block.is::<ParNode>();
|
||||
let mut chained = styles;
|
||||
if !self.last_block_was_par && is_par && !styles.get(ParNode::INDENT).is_zero() {
|
||||
let property = Property::new(ParNode::INDENT, Length::zero());
|
||||
reset = StyleEntry::Property(property);
|
||||
chained = reset.chain(&styles);
|
||||
}
|
||||
|
||||
// Layout the block itself.
|
||||
let frames = block.layout_block(world, &self.regions, styles)?;
|
||||
let frames = block.layout_block(world, &self.regions, chained)?;
|
||||
let len = frames.len();
|
||||
for (i, frame) in frames.into_iter().enumerate() {
|
||||
// Grow our size, shrink the region and save the frame for later.
|
||||
@ -166,6 +181,8 @@ impl FlowLayouter {
|
||||
}
|
||||
}
|
||||
|
||||
self.last_block_was_par = is_par;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -474,13 +474,14 @@ struct FlowBuilder<'a>(BehavedBuilder<'a>, bool);
|
||||
|
||||
impl<'a> FlowBuilder<'a> {
|
||||
fn accept(&mut self, content: &Content, styles: StyleChain<'a>) -> bool {
|
||||
let last_was_parbreak = self.1;
|
||||
self.1 = false;
|
||||
let last_was_parbreak = std::mem::replace(&mut self.1, false);
|
||||
|
||||
if content.is::<ParbreakNode>() {
|
||||
self.1 = true;
|
||||
return true;
|
||||
} else if content.is::<VNode>() || content.is::<ColbreakNode>() {
|
||||
self.0.push(content.clone(), styles);
|
||||
return true;
|
||||
} else if content.has::<dyn LayoutBlock>() {
|
||||
if !last_was_parbreak {
|
||||
let tight = if let Some(node) = content.downcast::<ListNode>() {
|
||||
@ -505,11 +506,10 @@ impl<'a> FlowBuilder<'a> {
|
||||
self.0.push(above.pack(), styles);
|
||||
self.0.push(content.clone(), styles);
|
||||
self.0.push(below.pack(), styles);
|
||||
} else {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
true
|
||||
false
|
||||
}
|
||||
|
||||
fn finish(self, doc: &mut DocBuilder<'a>, styles: StyleChain<'a>) {
|
||||
@ -545,39 +545,10 @@ impl<'a> ParBuilder<'a> {
|
||||
}
|
||||
|
||||
fn finish(self, parent: &mut Builder<'a>) {
|
||||
let (mut children, shared) = self.0.finish();
|
||||
if children.is_empty() {
|
||||
return;
|
||||
let (children, shared) = self.0.finish();
|
||||
if !children.is_empty() {
|
||||
parent.flow.accept(&ParNode(children).pack(), shared);
|
||||
}
|
||||
|
||||
// Paragraph indent should only apply if the paragraph starts with
|
||||
// text and follows directly after another paragraph.
|
||||
let indent = shared.get(ParNode::INDENT);
|
||||
if !indent.is_zero()
|
||||
&& children
|
||||
.items()
|
||||
.find_map(|child| {
|
||||
if child.is::<TextNode>() || child.is::<SmartQuoteNode>() {
|
||||
Some(true)
|
||||
} else if child.has::<dyn LayoutInline>() {
|
||||
Some(false)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or_default()
|
||||
&& parent
|
||||
.flow
|
||||
.0
|
||||
.items()
|
||||
.rev()
|
||||
.find(|child| child.has::<dyn LayoutBlock>())
|
||||
.map_or(false, |child| child.is::<ParNode>())
|
||||
{
|
||||
children.push_front(HNode::strong(indent.into()).pack());
|
||||
}
|
||||
|
||||
parent.flow.accept(&ParNode(children).pack(), shared);
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
|
@ -393,6 +393,26 @@ fn collect<'a>(
|
||||
let mut segments = vec![];
|
||||
let mut iter = par.0.iter().peekable();
|
||||
|
||||
let indent = styles.get(ParNode::INDENT);
|
||||
if !indent.is_zero()
|
||||
&& par
|
||||
.0
|
||||
.items()
|
||||
.find_map(|child| {
|
||||
if child.is::<TextNode>() || child.is::<SmartQuoteNode>() {
|
||||
Some(true)
|
||||
} else if child.has::<dyn LayoutInline>() {
|
||||
Some(false)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or_default()
|
||||
{
|
||||
full.push(SPACING_REPLACE);
|
||||
segments.push((Segment::Spacing(indent.into()), *styles));
|
||||
}
|
||||
|
||||
while let Some((child, map)) = iter.next() {
|
||||
let styles = map.chain(styles);
|
||||
let segment = if child.is::<SpaceNode>() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user