diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-11-26 23:42:40 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-11-26 23:52:01 +0100 |
| commit | 6bafc6391061d4b589dea835705a08b25a4df9f8 (patch) | |
| tree | 4add85f17fc56da341acfb58a223ea20d80c280a /library/src | |
| parent | 0579fd4409375aaa9fd8e87a06fd59097b5fcd97 (diff) | |
Document metadata
Diffstat (limited to 'library/src')
| -rw-r--r-- | library/src/layout/mod.rs | 37 | ||||
| -rw-r--r-- | library/src/lib.rs | 1 | ||||
| -rw-r--r-- | library/src/prelude.rs | 2 | ||||
| -rw-r--r-- | library/src/structure/doc.rs | 32 | ||||
| -rw-r--r-- | library/src/structure/document.rs | 47 | ||||
| -rw-r--r-- | library/src/structure/mod.rs | 4 |
6 files changed, 78 insertions, 45 deletions
diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs index 100e0611..e63a072e 100644 --- a/library/src/layout/mod.rs +++ b/library/src/layout/mod.rs @@ -29,7 +29,7 @@ use std::mem; use comemo::Tracked; use typed_arena::Arena; use typst::diag::SourceResult; -use typst::frame::Frame; +use typst::doc::Frame; use typst::geom::*; use typst::model::{ applicable, capability, realize, Content, Node, SequenceNode, Style, StyleChain, @@ -40,7 +40,7 @@ use typst::World; use crate::prelude::*; use crate::shared::BehavedBuilder; use crate::structure::{ - DescNode, DocNode, EnumNode, ListItem, ListNode, DESC, ENUM, LIST, + DescNode, DocumentNode, EnumNode, ListItem, ListNode, DESC, ENUM, LIST, }; use crate::text::{ LinebreakNode, ParNode, ParbreakNode, SmartQuoteNode, SpaceNode, TextNode, @@ -54,7 +54,7 @@ pub trait LayoutRoot { &self, world: Tracked<dyn World>, styles: StyleChain, - ) -> SourceResult<Vec<Frame>>; + ) -> SourceResult<Document>; } impl LayoutRoot for Content { @@ -63,7 +63,7 @@ impl LayoutRoot for Content { &self, world: Tracked<dyn World>, styles: StyleChain, - ) -> SourceResult<Vec<Frame>> { + ) -> SourceResult<Document> { let scratch = Scratch::default(); let (realized, styles) = realize_root(world, &scratch, self, styles)?; realized.with::<dyn LayoutRoot>().unwrap().layout_root(world, styles) @@ -245,7 +245,7 @@ fn realize_root<'a>( builder.accept(content, styles)?; builder.interrupt_page(Some(styles))?; let (pages, shared) = builder.doc.unwrap().pages.finish(); - Ok((DocNode(pages).pack(), shared)) + Ok((DocumentNode(pages).pack(), shared)) } /// Realize into a node that is capable of block-level layout. @@ -357,6 +357,10 @@ impl<'a> Builder<'a> { } } + if let Some(span) = content.span() { + bail!(span, "not allowed here"); + } + Ok(()) } @@ -378,13 +382,26 @@ impl<'a> Builder<'a> { map: &StyleMap, styles: Option<StyleChain<'a>>, ) -> SourceResult<()> { - if map.interrupts::<PageNode>() { + if let Some(Some(span)) = map.interruption::<DocumentNode>() { + if self.doc.is_none() { + bail!(span, "not allowed here"); + } + if !self.flow.0.is_empty() + || !self.par.0.is_empty() + || !self.list.items.is_empty() + { + bail!(span, "must appear before any content"); + } + } else if let Some(Some(span)) = map.interruption::<PageNode>() { + if self.doc.is_none() { + bail!(span, "not allowed here"); + } self.interrupt_page(styles)?; - } else if map.interrupts::<ParNode>() { + } else if map.interruption::<ParNode>().is_some() { self.interrupt_par()?; - } else if map.interrupts::<ListNode>() - || map.interrupts::<EnumNode>() - || map.interrupts::<DescNode>() + } else if map.interruption::<ListNode>().is_some() + || map.interruption::<EnumNode>().is_some() + || map.interruption::<DescNode>().is_some() { self.interrupt_list()?; } diff --git a/library/src/lib.rs b/library/src/lib.rs index 6107cf42..cf8cb490 100644 --- a/library/src/lib.rs +++ b/library/src/lib.rs @@ -44,6 +44,7 @@ fn scope() -> Scope { std.def_fn("smallcaps", text::smallcaps); // Structure. + std.def_node::<structure::DocumentNode>("document"); std.def_node::<structure::RefNode>("ref"); std.def_node::<structure::HeadingNode>("heading"); std.def_node::<structure::ListNode>("list"); diff --git a/library/src/prelude.rs b/library/src/prelude.rs index 6379e579..bc0ec31d 100644 --- a/library/src/prelude.rs +++ b/library/src/prelude.rs @@ -10,7 +10,7 @@ pub use comemo::Tracked; #[doc(no_inline)] pub use typst::diag::{bail, error, with_alternative, At, SourceResult, StrResult}; #[doc(no_inline)] -pub use typst::frame::*; +pub use typst::doc::*; #[doc(no_inline)] pub use typst::geom::*; #[doc(no_inline)] diff --git a/library/src/structure/doc.rs b/library/src/structure/doc.rs deleted file mode 100644 index e471a852..00000000 --- a/library/src/structure/doc.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::layout::{LayoutRoot, PageNode}; -use crate::prelude::*; - -/// A sequence of page runs. -#[derive(Hash)] -pub struct DocNode(pub StyleVec<PageNode>); - -#[node(LayoutRoot)] -impl DocNode {} - -impl LayoutRoot for DocNode { - /// Layout the document into a sequence of frames, one per page. - fn layout_root( - &self, - world: Tracked<dyn World>, - styles: StyleChain, - ) -> SourceResult<Vec<Frame>> { - let mut frames = vec![]; - for (page, map) in self.0.iter() { - let number = 1 + frames.len(); - frames.extend(page.layout(world, number, styles.chain(map))?); - } - Ok(frames) - } -} - -impl Debug for DocNode { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.write_str("Doc ")?; - self.0.fmt(f) - } -} diff --git a/library/src/structure/document.rs b/library/src/structure/document.rs new file mode 100644 index 00000000..2e5761e0 --- /dev/null +++ b/library/src/structure/document.rs @@ -0,0 +1,47 @@ +use crate::layout::{LayoutRoot, PageNode}; +use crate::prelude::*; + +/// The root node of the model. +#[derive(Hash)] +pub struct DocumentNode(pub StyleVec<PageNode>); + +#[node(LayoutRoot)] +impl DocumentNode { + /// The document's title. + #[property(referenced)] + pub const TITLE: Option<EcoString> = None; + + /// The document's author. + #[property(referenced)] + pub const AUTHOR: Option<EcoString> = None; +} + +impl LayoutRoot for DocumentNode { + /// Layout the document into a sequence of frames, one per page. + fn layout_root( + &self, + world: Tracked<dyn World>, + styles: StyleChain, + ) -> SourceResult<Document> { + let mut pages = vec![]; + for (page, map) in self.0.iter() { + let number = 1 + pages.len(); + pages.extend(page.layout(world, number, styles.chain(map))?); + } + + Ok(Document { + metadata: Metadata { + title: styles.get(Self::TITLE).clone(), + author: styles.get(Self::AUTHOR).clone(), + }, + pages, + }) + } +} + +impl Debug for DocumentNode { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.write_str("Document ")?; + self.0.fmt(f) + } +} diff --git a/library/src/structure/mod.rs b/library/src/structure/mod.rs index 8e13f76a..a1c27eed 100644 --- a/library/src/structure/mod.rs +++ b/library/src/structure/mod.rs @@ -1,12 +1,12 @@ //! Document structuring. -mod doc; +mod document; mod heading; mod list; mod reference; mod table; -pub use self::doc::*; +pub use self::document::*; pub use self::heading::*; pub use self::list::*; pub use self::reference::*; |
