Metadata-Version: 2.4
Name: xmlegant-format
Version: 0.0.1
Summary: Plugin-based XML formatter with a strong house style.
Project-URL: Homepage, https://github.com/DarthEivor/xmlegant
Project-URL: Source, https://github.com/DarthEivor/xmlegant
Project-URL: Issues, https://github.com/DarthEivor/xmlegant/issues
Project-URL: Changelog, https://github.com/DarthEivor/xmlegant/blob/master/CHANGELOG.md
Author: Marcus Ahlstrand
License-Expression: MIT
License-File: LICENSE
Keywords: formatter,linter,lxml,pretty-print,xml
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Markup :: XML
Requires-Python: >=3.10
Requires-Dist: lxml>=5.0.0
Description-Content-Type: text/markdown

# xmlegant

Plugin-based XML formatter with a strong house style.
Think `black` but for XML, but with a small plugin surface for domain-specific element layout.

## Install

`xmlegant` runs on Linux, macOS, and Windows with Python 3.10 or newer.

The PyPI distribution is published as `xmlegant-format` (the short name was
already taken on PyPI), but the installed CLI command and the import name
are both `xmlegant`. Pick whichever installer you already use:

```sh
pipx install xmlegant-format       # isolated, recommended for end users
uv tool install xmlegant-format    # if you use uv
pip install xmlegant-format        # plain pip into the active environment
```

After install, the `xmlegant` command is available on `PATH`:

```sh
xmlegant --help
```

## Commands

```
xmlegant format [-c CONFIG_DIR] [-o OUTPUT_FILE] FILE [FILE ...]
xmlegant check  [-c CONFIG_DIR] FILE [FILE ...]
```

- `format` rewrites each input file in place. With `-o`, writes to one output
  (errors out with two or more inputs).
- `check` prints a unified diff to stdout for files that would change. Exits 0
  when all files are already formatted, 1 when any file would change, 2 on
  error.

If the config directory (default `./.xmlegant`) doesn't exist, the tool runs
in canonicalization mode: parse and re-emit with the default layout.

## Development

This project uses [uv](https://docs.astral.sh/uv/).

```sh
uv sync
uv run xmlegant --help
uv run pytest
uv run ruff format .
uv run ruff check .
```

See [`AGENTS.md`](AGENTS.md) for agent-facing operational notes and design decisions.

## Releasing

Releases are cut from `master` and published to PyPI by GitHub Actions.
Versions are immutable on PyPI — once a number is published it cannot be
reused, so double-check before tagging.

1. Make sure CI is green on the `master` commit you want to release.
2. Bump `version` in [`pyproject.toml`](pyproject.toml).
3. In [`CHANGELOG.md`](CHANGELOG.md), rename the `## [Unreleased]` heading
   to `## [X.Y.Z] - YYYY-MM-DD` and add a fresh empty `## [Unreleased]`
   section above it.
4. Commit (`Release X.Y.Z`) and push to `master`.
5. Once that commit's CI is green, tag it and push the tag:

   ```sh
   git tag vX.Y.Z
   git push origin vX.Y.Z
   ```

6. The `publish` workflow builds the sdist and wheel and uploads them to
   PyPI via Trusted Publishing.
7. Draft the GitHub Release manually, pasting the relevant
   [`CHANGELOG.md`](CHANGELOG.md) section as the release notes.

### Release candidates

To rehearse a release without burning a real version number, tag with an
`-rcN` suffix (e.g. `v1.2.0-rc1`). The `testpypi` workflow uploads those
builds to [TestPyPI](https://test.pypi.org/) instead of PyPI.
