Native MoonBit DOCX to HTML/Markdown converter ported from Mammoth
Dependencies
moon add bobzhang/docx2html///|
test "convert document model to html" {
let doc = @docx2html.document([
@docx2html.paragraph([@docx2html.text("Hello.")]),
])
let result = @docx2html.convert_document_to_html(doc)
inspect(result.value, content="<p>Hello.</p>")
}///|
test "choose markdown output" {
let doc = @docx2html.document([
@docx2html.paragraph([@docx2html.text("Hello.")]),
])
let result = @docx2html.convert_document(doc, output_format=Markdown)
inspect(result.value, content="Hello\\.\n\n")
}///|
test "parse mammoth style map strings" {
let style_map_text =
#|# ignored
#|
#|p[style-name='Heading 1'] => h2
let style_map = @docx2html.read_style_map_string(style_map_text)
let doc = @docx2html.document([
@docx2html.paragraph(
[@docx2html.text("Title")],
properties=@docx2html.paragraph_properties(style_name=Some("Heading 1")),
),
])
let result = @docx2html.convert_document_to_html(doc, style_map~)
inspect(result.value, content="<h2>Title</h2>")
}///|
test "preflight style map diagnostics" {
let parsed = @docx2html.parse_style_map_string(
"p.SectionTitle => h2\np => span#",
)
inspect(parsed.mappings.length(), content="1")
debug_inspect(
parsed.messages,
content=(
#|[Warning("Did not understand this style mapping, so ignored it: p => span#\nError was at character number 10: Expected end but got unrecognisedCharacter \"#\"")]
),
)
}///|
test "build document model with helpers" {
let doc = @docx2html.document([
@docx2html.paragraph(
[
@docx2html.hyperlink(
[@docx2html.text("MoonBit")],
href=Some("https://www.moonbitlang.com"),
),
],
properties=@docx2html.paragraph_properties(style_name=Some("Heading 1")),
),
@docx2html.table([
@docx2html.table_row([
@docx2html.table_cell([@docx2html.paragraph([@docx2html.text("Cell")])]),
]),
]),
])
let result = @docx2html.convert_document_to_html(doc, style_map=[
"p[style-name='Heading 1'] => h2",
])
inspect(
result.value,
content="<h2><a href=\"https://www.moonbitlang.com\">MoonBit</a></h2><table><tr><td><p>Cell</p></td></tr></table>",
)
}///|
test "transform runs before conversion" {
let doc = @docx2html.document([
@docx2html.paragraph([@docx2html.run([@docx2html.text("Hello.")])]),
])
let transform_document = @docx2html.transform_runs(fn(_run) {
@docx2html.run([@docx2html.text("Goodbye.")])
})
let result = @docx2html.convert_document_to_html(doc, transform_document~)
inspect(result.value, content="<p>Goodbye.</p>")
let runs = @docx2html.document_descendants_where(doc, fn(element) {
element is Run(..)
})
inspect(runs.length(), content="1")
}moon run --target native cmd/docx2html -- input.docx
moon run --target native cmd/docx2html -- --output-format=markdown input.docx
moon run --target native cmd/docx2html -- --style-map style-map input.docx output.html
moon run --target native cmd/docx2html -- --output-dir out input.docxmoon cram test tests/cram///|
test "custom image conversion" {
let image = @docx2html.Image::{
content_type: "image/png",
alt_text: Some("chart"),
data: b"abc",
}
let doc = @docx2html.document([@docx2html.paragraph([Image(image)])])
let convert_image = @docx2html.inline_image(fn(_image) {
{ "src": "/assets/chart.png" }
})
let result = @docx2html.convert_document_to_html(doc, convert_image~)
inspect(
result.value,
content="<p><img alt=\"chart\" src=\"/assets/chart.png\" /></p>",
)
}///|
test "custom image conversion diagnostics" {
let image = @docx2html.image("image/png", b"abc", alt_text=Some("chart"))
let convert_image = fn(_image : @docx2html.Image) {
@docx2html.image_conversion([], messages=[@docx2html.error("image omitted")])
}
let result = @docx2html.convert_document_to_html(image, convert_image~)
inspect(result.value, content="")
debug_inspect(result.messages, content="[Error(\"image omitted\")]")
}///|
test "combine conversion results" {
let combined = @docx2html.combine_results([
@docx2html.success("One"),
{ value: "Two", messages: [Warning("same")] },
{ value: "Three", messages: [Warning("same")] },
])
inspect(combined.value, content="OneTwoThree")
debug_inspect(combined.messages, content="[Warning(\"same\")]")
}pub(all) suberror DocxError {
InvalidZip(message~ : String)
InvalidXml(message~ : String)
MissingPart(message~ : String)
Unsupported(message~ : String)
ResourceLimit(limit~ : DocxXmlResourceLimit, message~ : String)
WriteResourceLimit(kind~ : String, limit~ : Int64, actual~ : Int64, message~ : String)
} derive(Eq, Debug)fn comment(comment_id : String, body : Array[DocumentElement], author_name? : String, author_initials? : String) -> Commentfn comment_reply(author~ : String, initials? : String, date? : String, reply_to~ : Int, done? : Bool, body : Array[DocumentElement]) -> CommentSpec raise DocxErrorfn comment_spec(author~ : String, initials? : String, date? : String, from~ : Int, to~ : Int, done? : Bool, body : Array[DocumentElement]) -> CommentSpec raise DocxErrorfn convert(docx : BytesView, output_format? : OutputFormat, style_map? : Array[String], include_default_style_map? : Bool, include_embedded_style_map? : Bool, ignore_empty_paragraphs? : Bool, id_prefix? : String, pretty_print? : Bool, convert_image? : (Image) -> ImageConversion, transform_document? : (DocumentElement) -> DocumentElement, external_file_access? : Bool, read_external_file? : (String) -> Bytes?) -> ConversionResult raise DocxErrorfn convert_document(document : DocumentElement, output_format? : OutputFormat, style_map? : Array[String], include_default_style_map? : Bool, ignore_empty_paragraphs? : Bool, id_prefix? : String, pretty_print? : Bool, convert_image? : (Image) -> ImageConversion, transform_document? : (DocumentElement) -> DocumentElement) -> ConversionResultfn convert_document_to_html(document : DocumentElement, style_map? : Array[String], include_default_style_map? : Bool, ignore_empty_paragraphs? : Bool, id_prefix? : String, pretty_print? : Bool, convert_image? : (Image) -> ImageConversion, transform_document? : (DocumentElement) -> DocumentElement) -> ConversionResultfn convert_document_to_markdown(document : DocumentElement, style_map? : Array[String], include_default_style_map? : Bool, ignore_empty_paragraphs? : Bool, id_prefix? : String, convert_image? : (Image) -> ImageConversion, transform_document? : (DocumentElement) -> DocumentElement) -> ConversionResultfn convert_to_html(docx : BytesView, style_map? : Array[String], include_default_style_map? : Bool, include_embedded_style_map? : Bool, ignore_empty_paragraphs? : Bool, id_prefix? : String, pretty_print? : Bool, convert_image? : (Image) -> ImageConversion, transform_document? : (DocumentElement) -> DocumentElement, external_file_access? : Bool, read_external_file? : (String) -> Bytes?) -> ConversionResult raise DocxErrorfn convert_to_markdown(docx : BytesView, style_map? : Array[String], include_default_style_map? : Bool, include_embedded_style_map? : Bool, ignore_empty_paragraphs? : Bool, id_prefix? : String, convert_image? : (Image) -> ImageConversion, transform_document? : (DocumentElement) -> DocumentElement, external_file_access? : Bool, read_external_file? : (String) -> Bytes?) -> ConversionResult raise DocxErrorfn document(children : Array[DocumentElement], notes? : Array[Note], comments? : Array[Comment]) -> DocumentElementfn document_descendants_where(element : DocumentElement, predicate : (DocumentElement) -> Bool) -> Array[DocumentElement]fn escape_html_attribute(value : String) -> Stringfn escape_markdown_text(value : String) -> Stringfn extract_raw_text(docx : BytesView, external_file_access? : Bool, read_external_file? : (String) -> Bytes?) -> ConversionResult raise DocxErrorfn hyperlink(children : Array[DocumentElement], href? : String?, anchor? : String?, target_frame? : String?) -> DocumentElementfn new_blank_docx() -> Bytesfn paragraph(children : Array[DocumentElement], properties? : ParagraphProperties) -> DocumentElementfn paragraph_properties(style_id? : String?, style_name? : String?, numbering? : Numbering?, alignment? : String?, indent? : Indent) -> ParagraphPropertiesfn read_docx(docx : BytesView, external_file_access? : Bool, read_external_file? : (String) -> Bytes?) -> DocumentElement raise DocxErrorfn read_docx_annotated(docx : BytesView, external_file_access? : Bool, read_external_file? : (String) -> Bytes?) -> DocxAnnotatedResult raise DocxErrorfn read_docx_package(docx : BytesView, external_file_access? : Bool, read_external_file? : (String) -> Bytes?) -> DocxPackageResult raise DocxErrorfn read_docx_with_messages(docx : BytesView, external_file_access? : Bool, read_external_file? : (String) -> Bytes?) -> DocxReadResult raise DocxErrorfn read_xml_string(value : String, namespace_map? : Map[String, String]) -> XmlElement raise DocxErrorfn run_properties(style_id? : String?, style_name? : String?, is_bold? : Bool, is_underline? : Bool, is_italic? : Bool, is_strikethrough? : Bool, is_all_caps? : Bool, is_small_caps? : Bool, vertical_alignment? : VerticalAlignment, font? : String?, font_size? : Int?, highlight? : String?) -> RunPropertiesfn split_zip_path(path : String) -> (String, String)fn table_cell(children : Array[DocumentElement], col_span? : Int, row_span? : Int) -> DocumentElementfn transform_elements(element : DocumentElement, transform : (DocumentElement) -> DocumentElement) -> DocumentElementfn transform_paragraphs(transform : (DocumentElement) -> DocumentElement) -> ((DocumentElement) -> DocumentElement)fn transform_runs(transform : (DocumentElement) -> DocumentElement) -> ((DocumentElement) -> DocumentElement)fn write_docx_with_annotations(body : Array[DocumentElement], comments? : Array[CommentSpec], footnotes? : Array[NoteSpec], endnotes? : Array[NoteSpec]) -> Bytes raise DocxErrorfn write_docx_with_comments(body : Array[DocumentElement], comments : Array[CommentSpec]) -> Bytes raise DocxErrorfn xml_element(name : String, attributes? : Map[String, String], children? : Array[XmlNode]) -> XmlElementNative MoonBit DOCX to HTML/Markdown converter ported from Mammoth
Dependencies