mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-14 06:22:24 +00:00
craft-rtf: WordCraft's RTF reader and writer on craft-wordmodel and craft-flow (feature doc) * Add craft-wordmodel: WordCraft's document model without its editing code WordCraft's crates/doc (wordcraft-doc, at 07f97737) moved as it is, so the DOCX, RTF, ODT and other text-format crates can read into and write from one model. Module paths, type names and serde attributes are unchanged: an app that re-exports the crate keeps its native file format. Left in the app: range editing (edit.rs), IME text and equation editing. Not model, and already in craft-libs: code pages (craft-rtf), the ZIP entry-count check (craft-opc), the compound-file guard (craft-cfb). The paragraph walks moved to walk.rs and the unit helpers of wordcraft-geom to geom.rs. * craft-wordmodel: math_tree, the arguments of an equation node and a walk over its runs The DOCX reader and writer walk an equation's runs. The walk and the child accessors it uses were in WordCraft's equation editor (math_edit.rs), which stays in the app; they are structure, not editing. * craft-wordmodel: keep the document operations (edit.rs) with the model The DOCX and RTF readers use them: alternative-format chunks are merged into a document with adopt_blocks, and a reader formats ranges with format_range and inserts objects. They operate on the document, not on a view, so they belong beside it. The tests that drove them come back with them; the paragraph walks stay in walk.rs and edit re-exports them. base64 0.23, as WordCraft and craft-offcrypto use. * Add craft-flow: the flow model the text formats map to, on craft-wordmodel WordCraft's crates/formats/src/model (07f97737) moved as it is: Flow, FBlock, Para, Inline, Fmt, tables and cells, pictures, to_doc and from_doc, picture sniffing, colours, base64 and the Dropped report. Only the paths changed (wordcraft_doc is craft_wordmodel); the report helpers are public so the format crates can call them; the image re-encoding helper stays with WordCraft's RTF writer. * wip: WordCraft's RTF interpreter, as it is * Take main's side of files outside craft-rtf * craft-rtf: WordCraft's RTF reader and writer as they are at wordcraft 07f97737 crates/formats/src/rtf.rs and crates/formats/src/rtf/, unchanged and not yet compiled (no module declares them), so the next commit shows only what the move changes. * craft-rtf: WordCraft's RTF reader and writer as craft_rtf::doc (feature doc) On craft-flow and craft-wordmodel, with this crate's code pages (craft-codepage), dates and escaping in place of WordCraft's copies, and craft-metafile's metafile sniffing. A picture in a format RTF cannot carry is re-encoded as PNG with a bounded decode (100 megapixels, 512 MiB), as WordCraft's picture decoder bounded it. The 76 tests moved with it.
61 lines
2.9 KiB
Rust
61 lines
2.9 KiB
Rust
//! Rich Text Format, read into and written from the word model (`craft_wordmodel::Document`)
|
|
//! through the text formats' flow (`craft_flow`). Feature `doc`.
|
|
//!
|
|
//! WordCraft's RTF reader and writer.
|
|
//!
|
|
//! Export: font and colour tables, a small stylesheet (headings with outline levels, Title,
|
|
//! Quote, Code), list tables (`\listtable` / `\listoverridetable` with `\listtext` labels for
|
|
//! older readers), document info, page setup, paragraph formatting (`\pard`, alignment, page
|
|
//! break before), character formatting (`\b \i \ul \strike \super \sub \f \fs \cf \chcbpat`),
|
|
//! hyperlinks as `HYPERLINK` fields, bookmarks, pictures (`\pngblip` / `\jpegblip`), tables
|
|
//! (`\trowd … \cellx … \cell … \row`, header rows, vertical merges, shading), footnotes and
|
|
//! endnotes (`{\super\chftn}{\footnote[\ftnalt] …}`) and comments (`{\*\atrfstart n}` …
|
|
//! `{\*\atrfend n}` around the commented text, then `{\*\atnid initials}{\*\atnauthor name}`
|
|
//! `\chatn{\*\annotation{\*\atnref n}{\*\atndate …}` text `}`).
|
|
//!
|
|
//! Import: a tolerant reader for groups and destinations (unknown `\*` destinations and objects
|
|
//! are skipped; headers, footers, notes and comments are read into stories of their own),
|
|
//! `\par \line \tab \page`, `\uN` with `\ucN`
|
|
//! fallback skipping, `\'hh` and 8-bit text in the document's code page (`\ansicpg`, `\mac`, `\pc`, `\pca`) or
|
|
//! the current font's (`\fcharset`, `\cpg`: Cyrillic, Central European, Greek, Mac OS Roman, the
|
|
//! East Asian multibyte pages 932/936/949/950…; Windows-1252 when none is named). A multibyte
|
|
//! code page's bytes stream through one decoder, so a lead byte and its trail byte decode
|
|
//! together and a run that looks like a UTF-8 BOM is not mistaken for one; the formatting words
|
|
//! above, stylesheet-based
|
|
//! headings and `\outlinelevel`, lists through `\ls`/`\ilvl`, fields, bookmarks, pictures and
|
|
//! tables, footnotes, endnotes (`\footnote` with `\ftnalt`) and comments (author, initials, date,
|
|
//! text, the commented range). Group nesting, picture sizes and the number of notes and comments
|
|
//! are capped. Not kept: custom note marks, comment replies (`\atnparent`), notes inside
|
|
//! headers, footers and other notes, tables inside note and comment texts (flattened).
|
|
|
|
use std::collections::{HashMap, HashSet};
|
|
use std::sync::Arc;
|
|
|
|
use craft_wordmodel::props::VAlign;
|
|
use craft_wordmodel::{Align, Block, Blocks, Document, InlineObject, Paragraph, Rgb};
|
|
|
|
use craft_flow::{self as model, Cell, FBlock, FTable, Flow, Fmt, Inline, Kind, ListInfo, Meta, Para, RevMark, make_img};
|
|
|
|
use crate::date;
|
|
mod export;
|
|
mod parse;
|
|
mod reader;
|
|
mod state;
|
|
mod styles;
|
|
mod text;
|
|
mod word;
|
|
|
|
pub use date::{dttm_to_iso, iso_to_dttm};
|
|
#[cfg(test)]
|
|
use export::{Tables, Writer};
|
|
pub use export::{esc, export};
|
|
pub use parse::{import, parse};
|
|
use reader::Reader;
|
|
#[cfg(test)]
|
|
use state::MAX_SECTIONS;
|
|
#[cfg(test)]
|
|
use word::hyperlink;
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|