{"id":36236540,"url":"https://github.com/dahlia/hongdown","last_synced_at":"2026-05-30T07:01:58.595Z","repository":{"id":331790681,"uuid":"1129214146","full_name":"dahlia/hongdown","owner":"dahlia","description":"A Markdown formatter that enforces Hong Minhee's Markdown style conventions","archived":false,"fork":false,"pushed_at":"2026-04-30T07:25:25.000Z","size":1306,"stargazers_count":188,"open_issues_count":1,"forks_count":8,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-05-22T11:37:04.115Z","etag":null,"topics":["commonmark","formatter","gfm","markdown"],"latest_commit_sha":null,"homepage":"https://dahlia.github.io/hongdown/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dahlia.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE","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":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-01-06T19:13:53.000Z","updated_at":"2026-04-30T07:25:30.000Z","dependencies_parsed_at":"2026-03-01T09:05:09.884Z","dependency_job_id":null,"html_url":"https://github.com/dahlia/hongdown","commit_stats":null,"previous_names":["dahlia/hongdown"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/dahlia/hongdown","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahlia%2Fhongdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahlia%2Fhongdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahlia%2Fhongdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahlia%2Fhongdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dahlia","download_url":"https://codeload.github.com/dahlia/hongdown/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahlia%2Fhongdown/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33682998,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["commonmark","formatter","gfm","markdown"],"created_at":"2026-01-11T06:00:39.822Z","updated_at":"2026-05-30T07:01:58.584Z","avatar_url":"https://github.com/dahlia.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"Hongdown\n========\n\n[![crates.io][crates.io badge]][crates.io]\n[![npm][npm badge]][npm]\n[![@hongdown/wasm][@hongdown/wasm badge]][@hongdown/wasm]\n[![GitHub Actions][GitHub Actions badge]][GitHub Actions]\n\nHongdown is a Markdown formatter that enforces [Hong Minhee's Markdown\nstyle conventions](./STYLE.md).  The formatter is implemented in Rust using\nthe [Comrak] library for parsing.  It produces consistently formatted Markdown\noutput following a distinctive style used across multiple projects including\n[Fedify], [LogTape], and [Optique].\n\n[crates.io badge]: https://img.shields.io/crates/v/hongdown?logo=rust\n[crates.io]: https://crates.io/crates/hongdown\n[npm badge]: https://img.shields.io/npm/v/hongdown?logo=npm\n[npm]: https://www.npmjs.com/package/hongdown\n[@hongdown/wasm badge]: https://img.shields.io/npm/v/@hongdown/wasm?logo=webassembly\u0026label=%40hongdown%2Fwasm\n[@hongdown/wasm]: https://www.npmjs.com/package/@hongdown/wasm\n[GitHub Actions badge]: https://github.com/dahlia/hongdown/actions/workflows/main.yaml/badge.svg\n[GitHub Actions]: https://github.com/dahlia/hongdown/actions/workflows/main.yaml\n[Comrak]: https://comrak.ee/\n[Fedify]: https://fedify.dev/\n[LogTape]: https://logtape.org/\n[Optique]: https://optique.dev/\n\n\nInstallation\n------------\n\n### npm\n\n~~~~ bash\nnpm install -g hongdown\n~~~~\n\n### mise\n\n~~~~ bash\nmise use -g github:dahlia/hongdown\n~~~~\n\n### Cargo\n\n~~~~ bash\ncargo install hongdown\n~~~~\n\n### Nix\n\n~~~~ bash\nnix run github:dahlia/hongdown\n~~~~\n\n### Pre-built binaries\n\nPre-built binaries for Linux, macOS, and Windows are available on the\n[GitHub Releases] page.\n\n[GitHub Releases]: https://github.com/dahlia/hongdown/releases\n\n\nUsage\n-----\n\n### Basic usage\n\n~~~~ bash\n# Format a file and print to stdout\nhongdown input.md\n\n# Format a file in place\nhongdown --write input.md\nhongdown -w input.md\n\n# Format multiple files\nhongdown -w *.md\n\n# Format all Markdown files in a directory (recursive)\nhongdown -w .\nhongdown -w docs/\n\n# Check if files are formatted (exit 1 if not)\nhongdown --check input.md\nhongdown -c input.md\n\n# Show diff of formatting changes\nhongdown --diff input.md\nhongdown -d input.md\n\n# Read from stdin (use --stdin flag or - as filename)\necho \"# Hello\" | hongdown --stdin\necho \"# Hello\" | hongdown -\nhongdown --stdin \u003c input.md\nhongdown - \u003c input.md\n\n# Custom line width\nhongdown --line-width 100 input.md\n\n# Disable word wrapping entirely\nhongdown --no-line-width input.md\n~~~~\n\n### HTML comment directives\n\nHongdown supports special HTML comment directives to control formatting\nbehavior within documents.\n\n#### Disable formatting\n\nYou can disable formatting for specific sections:\n\n~~~~ markdown\n\u003c!-- hongdown-disable-file --\u003e\nThis entire file will not be formatted.\n~~~~\n\n~~~~ markdown\n\u003c!-- hongdown-disable-next-line --\u003e\nThis   line   preserves   its   spacing.\n\nThe next line will be formatted normally.\n~~~~\n\n~~~~ markdown\n\u003c!-- hongdown-disable-next-section --\u003e\nEverything here is preserved as-is\nuntil the next heading (h1 or h2).\n\nNext heading\n------------\n\nThis section will be formatted normally.\n~~~~\n\n~~~~ markdown\n\u003c!-- hongdown-disable --\u003e\nThis section is not formatted.\n\u003c!-- hongdown-enable --\u003e\nThis section is formatted again.\n~~~~\n\n#### Sentence case customization\n\nWhen sentence case is enabled, you can define document-specific proper nouns\nand common nouns:\n\n~~~~ markdown\n\u003c!-- hongdown-proper-nouns: Swift, Go --\u003e\n\u003c!-- hongdown-common-nouns: Python --\u003e\n\n# Using Swift And Go For Python Development\n\nThis heading will be formatted as: \"Using Swift and Go for python development\"\n~~~~\n\n -  `\u003c!-- hongdown-proper-nouns: Word1, Word2 --\u003e` – Defines proper nouns to\n    preserve (case-sensitive)\n -  `\u003c!-- hongdown-common-nouns: Word1, Word2 --\u003e` – Overrides built-in proper\n    nouns by treating them as common nouns\n\nThese directives are merged with configuration file settings.\n\n### Configuration file\n\nHongdown supports cascading configuration files from multiple locations.\nConfiguration files are loaded and merged in the following order (lowest to\nhighest priority):\n\n1.  **System-wide**: */etc/hongdown/config.toml* (Linux/Unix only)\n2.  **User (legacy)**: *~/.hongdown.toml* (all platforms)\n3.  **User (platform-specific)**:\n     -  Linux: *$XDG\\_CONFIG\\_HOME/hongdown/config.toml* or\n        *~/.config/hongdown/config.toml*\n     -  macOS: *~/Library/Application Support/hongdown/config.toml*\n     -  Windows: *%APPDATA%\\\\hongdown\\\\config.toml*\n4.  **Project**: *.hongdown.toml* in the current directory or any parent\n    directory\n\nSettings from higher-priority configurations override those from lower-priority\nones.  This allows you to set global defaults at the user or system level while\noverriding them for specific projects.\n\nYou can also specify a configuration file explicitly with the `--config` option,\nwhich bypasses the cascading system and uses only that file.\n\n#### Disabling configuration inheritance\n\nTo ignore all system and user configurations and use only your project config:\n\n~~~~ toml\nno_inherit = true\n\n# Your project-specific settings\nline_width = 100\n~~~~\n\nWhen `no_inherit = true`, only the project config and Hongdown's defaults are\nused.  This is useful for projects that need strict formatting control\nregardless of user preferences.\n\n#### Configuration options\n\nBelow is an example configuration with all available options and their\ndefault values:\n\n~~~~ toml\n# File patterns (glob syntax)\ninclude = []              # Files to format (default: none, specify on CLI)\nexclude = []              # Files to skip (default: none)\ngit_aware = true          # Respect .gitignore and skip .git directory (default: true)\n\n# Formatting options\nline_width = 80           # Maximum line width (min: 8, default: 80); set to false to disable wrapping\nmath = true               # Preserve TeX math ($…$ and $$…$$) verbatim (default: true)\n\n[heading]\nsetext_h1 = true          # Use === underline for h1 (default: true)\nsetext_h2 = true          # Use --- underline for h2 (default: true)\nsentence_case = false     # Convert headings to sentence case (default: false)\nproper_nouns = []         # Additional proper nouns to preserve (default: [])\ncommon_nouns = []         # Exclude built-in proper nouns (default: [])\nanchor_align = 0          # Spaces before anchor {#id}: positive = exact count,\n                          # 0/negative = right-align to line_width+anchor_align (default: 0)\n\n[unordered_list]\nunordered_marker = \"-\"    # \"-\", \"*\", or \"+\" (default: \"-\")\nleading_spaces = 1        # Spaces before marker (0–3, default: 1)\ntrailing_spaces = 2       # Spaces after marker (0–3, default: 2)\nindent_width = 4          # Indentation for nested items (min: 1, default: 4)\n\n[ordered_list]\nodd_level_marker = \".\"    # \".\" or \")\" at odd nesting levels (default: \".\")\neven_level_marker = \")\"   # \".\" or \")\" at even nesting levels (default: \")\")\npad = \"start\"             # \"start\" or \"end\" for number alignment (default: \"start\")\nindent_width = 4          # Indentation for nested items (min: 1, default: 4)\n\n[code_block]\nfence_char = \"~\"          # \"~\" or \"`\" (default: \"~\")\nmin_fence_length = 4      # Minimum fence length (min: 3, default: 4)\nspace_after_fence = true  # Space between fence and language (default: true)\ndefault_language = \"\"     # Default language for code blocks (default: \"\")\n\n# External code formatters (see \"External code formatters\" section)\n[code_block.formatters]\n# javascript = [\"deno\", \"fmt\", \"--ext=js\", \"-\"]\n\n[thematic_break]\n# Must be valid CommonMark: at least 3 of *, -, or _ (with optional spaces)\nstyle = \"- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\"\nleading_spaces = 3        # Leading spaces (0–3, default: 3)\n\n[punctuation]\ncurly_double_quotes = true   # \"text\" to \"text\" (default: true)\ncurly_single_quotes = true   # 'text' to 'text' (default: true)\ncurly_apostrophes = false    # it's to it's (default: false)\nellipsis = true              # ... to ... (default: true)\nen_dash = false              # Disabled by default (use \"--\" to enable)\nem_dash = \"--\"               # -- to --- (default: \"--\", use false to disable)\n~~~~\n\nConfiguration values are validated at parse time.  Invalid values will produce\ndescriptive error messages:\n\n~~~~ bash\n$ hongdown --config invalid.toml input.md\nError: failed to parse configuration file: line_width must be at least 8, got 5.\n~~~~\n\nWhen `include` patterns are configured, you can run Hongdown without\nspecifying files:\n\n~~~~ bash\n# Format all files matching include patterns\nhongdown --write\n\n# Check all files matching include patterns\nhongdown --check\n~~~~\n\nCLI options override configuration file settings:\n\n~~~~ bash\n# Use config file but override line width\nhongdown --line-width 100 input.md\n\n# Disable word wrapping (overrides config file)\nhongdown --no-line-width input.md\n\n# Use specific config file\nhongdown --config /path/to/.hongdown.toml input.md\n~~~~\n\n\nStyle rules\n-----------\n\nHongdown enforces the following conventions:\n\n### Headings\n\n -  Level 1 and 2 use Setext-style (underlined with `=` or `-`)\n -  Level 3+ use ATX-style (`###`, `####`, etc.)\n -  Optional sentence case conversion (disabled by default)\n\n~~~~ markdown\nDocument Title\n==============\n\nSection\n-------\n\n### Subsection\n~~~~\n\n#### Sentence case (optional)\n\nWhen `sentence_case = true` is set in the configuration, Hongdown automatically\nconverts headings to sentence case using intelligent heuristics:\n\n~~~~ markdown\n# Development Commands      → Development commands\n# Working With JSON APIs    → Working with JSON APIs\n# Using `MyClass` In Code   → Using `MyClass` in code\n~~~~\n\nThe converter:\n\n -  Capitalizes only the first word\n -  Preserves code spans (text in backticks)\n -  Preserves acronyms (2+ consecutive uppercase letters, e.g., `API`, `HTTP`)\n -  Preserves proper nouns (built-in list + user-configured)\n -  Handles hyphenated words (e.g., `JSON-RPC`)\n -  Respects quoted text capitalization\n -  Preserves non-Latin scripts (CJK, etc.)\n\nYou can add custom proper nouns to preserve:\n\n~~~~ toml\n[heading]\nsentence_case = true\nproper_nouns = [\"MyCompany\", \"MyProduct\", \"MyAPI\"]\n~~~~\n\nYou can also exclude built-in proper nouns by treating them as common nouns.\nThis is useful for words like “Go” which can be either a programming language\nor a common verb:\n\n~~~~ toml\n[heading]\nsentence_case = true\ncommon_nouns = [\"Go\", \"Swift\"]  # Treat these as common nouns, not proper nouns\n~~~~\n\nBuilt-in proper nouns include ~450 entries: programming languages (JavaScript,\nTypeScript, Python, Rust, Go), technologies (GitHub, Docker, React, Node.js),\ndatabases (PostgreSQL, MySQL, MongoDB), countries (United States, Republic of\nKorea), natural languages (English, Korean, Japanese), and more.\n\nYou can also use HTML comment directives to define document-specific proper\nnouns and common nouns.  See the “HTML comment directives” section for details.\n\n### Lists\n\n -  Unordered lists use ` -  ` (space-hyphen-two spaces)\n -  Ordered lists use `1.` format\n -  4-space indentation for nested items\n\n~~~~ markdown\n -  First item\n -  Second item\n     -  Nested item\n~~~~\n\n### Code blocks\n\n -  Fenced with four tildes (`~~~~`)\n -  Language identifier on the opening fence\n\n~~~~~ text\n~~~~ rust\nfn main() {\n    println!(\"Hello, world!\");\n}\n~~~~\n~~~~~\n\n### External code formatters\n\nYou can configure external formatters for code blocks in your *.hongdown.toml*.\nThis allows automatic formatting of embedded code using language-specific tools.\n\n~~~~ toml\n[code_block.formatters]\n# Simple format: command as array\njavascript = [\"deno\", \"fmt\", \"--ext=js\", \"-\"]\ntypescript = [\"deno\", \"fmt\", \"--ext=ts\", \"-\"]\nrust = [\"rustfmt\"]\n\n# With custom timeout (default is 5 seconds)\n[code_block.formatters.python]\ncommand = [\"black\", \"-\"]\ntimeout = 10\n~~~~\n\nBehavior:\n\n -  Language matching is exact only (`javascript` matches `javascript`, not\n    `js`)\n -  Code is passed to the formatter via stdin, formatted output read from stdout\n -  If the formatter fails (non-zero exit, timeout, etc.), the original code is\n    preserved and a warning is emitted\n -  External formatters are only available in CLI mode (not in WASM)\n\nTo skip formatting for a specific code block, add `hongdown-no-format` after the\nlanguage identifier:\n\n~~~~~ markdown\n~~~~ python hongdown-no-format\ndef hello(): print(\"Hello, World!\")\n~~~~\n~~~~~\n\nThe `hongdown-no-format` keyword is preserved in the output, ensuring the code\nblock remains unformatted on subsequent runs.\n\nFor WASM builds, use the `formatWithCodeFormatter` function with a callback:\n\n~~~~ typescript\nimport { formatWithCodeFormatter } from \"@hongdown/wasm\";\nimport * as prettier from \"prettier\";\n\nconst { output, warnings } = await formatWithCodeFormatter(markdown, {\n  codeFormatter: (language, code) =\u003e {\n    if (language === \"javascript\" || language === \"typescript\") {\n      return prettier.format(code, { parser: \"babel\" });\n    }\n    return null; // Keep original for other languages\n  },\n});\n~~~~\n\n### Line wrapping\n\n -  Lines wrap at approximately 80 display columns\n -  East Asian wide characters are counted as 2 columns\n -  Long words that cannot be broken are preserved\n\n### Math\n\n -  Inline (`$…$`) and display (`$$…$$`) TeX/LaTeX math is preserved verbatim,\n    never escaped or punctuation-transformed (like code spans)\n -  Inline math is kept on a single line when wrapping\n -  Dollar-math parsing follows GitHub's rules, so a lone `$`, `$ command`, or\n    `$5` stays literal text\n -  Disable with `math = false` in *.hongdown.toml* to treat every `$` as text\n\n~~~~ markdown\nThe complexity is $O(n \\log n)$.\n\n$$\nx = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}\n$$\n~~~~\n\n### Links\n\n -  External URLs are converted to reference-style links\n -  References are placed at the end of each section\n -  Relative/local URLs remain inline\n\n~~~~ markdown\nSee the [documentation] for more details.\n\n[documentation]: https://example.com/docs\n~~~~\n\n### Tables\n\n -  Pipes are aligned accounting for East Asian wide characters\n -  Minimum column width is maintained\n\nSee *[STYLE.md](./STYLE.md)* for the complete style specification, including\nthe philosophy behind these conventions and detailed formatting rules.\n\n\nEditor integrations\n-------------------\n\n### Zed\n\nAdd the following to your Zed settings to use Hongdown as the Markdown\nformatter (contributed by [Lee Dogeon][moreal zed]):\n\n~~~~ json\n{\n  \"languages\": {\n    \"Markdown\": {\n      \"formatter\": {\n        \"external\": {\n          \"command\": \"hongdown\",\n          \"arguments\": [\"-\"]\n        }\n      }\n    }\n  }\n}\n~~~~\n\n[moreal zed]: https://hackers.pub/@moreal/019bb141-dc94-7103-ab3d-779941125430\n\n### Neovim\n\nIf you use [none-ls.nvim] (a community-maintained fork of *null-ls.nvim*), you\ncan register Hongdown as a formatter (requires [none-ls-extras.nvim],\ncontributed by [Vladimir Rubin]):\n\n~~~~ lua\nlocal hongdown = require('none-ls.formatting.hongdown')\nnull_ls.register(hongdown)\n~~~~\n\n[none-ls.nvim]: https://github.com/nvimtools/none-ls.nvim\n[none-ls-extras.nvim]: https://github.com/nvimtools/none-ls-extras.nvim\n[Vladimir Rubin]: https://github.com/dahlia/hongdown/issues/4\n\n### Helix\n\nIf you use [Helix], you can register Hongdown as a formatter (contributed by\n[Jean Simard]):\n\n~~~~ toml\n[[language]]\nname = \"markdown\"\nauto-format = true\nformatter = { command = \"hongdown\", args = [\"--stdin\"] }\n~~~~\n\n[Helix]: https://helix-editor.com/\n[Jean Simard]: https://github.com/dahlia/hongdown/pull/12\n\n\nLibrary usage\n-------------\n\n### Rust\n\nHongdown can also be used as a Rust library:\n\n~~~~ rust\nuse hongdown::{format, Options};\n\nlet input = \"# Hello World\\nThis is a paragraph.\";\nlet options = Options::default();\nlet output = format(input, \u0026options).unwrap();\nprintln!(\"{}\", output);\n~~~~\n\n### JavaScript/TypeScript\n\nHongdown is available as a WebAssembly-based library for JavaScript and\nTypeScript:\n\n~~~~ bash\nnpm install @hongdown/wasm\n~~~~\n\n~~~~ typescript\nimport { format, formatWithWarnings } from \"@hongdown/wasm\";\n\n// Basic usage\nconst markdown = \"# Hello\\nWorld\";\nconst formatted = await format(markdown);\n\n// With options\nconst result = await format(markdown, {\n  lineWidth: 100,\n  setextH1: false,\n  fenceChar: \"`\",\n});\n\n// Get warnings along with formatted output\nconst { output, warnings } = await formatWithWarnings(markdown);\nif (warnings.length \u003e 0) {\n  for (const warning of warnings) {\n    console.warn(`Line ${warning.line}: ${warning.message}`);\n  }\n}\n~~~~\n\nThe library works in Node.js, Bun, Deno, and web browsers.  See the\n[TypeScript type definitions] for all available options.\n\n[TypeScript type definitions]: ./packages/wasm/src/types.ts\n\n\nDevelopment\n-----------\n\nThis project uses [mise] for task management.\n\n[mise]: https://mise.jdx.dev/\n\n### Initial setup\n\nAfter cloning the repository, set up the Git pre-commit hook to automatically\nrun quality checks before each commit:\n\n~~~~ bash\nmise generate git-pre-commit --task=check --write\n~~~~\n\n### Quality checks\n\nThe following tasks are available:\n\n~~~~ bash\n# Run all quality checks\nmise run check\n\n# Individual checks\nmise run check:clippy     # Run clippy linter\nmise run check:fmt        # Check code formatting\nmise run check:type       # Run Rust type checking\nmise run check:markdown   # Check Markdown formatting\n~~~~\n\nSee *[AGENTS.md]* for detailed development guidelines including TDD\npractices, code style conventions, and commit message guidelines.\n\n[AGENTS.md]: ./AGENTS.md\n\n\nEtymology\n---------\n\nThe name *Hongdown* is a portmanteau of *Hong* (from Hong Minhee, the author)\nand *Markdown*.  It also sounds like the Korean word *hongdapda* (홍답다),\nmeaning “befitting of Hong” or “Hong-like.”\n\n\nLicense\n-------\n\nDistributed under the [GPL-3.0-or-later].  See *[LICENSE]* for more information.\n\n[GPL-3.0-or-later]: https://www.gnu.org/licenses/gpl-3.0.html\n[LICENSE]: ./LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdahlia%2Fhongdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdahlia%2Fhongdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdahlia%2Fhongdown/lists"}