html-to-markdown 3.4.0 → 3.6.0.pre.rc.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +21 -0
- data/README.md +347 -0
- data/Steepfile +10 -2
- data/ext/html_to_markdown_rb/Cargo.toml +3 -2
- data/ext/html_to_markdown_rb/extconf.rb +5 -5
- data/ext/html_to_markdown_rb/native/Cargo.lock +962 -0
- data/ext/html_to_markdown_rb/native/Cargo.toml +6 -11
- data/ext/html_to_markdown_rb/native/extconf.rb +14 -0
- data/ext/html_to_markdown_rb/src/lib.rs +1715 -646
- data/lib/html_to_markdown/native.rb +913 -37
- data/lib/html_to_markdown/version.rb +3 -3
- data/lib/html_to_markdown.rb +9 -4
- data/lib/html_to_markdown_rb.so +0 -0
- data/sig/types.rbs +59 -292
- metadata +32 -179
- data/ext/html_to_markdown_rb/Makefile +0 -592
- data/lib/bin/html-to-markdown +0 -0
- data/vendor/Cargo.toml +0 -33
- data/vendor/html-to-markdown-rs/Cargo.toml +0 -54
- data/vendor/html-to-markdown-rs/README.md +0 -278
- data/vendor/html-to-markdown-rs/examples/basic.rs +0 -24
- data/vendor/html-to-markdown-rs/examples/table.rs +0 -25
- data/vendor/html-to-markdown-rs/examples/test_deser.rs +0 -12
- data/vendor/html-to-markdown-rs/examples/test_escape.rs +0 -58
- data/vendor/html-to-markdown-rs/examples/test_inline_formatting.rs +0 -113
- data/vendor/html-to-markdown-rs/examples/test_lists.rs +0 -39
- data/vendor/html-to-markdown-rs/examples/test_semantic_tags.rs +0 -89
- data/vendor/html-to-markdown-rs/examples/test_tables.rs +0 -100
- data/vendor/html-to-markdown-rs/examples/test_task_lists.rs +0 -61
- data/vendor/html-to-markdown-rs/examples/test_whitespace.rs +0 -34
- data/vendor/html-to-markdown-rs/src/convert_api.rs +0 -349
- data/vendor/html-to-markdown-rs/src/converter/block/blockquote.rs +0 -178
- data/vendor/html-to-markdown-rs/src/converter/block/container.rs +0 -114
- data/vendor/html-to-markdown-rs/src/converter/block/div.rs +0 -149
- data/vendor/html-to-markdown-rs/src/converter/block/heading.rs +0 -428
- data/vendor/html-to-markdown-rs/src/converter/block/horizontal_rule.rs +0 -103
- data/vendor/html-to-markdown-rs/src/converter/block/line_break.rs +0 -89
- data/vendor/html-to-markdown-rs/src/converter/block/mod.rs +0 -10
- data/vendor/html-to-markdown-rs/src/converter/block/paragraph.rs +0 -140
- data/vendor/html-to-markdown-rs/src/converter/block/preformatted.rs +0 -298
- data/vendor/html-to-markdown-rs/src/converter/block/table/builder.rs +0 -453
- data/vendor/html-to-markdown-rs/src/converter/block/table/caption.rs +0 -44
- data/vendor/html-to-markdown-rs/src/converter/block/table/cell.rs +0 -276
- data/vendor/html-to-markdown-rs/src/converter/block/table/cells.rs +0 -336
- data/vendor/html-to-markdown-rs/src/converter/block/table/layout.rs +0 -58
- data/vendor/html-to-markdown-rs/src/converter/block/table/mod.rs +0 -266
- data/vendor/html-to-markdown-rs/src/converter/block/table/scanner.rs +0 -146
- data/vendor/html-to-markdown-rs/src/converter/block/table/utils.rs +0 -34
- data/vendor/html-to-markdown-rs/src/converter/block/unknown.rs +0 -138
- data/vendor/html-to-markdown-rs/src/converter/context.rs +0 -208
- data/vendor/html-to-markdown-rs/src/converter/dom_context.rs +0 -337
- data/vendor/html-to-markdown-rs/src/converter/form/elements.rs +0 -770
- data/vendor/html-to-markdown-rs/src/converter/form/mod.rs +0 -82
- data/vendor/html-to-markdown-rs/src/converter/format/djot.rs +0 -64
- data/vendor/html-to-markdown-rs/src/converter/format/markdown.rs +0 -59
- data/vendor/html-to-markdown-rs/src/converter/format/mod.rs +0 -43
- data/vendor/html-to-markdown-rs/src/converter/handlers/blockquote.rs +0 -173
- data/vendor/html-to-markdown-rs/src/converter/handlers/code_block.rs +0 -434
- data/vendor/html-to-markdown-rs/src/converter/handlers/graphic.rs +0 -234
- data/vendor/html-to-markdown-rs/src/converter/handlers/image.rs +0 -282
- data/vendor/html-to-markdown-rs/src/converter/handlers/link.rs +0 -316
- data/vendor/html-to-markdown-rs/src/converter/handlers/mod.rs +0 -26
- data/vendor/html-to-markdown-rs/src/converter/inline/code.rs +0 -306
- data/vendor/html-to-markdown-rs/src/converter/inline/emphasis.rs +0 -345
- data/vendor/html-to-markdown-rs/src/converter/inline/link.rs +0 -428
- data/vendor/html-to-markdown-rs/src/converter/inline/mod.rs +0 -237
- data/vendor/html-to-markdown-rs/src/converter/inline/ruby.rs +0 -337
- data/vendor/html-to-markdown-rs/src/converter/inline/semantic/marks.rs +0 -566
- data/vendor/html-to-markdown-rs/src/converter/inline/semantic/mod.rs +0 -86
- data/vendor/html-to-markdown-rs/src/converter/inline/semantic/typography.rs +0 -558
- data/vendor/html-to-markdown-rs/src/converter/list/definition.rs +0 -232
- data/vendor/html-to-markdown-rs/src/converter/list/item.rs +0 -332
- data/vendor/html-to-markdown-rs/src/converter/list/mod.rs +0 -70
- data/vendor/html-to-markdown-rs/src/converter/list/ordered.rs +0 -201
- data/vendor/html-to-markdown-rs/src/converter/list/unordered.rs +0 -195
- data/vendor/html-to-markdown-rs/src/converter/list/utils.rs +0 -314
- data/vendor/html-to-markdown-rs/src/converter/main.rs +0 -710
- data/vendor/html-to-markdown-rs/src/converter/main_helpers.rs +0 -452
- data/vendor/html-to-markdown-rs/src/converter/media/embedded.rs +0 -393
- data/vendor/html-to-markdown-rs/src/converter/media/graphic.rs +0 -4
- data/vendor/html-to-markdown-rs/src/converter/media/image.rs +0 -183
- data/vendor/html-to-markdown-rs/src/converter/media/mod.rs +0 -87
- data/vendor/html-to-markdown-rs/src/converter/media/svg.rs +0 -280
- data/vendor/html-to-markdown-rs/src/converter/metadata.rs +0 -220
- data/vendor/html-to-markdown-rs/src/converter/mod.rs +0 -156
- data/vendor/html-to-markdown-rs/src/converter/plain_text.rs +0 -516
- data/vendor/html-to-markdown-rs/src/converter/preprocessing_helpers.rs +0 -201
- data/vendor/html-to-markdown-rs/src/converter/reference_collector.rs +0 -69
- data/vendor/html-to-markdown-rs/src/converter/semantic/attributes.rs +0 -269
- data/vendor/html-to-markdown-rs/src/converter/semantic/definition_list.rs +0 -266
- data/vendor/html-to-markdown-rs/src/converter/semantic/figure.rs +0 -391
- data/vendor/html-to-markdown-rs/src/converter/semantic/mod.rs +0 -112
- data/vendor/html-to-markdown-rs/src/converter/semantic/sectioning.rs +0 -85
- data/vendor/html-to-markdown-rs/src/converter/semantic/summary.rs +0 -324
- data/vendor/html-to-markdown-rs/src/converter/text/mod.rs +0 -8
- data/vendor/html-to-markdown-rs/src/converter/text/processing.rs +0 -56
- data/vendor/html-to-markdown-rs/src/converter/text_node.rs +0 -269
- data/vendor/html-to-markdown-rs/src/converter/utility/attributes.rs +0 -151
- data/vendor/html-to-markdown-rs/src/converter/utility/caching.rs +0 -74
- data/vendor/html-to-markdown-rs/src/converter/utility/content.rs +0 -271
- data/vendor/html-to-markdown-rs/src/converter/utility/mod.rs +0 -17
- data/vendor/html-to-markdown-rs/src/converter/utility/preprocessing.rs +0 -1002
- data/vendor/html-to-markdown-rs/src/converter/utility/serialization.rs +0 -126
- data/vendor/html-to-markdown-rs/src/converter/utility/siblings.rs +0 -97
- data/vendor/html-to-markdown-rs/src/converter/visitor_hooks.rs +0 -189
- data/vendor/html-to-markdown-rs/src/error.rs +0 -43
- data/vendor/html-to-markdown-rs/src/exports.rs +0 -24
- data/vendor/html-to-markdown-rs/src/inline_images.rs +0 -336
- data/vendor/html-to-markdown-rs/src/lib.rs +0 -139
- data/vendor/html-to-markdown-rs/src/metadata/collector.rs +0 -457
- data/vendor/html-to-markdown-rs/src/metadata/config.rs +0 -394
- data/vendor/html-to-markdown-rs/src/metadata/extraction.rs +0 -398
- data/vendor/html-to-markdown-rs/src/metadata/mod.rs +0 -288
- data/vendor/html-to-markdown-rs/src/metadata/types.rs +0 -477
- data/vendor/html-to-markdown-rs/src/options/conversion.rs +0 -559
- data/vendor/html-to-markdown-rs/src/options/inline_image.rs +0 -111
- data/vendor/html-to-markdown-rs/src/options/mod.rs +0 -20
- data/vendor/html-to-markdown-rs/src/options/preprocessing.rs +0 -201
- data/vendor/html-to-markdown-rs/src/options/validation.rs +0 -416
- data/vendor/html-to-markdown-rs/src/prelude.rs +0 -1
- data/vendor/html-to-markdown-rs/src/rcdom.rs +0 -487
- data/vendor/html-to-markdown-rs/src/text.rs +0 -358
- data/vendor/html-to-markdown-rs/src/types/document.rs +0 -191
- data/vendor/html-to-markdown-rs/src/types/mod.rs +0 -17
- data/vendor/html-to-markdown-rs/src/types/result.rs +0 -54
- data/vendor/html-to-markdown-rs/src/types/structure_builder.rs +0 -791
- data/vendor/html-to-markdown-rs/src/types/structure_collector.rs +0 -483
- data/vendor/html-to-markdown-rs/src/types/tables.rs +0 -52
- data/vendor/html-to-markdown-rs/src/types/warnings.rs +0 -33
- data/vendor/html-to-markdown-rs/src/validation.rs +0 -158
- data/vendor/html-to-markdown-rs/src/visitor/default_impl.rs +0 -63
- data/vendor/html-to-markdown-rs/src/visitor/mod.rs +0 -41
- data/vendor/html-to-markdown-rs/src/visitor/traits.rs +0 -370
- data/vendor/html-to-markdown-rs/src/visitor/types.rs +0 -319
- data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/callbacks/mod.rs +0 -1
- data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/content.rs +0 -126
- data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/mod.rs +0 -27
- data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/state.rs +0 -110
- data/vendor/html-to-markdown-rs/src/visitor_helpers/helpers/traversal.rs +0 -250
- data/vendor/html-to-markdown-rs/src/visitor_helpers.rs +0 -597
- data/vendor/html-to-markdown-rs/src/wrapper/sync.rs +0 -413
- data/vendor/html-to-markdown-rs/src/wrapper/utils.rs +0 -290
- data/vendor/html-to-markdown-rs/src/wrapper.rs +0 -9
- data/vendor/html-to-markdown-rs/tests/br_in_inline_test.rs +0 -87
- data/vendor/html-to-markdown-rs/tests/commonmark_compliance_test.rs +0 -297
- data/vendor/html-to-markdown-rs/tests/djot_output_test.rs +0 -153
- data/vendor/html-to-markdown-rs/tests/exclude_selectors_test.rs +0 -132
- data/vendor/html-to-markdown-rs/tests/integration_test.rs +0 -631
- data/vendor/html-to-markdown-rs/tests/issue_121_regressions.rs +0 -49
- data/vendor/html-to-markdown-rs/tests/issue_127_regressions.rs +0 -58
- data/vendor/html-to-markdown-rs/tests/issue_128_regressions.rs +0 -17
- data/vendor/html-to-markdown-rs/tests/issue_131_regressions.rs +0 -41
- data/vendor/html-to-markdown-rs/tests/issue_134_regressions.rs +0 -40
- data/vendor/html-to-markdown-rs/tests/issue_139_regressions.rs +0 -26
- data/vendor/html-to-markdown-rs/tests/issue_140_regressions.rs +0 -185
- data/vendor/html-to-markdown-rs/tests/issue_143_regressions.rs +0 -100
- data/vendor/html-to-markdown-rs/tests/issue_145_regressions.rs +0 -133
- data/vendor/html-to-markdown-rs/tests/issue_146_regressions.rs +0 -144
- data/vendor/html-to-markdown-rs/tests/issue_176_regressions.rs +0 -62
- data/vendor/html-to-markdown-rs/tests/issue_190_regressions.rs +0 -128
- data/vendor/html-to-markdown-rs/tests/issue_199_regressions.rs +0 -20
- data/vendor/html-to-markdown-rs/tests/issue_200_regressions.rs +0 -62
- data/vendor/html-to-markdown-rs/tests/issue_212_regressions.rs +0 -68
- data/vendor/html-to-markdown-rs/tests/issue_216_217_regressions.rs +0 -87
- data/vendor/html-to-markdown-rs/tests/issue_336_regressions.rs +0 -74
- data/vendor/html-to-markdown-rs/tests/issue_339_regressions.rs +0 -92
- data/vendor/html-to-markdown-rs/tests/issue_347_regressions.rs +0 -154
- data/vendor/html-to-markdown-rs/tests/issue_348_visitor_plain.rs +0 -93
- data/vendor/html-to-markdown-rs/tests/json_ld_script_extraction.rs +0 -44
- data/vendor/html-to-markdown-rs/tests/lists_test.rs +0 -199
- data/vendor/html-to-markdown-rs/tests/plain_output_test.rs +0 -273
- data/vendor/html-to-markdown-rs/tests/preprocessing_tests.rs +0 -61
- data/vendor/html-to-markdown-rs/tests/reference_links_test.rs +0 -169
- data/vendor/html-to-markdown-rs/tests/sectioning_elements_test.rs +0 -137
- data/vendor/html-to-markdown-rs/tests/skip_images_test.rs +0 -522
- data/vendor/html-to-markdown-rs/tests/tables_test.rs +0 -743
- data/vendor/html-to-markdown-rs/tests/test_custom_elements.rs +0 -41
- data/vendor/html-to-markdown-rs/tests/test_issue_187.rs +0 -204
- data/vendor/html-to-markdown-rs/tests/test_issue_218.rs +0 -68
- data/vendor/html-to-markdown-rs/tests/test_issue_277.rs +0 -77
- data/vendor/html-to-markdown-rs/tests/test_max_depth.rs +0 -82
- data/vendor/html-to-markdown-rs/tests/test_nested_simple.rs +0 -45
- data/vendor/html-to-markdown-rs/tests/test_script_style_stripping.rs +0 -396
- data/vendor/html-to-markdown-rs/tests/test_spa_bisect.rs +0 -34
- data/vendor/html-to-markdown-rs/tests/visitor_code_integration_test.rs +0 -121
- data/vendor/html-to-markdown-rs/tests/visitor_integration_test.rs +0 -1190
- data/vendor/html-to-markdown-rs/tests/xml_tables_test.rs +0 -372
|
@@ -1,477 +0,0 @@
|
|
|
1
|
-
#![allow(clippy::cast_precision_loss, clippy::cast_sign_loss, clippy::unused_self)]
|
|
2
|
-
//! Type definitions for metadata extraction.
|
|
3
|
-
|
|
4
|
-
use std::collections::BTreeMap;
|
|
5
|
-
|
|
6
|
-
/// Text directionality of document content.
|
|
7
|
-
///
|
|
8
|
-
/// Corresponds to the HTML `dir` attribute and `bdi` element directionality.
|
|
9
|
-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
10
|
-
#[cfg_attr(feature = "metadata", derive(serde::Serialize, serde::Deserialize))]
|
|
11
|
-
pub enum TextDirection {
|
|
12
|
-
/// Left-to-right text flow (default for Latin scripts)
|
|
13
|
-
#[cfg_attr(feature = "metadata", serde(rename = "ltr"))]
|
|
14
|
-
LeftToRight,
|
|
15
|
-
/// Right-to-left text flow (Hebrew, Arabic, Urdu, etc.)
|
|
16
|
-
#[cfg_attr(feature = "metadata", serde(rename = "rtl"))]
|
|
17
|
-
RightToLeft,
|
|
18
|
-
/// Automatic directionality detection
|
|
19
|
-
#[cfg_attr(feature = "metadata", serde(rename = "auto"))]
|
|
20
|
-
Auto,
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
impl std::fmt::Display for TextDirection {
|
|
24
|
-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
25
|
-
match self {
|
|
26
|
-
Self::LeftToRight => write!(f, "ltr"),
|
|
27
|
-
Self::RightToLeft => write!(f, "rtl"),
|
|
28
|
-
Self::Auto => write!(f, "auto"),
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
impl TextDirection {
|
|
34
|
-
/// Parse a text direction from string value.
|
|
35
|
-
///
|
|
36
|
-
/// # Arguments
|
|
37
|
-
///
|
|
38
|
-
/// * `s` - Direction string ("ltr", "rtl", or "auto")
|
|
39
|
-
///
|
|
40
|
-
/// # Returns
|
|
41
|
-
///
|
|
42
|
-
/// `Some(TextDirection)` if valid, `None` otherwise.
|
|
43
|
-
///
|
|
44
|
-
/// # Examples
|
|
45
|
-
///
|
|
46
|
-
/// ```
|
|
47
|
-
/// # use html_to_markdown_rs::metadata::TextDirection;
|
|
48
|
-
/// assert_eq!(TextDirection::parse("ltr"), Some(TextDirection::LeftToRight));
|
|
49
|
-
/// assert_eq!(TextDirection::parse("rtl"), Some(TextDirection::RightToLeft));
|
|
50
|
-
/// assert_eq!(TextDirection::parse("auto"), Some(TextDirection::Auto));
|
|
51
|
-
/// assert_eq!(TextDirection::parse("invalid"), None);
|
|
52
|
-
/// ```
|
|
53
|
-
#[must_use]
|
|
54
|
-
pub fn parse(s: &str) -> Option<Self> {
|
|
55
|
-
if s.eq_ignore_ascii_case("ltr") {
|
|
56
|
-
return Some(Self::LeftToRight);
|
|
57
|
-
}
|
|
58
|
-
if s.eq_ignore_ascii_case("rtl") {
|
|
59
|
-
return Some(Self::RightToLeft);
|
|
60
|
-
}
|
|
61
|
-
if s.eq_ignore_ascii_case("auto") {
|
|
62
|
-
return Some(Self::Auto);
|
|
63
|
-
}
|
|
64
|
-
None
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/// Link classification based on href value and document context.
|
|
69
|
-
///
|
|
70
|
-
/// Used to categorize links during extraction for filtering and analysis.
|
|
71
|
-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
72
|
-
#[cfg_attr(feature = "metadata", derive(serde::Serialize, serde::Deserialize))]
|
|
73
|
-
#[cfg_attr(feature = "metadata", serde(rename_all = "snake_case"))]
|
|
74
|
-
pub enum LinkType {
|
|
75
|
-
/// Anchor link within same document (href starts with #)
|
|
76
|
-
Anchor,
|
|
77
|
-
/// Internal link within same domain
|
|
78
|
-
Internal,
|
|
79
|
-
/// External link to different domain
|
|
80
|
-
External,
|
|
81
|
-
/// Email link (mailto:)
|
|
82
|
-
Email,
|
|
83
|
-
/// Phone link (tel:)
|
|
84
|
-
Phone,
|
|
85
|
-
/// Other protocol or unclassifiable
|
|
86
|
-
Other,
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
impl std::fmt::Display for LinkType {
|
|
90
|
-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
91
|
-
match self {
|
|
92
|
-
Self::Anchor => write!(f, "anchor"),
|
|
93
|
-
Self::Internal => write!(f, "internal"),
|
|
94
|
-
Self::External => write!(f, "external"),
|
|
95
|
-
Self::Email => write!(f, "email"),
|
|
96
|
-
Self::Phone => write!(f, "phone"),
|
|
97
|
-
Self::Other => write!(f, "other"),
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/// Image source classification for proper handling and processing.
|
|
103
|
-
///
|
|
104
|
-
/// Determines whether an image is embedded (data URI), inline SVG, external, or relative.
|
|
105
|
-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
106
|
-
#[cfg_attr(feature = "metadata", derive(serde::Serialize, serde::Deserialize))]
|
|
107
|
-
#[cfg_attr(feature = "metadata", serde(rename_all = "snake_case"))]
|
|
108
|
-
pub enum ImageType {
|
|
109
|
-
/// Data URI embedded image (base64 or other encoding)
|
|
110
|
-
DataUri,
|
|
111
|
-
/// Inline SVG element
|
|
112
|
-
InlineSvg,
|
|
113
|
-
/// External image URL (http/https)
|
|
114
|
-
External,
|
|
115
|
-
/// Relative image path
|
|
116
|
-
Relative,
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
impl std::fmt::Display for ImageType {
|
|
120
|
-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
121
|
-
match self {
|
|
122
|
-
Self::DataUri => write!(f, "data_uri"),
|
|
123
|
-
Self::InlineSvg => write!(f, "inline_svg"),
|
|
124
|
-
Self::External => write!(f, "external"),
|
|
125
|
-
Self::Relative => write!(f, "relative"),
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/// Structured data format type.
|
|
131
|
-
///
|
|
132
|
-
/// Identifies the schema/format used for structured data markup.
|
|
133
|
-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
134
|
-
#[cfg_attr(feature = "metadata", derive(serde::Serialize, serde::Deserialize))]
|
|
135
|
-
#[cfg_attr(feature = "metadata", serde(rename_all = "snake_case"))]
|
|
136
|
-
pub enum StructuredDataType {
|
|
137
|
-
/// JSON-LD (JSON for Linking Data) script blocks
|
|
138
|
-
#[cfg_attr(feature = "metadata", serde(rename = "json_ld"))]
|
|
139
|
-
JsonLd,
|
|
140
|
-
/// HTML5 Microdata attributes (itemscope, itemtype, itemprop)
|
|
141
|
-
Microdata,
|
|
142
|
-
/// RDF in Attributes (RDFa) markup
|
|
143
|
-
#[cfg_attr(feature = "metadata", serde(rename = "rdfa"))]
|
|
144
|
-
RDFa,
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
impl std::fmt::Display for StructuredDataType {
|
|
148
|
-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
149
|
-
match self {
|
|
150
|
-
Self::JsonLd => write!(f, "json_ld"),
|
|
151
|
-
Self::Microdata => write!(f, "microdata"),
|
|
152
|
-
Self::RDFa => write!(f, "rdfa"),
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/// Document-level metadata extracted from `<head>` and top-level elements.
|
|
158
|
-
///
|
|
159
|
-
/// Contains all metadata typically used by search engines, social media platforms,
|
|
160
|
-
/// and browsers for document indexing and presentation.
|
|
161
|
-
///
|
|
162
|
-
/// # Examples
|
|
163
|
-
///
|
|
164
|
-
/// ```
|
|
165
|
-
/// # use html_to_markdown_rs::metadata::DocumentMetadata;
|
|
166
|
-
/// let doc = DocumentMetadata {
|
|
167
|
-
/// title: Some("My Article".to_string()),
|
|
168
|
-
/// description: Some("A great article about Rust".to_string()),
|
|
169
|
-
/// keywords: vec!["rust".to_string(), "programming".to_string()],
|
|
170
|
-
/// ..Default::default()
|
|
171
|
-
/// };
|
|
172
|
-
///
|
|
173
|
-
/// assert_eq!(doc.title, Some("My Article".to_string()));
|
|
174
|
-
/// ```
|
|
175
|
-
#[derive(Debug, Clone, Default)]
|
|
176
|
-
#[cfg_attr(feature = "metadata", derive(serde::Serialize, serde::Deserialize))]
|
|
177
|
-
pub struct DocumentMetadata {
|
|
178
|
-
/// Document title from `<title>` tag
|
|
179
|
-
pub title: Option<String>,
|
|
180
|
-
|
|
181
|
-
/// Document description from `<meta name="description">` tag
|
|
182
|
-
pub description: Option<String>,
|
|
183
|
-
|
|
184
|
-
/// Document keywords from `<meta name="keywords">` tag, split on commas
|
|
185
|
-
pub keywords: Vec<String>,
|
|
186
|
-
|
|
187
|
-
/// Document author from `<meta name="author">` tag
|
|
188
|
-
pub author: Option<String>,
|
|
189
|
-
|
|
190
|
-
/// Canonical URL from `<link rel="canonical">` tag
|
|
191
|
-
pub canonical_url: Option<String>,
|
|
192
|
-
|
|
193
|
-
/// Base URL from `<base href="">` tag for resolving relative URLs
|
|
194
|
-
pub base_href: Option<String>,
|
|
195
|
-
|
|
196
|
-
/// Document language from `lang` attribute
|
|
197
|
-
pub language: Option<String>,
|
|
198
|
-
|
|
199
|
-
/// Document text direction from `dir` attribute
|
|
200
|
-
pub text_direction: Option<TextDirection>,
|
|
201
|
-
|
|
202
|
-
/// Open Graph metadata (og:* properties) for social media
|
|
203
|
-
/// Keys like "title", "description", "image", "url", etc.
|
|
204
|
-
pub open_graph: BTreeMap<String, String>,
|
|
205
|
-
|
|
206
|
-
/// Twitter Card metadata (twitter:* properties)
|
|
207
|
-
/// Keys like "card", "site", "creator", "title", "description", "image", etc.
|
|
208
|
-
pub twitter_card: BTreeMap<String, String>,
|
|
209
|
-
|
|
210
|
-
/// Additional meta tags not covered by specific fields
|
|
211
|
-
/// Keys are meta name/property attributes, values are content
|
|
212
|
-
pub meta_tags: BTreeMap<String, String>,
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/// Header element metadata with hierarchy tracking.
|
|
216
|
-
///
|
|
217
|
-
/// Captures heading elements (h1-h6) with their text content, identifiers,
|
|
218
|
-
/// and position in the document structure.
|
|
219
|
-
///
|
|
220
|
-
/// # Examples
|
|
221
|
-
///
|
|
222
|
-
/// ```
|
|
223
|
-
/// # use html_to_markdown_rs::metadata::HeaderMetadata;
|
|
224
|
-
/// let header = HeaderMetadata {
|
|
225
|
-
/// level: 1,
|
|
226
|
-
/// text: "Main Title".to_string(),
|
|
227
|
-
/// id: Some("main-title".to_string()),
|
|
228
|
-
/// depth: 0,
|
|
229
|
-
/// html_offset: 145,
|
|
230
|
-
/// };
|
|
231
|
-
///
|
|
232
|
-
/// assert_eq!(header.level, 1);
|
|
233
|
-
/// assert!(header.is_valid());
|
|
234
|
-
/// ```
|
|
235
|
-
#[derive(Debug, Clone)]
|
|
236
|
-
#[cfg_attr(feature = "metadata", derive(serde::Serialize, serde::Deserialize))]
|
|
237
|
-
pub struct HeaderMetadata {
|
|
238
|
-
/// Header level: 1 (h1) through 6 (h6)
|
|
239
|
-
pub level: u8,
|
|
240
|
-
|
|
241
|
-
/// Normalized text content of the header
|
|
242
|
-
pub text: String,
|
|
243
|
-
|
|
244
|
-
/// HTML id attribute if present
|
|
245
|
-
pub id: Option<String>,
|
|
246
|
-
|
|
247
|
-
/// Document tree depth at the header element
|
|
248
|
-
pub depth: usize,
|
|
249
|
-
|
|
250
|
-
/// Byte offset in original HTML document
|
|
251
|
-
pub html_offset: usize,
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
impl HeaderMetadata {
|
|
255
|
-
/// Validate that the header level is within valid range (1-6).
|
|
256
|
-
///
|
|
257
|
-
/// # Returns
|
|
258
|
-
///
|
|
259
|
-
/// `true` if level is 1-6, `false` otherwise.
|
|
260
|
-
///
|
|
261
|
-
/// # Examples
|
|
262
|
-
///
|
|
263
|
-
/// ```
|
|
264
|
-
/// # use html_to_markdown_rs::metadata::HeaderMetadata;
|
|
265
|
-
/// let valid = HeaderMetadata {
|
|
266
|
-
/// level: 3,
|
|
267
|
-
/// text: "Title".to_string(),
|
|
268
|
-
/// id: None,
|
|
269
|
-
/// depth: 2,
|
|
270
|
-
/// html_offset: 100,
|
|
271
|
-
/// };
|
|
272
|
-
/// assert!(valid.is_valid());
|
|
273
|
-
///
|
|
274
|
-
/// let invalid = HeaderMetadata {
|
|
275
|
-
/// level: 7, // Invalid
|
|
276
|
-
/// text: "Title".to_string(),
|
|
277
|
-
/// id: None,
|
|
278
|
-
/// depth: 2,
|
|
279
|
-
/// html_offset: 100,
|
|
280
|
-
/// };
|
|
281
|
-
/// assert!(!invalid.is_valid());
|
|
282
|
-
/// ```
|
|
283
|
-
#[must_use]
|
|
284
|
-
pub const fn is_valid(&self) -> bool {
|
|
285
|
-
self.level >= 1 && self.level <= 6
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/// Hyperlink metadata with categorization and attributes.
|
|
290
|
-
///
|
|
291
|
-
/// Represents `<a>` elements with parsed href values, text content, and link type classification.
|
|
292
|
-
///
|
|
293
|
-
/// # Examples
|
|
294
|
-
///
|
|
295
|
-
/// ```
|
|
296
|
-
/// # use html_to_markdown_rs::metadata::{LinkMetadata, LinkType};
|
|
297
|
-
/// let link = LinkMetadata {
|
|
298
|
-
/// href: "https://example.com".to_string(),
|
|
299
|
-
/// text: "Example".to_string(),
|
|
300
|
-
/// title: Some("Visit Example".to_string()),
|
|
301
|
-
/// link_type: LinkType::External,
|
|
302
|
-
/// rel: vec!["nofollow".to_string()],
|
|
303
|
-
/// attributes: Default::default(),
|
|
304
|
-
/// };
|
|
305
|
-
///
|
|
306
|
-
/// assert_eq!(link.link_type, LinkType::External);
|
|
307
|
-
/// assert_eq!(link.text, "Example");
|
|
308
|
-
/// ```
|
|
309
|
-
#[derive(Debug, Clone)]
|
|
310
|
-
#[cfg_attr(feature = "metadata", derive(serde::Serialize, serde::Deserialize))]
|
|
311
|
-
pub struct LinkMetadata {
|
|
312
|
-
/// The href URL value
|
|
313
|
-
pub href: String,
|
|
314
|
-
|
|
315
|
-
/// Link text content (normalized, concatenated if mixed with elements)
|
|
316
|
-
pub text: String,
|
|
317
|
-
|
|
318
|
-
/// Optional title attribute (often shown as tooltip)
|
|
319
|
-
pub title: Option<String>,
|
|
320
|
-
|
|
321
|
-
/// Link type classification
|
|
322
|
-
pub link_type: LinkType,
|
|
323
|
-
|
|
324
|
-
/// Rel attribute values (e.g., "nofollow", "stylesheet", "canonical")
|
|
325
|
-
pub rel: Vec<String>,
|
|
326
|
-
|
|
327
|
-
/// Additional HTML attributes
|
|
328
|
-
pub attributes: BTreeMap<String, String>,
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
impl LinkMetadata {
|
|
332
|
-
/// Classify a link based on href value.
|
|
333
|
-
///
|
|
334
|
-
/// # Arguments
|
|
335
|
-
///
|
|
336
|
-
/// * `href` - The href attribute value
|
|
337
|
-
///
|
|
338
|
-
/// # Returns
|
|
339
|
-
///
|
|
340
|
-
/// Appropriate [`LinkType`] based on protocol and content.
|
|
341
|
-
///
|
|
342
|
-
/// # Examples
|
|
343
|
-
///
|
|
344
|
-
/// ```
|
|
345
|
-
/// # use html_to_markdown_rs::metadata::{LinkMetadata, LinkType};
|
|
346
|
-
/// assert_eq!(LinkMetadata::classify_link("#section"), LinkType::Anchor);
|
|
347
|
-
/// assert_eq!(LinkMetadata::classify_link("mailto:test@example.com"), LinkType::Email);
|
|
348
|
-
/// assert_eq!(LinkMetadata::classify_link("tel:+1234567890"), LinkType::Phone);
|
|
349
|
-
/// assert_eq!(LinkMetadata::classify_link("https://example.com"), LinkType::External);
|
|
350
|
-
/// ```
|
|
351
|
-
#[must_use]
|
|
352
|
-
pub fn classify_link(href: &str) -> LinkType {
|
|
353
|
-
if href.starts_with('#') {
|
|
354
|
-
LinkType::Anchor
|
|
355
|
-
} else if href.starts_with("mailto:") {
|
|
356
|
-
LinkType::Email
|
|
357
|
-
} else if href.starts_with("tel:") {
|
|
358
|
-
LinkType::Phone
|
|
359
|
-
} else if href.starts_with("http://") || href.starts_with("https://") {
|
|
360
|
-
LinkType::External
|
|
361
|
-
} else if href.starts_with('/') || href.starts_with("../") || href.starts_with("./") {
|
|
362
|
-
LinkType::Internal
|
|
363
|
-
} else {
|
|
364
|
-
LinkType::Other
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/// Image metadata with source and dimensions.
|
|
370
|
-
///
|
|
371
|
-
/// Captures `<img>` elements and inline `<svg>` elements with metadata
|
|
372
|
-
/// for image analysis and optimization.
|
|
373
|
-
///
|
|
374
|
-
/// # Examples
|
|
375
|
-
///
|
|
376
|
-
/// ```
|
|
377
|
-
/// # use html_to_markdown_rs::metadata::{ImageMetadata, ImageType};
|
|
378
|
-
/// let img = ImageMetadata {
|
|
379
|
-
/// src: "https://example.com/image.jpg".to_string(),
|
|
380
|
-
/// alt: Some("An example image".to_string()),
|
|
381
|
-
/// title: Some("Example".to_string()),
|
|
382
|
-
/// dimensions: Some((800, 600)),
|
|
383
|
-
/// image_type: ImageType::External,
|
|
384
|
-
/// attributes: Default::default(),
|
|
385
|
-
/// };
|
|
386
|
-
///
|
|
387
|
-
/// assert_eq!(img.image_type, ImageType::External);
|
|
388
|
-
/// ```
|
|
389
|
-
#[derive(Debug, Clone)]
|
|
390
|
-
#[cfg_attr(feature = "metadata", derive(serde::Serialize, serde::Deserialize))]
|
|
391
|
-
pub struct ImageMetadata {
|
|
392
|
-
/// Image source (URL, data URI, or SVG content identifier)
|
|
393
|
-
pub src: String,
|
|
394
|
-
|
|
395
|
-
/// Alternative text from alt attribute (for accessibility)
|
|
396
|
-
pub alt: Option<String>,
|
|
397
|
-
|
|
398
|
-
/// Title attribute (often shown as tooltip)
|
|
399
|
-
pub title: Option<String>,
|
|
400
|
-
|
|
401
|
-
/// Image dimensions as (width, height) if available
|
|
402
|
-
pub dimensions: Option<(u32, u32)>,
|
|
403
|
-
|
|
404
|
-
/// Image type classification
|
|
405
|
-
pub image_type: ImageType,
|
|
406
|
-
|
|
407
|
-
/// Additional HTML attributes
|
|
408
|
-
pub attributes: BTreeMap<String, String>,
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
/// Structured data block (JSON-LD, Microdata, or RDFa).
|
|
412
|
-
///
|
|
413
|
-
/// Represents machine-readable structured data found in the document.
|
|
414
|
-
/// JSON-LD blocks are collected as raw JSON strings for flexibility.
|
|
415
|
-
///
|
|
416
|
-
/// # Examples
|
|
417
|
-
///
|
|
418
|
-
/// ```
|
|
419
|
-
/// # use html_to_markdown_rs::metadata::{StructuredData, StructuredDataType};
|
|
420
|
-
/// let schema = StructuredData {
|
|
421
|
-
/// data_type: StructuredDataType::JsonLd,
|
|
422
|
-
/// raw_json: r#"{"@context":"https://schema.org","@type":"Article"}"#.to_string(),
|
|
423
|
-
/// schema_type: Some("Article".to_string()),
|
|
424
|
-
/// };
|
|
425
|
-
///
|
|
426
|
-
/// assert_eq!(schema.data_type, StructuredDataType::JsonLd);
|
|
427
|
-
/// ```
|
|
428
|
-
#[derive(Debug, Clone)]
|
|
429
|
-
#[cfg_attr(feature = "metadata", derive(serde::Serialize, serde::Deserialize))]
|
|
430
|
-
pub struct StructuredData {
|
|
431
|
-
/// Type of structured data (JSON-LD, Microdata, RDFa)
|
|
432
|
-
pub data_type: StructuredDataType,
|
|
433
|
-
|
|
434
|
-
/// Raw JSON string (for JSON-LD) or serialized representation
|
|
435
|
-
pub raw_json: String,
|
|
436
|
-
|
|
437
|
-
/// Schema type if detectable (e.g., "Article", "Event", "Product")
|
|
438
|
-
pub schema_type: Option<String>,
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
/// Comprehensive metadata extraction result from HTML document.
|
|
442
|
-
///
|
|
443
|
-
/// Contains all extracted metadata types in a single structure,
|
|
444
|
-
/// suitable for serialization and transmission across language boundaries.
|
|
445
|
-
///
|
|
446
|
-
/// # Examples
|
|
447
|
-
///
|
|
448
|
-
/// ```
|
|
449
|
-
/// # use html_to_markdown_rs::metadata::HtmlMetadata;
|
|
450
|
-
/// let metadata = HtmlMetadata {
|
|
451
|
-
/// document: Default::default(),
|
|
452
|
-
/// headers: Vec::new(),
|
|
453
|
-
/// links: Vec::new(),
|
|
454
|
-
/// images: Vec::new(),
|
|
455
|
-
/// structured_data: Vec::new(),
|
|
456
|
-
/// };
|
|
457
|
-
///
|
|
458
|
-
/// assert!(metadata.headers.is_empty());
|
|
459
|
-
/// ```
|
|
460
|
-
#[derive(Debug, Clone, Default)]
|
|
461
|
-
#[cfg_attr(feature = "metadata", derive(serde::Serialize, serde::Deserialize))]
|
|
462
|
-
pub struct HtmlMetadata {
|
|
463
|
-
/// Document-level metadata (title, description, canonical, etc.)
|
|
464
|
-
pub document: DocumentMetadata,
|
|
465
|
-
|
|
466
|
-
/// Extracted header elements with hierarchy
|
|
467
|
-
pub headers: Vec<HeaderMetadata>,
|
|
468
|
-
|
|
469
|
-
/// Extracted hyperlinks with type classification
|
|
470
|
-
pub links: Vec<LinkMetadata>,
|
|
471
|
-
|
|
472
|
-
/// Extracted images with source and dimensions
|
|
473
|
-
pub images: Vec<ImageMetadata>,
|
|
474
|
-
|
|
475
|
-
/// Extracted structured data blocks
|
|
476
|
-
pub structured_data: Vec<StructuredData>,
|
|
477
|
-
}
|