mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-14 22:42:46 +00:00
Move IDML index serialization into shared model
This commit is contained in:
2 files changed
+70
-3
No files matched your search
@@ -45,9 +45,9 @@ pub use spread::{
|
||||
TextWrapPreference, spreads,
|
||||
};
|
||||
pub use story::{
|
||||
Ace, AnchoredObjectValues, CONTAINERS, Cell, CellOptions, Container, ContainerKind, ContentPart, PageReference, Range, SavedCrossReference,
|
||||
SavedCrossReferencePart, Story, StoryAnchor, StoryPreference, Table, TableChild, TableColumn, TableLayout, TableRow, TextNode, TrackedChangeKind,
|
||||
stories,
|
||||
Ace, AnchoredObjectValues, CONTAINERS, Cell, CellOptions, Container, ContainerKind, ContentPart, IndexCrossReferenceValues, IndexValues,
|
||||
PageReference, Range, SavedCrossReference, SavedCrossReferencePart, Story, StoryAnchor, StoryPreference, Table, TableChild, TableColumn,
|
||||
TableLayout, TableRow, TextNode, TrackedChangeKind, stories,
|
||||
};
|
||||
|
||||
use crate::value::{matrix, nums};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
//! anchored page items, hyperlink and change containers).
|
||||
|
||||
use craft_xml::{El, Local, Node};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use super::{PageItem, Values, tidy};
|
||||
|
||||
@@ -127,6 +128,72 @@ pub struct PageReference {
|
||||
pub values: Values,
|
||||
}
|
||||
|
||||
/// Nested index topics and their See / See also references for one IDML `Index`.
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct IndexValues {
|
||||
pub topics: BTreeMap<Vec<String>, String>,
|
||||
pub cross_references: Vec<IndexCrossReferenceValues>,
|
||||
}
|
||||
|
||||
/// An index cross-reference attached to a topic path.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct IndexCrossReferenceValues {
|
||||
pub from: Vec<String>,
|
||||
pub reference_type: String,
|
||||
pub target: String,
|
||||
}
|
||||
|
||||
impl IndexValues {
|
||||
/// Builds the IDML `Self` value for a topic path.
|
||||
pub fn topic_self(path: &[String]) -> String {
|
||||
let mut id = String::from("ix");
|
||||
for part in path {
|
||||
id.push_str("Topicn");
|
||||
id.push_str(&crate::value::escape_id(part));
|
||||
}
|
||||
id
|
||||
}
|
||||
|
||||
/// Writes the nested IDML index grammar, assigning a fresh ID to each cross-reference.
|
||||
pub fn to_el(&self, mut fresh: impl FnMut() -> String) -> El {
|
||||
let mut topics = self.topics.clone();
|
||||
for reference in &self.cross_references {
|
||||
topics.entry(vec![reference.target.clone()]).or_default();
|
||||
}
|
||||
|
||||
fn build(
|
||||
topics: &BTreeMap<Vec<String>, String>,
|
||||
references: &[IndexCrossReferenceValues],
|
||||
prefix: &[String],
|
||||
fresh: &mut impl FnMut() -> String,
|
||||
) -> Vec<El> {
|
||||
let mut out = Vec::new();
|
||||
for (path, sort_order) in topics.iter().filter(|(path, _)| path.len() == prefix.len() + 1 && path.starts_with(prefix)) {
|
||||
let mut element = El::new("Topic")
|
||||
.with_attr("Self", IndexValues::topic_self(path))
|
||||
.with_attr("SortOrder", sort_order)
|
||||
.with_attr("Name", path.last().map_or("", String::as_str));
|
||||
for reference in references.iter().filter(|reference| reference.from == *path) {
|
||||
element.push(
|
||||
El::new("CrossReference")
|
||||
.with_attr("Self", fresh())
|
||||
.with_attr("ReferencedTopic", IndexValues::topic_self(std::slice::from_ref(&reference.target)))
|
||||
.with_attr("CrossReferenceType", &reference.reference_type)
|
||||
.with_attr("CustomTypeString", ""),
|
||||
);
|
||||
}
|
||||
element.children.extend(build(topics, references, path, fresh).into_iter().map(Node::El));
|
||||
out.push(element);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
let mut element = El::new("Index").with_attr("Self", "ix");
|
||||
element.children = build(&topics, &self.cross_references, &[], &mut fresh).into_iter().map(Node::El).collect();
|
||||
element
|
||||
}
|
||||
}
|
||||
|
||||
/// Text saved inside an IDML `CrossReferenceSource` before the application regenerates it from
|
||||
/// the cross-reference format. Page-number variables are separate segments so callers can retain
|
||||
/// the last displayed page while mapping to their own text model.
|
||||
|
||||
Reference in new issue
Block a user