sim_codec_doc/
asciidoc.rs1use std::collections::BTreeMap;
4
5use asciidork_parser::prelude::{Bump, Parser, SourceFile};
6
7use crate::MarkupFidelity;
8use crate::backend::{MarkupBackend, MarkupDecodeOptions, MarkupEncodeOptions, MarkupError};
9use crate::markup::{BackendId, MarkupDoc, SourceDoc};
10
11#[path = "asciidoc_decoder.rs"]
12mod asciidoc_decoder;
13#[path = "asciidoc_support.rs"]
14mod asciidoc_support;
15#[path = "asciidoc_writer.rs"]
16mod asciidoc_writer;
17
18use asciidoc_decoder::AsciiDocDecoder;
19use asciidoc_support::{asciidoc_id, inline_plain_text, mask_directives, raw_directives};
20use asciidoc_writer::AsciiDocEncoder;
21
22#[derive(Clone, Debug, Default)]
24pub struct AsciiDocBackend;
25
26impl MarkupBackend for AsciiDocBackend {
27 fn id(&self) -> BackendId {
28 asciidoc_id()
29 }
30
31 fn decode(
32 &self,
33 input: &str,
34 opts: &MarkupDecodeOptions,
35 ) -> Result<(MarkupDoc, MarkupFidelity), MarkupError> {
36 let directives = raw_directives(input);
37 let masked = mask_directives(input, &directives);
38 let parse_input = masked.as_ref();
39 let bump = Bump::new();
40 let parser = Parser::from_str(parse_input, SourceFile::Tmp, &bump);
41 let result = parser.parse().map_err(|diagnostics| {
42 MarkupError::Decode(
43 diagnostics
44 .into_iter()
45 .map(|diagnostic| diagnostic.message)
46 .collect::<Vec<_>>()
47 .join("; "),
48 )
49 })?;
50
51 let mut decoder = AsciiDocDecoder::new(input, opts);
52 decoder.fidelity.warnings.extend(
53 result
54 .warnings
55 .into_iter()
56 .map(|diagnostic| diagnostic.message),
57 );
58 decoder.record_directives(&directives);
59 let title = result
60 .document
61 .title()
62 .map(|title| inline_plain_text(&decoder.inlines(&title.main)));
63 let parsed_blocks = decoder.blocks_from_content(&result.document.content);
64 let blocks = decoder.merge_directives(parsed_blocks);
65 let source = opts.preserve_source.then(|| SourceDoc {
66 backend: asciidoc_id(),
67 text: input.to_owned(),
68 });
69
70 Ok((
71 MarkupDoc {
72 title,
73 blocks,
74 attrs: BTreeMap::new(),
75 source,
76 },
77 decoder.fidelity,
78 ))
79 }
80
81 fn encode(
82 &self,
83 doc: &MarkupDoc,
84 opts: &MarkupEncodeOptions,
85 ) -> Result<(String, MarkupFidelity), MarkupError> {
86 let mut encoder = AsciiDocEncoder::new(opts);
87 let source = encoder.write_doc(doc);
88 if opts.fail_on_loss && !encoder.fidelity().dropped.is_empty() {
89 return Err(MarkupError::Encode(format!(
90 "asciidoc encode dropped {} unsupported fragment(s)",
91 encoder.fidelity().dropped.len()
92 )));
93 }
94 Ok((source, encoder.into_fidelity()))
95 }
96}