Repository navigation
·
51 commits
to main
since this release
Immutable
release. Only release title and notes can be modified.
🎯 Highlights
- Rewritten Markdown parser: now built in instead of relying on markdown-rs. Faster and more conformant (CommonMark/GFM), with support for Obsidian syntax and MDX frontmatter.
- Smarter type checker: fewer false positives and clearer errors. Uncertain errors are hidden unless you ask for them.
- Closer to jq: jq exit codes, JSON Lines input and output, and @html/@uri/sh now match jq.
- Easier CLI: pass a directory or glob and mq finds the Markdown files. --color auto-detects, and there's a Windows install.ps1.
⚠️ Breaking Changes
Query language
??and@precedence changed.??now binds looser than arithmetic and comparison operators (between||and&&), and@binds tighter than*/%.a ?? b + cis nowa ?? (b + c). Add parentheses where you mixed them.@ :htmlnow escapes HTML. It HTML-escapes the value, like jq's@html, and no longer renders Markdown. Useto_htmlfor that.@ :uriandurl_encodeno longer escape-_.~.- Removed
http_*wrapper builtins.http_get,http_post,http_put,http_patch,http_delete,http_headand thehttp_*_jsonvariants are gone. Usehttp(:get, url, headers)instead.
CLI
- Exit codes for errors changed. Uncaught errors now exit with
2(unreadable file),3(syntax or module error) or5(runtime error) without-e. They used to exit with1. -cis now--compact, as in jq.--countis long-only.--args NAME VALUEis now--arg NAME VALUE, and--argvis now--args.--listis nowmq commands.
Markdown
- Markdown is now parsed by mq's own parser instead of
markdown-rs.
What's Changed
Features
- ✨ feat(check): type-check the module definitions that user code reaches by @harehare in #2572
- ✨ feat(check): split type errors into definite and possible, and cut false positives by @harehare in #2602
- ✨ feat(check): type array first/last/get as element | none by @harehare in #2704
- ✨ feat(check): make the type checker more reliable and its diagnostics clearer by @harehare in #2715
- ✨ feat(ffi): add structured errors, typed values and opaque options by @harehare in #2671
- ✨ feat(install): add install.ps1 for Windows by @harehare in #2712
- ✨ feat(lang): add multi-key sort_rows and transform_tables to table module by @harehare in #2622
- ✨ feat(lang): accept column names in table module functions by @harehare in #2624
- ✨ feat(lang): add mkdir builtin by @harehare in #2688
- ✨ feat(markdown): add native Markdown parser by @harehare in #2489
- ✨ feat(run): follow jq exit codes under --exit-status by @harehare in #2614
- ✨ feat(run): support JSON Lines input and output by @harehare in #2638
- ✨ feat(run): read Markdown files under a directory argument by @harehare in #2648
- ✨ feat(run): auto-detect color output with --color by @harehare in #2697
Fixes
- 🐛 fix(bench): report failing benchmarks in output and on stderr by @harehare in #2679
- 🐛 fix(check): resolve feature-gated builtins in builtin.mq and html.mq by @harehare in #2659
- 🐛 fix(check): report type errors for mkdir and in with a dict by @harehare in #2690
- 🐛 fix(check): type argument selectors on unknown input and self[...] by @harehare in #2705
- 🐛 fix(crawler): honour robots.txt per origin and bound responses by @harehare in #2674
- 🐛 fix(docs): add missing keywords to syntax highlighters by @harehare in #2709
- 🐛 fix(ffi): harden the C API for untrusted queries by @harehare in #2670
- 🐛 fix(formatter): do not indent a literal with bracket access after def by @harehare in #2609
- 🐛 fix(formatter): do not add spaces around a tokenless block in call args by @harehare in #2653
- 🐛 fix(formatter): stop duplicating comments above space-chained selectors by @harehare in #2676
- 🐛 fix(lang): order mixed-type arrays in sort and sort_by by @harehare in #2561
- 🐛 fix(lang): lex
+/-after a value as binary operators by @harehare in #2571 - 🐛 fix(lang): parse index access on dict literals by @harehare in #2596
- 🐛 fix(lang): parse index access on string literals by @harehare in #2597
- 🐛 fix(lang): report circular module dependencies as an error by @harehare in #2599
- 🐛 fix(lang): keep postfix index and call across newlines in CST by @harehare in #2600
- 🐛 fix(lang): return None for out-of-range negative index by @harehare in #2603
- 🐛 fix(lang): return None for non-integer index by @harehare in #2604
- 🐛 fix(lang): report unindexable values as an indexing error by @harehare in #2606
- 🐛 fix(lang): return none for non-integer slice bounds by @harehare in #2608
- 🐛 fix(lang): put number before string in number + string concatenation by @harehare in #2631
- 🐛 fix(lang): include function name and value in conversion errors by @harehare in #2632
- 🐛 fix(lang): align CST and AST on selector chains and while conditions by @harehare in #2634
- 🐛 fix(lang): reject non-integer sizes in chunks by @harehare in #2662
- 🐛 fix(lang): make NaN comparisons follow IEEE 754 by @harehare in #2663
- 🐛 fix(lang): reject non-finite or non-integer args in gcd and lcm by @harehare in #2664
- 🐛 fix(lang): report callee name in arity errors for mq-defined functions by @harehare in #2665
- 🐛 fix(lang): return character offsets from index, rindex and indices by @harehare in #2667
- 🐛 fix(lang): keep Unicode letters in slugify by @harehare in #2668
- 🐛 fix(lang): treat an empty dict as falsy in conditions by @harehare in #2685
- 🐛 fix(lang): make array * number repeat-only by @harehare in #2686
- 🐛 fix(lang): hint at mq literals when null, True or False is used by @harehare in #2698
- 🐛 fix(lang): keep earlier closures' captured value when
letis rebound by @harehare in #2703 - 🐛 fix(lang): skip leading BOM in query and module sources by @harehare in #2707
- 🐛 fix(lang): hint dict key access for selectors written after an iden by @harehare in #2708
- 🐛 fix(lang): reject duplicate def and conflicting members across module declarations by @harehare in #2711
- 💥 fix(lang)!: align
@ :html,@ :uriand@ :shwith jq by @harehare in #2716 - 🐛 fix(lang): reject stack-growing bytecode loops and add Kani proofs by @harehare in #2724
- 🐛 fix(lang): require
endin match expressions by @harehare in #2728 - 💥 fix(lang)!: lower ?? below && and raise @ above multiplicative by @harehare in #2731
- 🐛 fix(lint): do not report unused functions in module files by @harehare in #2657
- 🐛 fix(lsp): validate new name in textDocument/rename by @harehare in #2677
- 🐛 fix(markdown): do not loosen a list when a fence follows a quote in an item by @harehare in #2594
- 🐛 fix(markdown): convert
<b>and<i>to bold and italic in html_to_markdown by @harehare in #2666 - 🐛 fix(markdown): replace U+0000 with U+FFFD when parsing by @harehare in #2723
- 🐛 fix(repl): hide module symbols from /vars by @harehare in #2680
- 🐛 fix(run): pass options through to external subcommands without
--by @harehare in #2615 - 🐛 fix(run): write every input to -o instead of keeping only the last by @harehare in #2621
- 🐛 fix(run): run
.instead of starting the REPL when stdin is piped without a query by @harehare in #2642 - 🐛 fix(run): hide internal query prelude from diagnostics by @harehare in #2645
- 🐛 fix(run)!: return jq exit codes 2/3/5 for errors without --exit-status by @harehare in #2651
- 🐛 fix(run): write -o output through a symlink instead of replacing it by @harehare in #2652
- 🐛 fix(run): reject --args that leaves no query by @harehare in #2673
- 🐛 fix(run): report one-based source positions in the debugger by @harehare in #2675
- 🐛 fix(run): make --exit-status depend only on whether a result is empty by @harehare in #2682
- 🐛 fix(run): ignore write failures when reporting errors to stderr by @harehare in #2684
- 🐛 fix(run): compile the query before reading stdin by @harehare in #2689
- 🐛 fix(run): ignore access events in --watch by @harehare in #2691
- 🐛 fix(run): write well-formed XML for invalid names and attributes by @harehare in #2692
- 🐛 fix(run): omit None keys in TOML output and name the path of None in arrays by @harehare in #2693
- 🐛 fix(run): quote 0o octal, underscored integer and date strings in YAML output by @harehare in #2694
- 🐛 fix(run): reject empty, whitespace-only and comment-only queries consistently by @harehare in #2699
- 🐛 fix(run): report input line numbers for invalid JSONL records by @harehare in #2730
- 🔒 fix(run)!: prefix
-F shellvariable names to prevent env overwrite by @harehare in #2733 - 🐛 fix(test): support
import "test"in mq-test files by @harehare in #2687 - reject trailing pipe without a right-hand expression by @mvanhorn in #2598
Documentation
- 📝 docs(lang): document terminators for nested functions by @harehare in #2706
- 📝 docs(run): clarify --aggregate and --eval-all help by @harehare in #2633
- 📝 docs(skills): use -I raw instead of the non-existent --csv flag by @harehare in #2696
- 📝 docs: deny missing_docs and document all public items by @harehare in #2573
- 📝 docs: add Scoop installation instructions by @harehare in #2595
- 📝 docs: fix incorrect examples and make them executable by @harehare in #2643
- 📝 docs: add a README to each crate that shared the top-level one by @harehare in #2678
- 📝 docs: add evaluation model page and clarify exit status on Markdown input by @harehare in #2681
Refactoring
- ♻ refactor(editors): replace Start LSP Server with Restart by @harehare in #2639
- ♻ refactor(lang): mark error enums as non_exhaustive by @harehare in #2562
- ♻ refactor(lang): remove section::has_content, deprecate *_header_depth by @harehare in #2607
- 🔥 refactor(lang): remove deprecated increase_header_depth and decrease_header_depth by @harehare in #2626
- 🔥 refactor(lang)!: remove http_* wrapper builtins by @harehare in #2656
- ♻ refactor(lang): remove unwrap from parser by @harehare in #2729
- ♻ refactor(run): align CLI flags with jq and move actions to subcommnds by @harehare in #2575
- ♻ refactor(scripts): bump versions through the toml and json modules by @harehare in #2563
- ♻ refactor: shrink the release binary and remove dead code by @harehare in #2580
- ♻ refactor: move mq-web-api to its own repository by @harehare in #2623
- 🧹 chore: remove deprecated builtins and dead code, split large test modules by @harehare in #2627
Performance
- ⚡ perf(check): shrink binaries and tidy mq-check internals by @harehare in #2564
- ⚡ perf(lang): compile x = set(x, k, v) to an in-place index assignment by @harehare in #2579
- ⚡ perf(markdown): parse deeply nested lists in time linear in the input by @harehare in #2658
- ⚡ perf(markdown): reduce memory used by large Markdown inputs by @harehare in #2710
- ⚡ perf(wasm): build wasm packages with opt-level=z by @harehare in #2582
- ⚡ perf: compile syntax highlight regexes once by @harehare in #2581
Test
- 👷 ci: run tests on all OSes for every push and PR by @harehare in #2588
- ✨ ci: report spec conformance in the weekly job summary by @harehare in #2593
Other
- 🔧 chore(bench): remove benchmarks not run by CI or any just recipe by @harehare in #2574
- 💄 style(playground): use Space Grotesk for header title by @harehare in #2655
- 🔧 chore(task): sync task.md with justfile and use mq-task parallel/if/cache by @harehare in #2569
- 🔧 build: align Dockerfile and rust-toolchain to Rust 1.99.1 by @harehare in #2644
- 👷 ci: manage action versions with gh actions-lock by @harehare in #2732
Dependency Updates
Dependency Updates (40)
- ⬆ build(deps): update Cargo.lock dependencies by @harehare in #2641
- 📦 build(deps): bump scraper to 0.29 to unify html5ever and cssparser by @harehare in #2718
- ⬆ build(packages): update mq-chrome-extension and mq-web dependencies by @harehare in #2640
- chore(deps): bump the dependencies group with 4 updates by @dependabot[bot] in #2568
- chore(deps): bump toon-format from 0.5.0 to 0.6.1 in the dependencies group by @dependabot[bot] in #2566
- chore(deps): bump the dependencies group with 2 updates by @dependabot[bot] in #2577
- chore(deps): bump rust from 1.98.1-slim to 1.99.0-slim in the dependencies group by @dependabot[bot] in #2585
- chore(deps): bump the dependencies group with 2 updates by @dependabot[bot] in #2587
- chore(deps): bump the dependencies group with 2 updates by @dependabot[bot] in #2619
- chore(deps): bump the dependencies group with 2 updates by @dependabot[bot] in #2620
- chore(deps): bump the dependencies group in /packages/mq-playground with 3 updates by @dependabot[bot] in #2636
- chore(deps): bump the dependencies group with 2 updates by @dependabot[bot] in #2637
- chore(deps): bump the dependencies group with 3 updates by @dependabot[bot] in #2647
- chore(deps): bump taiki-e/install-action from 2.87.28 to 2.87.29 in the dependencies group by @dependabot[bot] in #2661
- chore(deps): bump the dependencies group with 2 updates by @dependabot[bot] in #2702
- chore(deps): bump Swatinem/rust-cache from 2.9.2 to 2.9.3 in the dependencies group by @dependabot[bot] in #2714
- httpmock: chore(deps): bump httpmock from 0.8.3 to 0.9.0 in the dependencies group by @dependabot[bot] in #2721
- chore(deps): bump the dependencies group with 3 updates by @dependabot[bot] in #2722
- chore(deps): bump vscode-languageclient from 10.1.2 to 11.0.0 in /editors/vscode in the dependencies group by @dependabot[bot] in #2725
- chore(deps): bump CodSpeedHQ/action from 5.5.0 to 5.6.0 in the dependencies group by @dependabot[bot] in #2727
- chore(deps-dev): bump oxlint from 1.86.0 to 1.87.0 in /editors/vscode in the dependencies group by @dependabot[bot] in #2565
- chore(deps-dev): bump the dependencies group in /packages/mq-playground with 5 updates by @dependabot[bot] in #2567
- chore(deps-dev): bump @babel/core from 7.29.7 to 8.0.7 in /packages/mq-playground in the dependencies group by @dependabot[bot] in #2570
- chore(deps-dev): bump the dependencies group in /packages/mq-playground with 2 updates by @dependabot[bot] in #2576
- chore(deps-dev): bump @types/node from 26.6.4 to 26.6.5 in /editors/vscode in the dependencies group by @dependabot[bot] in #2583
- chore(deps-dev): bump @types/node from 26.6.4 to 26.6.5 in /packages/mq-web in the dependencies group by @dependabot[bot] in #2584
- chore(deps-dev): bump @babel/core from 7.29.7 to 8.0.7 in /packages/mq-playground in the dependencies group by @dependabot[bot] in #2586
- chore(deps-dev): bump vitest from 5.0.3 to 5.0.4 in /packages/mq-web in the dependencies group by @dependabot[bot] in #2617
- chore(deps-dev): bump vitest from 5.0.3 to 5.0.4 in /packages/mq-playground in the dependencies group by @dependabot[bot] in #2618
- chore(deps-dev): bump oxlint from 1.87.0 to 1.88.0 in /editors/vscode in the dependencies group by @dependabot[bot] in #2628
- chore(deps-dev): bump oxlint from 1.87.0 to 1.88.0 in /packages/mq-web in the dependencies group by @dependabot[bot] in #2629
- chore(deps-dev): bump the dependencies group in /packages/mq-playground with 3 updates by @dependabot[bot] in #2630
- chore(deps-dev): bump tsup from 8.5.1 to 9.0.0 in /packages/mq-web in the dependencies group by @dependabot[bot] in #2635
- chore(deps-dev): bump the dependencies group in /packages/mq-playground with 3 updates by @dependabot[bot] in #2646
- chore(deps-dev): bump @babel/core from 7.29.7 to 8.0.7 in /packages/mq-playground in the dependencies group by @dependabot[bot] in #2660
- chore(deps-dev): bump oxlint from 1.88.0 to 1.89.0 in /editors/vscode in the dependencies group by @dependabot[bot] in #2700
- chore(deps-dev): bump the dependencies group in /packages/mq-playground with 2 updates by @dependabot[bot] in #2701
- chore(deps-dev): bump @babel/core from 7.29.7 to 8.0.7 in /packages/mq-playground in the dependencies group by @dependabot[bot] in #2713
- chore(deps-dev): bump the dependencies group in /packages/mq-playground with 2 updates by @dependabot[bot] in #2720
- chore(deps-dev): bump @babel/core from 7.29.7 to 8.0.7 in /packages/mq-playground in the dependencies group by @dependabot[bot] in #2726
New Contributors
Full Changelog: v0.9.3...v0.10.0