html-to-markdown 3.4.0 → 3.6.0.pre.rc.24
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,82 +0,0 @@
|
|
|
1
|
-
//! Form element handlers for HTML to Markdown conversion.
|
|
2
|
-
//!
|
|
3
|
-
//! This module provides specialized handlers for HTML form elements:
|
|
4
|
-
//! - Container elements (form, fieldset, legend, label)
|
|
5
|
-
//! - Input elements (input, textarea, select, option, optgroup, button)
|
|
6
|
-
//! - Measurement elements (progress, meter, output, datalist)
|
|
7
|
-
//!
|
|
8
|
-
//! These handlers are designed to be extracted from the main `converter.rs`
|
|
9
|
-
//! file and integrated through the dispatcher function.
|
|
10
|
-
//!
|
|
11
|
-
//! **Integration Pattern:**
|
|
12
|
-
//! Each handler function takes the same signature:
|
|
13
|
-
//! - `tag_name: &str` - The HTML tag being processed
|
|
14
|
-
//! - `node_handle: &NodeHandle` - The DOM node handle
|
|
15
|
-
//! - `parser: &Parser` - The HTML parser reference
|
|
16
|
-
//! - `output: &mut String` - The output buffer to write to
|
|
17
|
-
//! - `options: &ConversionOptions` - Conversion configuration
|
|
18
|
-
//! - `ctx: &Context` - Processing context (state tracking)
|
|
19
|
-
//! - `depth: usize` - Current DOM tree depth
|
|
20
|
-
//! - `dom_ctx: &DomContext` - DOM context for tree relationships
|
|
21
|
-
//!
|
|
22
|
-
//! The main dispatcher function `dispatch_form_handler` routes tags to
|
|
23
|
-
//! their appropriate handlers and returns a boolean indicating success.
|
|
24
|
-
|
|
25
|
-
pub mod elements;
|
|
26
|
-
|
|
27
|
-
// Re-export types from parent module for submodule access
|
|
28
|
-
pub use super::walk_node;
|
|
29
|
-
pub use super::{Context, DomContext};
|
|
30
|
-
|
|
31
|
-
// Re-export handler function for direct use
|
|
32
|
-
pub use elements::handle as handle_form_elements;
|
|
33
|
-
|
|
34
|
-
// Re-exports are done via the dispatch function parameter types
|
|
35
|
-
|
|
36
|
-
/// Dispatches form element handling to the appropriate handler.
|
|
37
|
-
///
|
|
38
|
-
/// This function routes form-related HTML elements to their specialized handlers
|
|
39
|
-
/// based on tag name. It is designed to be called from the main `walk_node`
|
|
40
|
-
/// function in `converter.rs`.
|
|
41
|
-
///
|
|
42
|
-
/// # Routing Table
|
|
43
|
-
///
|
|
44
|
-
/// The following tag routes are supported:
|
|
45
|
-
/// - **Containers**: form, fieldset, legend, label
|
|
46
|
-
/// - **Inputs**: input, textarea, select, option, optgroup, button
|
|
47
|
-
/// - **Measurements**: progress, meter, output, datalist
|
|
48
|
-
///
|
|
49
|
-
/// # Returns
|
|
50
|
-
///
|
|
51
|
-
/// Returns `true` if the tag was successfully handled by a form handler,
|
|
52
|
-
/// `false` if the tag is not a form element and requires other handling.
|
|
53
|
-
///
|
|
54
|
-
/// # Example
|
|
55
|
-
///
|
|
56
|
-
/// ```text
|
|
57
|
-
/// if dispatch_form_handler(tag_name, &node_handle, &parser, output, options, ctx, depth, dom_ctx) {
|
|
58
|
-
/// // Tag was handled
|
|
59
|
-
/// } else {
|
|
60
|
-
/// // Continue with other handlers
|
|
61
|
-
/// }
|
|
62
|
-
/// ```
|
|
63
|
-
pub fn dispatch_form_handler(
|
|
64
|
-
tag_name: &str,
|
|
65
|
-
node_handle: &tl::NodeHandle,
|
|
66
|
-
parser: &tl::Parser,
|
|
67
|
-
output: &mut String,
|
|
68
|
-
options: &crate::options::ConversionOptions,
|
|
69
|
-
ctx: &super::Context,
|
|
70
|
-
depth: usize,
|
|
71
|
-
dom_ctx: &super::DomContext,
|
|
72
|
-
) -> bool {
|
|
73
|
-
match tag_name {
|
|
74
|
-
// Form containers and metadata
|
|
75
|
-
"form" | "fieldset" | "legend" | "label" | "input" | "textarea" | "select" | "option" | "optgroup"
|
|
76
|
-
| "button" | "progress" | "meter" | "output" | "datalist" => {
|
|
77
|
-
handle_form_elements(tag_name, node_handle, parser, output, options, ctx, depth, dom_ctx);
|
|
78
|
-
true
|
|
79
|
-
}
|
|
80
|
-
_ => false,
|
|
81
|
-
}
|
|
82
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
//! Djot format renderer.
|
|
2
|
-
|
|
3
|
-
use super::FormatRenderer;
|
|
4
|
-
|
|
5
|
-
/// Renderer for Djot lightweight markup output.
|
|
6
|
-
#[derive(Debug, Clone, Copy, Default)]
|
|
7
|
-
pub struct DjotRenderer;
|
|
8
|
-
|
|
9
|
-
impl FormatRenderer for DjotRenderer {
|
|
10
|
-
fn emphasis(&self, content: &str) -> String {
|
|
11
|
-
format!("_{content}_")
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
fn strong(&self, content: &str, _symbol: char) -> String {
|
|
15
|
-
// Djot always uses single asterisk for strong
|
|
16
|
-
format!("*{content}*")
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
fn strikethrough(&self, content: &str) -> String {
|
|
20
|
-
format!("{{-{content}-}}")
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
fn highlight(&self, content: &str) -> String {
|
|
24
|
-
format!("{{={content}=}}")
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
fn inserted(&self, content: &str) -> String {
|
|
28
|
-
format!("{{+{content}+}}")
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
fn subscript(&self, content: &str, _custom_symbol: &str) -> String {
|
|
32
|
-
// Djot has native subscript support
|
|
33
|
-
format!("~{content}~")
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
fn superscript(&self, content: &str, _custom_symbol: &str) -> String {
|
|
37
|
-
// Djot has native superscript support
|
|
38
|
-
format!("^{content}^")
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
fn span_with_attributes(&self, content: &str, classes: &[&str], id: Option<&str>) -> String {
|
|
42
|
-
if classes.is_empty() && id.is_none() {
|
|
43
|
-
return content.to_string();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
let mut attrs = classes.iter().map(|c| format!(".{c}")).collect::<Vec<_>>();
|
|
47
|
-
if let Some(id_val) = id {
|
|
48
|
-
attrs.push(format!("#{id_val}"));
|
|
49
|
-
}
|
|
50
|
-
format!("[{content}]{{{}}}", attrs.join(" "))
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
fn div_with_attributes(&self, content: &str, classes: &[&str]) -> String {
|
|
54
|
-
if classes.is_empty() {
|
|
55
|
-
return content.to_string();
|
|
56
|
-
}
|
|
57
|
-
let class_str = classes.join(" ");
|
|
58
|
-
format!("::: {class_str}\n{content}\n:::")
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
fn is_djot(&self) -> bool {
|
|
62
|
-
true
|
|
63
|
-
}
|
|
64
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
//! Markdown format renderer.
|
|
2
|
-
|
|
3
|
-
use super::FormatRenderer;
|
|
4
|
-
|
|
5
|
-
/// Renderer for standard Markdown output.
|
|
6
|
-
#[derive(Debug, Clone, Copy, Default)]
|
|
7
|
-
pub struct MarkdownRenderer;
|
|
8
|
-
|
|
9
|
-
impl FormatRenderer for MarkdownRenderer {
|
|
10
|
-
fn emphasis(&self, content: &str) -> String {
|
|
11
|
-
format!("*{content}*")
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
fn strong(&self, content: &str, symbol: char) -> String {
|
|
15
|
-
format!("{symbol}{symbol}{content}{symbol}{symbol}")
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
fn strikethrough(&self, content: &str) -> String {
|
|
19
|
-
format!("~~{content}~~")
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
fn highlight(&self, content: &str) -> String {
|
|
23
|
-
format!("=={content}==")
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
fn inserted(&self, content: &str) -> String {
|
|
27
|
-
format!("++{content}++")
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
fn subscript(&self, content: &str, custom_symbol: &str) -> String {
|
|
31
|
-
if custom_symbol.is_empty() {
|
|
32
|
-
format!("~{content}~")
|
|
33
|
-
} else {
|
|
34
|
-
format!("{custom_symbol}{content}{custom_symbol}")
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
fn superscript(&self, content: &str, custom_symbol: &str) -> String {
|
|
39
|
-
if custom_symbol.is_empty() {
|
|
40
|
-
format!("^{content}^")
|
|
41
|
-
} else {
|
|
42
|
-
format!("{custom_symbol}{content}{custom_symbol}")
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
fn span_with_attributes(&self, content: &str, _classes: &[&str], _id: Option<&str>) -> String {
|
|
47
|
-
// Markdown doesn't support span attributes, just return content
|
|
48
|
-
content.to_string()
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
fn div_with_attributes(&self, content: &str, _classes: &[&str]) -> String {
|
|
52
|
-
// Markdown doesn't support div attributes, just return content
|
|
53
|
-
content.to_string()
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
fn is_djot(&self) -> bool {
|
|
57
|
-
false
|
|
58
|
-
}
|
|
59
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
//! Output format renderers for HTML to Markdown/Djot conversion.
|
|
2
|
-
//!
|
|
3
|
-
//! This module provides format-specific rendering through the `FormatRenderer` trait,
|
|
4
|
-
//! allowing clean separation between Markdown and Djot output syntax.
|
|
5
|
-
|
|
6
|
-
mod djot;
|
|
7
|
-
mod markdown;
|
|
8
|
-
|
|
9
|
-
/// Trait for format-specific rendering of inline elements.
|
|
10
|
-
///
|
|
11
|
-
/// Implementations provide the syntax for emphasis, strong, strikethrough, etc.
|
|
12
|
-
/// in their respective output formats.
|
|
13
|
-
pub trait FormatRenderer: Send + Sync {
|
|
14
|
-
/// Render emphasis (em, i elements)
|
|
15
|
-
fn emphasis(&self, content: &str) -> String;
|
|
16
|
-
|
|
17
|
-
/// Render strong emphasis (strong, b elements)
|
|
18
|
-
fn strong(&self, content: &str, symbol: char) -> String;
|
|
19
|
-
|
|
20
|
-
/// Render strikethrough (del, s elements)
|
|
21
|
-
fn strikethrough(&self, content: &str) -> String;
|
|
22
|
-
|
|
23
|
-
/// Render highlight (mark element)
|
|
24
|
-
fn highlight(&self, content: &str) -> String;
|
|
25
|
-
|
|
26
|
-
/// Render inserted text (ins element)
|
|
27
|
-
fn inserted(&self, content: &str) -> String;
|
|
28
|
-
|
|
29
|
-
/// Render subscript (sub element)
|
|
30
|
-
fn subscript(&self, content: &str, custom_symbol: &str) -> String;
|
|
31
|
-
|
|
32
|
-
/// Render superscript (sup element)
|
|
33
|
-
fn superscript(&self, content: &str, custom_symbol: &str) -> String;
|
|
34
|
-
|
|
35
|
-
/// Render span with attributes (for Djot: [text]{.class})
|
|
36
|
-
fn span_with_attributes(&self, content: &str, classes: &[&str], id: Option<&str>) -> String;
|
|
37
|
-
|
|
38
|
-
/// Render div with attributes (for Djot: ::: class)
|
|
39
|
-
fn div_with_attributes(&self, content: &str, classes: &[&str]) -> String;
|
|
40
|
-
|
|
41
|
-
/// Check if this is Djot format
|
|
42
|
-
fn is_djot(&self) -> bool;
|
|
43
|
-
}
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
//! Blockquote element handler for HTML to Markdown conversion.
|
|
2
|
-
//!
|
|
3
|
-
//! Handles `<blockquote>` elements including:
|
|
4
|
-
//! - Basic blockquote markdown output with `> ` prefix
|
|
5
|
-
//! - Nested blockquotes
|
|
6
|
-
//! - Citation URLs via `cite` attribute
|
|
7
|
-
//! - Visitor callback integration
|
|
8
|
-
|
|
9
|
-
use crate::converter::Context;
|
|
10
|
-
use crate::converter::dom_context::DomContext;
|
|
11
|
-
use crate::converter::main::walk_node;
|
|
12
|
-
use crate::options::ConversionOptions;
|
|
13
|
-
|
|
14
|
-
#[cfg(feature = "visitor")]
|
|
15
|
-
#[cfg(feature = "visitor")]
|
|
16
|
-
use crate::converter::utility::content::collect_tag_attributes;
|
|
17
|
-
#[cfg(feature = "visitor")]
|
|
18
|
-
use std::collections::BTreeMap;
|
|
19
|
-
|
|
20
|
-
#[cfg(feature = "visitor")]
|
|
21
|
-
use crate::converter::utility::serialization::serialize_node_to_html;
|
|
22
|
-
|
|
23
|
-
/// Handle a `<blockquote>` element and convert to Markdown.
|
|
24
|
-
///
|
|
25
|
-
/// This handler processes blockquote elements including:
|
|
26
|
-
/// - Converting inline blockquotes by processing children as inline
|
|
27
|
-
/// - Handling nested blockquotes via blockquote_depth tracking
|
|
28
|
-
/// - Processing citation URLs from cite attribute
|
|
29
|
-
/// - Invoking visitor callbacks when the visitor feature is enabled
|
|
30
|
-
/// - Adding proper spacing and blockquote prefix formatting
|
|
31
|
-
#[allow(clippy::too_many_arguments)]
|
|
32
|
-
#[allow(clippy::too_many_lines)]
|
|
33
|
-
#[cfg_attr(not(feature = "visitor"), allow(unused_variables))]
|
|
34
|
-
pub fn handle_blockquote(
|
|
35
|
-
node_handle: &tl::NodeHandle,
|
|
36
|
-
tag: &tl::HTMLTag,
|
|
37
|
-
parser: &tl::Parser,
|
|
38
|
-
output: &mut String,
|
|
39
|
-
options: &ConversionOptions,
|
|
40
|
-
ctx: &Context,
|
|
41
|
-
depth: usize,
|
|
42
|
-
dom_ctx: &DomContext,
|
|
43
|
-
) {
|
|
44
|
-
// If in inline conversion mode, just process children inline
|
|
45
|
-
if ctx.convert_as_inline {
|
|
46
|
-
let children = tag.children();
|
|
47
|
-
{
|
|
48
|
-
for child_handle in children.top().iter() {
|
|
49
|
-
walk_node(child_handle, parser, output, options, ctx, depth + 1, dom_ctx);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Extract cite attribute if present
|
|
56
|
-
let cite = tag
|
|
57
|
-
.attributes()
|
|
58
|
-
.get("cite")
|
|
59
|
-
.flatten()
|
|
60
|
-
.map(|v| v.as_utf8_str().to_string());
|
|
61
|
-
|
|
62
|
-
// Create context for nested blockquote processing
|
|
63
|
-
let blockquote_ctx = Context {
|
|
64
|
-
blockquote_depth: ctx.blockquote_depth + 1,
|
|
65
|
-
..ctx.clone()
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// Process blockquote content
|
|
69
|
-
let mut content = String::with_capacity(256);
|
|
70
|
-
let children = tag.children();
|
|
71
|
-
{
|
|
72
|
-
for child_handle in children.top().iter() {
|
|
73
|
-
walk_node(
|
|
74
|
-
child_handle,
|
|
75
|
-
parser,
|
|
76
|
-
&mut content,
|
|
77
|
-
options,
|
|
78
|
-
&blockquote_ctx,
|
|
79
|
-
depth + 1,
|
|
80
|
-
dom_ctx,
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
let trimmed_content = content.trim();
|
|
86
|
-
|
|
87
|
-
// Handle visitor integration
|
|
88
|
-
#[cfg(feature = "visitor")]
|
|
89
|
-
if let Some(ref visitor) = ctx.visitor {
|
|
90
|
-
use crate::visitor::{NodeContext, NodeType, VisitResult};
|
|
91
|
-
|
|
92
|
-
let attributes: BTreeMap<String, String> = collect_tag_attributes(tag);
|
|
93
|
-
|
|
94
|
-
let node_id = node_handle.get_inner();
|
|
95
|
-
let parent_tag = dom_ctx.parent_tag_name(node_id, parser);
|
|
96
|
-
let index_in_parent = dom_ctx.get_sibling_index(node_id).unwrap_or(0);
|
|
97
|
-
|
|
98
|
-
let node_ctx = NodeContext {
|
|
99
|
-
node_type: NodeType::Blockquote,
|
|
100
|
-
tag_name: "blockquote".to_string(),
|
|
101
|
-
attributes,
|
|
102
|
-
depth,
|
|
103
|
-
index_in_parent,
|
|
104
|
-
parent_tag,
|
|
105
|
-
is_inline: false,
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
let mut visitor_ref = visitor.borrow_mut();
|
|
109
|
-
match visitor_ref.visit_blockquote(&node_ctx, trimmed_content, ctx.blockquote_depth) {
|
|
110
|
-
VisitResult::Continue => {}
|
|
111
|
-
VisitResult::Custom(custom) => {
|
|
112
|
-
output.push_str(&custom);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
VisitResult::Skip => return,
|
|
116
|
-
VisitResult::PreserveHtml => {
|
|
117
|
-
let mut html_output = String::new();
|
|
118
|
-
serialize_node_to_html(node_handle, parser, &mut html_output);
|
|
119
|
-
output.push_str(&html_output);
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
VisitResult::Error(err) => {
|
|
123
|
-
if ctx.visitor_error.borrow().is_none() {
|
|
124
|
-
*ctx.visitor_error.borrow_mut() = Some(err);
|
|
125
|
-
}
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Output blockquote if content is not empty
|
|
132
|
-
if !trimmed_content.is_empty() {
|
|
133
|
-
// Add proper spacing based on blockquote depth
|
|
134
|
-
if ctx.blockquote_depth > 0 {
|
|
135
|
-
output.push_str("\n\n\n");
|
|
136
|
-
} else if !output.is_empty() {
|
|
137
|
-
if output.ends_with("\n\n") {
|
|
138
|
-
// Paragraph already added \n\n; blockquote needs just \n
|
|
139
|
-
output.truncate(output.len() - 1);
|
|
140
|
-
} else if !output.ends_with('\n') {
|
|
141
|
-
output.push_str("\n\n");
|
|
142
|
-
} else if !output.ends_with("\n\n") {
|
|
143
|
-
output.push('\n');
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Add blockquote prefix to each line
|
|
148
|
-
let prefix = "> ";
|
|
149
|
-
|
|
150
|
-
for line in trimmed_content.lines() {
|
|
151
|
-
output.push_str(prefix);
|
|
152
|
-
output.push_str(line.trim());
|
|
153
|
-
output.push('\n');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Add citation if present
|
|
157
|
-
if let Some(url) = cite {
|
|
158
|
-
output.push('\n');
|
|
159
|
-
output.push_str("— <");
|
|
160
|
-
output.push_str(&url);
|
|
161
|
-
output.push_str(">\n\n");
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Add trailing newlines only when appropriate for proper spacing
|
|
165
|
-
// (matching paragraph conditional logic for CommonMark compliance)
|
|
166
|
-
if !ctx.convert_as_inline && !ctx.in_table_cell && !ctx.in_list_item {
|
|
167
|
-
while output.ends_with('\n') {
|
|
168
|
-
output.truncate(output.len() - 1);
|
|
169
|
-
}
|
|
170
|
-
output.push_str("\n\n");
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|