MQNet 0.6.5

dotnet add package MQNet --version 0.6.5
                    
NuGet\Install-Package MQNet -Version 0.6.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MQNet" Version="0.6.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MQNet" Version="0.6.5" />
                    
Directory.Packages.props
<PackageReference Include="MQNet" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MQNet --version 0.6.5
                    
#r "nuget: MQNet, 0.6.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MQNet@0.6.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MQNet&version=0.6.5
                    
Install as a Cake Addin
#tool nuget:?package=MQNet&version=0.6.5
                    
Install as a Cake Tool

MQNet

Tests CI NuGet

A .NET wrapper for mq — a jq-like query tool for Markdown. Query headings, code blocks, paragraphs, and more using a simple, composable query language.

How it works

MQNet is a thin managed wrapper around the native mq-ffi library, which is compiled from the mq Rust crate. At runtime, .NET's P/Invoke loads the platform-native binary (mq_ffi.dll / libmq_ffi.so / libmq_ffi.dylib) and marshals calls across the native boundary.

The package ships in two layers:

  • MQNet — the managed API you reference in your project.
  • MQNet.Runtime.<rid> — thin packages containing only the native binary for a specific platform (e.g. MQNet.Runtime.linux-x64). NuGet's runtime identifier graph selects the right one automatically at restore time.

You only need to install MQNet; the correct native binary is pulled in automatically.

Installation

dotnet add package MQNet

MQNet uses a split NuGet package model. The main package contains the managed library; native binaries are in separate runtime packages that NuGet resolves automatically based on your platform:

Platform Runtime Package
Windows x64 MQNet.Runtime.win-x64
Windows ARM64 MQNet.Runtime.win-arm64
Linux x64 MQNet.Runtime.linux-x64
Linux ARM64 MQNet.Runtime.linux-arm64
macOS x64 MQNet.Runtime.osx-x64
macOS ARM64 MQNet.Runtime.osx-arm64

Quick Start

using MQNet;

// Fluent API — quick one-shot queries
var result = Mq.Query(".h(1)")
    .On("# Hello\n\n## World\n\n# Another")
    .Run();

// result[0]  → "# Hello"
// result[1]  → "# Another"
// result.Text → "# Hello\n# Another"

Usage

Fluent API

// Extract all H2 headings
var headings = Mq.Query(".h(2)").On(markdown).Run();

// Filter headings containing a word
var filtered = Mq.Query(".h | select(contains(\"API\"))").On(markdown).Run();

// Extract code blocks by language
var rustBlocks = Mq.Query(".code(\"rust\")").On(markdown).Run();

// Query from HTML input
var result = Mq.Query(".h(1)")
    .On("<h1>Title</h1><p>Body</p>")
    .WithFormat(InputFormat.Html)
    .Run();

// Query plain text line by line
var matches = Mq.Query("select(contains(\"error\"))")
    .On(logOutput)
    .WithFormat(InputFormat.Text)
    .Run();

Typed Markdown Tags

Instead of writing raw mq selector strings, use MarkdownTag for strongly-typed, IntelliSense-discoverable selectors:

// Before — raw strings (still supported)
Mq.Query(".h(1)").On(markdown).Run();
Mq.Query(".code(\"rust\")").On(markdown).Run();

// After — typed selectors
Mq.Query(MarkdownTag.H1).On(markdown).Run();
Mq.Query(MarkdownTag.H2).On(markdown).Run();
Mq.Query(MarkdownTag.AllHeadings).On(markdown).Run(); // all headings, any level
Mq.Query(MarkdownTag.Code).On(markdown).Run();       // all code blocks
Mq.Query(MarkdownTag.Link).On(markdown).Run();
Mq.Query(MarkdownTag.List).On(markdown).Run();
Well-known tags
Tag Selector Description
MarkdownTag.H1MarkdownTag.H6 .h(1).h(6) Heading at a specific level
MarkdownTag.AllHeadings .h All headings (any level)
MarkdownTag.Paragraph / MarkdownTag.Text .text Paragraph / text nodes
MarkdownTag.Code .code All fenced code blocks
MarkdownTag.InlineCode .code_inline Inline code spans
MarkdownTag.Link .link Link nodes
MarkdownTag.Image .image Image nodes
MarkdownTag.List .list List items
MarkdownTag.Blockquote .blockquote Block quotes
MarkdownTag.Table .table Tables
MarkdownTag.HorizontalRule .horizontal_rule Horizontal rules
MarkdownTag.LineBreak .break Line breaks
MarkdownTag.Footnote .footnote Footnotes
MarkdownTag.MathInline .math_inline Inline math
MarkdownTag.Html .html Raw HTML nodes
Factory methods
// Language-filtered code blocks
Mq.Query(MarkdownTag.CodeBlock("rust")).On(markdown).Run();

// Heading at a specific level (1–6)
Mq.Query(MarkdownTag.HeadingLevel(3)).On(markdown).Run();

// Heading range — inclusive (both ends included)
Mq.Query(MarkdownTag.HeadingRange(1, 3)).On(markdown).Run();  // H1, H2, H3

// Heading range — C# Range syntax (exclusive end, follows C# Range convention)
Mq.Query(MarkdownTag.Heading(1..3)).On(markdown).Run();   // H1, H2 (NOT H3 — exclusive end)
Mq.Query(MarkdownTag.Heading(1..)).On(markdown).Run();    // H1–H6 (open end)
Mq.Query(MarkdownTag.Heading(^3..)).On(markdown).Run();   // H3–H6 (from-end index)

Range semantics note: HeadingRange(from, to) uses inclusive bounds — HeadingRange(1, 3) selects H1, H2, and H3. Heading(Range) follows standard C# Range semantics with an exclusive end — Heading(1..3) selects H1 and H2 only.

Convenience methods
// Shorthand for Mq.Query(MarkdownTag.HeadingLevel(1))
Mq.Heading(1).On(markdown).Run();

// Shorthand for Mq.Query(MarkdownTag.CodeBlock("rust"))
Mq.CodeBlock("rust").On(markdown).Run();

MqEngine (reuse across multiple queries)

using var engine = new MqEngine();

var h1 = engine.Eval(".h(1)", markdown);
var code = engine.Eval(".code", markdown);
var links = engine.Eval(".link", markdown);

HTML to Markdown conversion

// Basic conversion
string markdown = MqEngine.HtmlToMarkdown("<h1>Hello</h1><p>World</p>");

// With options
string markdown = MqEngine.HtmlToMarkdown(html, new ConversionOptions
{
    UseTitleAsH1 = true,
    GenerateFrontMatter = true,
    ExtractScriptsAsCodeBlocks = true
});

Working with results

MqResult result = Mq.Query(".h").On(markdown).Run();

result.Count       // number of matches
result[0]          // first match
result.Values      // IReadOnlyList<string>
result.Text        // all matches joined by "\n"

foreach (var item in result)
    Console.WriteLine(item);

Plain text output (no Markdown formatting)

mq has a built-in to_text() function that strips Markdown formatting at the AST level. Use it by piping your query through to_text, or use the WithPlainText() convenience method on the fluent API:

// Fluent API — WithPlainText() appends "| to_text" to the query
var result = Mq.Query(".h(1)")
    .On("# Hello **World**\n\n## Section")
    .WithPlainText()
    .Run();

// result[0] → "Hello World"  (no # or ** markers)

// Equivalent using MqEngine directly
using var engine = new MqEngine();
var result = engine.Eval(".h | to_text", "# Hello\n\n## World");

// result.Values → ["Hello", "World"]

Built-in Modules (v0.6+)

mq ships 15 standard modules embedded in the native binary. Load them with LoadModule (global scope) or ImportModule (namespaced) on an MqEngine instance — no file paths required.

using var engine = new MqEngine();

// LoadModule puts functions in global scope
engine.LoadModule("json");
var result = engine.Eval("""
    .code("json") | to_text | json_parse | json_stringify
    """, markdown);

// ImportModule requires a namespace prefix
engine.ImportModule("semver");
var ok = engine.Eval(
    """semver::semver_satisfies("1.5.0", ">=1.0.0,<2.0.0")""",
    "ignored", InputFormat.Text);
// → ["true"]

Available modules

Module Load name Key functions
md "md" Build Markdown nodes — h(), code(), text(), strong(), em(), link(), image(), list(), table_row(), doc()
section "section" Structure by headings — sections(), section(), title_contains(), body(), toc(), collect(), split(), by_level()
json "json" json_parse(), json_stringify(), json_to_markdown_table()
yaml "yaml" yaml_parse(), yaml_stringify(), yaml_to_markdown_table(), to_frontmatter()
toml "toml" toml_parse(), toml_stringify(), toml_to_json(), toml_to_markdown_table()
csv "csv" csv_parse(), tsv_parse(), psv_parse(), csv_stringify(), csv_to_markdown_table()
xml "xml" xml_parse(), xml_stringify(), xml_to_markdown_table()
hcl "hcl" hcl_parse(), hcl_stringify() — HashiCorp Configuration Language
semver "semver" semver_parse(), semver_compare(), semver_gt/lt/eq/gte/lte(), semver_sort(), semver_bump_major/minor/patch(), semver_satisfies()
table "table" Structured Markdown table manipulation — tables(), add_row(), add_column(), filter_rows(), sort_rows(), to_csv()
fuzzy "fuzzy" Fuzzy string matching — levenshtein(), jaro(), jaro_winkler(), fuzzy_match(), fuzzy_filter()
cbor "cbor" cbor_parse() (base64 or raw bytes), cbor_stringify()
toon "toon" TOON format — toon_parse(), toon_stringify()
ast "ast" mq AST introspection — get_args(), to_code()
test "test" Testing framework — assert_eq(), assert_true(), run_tests(), test_case()

Module examples

Parse a JSON code block and reformat it:

using var engine = new MqEngine();
engine.LoadModule("json");

string markdown = """
    # Config

    ```json
    {"name":"acme","version":"1.0.0"}
    ```
    """;

// Extract the JSON code block, parse it, then stringify
var result = engine.Eval(
    """.code("json") | to_text | json_parse | json_stringify""",
    markdown);
// result[0] → "{\"name\": \"acme\", \"version\": \"1.0.0\"}"

Collect all headings as a table of contents:

using var engine = new MqEngine();
engine.LoadModule("section");

var toc = engine.Eval("sections(.) | toc", markdown);
// result → ["- Introduction", "  - Background", "- Usage", ...]

Check if a version matches a range:

using var engine = new MqEngine();
engine.ImportModule("semver");

var result = engine.Eval(
    """semver::semver_satisfies("2.3.1", ">=2.0.0,<3.0.0")""",
    "ignored", InputFormat.Text);
// result[0] → "true"

Build Markdown programmatically:

using var engine = new MqEngine();
engine.LoadModule("md");

var result = engine.Eval(
    """doc(h("Hello", 1), text("World"), code("let x = 1;", "rust"))""",
    "ignored", InputFormat.Text);
// result[0] → "# Hello\n\nWorld\n\n```rust\nlet x = 1;\n```"

User-defined modules

Load .mq files from the file system with SetSearchPaths:

using var engine = new MqEngine();
engine.SetSearchPaths(["/path/to/my/modules"]);

// Load myutils.mq — functions available in global scope
engine.LoadModule("myutils");

// Import myutils.mq — functions available as myutils::fn_name()
engine.ImportModule("myutils");

Input Formats

Format Description
InputFormat.Markdown CommonMark / GFM Markdown (default)
InputFormat.Mdx Markdown with JSX (MDX)
InputFormat.Html HTML — auto-converted to Markdown before querying
InputFormat.Text Plain text, split by lines
InputFormat.Raw Raw string, no parsing

Requirements

  • .NET 8 or .NET 10
  • Supported platforms: Windows x64/ARM64, Linux x64/ARM64, macOS x64/ARM64

mq Query Language

MQNet wraps the mq Rust library. For the full query language reference, see the mq documentation.

Some common queries:

.h          # all headings
.h(1)       # H1 headings only
.h(2)       # H2 headings only
.code       # all code blocks
.code("go") # code blocks with language "go"
.text       # paragraphs / text nodes
.link       # links
.image      # images
.list       # list items

# Combinators
.h | select(contains("API"))         # headings containing "API"
.h | map(ascii_downcase)             # lowercase all headings
.code | select(startswith("fn "))    # code blocks starting with "fn "

# Plain text (strip Markdown formatting)
.h | to_text                         # heading text without # markers
.h(1) | to_text                      # H1 text only, no formatting

License

MIT — see LICENSE.

This project wraps mq by harehare, which is also MIT licensed.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.6.5 70 7/15/2026
0.5.36 112 6/28/2026
0.5.35 114 6/22/2026
0.5.34 111 6/13/2026
0.5.32 112 6/8/2026
0.5.31 108 6/8/2026