1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// The clipboard port mirrors the React `clipboardHtml.ts` module
// structure deliberately; several pedantic lints fire on idiomatic
// patterns (boolean-heavy mark sets, identical match arms for text
// node dispatch, explicit closures that document intent better than
// bare fn references, etc.). We allow them at the crate level so the
// port stays side-by-side comparable with the upstream TS.
//
// This list has been aggressively trimmed. Each remaining allow has a
// justification in this comment block:
//
// - `struct_excessive_bools`: `MarkSet` carries 5 booleans for the 5
// boolean marks. Refactoring into a bitflags struct would obscure the
// 1:1 correspondence with the TS mark names.
// - `too_many_lines`: `visit_block` is one long dispatch `match` — each
// tag handler is short but there are many of them.
// - `module_name_repetitions`: `HtmlError` alongside the `html` module.
// - `doc_markdown`: English prose in doc comments contains backtick-free
// references (Notion, Word) that pedantic lint flags as missing code
// fences.
// - `match_same_arms`: `handle_dispatch` has multiple arms that return
// the same paragraph fallback for distinct tag names — explicit for
// readability.
// - `similar_names`: `open_idx` / `close_idx` are the established naming
// from the TS source; renaming loses parity.
// - `missing_errors_doc` / `missing_panics_doc`: all public errors are
// documented on the `HtmlError` enum; per-fn boilerplate is noise.
// - `must_use_candidate`: every public function here has semantics where
// ignoring the return would be ambiguous (debug logging, side-channel
// validation in tests). `#[must_use]` is applied selectively where it
// adds value.
//! HTML ↔ [`devup_editor_core::Document`] conversion for the devup editor.
//!
//! Implements [`DocumentExport`] and [`DocumentImport`] from
//! `devup-editor-core`, plus a clipboard-oriented API
//! ([`blocks_to_html`] / [`html_to_copied_blocks`]) that mirrors the
//! behaviour of the React TypeScript `clipboardHtml.ts` exactly so
//! clipboard interop with Word / Notion / Google Docs keeps working.
//!
//! ## Structural support
//!
//! Export and import both cover:
//! - Headings (h1–h6)
//! - Paragraphs (p)
//! - Quotes (blockquote)
//! - Pre / code (language class preserved)
//! - Unordered & ordered lists (with nested indent tracking)
//! - Todo lists (via `<ul data-devup-type="todo">` marker OR
//! `<input type="checkbox">` heuristic OR Notion `<ul class="to-do-list">`)
//! - Dividers (hr)
//! - Toggle blocks: `<details><summary>`, Notion `<ul class="toggle">`,
//! plus Notion v3's `<li>`-with-multiple-block-children heuristic
//! - Tables: `colspan`, `rowspan`, `<colgroup>` widths, cell / row /
//! table styling via `data-devup-props` marker and inline `style=""`
//!
//! Marks on export wrap text in `<strong>`, `<em>`, `<u>`, `<s>`,
//! `<code>`, `<a href="…" rel="noopener noreferrer">`, and
//! `<span style="color:…">` / `<span style="background-color:…">` for
//! color / highlight. Unknown mark types survive via a
//! `<span data-mark="type">` fallback so copy never silently drops text.
//!
//! ## Clipboard-specific features
//!
//! The [`clipboard`](crate::clipboard) module provides:
//! - [`encode_props`] / [`decode_props`] — base64+JSON round-trip marker
//! (`data-devup-props="…"`) for lossless devup→devup copy/paste of
//! table prop maps.
//! - [`clean_html`] — strips Word / HWP preprocessing artifacts
//! (`<!--StartFragment-->`, `<o:p>` tags) before parsing.
//!
//! See [`CopiedBlocks`] for the clipboard subtree shape used by the
//! React layer.
pub use ;
pub use ;
pub use html_to_copied_blocks;
pub use slice_content;
/// Test-only re-export of the internal `is_safe_href` helper so the
/// parity integration test (`tests/href_parity.rs`) can reach it. Not
/// part of the stable public API — production callers should use the
/// link-aware serialisation via `blocks_to_html` instead.
use Error;