microsoft / microsoft/markitdown
Exposing markdownify options in the docx converter
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 186k
- Forks
- 13.7k
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 49
Description
There are some features in Markdownify that currently don't seem to be exposed or settable in the default configuration. For example, I wanted to customize superscript and subscript conversions (which by default are not formatted when converting docx->md) but this isn't possible by default?
This isn't too hard to fix and it might be useful to expose these. Note the markdownify options are themselves well documented.
So I just thought I'd mention this limitation and share a workaround below. It may be worth simply putting this into the existing DocxConverter:
import sys
from typing import Any, BinaryIO
import mammoth
from markitdown._base_converter import DocumentConverterResult
from markitdown._exceptions import MISSING_DEPENDENCY_MESSAGE, MissingDependencyException
from markitdown._stream_info import StreamInfo
from markitdown.converters._docx_converter import DocxConverter
from typing_extensions import override
# Based on markitdown.converters._docx_converter.DocxConverter.
_dependency_exc_info = None
try:
import mammoth
except ImportError:
_dependency_exc_info = sys.exc_info()
# Accepted types (copied exactly from original DocxConverter)
ACCEPTED_MIME_TYPE_PREFIXES = [
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
]
ACCEPTED_FILE_EXTENSIONS = [".docx"]
class CustomDocxConverter(DocxConverter):
"""
A custom DocxConverter derived from the original, modified only
to allow passing markdownify options to the underlying markdownify
HtmlConverter.
See options:
https://github.com/matthewwithanm/python-markdownify
"""
def __init__(self, markdownify_options: dict[str, Any] | None = None):
"""
Initializes the converter, storing custom markdownify options.
"""
super().__init__() # Call base class init (initializes self._html_converter)
# Store custom options for markdownify
self.markdownify_options = markdownify_options if markdownify_options is not None else {} # pyright: ignore
@override
def convert(
self,
file_stream: BinaryIO,
stream_info: StreamInfo,
**kwargs: Any, # Options passed from MarkItDown.convert (e.g., llm_client)
) -> DocumentConverterResult:
"""
Converts the DOCX stream using mammoth, then converts the resulting
HTML to Markdown using the internal HtmlConverter, passing along
any stored markdownify options.
"""
# Same as original DocxConverter:
if _dependency_exc_info is not None:
raise MissingDependencyException(
MISSING_DEPENDENCY_MESSAGE.format(
converter=type(self).__name__,
extension=".docx",
feature="docx",
)
) from _dependency_exc_info[1].with_traceback( # type: ignore[union-attr] # pyright: ignore
_dependency_exc_info[2]
)
# Changes start here:
# Extract mammoth-specific options if any are passed via kwargs
style_map = kwargs.get("style_map", None)
html_result = mammoth.convert_to_html(file_stream, style_map=style_map)
html_content = html_result.value
# Add custom markdownify options to the kwargs.
combined_options = {**kwargs, **self.markdownify_options}
# Call the internal HtmlConverter's convert_string method with the combined options.
return self._html_converter.convert_string(
html_content, url=stream_info.url, **combined_options
)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in markitdown/converters/_docx_converter.py and inspect DocxConverter, especially how it invokes Mammoth and the internal Markdownify converter. Compare the documented Markdownify options with what the converter accepts or forwards. Done means callers can configure relevant options, such as superscript and subscript conversion, when converting DOCX to Markdown.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, content
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 72/100