Python bindings for the mq Markdown processor.
pip install markdown-queryUse the run function to process Markdown with mq queries:
import mq
# Extract all level 1 headings
result = mq.run(".h1", "# Hello World\n\n## Heading2\n\nText")
print(result.values) # ['# Hello World']
# Extract all level 2 headings
result = mq.run(".h2", "# Main Title\n\n## Section A\n\n## Section B")
print(result.values) # ['## Section A', '## Section B']
# Get all results as a single string
print(result.text) # '## Section A\n## Section B'Use mq query syntax to filter and transform Markdown:
import mq
markdown = """
# Product
## Features
Great features here.
## Installation
Install instructions.
"""
# Filter headings containing specific text
result = mq.run('.h2 | select(contains("Feature"))', markdown)
print(result.values) # ['## Features']
# Extract list items
result = mq.run(".[]", "# List\n\n- Item 1\n- Item 2\n- Item 3")
print(result.values) # ['- Item 1', '- Item 2', '- Item 3']
# Extract code blocks
result = mq.run(".code", "# Code\n\n```python\nprint('Hello')\n```")
print(result.values) # ["```python\nprint('Hello')\n```"]mq supports multiple input formats:
import mq
# Markdown (default)
result = mq.run(".h1", "# Heading", mq.Options(input_format=mq.InputFormat.MARKDOWN))
# MDX (Markdown with JSX)
options = mq.Options(input_format=mq.InputFormat.MDX)
result = mq.run("select(is_mdx())", "# MDX\n\n<Component />", options)
print(result.values) # ['<Component />']
# HTML
options = mq.Options(input_format=mq.InputFormat.HTML)
result = mq.run('select(contains("Hello"))', "<h1>Hello</h1><p>World</p>", options)
print(result.values) # ['# Hello']
# Plain text
options = mq.Options(input_format=mq.InputFormat.TEXT)
result = mq.run('select(contains("2"))', "Line 1\nLine 2\nLine 3", options)
print(result.values) # ['Line 2']Available input formats:
InputFormat.MARKDOWN- Standard Markdown (default)InputFormat.MDX- Markdown with JSXInputFormat.HTML- HTML contentInputFormat.TEXT- Plain textInputFormat.RAW- Raw string inputInputFormat.NULL- Null input
mq.Options accepts keyword arguments, and every option can also be set as an attribute:
import mq
options = mq.Options(input_format=mq.InputFormat.HTML, list_style=mq.ListStyle.PLUS)
options.link_url_style = mq.UrlSurroundStyle.ANGLEOptions that are not set use their defaults (shown below).
Use MQResult.render() to render the result as Markdown, HTML or plain text.
The rendering options (list_style, link_title_style, link_url_style) are applied to the output:
import mq
markdown = "# Title\n\n- Item 1\n- Item 2\n\n[link](https://example.com \"title\")"
options = mq.Options(
list_style=mq.ListStyle.PLUS, # Use '+' for list items
link_title_style=mq.TitleSurroundStyle.SINGLE, # Use single quotes for link titles
link_url_style=mq.UrlSurroundStyle.ANGLE, # Use angle brackets for URLs
)
result = mq.run(".", markdown, options)
print(result.render()) # Markdown (default)
print(result.render(mq.OutputFormat.HTML)) # HTML
print(result.render(mq.OutputFormat.TEXT)) # Plain text
# The default format of render() can be set with output_format
options = mq.Options(output_format=mq.OutputFormat.HTML)
print(mq.run(".h1", "# Hello", options).render()) # '<h1>Hello</h1>\n'Available options:
OutputFormat:MARKDOWN(default),HTML,TEXTListStyle:DASH(default),PLUS,STARTitleSurroundStyle:DOUBLE(default),SINGLE,PARENUrlSurroundStyle:NONE(default),ANGLE
Convert HTML to Markdown:
import mq
html = "<h1>Hello World</h1><p>This is a <strong>test</strong>.</p>"
markdown = mq.html_to_markdown(html)
print(markdown) # '# Hello World\n\nThis is a **test**.'
# With conversion options
options = mq.ConversionOptions()
options.extract_scripts_as_code_blocks = True # Convert <script> tags to code blocks
options.generate_front_matter = True # Generate front matter from metadata
options.use_title_as_h1 = True # Use <title> as h1 heading
markdown = mq.html_to_markdown(html, options)The run function returns an MQResult object:
import mq
result = mq.run(".h", "# H1\n\n## H2\n\n### H3")
# Get the number of results
print(len(result)) # 3
# Access individual results by index
print(result[0].text) # '# H1'
# Iterate over results
for value in result.values:
print(value)
# Get all results as a single string
print(result.text) # '# H1\n## H2\n### H3'
# Check if a value is in the result
print("# H1" in result.values) # TrueEach MQValue has the following properties:
text- The string representation of the valuevalues- For arrays, returns the list of values (otherwise a list containing the value itself)markdown_type- The type of Markdown element (e.g.,Heading,Code,List)is_array()- Check if the value is an arrayis_markdown()- Check if the value is a Markdown element
Invalid queries and inputs that cannot be parsed raise a RuntimeError:
import mq
try:
result = mq.run(".invalid!!!", "# Heading")
except RuntimeError as e:
print(f"Query error: {e}")git clone https://github.com/harehare/mq-python
cd mq-python
uv sync --dev
uv run maturin developuv run pytest tests/Licensed under the MIT License.