{"id":50836262,"url":"https://github.com/dheid/adocfmt","last_synced_at":"2026-06-14T03:30:46.812Z","repository":{"id":362385780,"uuid":"1258455021","full_name":"dheid/adocfmt","owner":"dheid","description":"An opinionated AsciiDoc formatter for Java and the command line.","archived":false,"fork":false,"pushed_at":"2026-06-04T03:00:54.000Z","size":66,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-04T03:05:56.838Z","etag":null,"topics":["asciidoc","cli","formatter","formatting","java","library","maven","nfpm","tool"],"latest_commit_sha":null,"homepage":"https://dheid.github.io/adocfmt/","language":"Java","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/dheid.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","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},"funding":{"github":["dheid"],"ko_fi":"dheid"}},"created_at":"2026-06-03T15:40:09.000Z","updated_at":"2026-06-04T01:24:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dheid/adocfmt","commit_stats":null,"previous_names":["dheid/adocfmt"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/dheid/adocfmt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dheid%2Fadocfmt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dheid%2Fadocfmt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dheid%2Fadocfmt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dheid%2Fadocfmt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dheid","download_url":"https://codeload.github.com/dheid/adocfmt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dheid%2Fadocfmt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34308622,"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-06-14T02:00:07.365Z","response_time":62,"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":["asciidoc","cli","formatter","formatting","java","library","maven","nfpm","tool"],"created_at":"2026-06-14T03:30:45.821Z","updated_at":"2026-06-14T03:30:46.806Z","avatar_url":"https://github.com/dheid.png","language":"Java","funding_links":["https://github.com/sponsors/dheid","https://ko-fi.com/dheid"],"categories":[],"sub_categories":[],"readme":"# adocfmt\n\n[![Java CI with Maven](https://github.com/dheid/adocfmt/actions/workflows/ci.yml/badge.svg)](https://github.com/dheid/adocfmt/actions/workflows/ci.yml)\n[![Maven Central](https://img.shields.io/maven-central/v/org.drjekyll/adocfmt)](https://central.sonatype.com/artifact/org.drjekyll/adocfmt)\n[![GitHub Release](https://img.shields.io/github/v/release/dheid/adocfmt)](https://github.com/dheid/adocfmt/releases/latest)\n[![Java](https://img.shields.io/badge/Java-17%2B-blue)](https://adoptium.net/)\n\nAn opinionated AsciiDoc formatter for Java and the command line.\n\n![adocfmt Banner](banner.png)\n\n## Features\n\nadocfmt applies a configurable set of transformations to AsciiDoc source files.\nThe following transformations are available (default state shown):\n\n|          Transformation          | Default |                               Description                                |\n|----------------------------------|---------|--------------------------------------------------------------------------|\n| Normalize setext headings        | **on**  | Convert underline-style headings to ATX-style (`=` prefix)               |\n| Collapse consecutive blank lines | **on**  | Reduce runs of multiple blank lines to a single blank line               |\n| One sentence per line            | **on**  | Reflow paragraph text so each sentence starts on its own line            |\n| Normalize block delimiters       | **on**  | Shorten delimiter lines to exactly four characters (e.g. `----`)         |\n| Remove trailing header `=` signs | **on**  | Strip trailing `=` from headings (e.g. `== Title ==` → `== Title`)       |\n| Remove trailing whitespace       | **on**  | Strip trailing whitespace from every line                                |\n| Ensure heading blank lines       | **on**  | Surround each section heading with exactly one blank line                |\n| Title case                       | off     | Apply title-case formatting to section headings and block titles         |\n| Normalize list bullets           | off     | Normalise unordered list bullets from `- ` to `* `                       |\n| Normalize ordered list markers   | off     | Replace explicit numbers (`1. `, `2. `) with the auto-number marker `. ` |\n| Ensure source delimiters         | off     | Wrap bare `[source]`/`[listing]` blocks in `----` delimiters             |\n\n**Invariants guaranteed by every run:**\n\n- **Idempotent:** `format(format(x)) == format(x)`.\n- **Safe:** Delimited blocks (code, literal, passthrough), comments, and directives are never modified.\n- **Semantic:** Input and output render to identical normalised HTML (verified via AsciidoctorJ in tests).\n- **Trailing Newline:** Formatted output always ends with exactly one newline.\n\n## Code Style\n\nThis section describes the AsciiDoc style that adocfmt enforces.\nThe rationale behind each rule is consistent diffs, readable source, and\nunambiguous structure -- not aesthetic preference.\n\n### ATX Headings\n\nUse `=`-prefixed headings (ATX style) instead of underline-style (setext) headings.\nThe level maps directly to the number of `=` signs: one for the document title, two\nfor the first section level, and so on.\n\n```asciidoc\n// Before\nMy Document Title\n=================\n\nIntroduction\n------------\n\n// After\n= My Document Title\n\n== Introduction\n```\n\nTrailing `=` signs are also removed:\n\n```asciidoc\n// Before\n== Installation ==\n\n// After\n== Installation\n```\n\n### Blank Lines Around Headings\n\nEvery section heading is surrounded by exactly one blank line on each side.\nThis makes section boundaries visible at a glance and avoids parser ambiguity.\n\n```asciidoc\n// Before\nSome text.\n== Next Section\nMore text.\n\n// After\nSome text.\n\n== Next Section\n\nMore text.\n```\n\n### One Sentence Per Line\n\nEach sentence in a paragraph is placed on its own line.\nThis produces minimal, meaningful diffs: editing one sentence touches exactly one line,\nand adding a sentence does not reflow the paragraph.\n\n```asciidoc\n// Before\nAsciiDoc is a lightweight markup language. It is used for writing documentation. It can be converted to HTML, PDF, and other formats.\n\n// After\nAsciiDoc is a lightweight markup language.\nIt is used for writing documentation.\nIt can be converted to HTML, PDF, and other formats.\n```\n\nCommon abbreviations (e.g. `Dr.`, `etc.`, `ca.`) are recognised and do not trigger a split.\n\n### Consecutive Blank Lines\n\nAt most one consecutive blank line is permitted.\nMultiple blank lines carry no structural meaning in AsciiDoc and are collapsed to one.\n\n```asciidoc\n// Before\nFirst paragraph.\n\n\n\nSecond paragraph.\n\n// After\nFirst paragraph.\n\nSecond paragraph.\n```\n\n### Block Delimiters\n\nBlock delimiter lines use exactly four characters, regardless of how many were written originally.\nThis removes visual noise and prevents mismatched delimiter lengths from silently breaking block structure.\n\n```asciidoc\n// Before\n--------\n$ echo hello\n--------\n\n// After\n----\n$ echo hello\n----\n```\n\n### Source Blocks (optional, off by default)\n\n`[source]` and `[listing]` attribute lines that are not followed by `----` delimiters\nhave them added automatically, ensuring the code is rendered as a verbatim block.\n\n```asciidoc\n// Before\n[source,java]\nint x = 1;\n\n// After\n[source,java]\n----\nint x = 1;\n----\n```\n\n### List Bullets (optional, off by default)\n\nUnordered list items use `*` as the bullet character.\nThe `-` form is converted for consistency.\n\n```asciidoc\n// Before\n- Item A\n- Item B\n\n// After\n* Item A\n* Item B\n```\n\n### Ordered Lists (optional, off by default)\n\nOrdered list items use the AsciiDoc auto-numbering marker `.` instead of explicit numbers.\nThis prevents numbering from going out of sync when items are reordered.\n\n```asciidoc\n// Before\n1. First\n2. Second\n3. Third\n\n// After\n. First\n. Second\n. Third\n```\n\n### Title Case (optional, off by default)\n\nSection headings and block titles are formatted in title case.\nShort words (articles, conjunctions, short prepositions) are lowercased unless they\nappear as the first or last word.\n\n```asciidoc\n// Before\n== getting started with the cli\n\n// After\n== Getting Started with the CLI\n```\n\n## Installation\n\nRequires **Java 17+**.\n\n### Debian / Ubuntu\n\nDownload the `.deb` from the latest release and run:\n\n```bash\nsudo apt install ./adocfmt_\u003cversion\u003e_all.deb\n```\n\n### Fedora / RHEL / CentOS\n\nDownload the `.rpm` from the latest release and run:\n\n```bash\nsudo dnf install ./adocfmt-\u003cversion\u003e.noarch.rpm\n```\n\n### macOS (Homebrew)\n\n```bash\nbrew install drjekyll-org/tap/adocfmt\n```\n\n### Windows\n\nDownload `adocfmt.exe` from the latest release. Ensure Java 17+ is on your PATH.\n\n### Universal (Any Platform)\n\nDownload `adocfmt.jar` from the latest release and run:\n\n```bash\njava -jar adocfmt.jar [args]\n```\n\n## Usage\n\n### Java Library\n\nRequires Java 17+. Add the core module to your project:\n\n```xml\n\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.drjekyll\u003c/groupId\u003e\n    \u003cartifactId\u003eadocfmt\u003c/artifactId\u003e\n    \u003cversion\u003e0.2.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nBuild an `AsciidocFormatterConfig` with the desired transformations enabled, then create an `AsciidocFormatter` and call\none of its `format` overloads:\n\n```java\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport org.drjekyll.adocfmt.AsciidocFormatter;\nimport org.drjekyll.adocfmt.AsciidocFormatterConfig;\nimport org.drjekyll.adocfmt.UnsupportedLineEndingException;\n\nAsciidocFormatterConfig config = AsciidocFormatterConfig.builder()\n        .normalizeSetextHeadings(true)\n        .collapseConsecutiveBlankLines(true)\n        .oneSentencePerLine(true)\n        .normalizeBlockDelimiters(true)\n        .removeTrailingHeaderEqualsSign(true)\n        .removeTrailingWhitespace(true)\n        .ensureHeadingBlankLines(true)\n        .titleCase(false)\n        .normalizeListBullets(false)\n        .normalizeOrderedListMarkers(false)\n        .ensureSourceDelimiters(false)\n        .build();\n\nAsciidocFormatter formatter = new AsciidocFormatter(config);\n\n// Format a string\nString formatted = formatter.format(\"== my title\\n\\ncontent\");\n\n// Format a file (charset is auto-detected and preserved)\nPath path = Path.of(\"my.adoc\");\nbyte[] formattedBytes = formatter.format(Files.readAllBytes(path));\n\n// Format a stream\ntry (InputStream in = Files.newInputStream(path);\n     OutputStream out = Files.newOutputStream(path)) {\n    formatter.format(in, out);\n}\n```\n\n### CLI\n\n```\nUsage: adocfmt [-chVw] [-cbl[=\u003ctrue|false\u003e]] [-ehlb[=\u003ctrue|false\u003e]]\n               [-esd[=\u003ctrue|false\u003e]] [-nbd[=\u003ctrue|false\u003e]] [-nlb[=\u003ctrue|false\u003e]]\n               [-nolm[=\u003ctrue|false\u003e]] [-nsh[=\u003ctrue|false\u003e]] [-ols[=\u003ctrue|false\u003e]]\n               [-rthe[=\u003ctrue|false\u003e]] [-rtrw[=\u003ctrue|false\u003e]] [-tc[=\u003ctrue|false\u003e]]\n               [\u003cfiles\u003e...]\n```\n\n|                   Option                    | Default |                                Description                                |\n|---------------------------------------------|---------|---------------------------------------------------------------------------|\n| `-w`, `--write`                             | --      | Write formatted content back to files                                     |\n| `-c`, `--check`                             | --      | Check formatting without modifying files; exit 1 if any file would change |\n| `-nsh`, `--normalize-setext-headings`       | `true`  | Convert setext headings to ATX                                            |\n| `-cbl`, `--collapse-blank-lines`            | `true`  | Collapse consecutive blank lines                                          |\n| `-ols`, `--one-sentence-per-line`           | `true`  | One sentence per line                                                     |\n| `-nbd`, `--normalize-block-delimiters`      | `true`  | Normalise block delimiters to four characters                             |\n| `-rthe`, `--remove-trailing-header-equals`  | `true`  | Remove trailing `=` from headings                                         |\n| `-rtrw`, `--remove-trailing-whitespace`     | `true`  | Remove trailing whitespace                                                |\n| `-ehlb`, `--ensure-heading-blank-lines`     | `true`  | Ensure blank lines around headings                                        |\n| `-tc`, `--title-case`                       | `false` | Apply title case to headings                                              |\n| `-nlb`, `--normalize-list-bullets`          | `false` | Normalise list bullets to `*`                                             |\n| `-nolm`, `--normalize-ordered-list-markers` | `false` | Replace explicit numbers with `.`                                         |\n| `-esd`, `--ensure-source-delimiters`        | `false` | Add missing `----` delimiters around source blocks                        |\n\n#### Exit Codes\n\n| Code |                             Meaning                              |\n|------|------------------------------------------------------------------|\n| `0`  | Success -- all files processed without error                     |\n| `1`  | Unformatted files detected (only when `--check` is active)       |\n| `2`  | Processing error (file not found, not readable, I/O error, etc.) |\n\n#### Examples\n\n```bash\n# Format a single file in-place\nadocfmt -w my.adoc\n\n# Format multiple files in-place\nadocfmt -w docs/getting-started.adoc docs/reference.adoc\n\n# Format all .adoc files in a directory tree\nfind . -name \"*.adoc\" | xargs adocfmt -w\n\n# Preview formatted output without modifying the file (single file → stdout)\nadocfmt my.adoc\n\n# Format stdin to stdout\ncat my.adoc | adocfmt\n\n# Check formatting in CI -- exits 1 if any file would change\nadocfmt --check docs/*.adoc\n\n# Check all .adoc files in a directory tree in CI\nfind . -name \"*.adoc\" | xargs adocfmt --check\n\n# Check only the staged .adoc files (useful in a pre-commit hook)\ngit diff --cached --name-only --diff-filter=ACM | grep '\\.adoc$' | xargs adocfmt --check\n\n# Disable a transformation that is on by default\nadocfmt -w --one-sentence-per-line=false my.adoc\n\n# Disable multiple default transformations\nadocfmt -w -ols=false -cbl=false my.adoc\n\n# Enable optional transformations\nadocfmt -w --title-case --normalize-list-bullets my.adoc\n\n# Enable optional transformations using short aliases\nadocfmt -w -tc -nlb -nolm -esd my.adoc\n\n# Enable all optional transformations and disable one default\nadocfmt -w -tc -nlb -nolm -esd -ols=false my.adoc\n```\n\n## pre-commit\n\nadocfmt can be used as a [pre-commit](https://pre-commit.com/) hook.\nAdd the following to your `.pre-commit-config.yaml`:\n\n```yaml\nrepos:\n  - repo: https://github.com/dheid/adocfmt\n    rev: v0.2.0\n    hooks:\n      - id: adocfmt        # formats .adoc/.asciidoc files in place\n      - id: adocfmt-check  # CI mode: fails if any file would change\n```\n\nUse `adocfmt` in a local developer workflow (rewrites files before the commit is\nrecorded) and `adocfmt-check` in CI (read-only, exits 1 if any file is not\nformatted).\n\n**Requirement:** Java 17 or later must be on your `PATH`.\nThe hook downloads `adocfmt.jar` from the GitHub release on first use and caches\nit in `~/.cache/adocfmt/` (or `$XDG_CACHE_HOME/adocfmt/`).\nSet the `ADOCFMT_JAR` environment variable to point at a local jar to skip the\ndownload entirely.\n\n## GitHub Actions\n\nadocfmt is available as a reusable composite GitHub Action.\nJava is set up automatically — no pre-installed runtime is required in the\ncalling workflow.\n\n### Check mode (gate a PR)\n\nFails the job when any `.adoc` or `.asciidoc` file is not formatted.\nDirectories are walked recursively.\n\n```yaml\nsteps:\n  - uses: actions/checkout@v6\n  - uses: dheid/adocfmt@v0.2.0\n    with:\n      mode: check    # default — can be omitted\n      paths: .       # default — whole repo\n```\n\n### Write mode (auto-fix)\n\nFormats files in place and leaves the working tree changed.\nThe action does not commit or open a PR; use a separate step for that,\nfor example [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action)\nor [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request).\n\n```yaml\nsteps:\n  - uses: actions/checkout@v6\n  - uses: dheid/adocfmt@v0.2.0\n    with:\n      mode: write\n      paths: docs     # limit to a subdirectory\n  # working tree now contains any formatting changes — commit or PR here\n```\n\n### Inputs\n\n|   Input   | Default |                               Description                                |\n|-----------|---------|--------------------------------------------------------------------------|\n| `mode`    | `check` | `check` or `write`                                                       |\n| `paths`   | `.`     | Space-separated files or directories; directories are walked recursively |\n| `version` | `0.2.0` | adocfmt version to download; override to pin to a specific release       |\n\n**Notes:**\n\n- Java 17 is set up via [actions/setup-java](https://github.com/actions/setup-java) (Temurin distribution) as part of the action.\n- Only `.adoc` and `.asciidoc` files are selected during directory traversal. Explicitly listed file paths are always processed regardless of extension.\n- The action downloads the adocfmt jar from the GitHub release on first use. Subsequent runs in the same job reuse the cached jar.\n\n## Development\n\n- **Layout:** `adocfmt` (core library) | `adocfmt-cli` (shaded JAR)\n- **Build:** `mvn verify`\n- **Versioning:** Semantic. Any change to formatting output is at least a minor update as it affects `--check` builds.\n\n## Project Info\n\n- **License:** [Apache License, Version 2.0](LICENSE)\n- **Author:** Daniel Heid\n- **Contributing:** [CONTRIBUTING.md](CONTRIBUTING.md)\n- **Changelog:** [CHANGELOG.md](CHANGELOG.md)\n- **Code of Conduct:** [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdheid%2Fadocfmt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdheid%2Fadocfmt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdheid%2Fadocfmt/lists"}