{"id":15048490,"url":"https://github.com/yshavit/mdq","last_synced_at":"2026-04-01T22:50:36.714Z","repository":{"id":243474483,"uuid":"805931732","full_name":"yshavit/mdq","owner":"yshavit","description":"like jq but for Markdown: find specific elements in a md doc","archived":false,"fork":false,"pushed_at":"2026-03-16T01:08:37.000Z","size":969,"stargazers_count":1684,"open_issues_count":14,"forks_count":20,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-03-16T11:43:25.715Z","etag":null,"topics":["jq","markdown","md","querying"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yshavit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-05-25T22:02:10.000Z","updated_at":"2026-03-16T01:08:39.000Z","dependencies_parsed_at":"2024-06-09T08:29:36.345Z","dependency_job_id":"655275da-3686-434b-960b-c95e69c3d164","html_url":"https://github.com/yshavit/mdq","commit_stats":null,"previous_names":["yshavit/mdq"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/yshavit/mdq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yshavit%2Fmdq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yshavit%2Fmdq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yshavit%2Fmdq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yshavit%2Fmdq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yshavit","download_url":"https://codeload.github.com/yshavit/mdq/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yshavit%2Fmdq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292703,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jq","markdown","md","querying"],"created_at":"2024-09-24T21:13:25.614Z","updated_at":"2026-04-01T22:50:36.701Z","avatar_url":"https://github.com/yshavit.png","language":"Rust","readme":"# mdq: jq for Markdown\n\n[![Code Coverage][coverage-shield]][coverage-link]\n[![Build status][build-shield]][build-link]\n[![Pending TODOs][todos-shield]][todos-link]\n[![Ignored tests][ignoreds-shield]][ignoreds-link]\n\n[coverage-shield]: https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2Fyshavit%2F53901a0115b596e015a891c41fb0f256%2Fraw%2Fmdq-coverage.json\n\n[coverage-link]: https://github.com/yshavit/mdq/actions/workflows/coverage.yml?query=branch%3Amain\n\n[build-shield]: https://github.com/yshavit/mdq/actions/workflows/rust.yml/badge.svg\n\n[build-link]: https://github.com/yshavit/mdq/actions/workflows/rust.yml?query=branch%3Amain\n\n[todos-shield]: https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2Fyshavit%2Fe7a9e9e72651da0d7d2b1fbbe56237d0%2Fraw%2Fmdq-todos.json\n\n[todos-link]: https://github.com/search?q=repo%3Ayshavit%2Fmdq+NOT+path%3A.github%2Fworkflows%2Fcoverage.yml+NOT+path%3AREADME.md+todo\u0026type=code\n\n[ignoreds-shield]: https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2Fyshavit%2F782a8dc5f77d2cf4b1c774da72636f00%2Fraw%2Fmdq-ignoreds.json\n\n[ignoreds-link]: https://github.com/search?q=repo%3Ayshavit%2Fmdq+%28%28path%3A%2F%5C.rs%24%2F+%22%23%5Bignore%5D%22%29+OR+%28path%3Atests%2Fmd_cases+%2F%5Eignore%2F%29%29\u0026type=code\n\n## What is mdq?\n\nmdq aims to do for Markdown what jq does for JSON: provide an easy way to zero in on specific parts of a document.\n\nFor example, GitHub PRs are Markdown documents, and some organizations have specific templates with checklists for all\nreviewers to complete. Enforcing these often requires ugly regexes that are a pain to write and worse to debug. Instead,\nyou can (for example) ask mdq for all uncompleted tasks:\n\n```shell\nmdq '- [ ]'\n```\n\nmdq is available under the Apache 2.0 or MIT licenses, at your option. I am open to other permissive licenses, if you\nhave one you prefer.\n\n# Installation\n\n\u003e [!tip]\n\u003e You can try mdq live in your browser at https://yshavit.github.io/mdq-playground.\n\nTo install mdq locally, any of these will work:\n\n1. ```shell\n   # (Mac and Linux, with brew installed)\n   brew install mdq\n   ```\n1. ```bash\n   docker pull yshavit/mdq\n   echo 'My [example](https://github.com/yshavit/mdq) markdown' | docker run --rm -i yshavit/mdq '[]()'\n   ```\n   To use a specific release version, use `yshavit/mdq:\u003cversion\u003e`. See [Docker Hub] for available version tags.\n1. Download binaries from [the latest release] (or any other release, of course).\n   \u003cdetails\u003e\n   \u003csummary\u003eMac users\u003c/summary\u003e\n      \n   Macs quarantine downloads from the internet by default. If you get an error saying that Apple cannot check the binary for malicious software, you can remove this flag by running the following on the binary after extracting it from the artifact zip:\n   ```bash\n   xattr -d com.apple.quarantine mdq\n   ```\n   \n   \u003c/details\u003e\n   \n   \u003cdetails\u003e\n   \u003csummary\u003eSecurity concerns\u003c/summary\u003e\n   \n   The release and latest-workflow binaries are built on GitHub's servers, so if you trust my code (and dependencies), and you trust GitHub,\n   you can trust the binaries. See https://github.com/yshavit/mdq/wiki/Release-binaries for information on how to verify them.\n   \n   \u003c/details\u003e\n   \n   \u003cdetails\u003e\n   \u003csummary\u003eNon-release builds\u003c/summary\u003e\n\n   You can also grab the binaries from the latest [build-release] workflow run. You must be logged into GitHub to do\n   that (this is GitHub's limitation, not mine). You'll have to `chmod +x` them before you can run them.\n\n   \u003c/details\u003e \n1. ```shell\n   cargo install --git https://github.com/yshavit/mdq\n   ```\n   Requires rustc \u003e= 1.85.1\n\n[Docker Hub]: https://hub.docker.com/r/yshavit/mdq/tags\n\n[the latest release]: https://github.com/yshavit/mdq/releases/latest\n\n[build-release]: https://github.com/yshavit/mdq/actions/workflows/build-release.yml\n\n# Basic Usage\n\nSimple example to select sections containing \"usage\":\n\n```shell\ncat example.md | mdq '# usage'\n```\n\nUse pipe (`|`) to chain filters together. For example, to select sections containing \"usage\", and within those find\nall unordered list items:\n\n```shell\ncat example.md | mdq '# usage | -'\n```\n\nThe filter syntax is designed to mirror Markdown syntax. You can select...\n\n| Element          | Syntax                              |\n|------------------|-------------------------------------|\n| Sections         | `# title text`                      |\n| Lists            | `- unordered list item text`        |\n| \"                | `1. ordered list item text`         |\n| \"                | `- [ ] uncompleted task`            |\n| \"                | `- [x] completed task`              |\n| \"                | `- [?] any task`                    |\n| Links            | `[display text](url)`               |\n| Images           | `![alt text](url)`                  |\n| Block quotes     | `\u003e block quote text`                |\n| Code blocks      | ` ```language \u003ccode block text\u003e`    |\n| Raw HTML         | `\u003c/\u003e html_tag`                      |\n| Plain paragraphs | `P: paragraph text `                |\n| Tables           | `:-: header text :-: row text`      |\n| Front matter     | `+++[toml\\|yaml] front matter text` |\n\n(Tables selection differs from other selections in that you can actually select only certain headers and rows, such that\nthe resulting element is of a different shape than the original. See the example below, or the wiki for more detail.)\n\nIn any of the above, the text may be:\n\n- an `unquoted string` that starts with a letter; this is case-insensitive\n- a `\"quoted string\"` (either single or double quotes); this is case-sensitive\n- a string (quoted or unquoted) anchored by `^` or `$` (for start and end of string, respectively)\n- a `/regex/` match or `!s/regex/replace/` (see the user manual for [caveats about replacements])\n- omitted or `*`, to mean \"any\"\n\nSee the [tutorial] for a bit more detail, and [user manual] for the full picture.\n\n[caveats about replacements]: https://github.com/yshavit/mdq/wiki/Full-User-Manual#regex-replacements\n\n[tutorial]: https://github.com/yshavit/mdq/wiki/Tutorial\n\n[user manual]: https://github.com/yshavit/mdq/wiki/Full-User-Manual\n\n## Examples\n\n### Ensuring that people have searched existing issues before submitting a bug report\n\nMany projects have bug report templates that ask the submitter to attest that they've checked existing issues for possible duplicates. In mdq, you can do:\n\n```bash\nif echo \"$ISSUE_TEXT\" | mdq -q '- [x] I have searched for existing issues' ; then\n  ...\n```\n\n(The `-q` option is like grep's: it doesn't output anything to stdout, but exits 0 if any items were found, or non-0 otherwise.)\n\nThis will match:\n\n\u003e - [x] I have searched for existing issues\n\n... but will fail if the checkbox is unchecked:\n\n\u003e - [ ] I have searched for existing issues\n\n### Extracting a referenced ticket\n\nSome organizations use GitHub Actions to update their ticket tracker, if a PR mentions a ticket. You can use mdq to extract the link from Markdown as JSON, and then use jq to get the URL:\n\n```bash\nTICKET_URL=\"$(echo \"$PR_TEXT\"\n  | mdq --output json '# Ticket | [](^https://tickets.example.com/[A-Z]+-\\d+$)'\n  | jq -r '.items[].link.url')\"\n```\n\nThis will match Markdown like:\n\n\u003e #### Ticket\n\u003e\n\u003e https://tickets.example.com/PROJ-1234\n\n### Whittling down a big table\n\nLet's say you have a table whose columns reference people in an on-call schedule, rows correspond to weeks in `YYYY-MM-DD` format:\n\n\u003e |   On-Call  | Alice | Bob | Sam | Pat |\n\u003e |:----------:|:-----:|:---:|:---:|:---:|\n\u003e | 2024-01-08 |   x   |     |     |     |\n\u003e | 2024-01-15 |       |     |  x  |     |\n\u003e | 2024-01-22 |       | x   |     |     |\n\nTo find out when Alice is on call:\n\n```bash\ncat oncall.md | mdq ':-: /On-Call|Alice/:-: *'\n```\n```markdown\n|  On-Call   | Alice |\n|:----------:|:-----:|\n| 2024-01-08 |   x   |\n| 2024-01-15 |       |\n| 2024-01-22 |       |\n```\n\nOr, to find out who's on call for the week of Jan 15:\n\n```bash\ncat oncall.md | mdq ':-: * :-: 2024-01-15'\n```\n```markdown\n|  On-Call   | Alice | Bob | Sam | Pat |\n|:----------:|:-----:|:---:|:---:|----:|\n| 2024-01-15 |       |     |  x  |     |\n```\n\n# Development\n\n## Using mdq in your library\n\nmdq is available as a Rust library at https://crates.io/crates/mdq. Its docs are available at https://docs.rs/mdq/latest/mdq/.\n\n## Working on mdq itself\n\nRequires rustc \u003e= 1.85.1\n\n```bash\ncargo build\n```\n\n```bash\ncargo test\n```\n","funding_links":[],"categories":["markdown","Command line","Rust","其他工具"],"sub_categories":["命令行工具"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyshavit%2Fmdq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyshavit%2Fmdq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyshavit%2Fmdq/lists"}