Make HTML data structures cheaper to clone (#6708)
This commit is contained in:
parent
d0026093d4
commit
15d5591a42
|
|
@ -1,3 +1,4 @@
|
|||
use ecow::EcoVec;
|
||||
use typst_library::diag::{SourceResult, warning};
|
||||
use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{Content, StyleChain, Target, TargetElem};
|
||||
|
|
@ -15,8 +16,8 @@ pub fn convert_to_nodes<'a>(
|
|||
engine: &mut Engine,
|
||||
locator: &mut SplitLocator,
|
||||
children: impl IntoIterator<Item = Pair<'a>>,
|
||||
) -> SourceResult<Vec<HtmlNode>> {
|
||||
let mut output = Vec::new();
|
||||
) -> SourceResult<EcoVec<HtmlNode>> {
|
||||
let mut output = EcoVec::new();
|
||||
for (child, styles) in children {
|
||||
handle(engine, child, locator, styles, &mut output)?;
|
||||
}
|
||||
|
|
@ -29,12 +30,12 @@ fn handle(
|
|||
child: &Content,
|
||||
locator: &mut SplitLocator,
|
||||
styles: StyleChain,
|
||||
output: &mut Vec<HtmlNode>,
|
||||
output: &mut EcoVec<HtmlNode>,
|
||||
) -> SourceResult<()> {
|
||||
if let Some(elem) = child.to_packed::<TagElem>() {
|
||||
output.push(HtmlNode::Tag(elem.tag.clone()));
|
||||
} else if let Some(elem) = child.to_packed::<HtmlElem>() {
|
||||
let mut children = vec![];
|
||||
let mut children = EcoVec::new();
|
||||
if let Some(body) = elem.body.get_ref(styles) {
|
||||
children = html_fragment(engine, body, locator.next(&elem.span()), styles)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::num::NonZeroUsize;
|
||||
|
||||
use comemo::{Tracked, TrackedMut};
|
||||
use ecow::{EcoVec, eco_vec};
|
||||
use rustc_hash::FxHashSet;
|
||||
use typst_library::World;
|
||||
use typst_library::diag::{SourceResult, bail};
|
||||
|
|
@ -141,19 +142,22 @@ fn introspect_html(
|
|||
|
||||
/// Wrap the nodes in `<html>` and `<body>` if they are not yet rooted,
|
||||
/// supplying a suitable `<head>`.
|
||||
fn root_element(output: Vec<HtmlNode>, info: &DocumentInfo) -> SourceResult<HtmlElement> {
|
||||
fn root_element(
|
||||
output: EcoVec<HtmlNode>,
|
||||
info: &DocumentInfo,
|
||||
) -> SourceResult<HtmlElement> {
|
||||
let head = head_element(info);
|
||||
let body = match classify_output(output)? {
|
||||
OutputKind::Html(element) => return Ok(element),
|
||||
OutputKind::Body(body) => body,
|
||||
OutputKind::Leafs(leafs) => HtmlElement::new(tag::body).with_children(leafs),
|
||||
};
|
||||
Ok(HtmlElement::new(tag::html).with_children(vec![head.into(), body.into()]))
|
||||
Ok(HtmlElement::new(tag::html).with_children(eco_vec![head.into(), body.into()]))
|
||||
}
|
||||
|
||||
/// Generate a `<head>` element.
|
||||
fn head_element(info: &DocumentInfo) -> HtmlElement {
|
||||
let mut children = vec![];
|
||||
let mut children = EcoVec::new();
|
||||
|
||||
children.push(HtmlElement::new(tag::meta).with_attr(attr::charset, "utf-8").into());
|
||||
|
||||
|
|
@ -167,7 +171,7 @@ fn head_element(info: &DocumentInfo) -> HtmlElement {
|
|||
if let Some(title) = &info.title {
|
||||
children.push(
|
||||
HtmlElement::new(tag::title)
|
||||
.with_children(vec![HtmlNode::Text(title.clone(), Span::detached())])
|
||||
.with_children(eco_vec![HtmlNode::Text(title.clone(), Span::detached())])
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
|
@ -203,9 +207,9 @@ fn head_element(info: &DocumentInfo) -> HtmlElement {
|
|||
}
|
||||
|
||||
/// Determine which kind of output the user generated.
|
||||
fn classify_output(mut output: Vec<HtmlNode>) -> SourceResult<OutputKind> {
|
||||
fn classify_output(mut output: EcoVec<HtmlNode>) -> SourceResult<OutputKind> {
|
||||
let count = output.iter().filter(|node| !matches!(node, HtmlNode::Tag(_))).count();
|
||||
for node in &mut output {
|
||||
for node in output.make_mut() {
|
||||
let HtmlNode::Element(elem) = node else { continue };
|
||||
let tag = elem.tag;
|
||||
let mut take = || std::mem::replace(elem, HtmlElement::new(tag::html));
|
||||
|
|
@ -232,5 +236,5 @@ enum OutputKind {
|
|||
/// one, but need supply the `<html>` element.
|
||||
Body(HtmlElement),
|
||||
/// The user generated leafs which we wrap in a `<body>` and `<html>`.
|
||||
Leafs(Vec<HtmlNode>),
|
||||
Leafs(EcoVec<HtmlNode>),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ pub struct HtmlElement {
|
|||
/// The element's attributes.
|
||||
pub attrs: HtmlAttrs,
|
||||
/// The element's children.
|
||||
pub children: Vec<HtmlNode>,
|
||||
pub children: EcoVec<HtmlNode>,
|
||||
/// The span from which the element originated, if any.
|
||||
pub span: Span,
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ impl HtmlElement {
|
|||
Self {
|
||||
tag,
|
||||
attrs: HtmlAttrs::default(),
|
||||
children: vec![],
|
||||
children: EcoVec::new(),
|
||||
span: Span::detached(),
|
||||
}
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ impl HtmlElement {
|
|||
/// Attach children to the element.
|
||||
///
|
||||
/// Note: This overwrites potential previous children.
|
||||
pub fn with_children(mut self, children: Vec<HtmlNode>) -> Self {
|
||||
pub fn with_children(mut self, children: EcoVec<HtmlNode>) -> Self {
|
||||
self.children = children;
|
||||
self
|
||||
}
|
||||
|
|
@ -337,7 +337,7 @@ pub struct HtmlFrame {
|
|||
/// An ID to assign to the SVG itself.
|
||||
pub id: Option<EcoString>,
|
||||
/// IDs to assign to destination jump points within the SVG.
|
||||
pub link_points: Vec<(Point, EcoString)>,
|
||||
pub link_points: EcoVec<(Point, EcoString)>,
|
||||
}
|
||||
|
||||
impl HtmlFrame {
|
||||
|
|
@ -347,7 +347,7 @@ impl HtmlFrame {
|
|||
inner,
|
||||
text_size: styles.resolve(TextElem::size),
|
||||
id: None,
|
||||
link_points: vec![],
|
||||
link_points: EcoVec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use comemo::{Track, Tracked, TrackedMut};
|
||||
use ecow::EcoVec;
|
||||
use typst_library::diag::{At, SourceResult};
|
||||
use typst_library::engine::{Engine, Route, Sink, Traced};
|
||||
use typst_library::foundations::{Content, StyleChain};
|
||||
|
|
@ -16,7 +17,7 @@ pub fn html_fragment(
|
|||
content: &Content,
|
||||
locator: Locator,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<Vec<HtmlNode>> {
|
||||
) -> SourceResult<EcoVec<HtmlNode>> {
|
||||
html_fragment_impl(
|
||||
engine.routines,
|
||||
engine.world,
|
||||
|
|
@ -43,7 +44,7 @@ fn html_fragment_impl(
|
|||
content: &Content,
|
||||
locator: Tracked<Locator>,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<Vec<HtmlNode>> {
|
||||
) -> SourceResult<EcoVec<HtmlNode>> {
|
||||
let link = LocatorLink::new(locator);
|
||||
let mut locator = Locator::link(&link).split();
|
||||
let mut engine = Engine {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::collections::VecDeque;
|
||||
|
||||
use comemo::Track;
|
||||
use ecow::{EcoString, eco_format};
|
||||
use ecow::{EcoString, EcoVec, eco_format, eco_vec};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use typst_library::foundations::{Label, NativeElement};
|
||||
use typst_library::introspection::{Introspector, Location, Tag};
|
||||
|
|
@ -75,11 +75,11 @@ fn traverse(
|
|||
work: &mut Work,
|
||||
targets: &FxHashSet<Location>,
|
||||
identificator: &mut Identificator<'_>,
|
||||
nodes: &mut Vec<HtmlNode>,
|
||||
nodes: &mut EcoVec<HtmlNode>,
|
||||
) {
|
||||
let mut i = 0;
|
||||
while i < nodes.len() {
|
||||
let node = &mut nodes[i];
|
||||
let node = &mut nodes.make_mut()[i];
|
||||
match node {
|
||||
// When visiting a start tag, we check whether the element needs an
|
||||
// ID and if so, add it to the queue, so that its first child node
|
||||
|
|
@ -115,7 +115,7 @@ fn traverse(
|
|||
HtmlNode::Text(..) => {
|
||||
work.drain(|label| {
|
||||
let mut element =
|
||||
HtmlElement::new(tag::span).with_children(vec![node.clone()]);
|
||||
HtmlElement::new(tag::span).with_children(eco_vec![node.clone()]);
|
||||
let id = identificator.assign(&mut element, label);
|
||||
*node = HtmlNode::Element(element);
|
||||
id
|
||||
|
|
@ -148,7 +148,7 @@ fn traverse_frame(
|
|||
targets: &FxHashSet<Location>,
|
||||
identificator: &mut Identificator<'_>,
|
||||
frame: &Frame,
|
||||
link_points: &mut Vec<(Point, EcoString)>,
|
||||
link_points: &mut EcoVec<(Point, EcoString)>,
|
||||
) {
|
||||
for (_, item) in frame.items() {
|
||||
match item {
|
||||
|
|
|
|||
Loading…
Reference in New Issue