readwright 0.3.0__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. readwright-0.5.0/.agents/skills/readwright/SKILL.md +166 -0
  2. readwright-0.5.0/.agents/skills/readwright/helpers.md +130 -0
  3. readwright-0.5.0/AGENTS.md +85 -0
  4. readwright-0.5.0/CLAUDE.md +18 -0
  5. {readwright-0.3.0 → readwright-0.5.0}/PKG-INFO +32 -4
  6. {readwright-0.3.0 → readwright-0.5.0}/README.md +31 -3
  7. {readwright-0.3.0 → readwright-0.5.0}/README.md.j2 +27 -1
  8. {readwright-0.3.0 → readwright-0.5.0}/examples/README.md +7 -5
  9. readwright-0.5.0/examples/dotnet-tool/DotTool.csproj +10 -0
  10. readwright-0.5.0/examples/dotnet-tool/README.md +20 -0
  11. readwright-0.5.0/examples/dotnet-tool/readme.yaml +7 -0
  12. readwright-0.5.0/examples/go-cli/README.md +20 -0
  13. readwright-0.5.0/examples/go-cli/go.mod +3 -0
  14. readwright-0.5.0/examples/go-cli/readme.yaml +6 -0
  15. readwright-0.5.0/examples/node-cli/README.md +20 -0
  16. readwright-0.5.0/examples/node-cli/package.json +7 -0
  17. readwright-0.5.0/examples/node-cli/readme.yaml +2 -0
  18. readwright-0.5.0/examples/rust-cli/Cargo.toml +6 -0
  19. readwright-0.5.0/examples/rust-cli/README.md +20 -0
  20. readwright-0.5.0/examples/rust-cli/readme.yaml +7 -0
  21. {readwright-0.3.0 → readwright-0.5.0}/pyproject.toml +4 -1
  22. readwright-0.5.0/src/readwright/__init__.py +12 -0
  23. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/changelog.py +3 -1
  24. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/cli.py +155 -50
  25. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/config.py +2 -2
  26. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/helpers.py +22 -8
  27. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/images.py +1 -1
  28. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/metadata.py +10 -9
  29. {readwright-0.3.0 → readwright-0.5.0}/tests/conftest.py +8 -0
  30. {readwright-0.3.0 → readwright-0.5.0}/tests/test_cli.py +63 -0
  31. {readwright-0.3.0 → readwright-0.5.0}/tests/test_examples.py +21 -14
  32. {readwright-0.3.0 → readwright-0.5.0}/uv.lock +1 -1
  33. readwright-0.3.0/examples/flow-plugin/README.md +0 -26
  34. readwright-0.3.0/examples/flow-plugin/README.md.j2 +0 -7
  35. readwright-0.3.0/examples/flow-plugin/plugin.json +0 -1
  36. readwright-0.3.0/examples/flow-plugin/readme.yaml +0 -2
  37. readwright-0.3.0/examples/ha-card/README.md +0 -34
  38. readwright-0.3.0/examples/ha-card/README.md.j2 +0 -23
  39. readwright-0.3.0/examples/ha-card/docs/example.yaml +0 -2
  40. readwright-0.3.0/examples/ha-card/hacs.json +0 -1
  41. readwright-0.3.0/examples/ha-card/package.json +0 -1
  42. readwright-0.3.0/examples/ha-card/readme.yaml +0 -2
  43. readwright-0.3.0/examples/minecraft-mod/README.md +0 -32
  44. readwright-0.3.0/examples/minecraft-mod/README.md.j2 +0 -9
  45. readwright-0.3.0/examples/minecraft-mod/build.gradle +0 -1
  46. readwright-0.3.0/examples/minecraft-mod/gradle.properties +0 -6
  47. readwright-0.3.0/examples/minecraft-mod/readme.yaml +0 -10
  48. readwright-0.3.0/examples/minecraft-mod/src/main/resources/META-INF/neoforge.mods.toml +0 -8
  49. readwright-0.3.0/src/readwright/__init__.py +0 -8
  50. {readwright-0.3.0 → readwright-0.5.0}/.github/workflows/ci.yml +0 -0
  51. {readwright-0.3.0 → readwright-0.5.0}/.github/workflows/release.yml +0 -0
  52. {readwright-0.3.0 → readwright-0.5.0}/.gitignore +0 -0
  53. {readwright-0.3.0 → readwright-0.5.0}/.pre-commit-config.yaml +0 -0
  54. {readwright-0.3.0 → readwright-0.5.0}/.pre-commit-hooks.yaml +0 -0
  55. {readwright-0.3.0 → readwright-0.5.0}/.python-version +0 -0
  56. {readwright-0.3.0 → readwright-0.5.0}/LICENSE +0 -0
  57. {readwright-0.3.0 → readwright-0.5.0}/action.yml +0 -0
  58. {readwright-0.3.0 → readwright-0.5.0}/examples/config-only/README.md +0 -0
  59. {readwright-0.3.0 → readwright-0.5.0}/examples/config-only/docs/screenshots/CREDITS.md +0 -0
  60. {readwright-0.3.0 → readwright-0.5.0}/examples/config-only/docs/screenshots/captions.yaml +0 -0
  61. {readwright-0.3.0 → readwright-0.5.0}/examples/config-only/docs/screenshots/dashboard.jpg +0 -0
  62. {readwright-0.3.0 → readwright-0.5.0}/examples/config-only/docs/screenshots/editor-dark.jpg +0 -0
  63. {readwright-0.3.0 → readwright-0.5.0}/examples/config-only/docs/screenshots/editor-light.jpg +0 -0
  64. {readwright-0.3.0 → readwright-0.5.0}/examples/config-only/pyproject.toml +0 -0
  65. {readwright-0.3.0 → readwright-0.5.0}/examples/config-only/readme.yaml +0 -0
  66. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/.all-contributorsrc +0 -0
  67. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/.env.example +0 -0
  68. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/CHANGELOG.md +0 -0
  69. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/LICENSE +0 -0
  70. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/README.md +0 -0
  71. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/README.md.j2 +0 -0
  72. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/demo_tool/__init__.py +0 -0
  73. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/demo_tool/cli.py +0 -0
  74. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/docs/logo.svg +0 -0
  75. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/docs/screenshots/CREDITS.md +0 -0
  76. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/docs/screenshots/captions.yaml +0 -0
  77. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/docs/screenshots/main.jpg +0 -0
  78. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/docs/screenshots/mobile/captions.yaml +0 -0
  79. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/docs/screenshots/mobile/phone.jpg +0 -0
  80. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/docs/screenshots/settings-dark.jpg +0 -0
  81. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/docs/screenshots/settings-light.jpg +0 -0
  82. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/docs/usage.md +0 -0
  83. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/pyproject.toml +0 -0
  84. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/readme.yaml +0 -0
  85. {readwright-0.3.0 → readwright-0.5.0}/examples/kitchen-sink/templates/partials/contributing.md.j2 +0 -0
  86. {readwright-0.3.0 → readwright-0.5.0}/readme.yaml +0 -0
  87. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/badges.py +0 -0
  88. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/py.typed +0 -0
  89. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/renderer.py +0 -0
  90. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/templates/base.md.j2 +0 -0
  91. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/templates/partials/badges.md.j2 +0 -0
  92. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/templates/partials/contributing.md.j2 +0 -0
  93. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/templates/partials/donate.md.j2 +0 -0
  94. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/templates/partials/header.md.j2 +0 -0
  95. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/templates/partials/install.md.j2 +0 -0
  96. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/templates/partials/license.md.j2 +0 -0
  97. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/templates/partials/screenshots.md.j2 +0 -0
  98. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/templates/partials/usage.md.j2 +0 -0
  99. {readwright-0.3.0 → readwright-0.5.0}/src/readwright/toc.py +0 -0
  100. {readwright-0.3.0 → readwright-0.5.0}/tests/golden/base.md +0 -0
  101. {readwright-0.3.0 → readwright-0.5.0}/tests/test_badges.py +0 -0
  102. {readwright-0.3.0 → readwright-0.5.0}/tests/test_changelog.py +0 -0
  103. {readwright-0.3.0 → readwright-0.5.0}/tests/test_config.py +0 -0
  104. {readwright-0.3.0 → readwright-0.5.0}/tests/test_helpers.py +0 -0
  105. {readwright-0.3.0 → readwright-0.5.0}/tests/test_images.py +0 -0
  106. {readwright-0.3.0 → readwright-0.5.0}/tests/test_metadata.py +0 -0
  107. {readwright-0.3.0 → readwright-0.5.0}/tests/test_renderer.py +0 -0
  108. {readwright-0.3.0 → readwright-0.5.0}/tests/test_toc.py +0 -0
  109. {readwright-0.3.0 → readwright-0.5.0}/tox.ini +0 -0
@@ -0,0 +1,166 @@
1
+ ---
2
+ name: readwright
3
+ description: Use when creating or editing a project's README.md that is managed by readwright — writing/extending README.md.j2, configuring readme.yaml or [tool.readme], adding badges/screenshots/TOC/changelog sections, or a "readwright check" / pre-commit readwright-check failure shows README.md is stale or was hand-edited.
4
+ ---
5
+
6
+ # readwright
7
+
8
+ ## Overview
9
+
10
+ readwright renders `README.md` from a Jinja2 template (`README.md.j2`) plus a config
11
+ file (`readme.yaml` or `[tool.readme]` in `pyproject.toml`). `README.md` carries a
12
+ `<!-- generated by readwright -->` marker and is **never hand-edited** — edit the
13
+ template/config, then re-render.
14
+
15
+ ## Workflow
16
+
17
+ 1. New project: `readwright init` (autodetects owner/repo/name/license from git
18
+ remote + manifest files). Existing README to preserve: `readwright init
19
+ --from-readme`. Prefer config in `pyproject.toml`: `readwright init --pyproject`.
20
+ 2. Edit `README.md.j2` — it extends the packaged `base.md.j2` and overrides only the
21
+ `{% block %}` sections it needs — and/or `readme.yaml`.
22
+ 3. `readwright render` to write `README.md` (`--watch` to re-render on save, `-o -`
23
+ to preview on stdout instead of writing).
24
+ 4. `readwright check` before committing — exits 1 with a diff if `README.md` is
25
+ stale versus what the template+config would produce. This is what CI / the
26
+ `readwright-check` pre-commit hook run; if it fails, run `render` again, don't
27
+ hand-patch `README.md`.
28
+
29
+ ## Commands
30
+
31
+ | Command | Purpose |
32
+ | --- | --- |
33
+ | `readwright init [--from-readme] [--pyproject]` | Scaffold `readme.yaml` + `README.md.j2` |
34
+ | `readwright render [--watch] [-o -] [--user-config]` | Write `README.md` |
35
+ | `readwright check` | Fail with a diff if `README.md` is stale (CI/pre-commit) |
36
+ | `readwright badges` | List available badge presets |
37
+ | `readwright blocks` | List overridable template blocks/partials |
38
+ | `readwright skill [--install] [--dest DIR] [--force]` | Print the bundled copy of this skill, or install it into a project's `.agents/skills/` (or `--dest`) |
39
+ | `readwright show <template>` | Print a packaged template (`base.md.j2` for the block order, or e.g. `partials/install.md.j2`) to copy and customize |
40
+ | `readwright completion <shell>` | Print a bash/zsh/fish/PowerShell completion script |
41
+
42
+ All accept `-C/--root` (repo root) and `-c/--config` (explicit config path) as
43
+ options *after* the subcommand, e.g. `readwright render -C /path/to/repo` —
44
+ `readwright -C /path render` fails with "No such option: -C".
45
+
46
+ ## Template helpers
47
+
48
+ Full reference with examples: [helpers.md](helpers.md). Quick index:
49
+
50
+ | Helper | Purpose |
51
+ | --- | --- |
52
+ | `badge()`, `shield()`, `badges()`, `donate_badges()` | Badges from presets, custom shields.io badges, or config-driven rows |
53
+ | `screenshot()`, `screenshots()`, `image()`, `logo()`, `video()`, `unsplash()` | Images: single shot, gallery, explicit image, theme-aware logo, video/gif, Unsplash hero |
54
+ | `toc()` | Table of contents from headings below the call |
55
+ | `changelog()` | Latest N entries from `CHANGELOG.md` |
56
+ | `cli_help()` | Runs a command and fences its `--help` output (needs `allow_exec: true`) |
57
+ | `include_file()`, `code_block()`, `snippet()` | Pull in a file, a fenced file, or a marked region |
58
+ | `config_table()`, `env_table()`, `entry_points_table()` | Tables from YAML/TOML/JSON, `.env` files, `[project.scripts]` |
59
+ | `gh_link()`, `spdx_link()`, `my_ha_link()` | Repo-relative GitHub links, SPDX license link, My Home Assistant buttons |
60
+ | `callout()`, `details()`, `center()`, `columns()` | GitHub alerts, collapsibles, centered blocks, side-by-side layout |
61
+ | `contributors()` | Avatar grid |
62
+ | `flow_install_cmd()`, `mc_versions()`, `mod_dependencies()`, `related_repos()` | Flow Launcher / Minecraft mod / related-repo tables |
63
+ | `git_sha()`, `git_tag()`, `today()` | Build metadata — these change between renders, so `check` will flag a README rendered with them as stale until re-rendered at release/CI time |
64
+ | `project.*`, `vars.*` | Autodetected repo metadata and free-form config values |
65
+
66
+ Image helpers emit plain markdown by default; pass `width=`, `html=True`, or set
67
+ `screenshots.style: html` to get `<img>`/`<picture>`/`<table>` output instead.
68
+
69
+ ## Overriding blocks and partials
70
+
71
+ `base.md.j2` blocks: `header`, `badges`, `donate`, `toc`, `screenshots`, `install`,
72
+ `usage`, `extra`, `contributing`, `license`. Override any block in `README.md.j2`:
73
+
74
+ ```jinja
75
+ {% extends "base.md.j2" %}
76
+ {% block usage %}
77
+ ## Usage
78
+ {{ screenshot("main", width=600) }}
79
+ Run `{{ project.name }} --help`.
80
+ {% endblock %}
81
+ ```
82
+
83
+ Add to the top badge row without touching the config list via the `badges_extra` /
84
+ `donate_extra` hooks. Any packaged partial can be shadowed by a same-named file
85
+ under `templates/partials/` in the repo (or `~/.config/readwright/templates/` for
86
+ all repos) — `readwright show <partial>` prints the original to copy.
87
+
88
+ To insert a whole new section where there's no dedicated hook (e.g. a Changelog
89
+ section between Contributing and License — there's no `contributing_extra` block),
90
+ override the nearest existing block and call `{{ super() }}` to keep its content,
91
+ then append (or prepend) yours:
92
+
93
+ ```jinja
94
+ {% block contributing %}
95
+ {{ super() }}
96
+
97
+ ## Changelog
98
+
99
+ {{ changelog(2) }}
100
+ {% endblock %}
101
+ ```
102
+
103
+ ## Configuration (`readme.yaml`)
104
+
105
+ ```yaml
106
+ template: README.md.j2
107
+ templates: [../shared-readme-templates, "pkg:my_org_templates"] # extra search paths
108
+ output: README.md
109
+ strict: false # missing screenshot -> error, not warning
110
+ allow_exec: false # let cli_help() run commands during render
111
+ badges_style: flat-square # shields.io style for every badge
112
+ related: [{repo: other-tool, description: Sibling project}]
113
+ banner: {unsplash: photo-1518770660439-4636190af475, credit: Name, user: handle}
114
+ screenshots: {dir: docs/screenshots, width: 720, style: markdown}
115
+ badges: [pypi, python, license, {preset: ci, workflow: test.yml}, {shield: {label: Docs, message: latest, color: success}}]
116
+ badges_custom:
117
+ discord: {label: Discord, message: chat, color: 5865F2, link: https://discord.gg/xyz}
118
+ donate: [kofi, github-sponsors]
119
+ donate_handles: {kofi: yourname, github-sponsors: yourname}
120
+ project: {name: ..., owner: ..., repo: ..., tagline: ..., pypi: ..., npm: ..., license: ..., ci_workflow: ...}
121
+ vars: {anything: you like}
122
+ ```
123
+
124
+ Metadata not set explicitly is autodetected from the git remote, `LICENSE`, and
125
+ whichever manifest exists (`pyproject.toml`, `package.json`, `Cargo.toml`, `go.mod`,
126
+ `*.csproj`, Gradle `gradle.properties`, `hacs.json`, Flow Launcher `plugin.json`) —
127
+ the install section adapts to the detected project type. Shared values (donation
128
+ handles, owner, custom badges) go in `~/.config/readwright/config.yaml`; `init`
129
+ bakes them into the new `readme.yaml`, or merge them ad hoc with `render
130
+ --user-config`.
131
+
132
+ ## Screenshots
133
+
134
+ Drop images in `docs/screenshots/` (or the configured `screenshots.dir`).
135
+ `screenshot("main")` finds `main.{png,jpg,gif,webp,svg}`; a `main-dark.*` +
136
+ `main-light.*` pair becomes a theme-aware image using GitHub's
137
+ `#gh-light-mode-only` / `#gh-dark-mode-only` fragments. `screenshots(columns=2)`
138
+ builds a gallery of everything in the directory; control order/captions with
139
+ `order=[...]`, `captions={...}`, or a `captions.yaml` file in the folder.
140
+
141
+ ## pre-commit and CI
142
+
143
+ ```yaml
144
+ # .pre-commit-config.yaml
145
+ - repo: https://github.com/Garulf/readwright
146
+ rev: v0.4.0 # pin to the latest release tag
147
+ hooks:
148
+ - id: readwright-check
149
+ ```
150
+
151
+ ```yaml
152
+ # .github/workflows/ci.yml
153
+ - uses: Garulf/readwright@v0.4.0
154
+ with:
155
+ mode: check # or render
156
+ ```
157
+
158
+ ## Common mistakes
159
+
160
+ | Mistake | Fix |
161
+ | --- | --- |
162
+ | Editing `README.md` directly | Edit `README.md.j2`/`readme.yaml`, then `readwright render` |
163
+ | `readwright check` fails in CI only | A helper like `git_sha()`/`git_tag()`/`today()` makes output change between renders — avoid them in checked README content, or re-render right before the check |
164
+ | `cli_help()` renders empty/errors | Set `allow_exec: true` in config — it's off by default |
165
+ | Screenshot not picked up | Check the file lives in `screenshots.dir` (default `docs/screenshots/`) and matches the base name passed to `screenshot()` |
166
+ | Custom badge/partial ignored | Custom badges go under `badges_custom` in config, not a template edit; custom partials go in `templates/partials/<same-name>` to shadow the packaged one |
@@ -0,0 +1,130 @@
1
+ # readwright template helpers — full reference
2
+
3
+ All helpers are called from `README.md.j2` (or any partial it includes). Signatures
4
+ below match the Python implementation; Jinja calls omit `self`.
5
+
6
+ ## Badges
7
+
8
+ - `badge(preset, **options)` — a preset badge (`readwright badges` lists names:
9
+ `pypi`, `pypi-downloads`, `python`, `license`, `ci`, `codecov`, `npm`,
10
+ `github-release`, `github-stars`, `pre-commit`, `ruff`, `version`, `modrinth`,
11
+ `curseforge`, `hacs`, `ha-version`; donation presets: `kofi`, `buymeacoffee`,
12
+ `github-sponsors`, `patreon`, `paypal`). Presets pull from `project.*` in config —
13
+ e.g. `badge("ci", workflow="test.yml")` needs `project.owner`/`project.repo`.
14
+ - `shield(label, message, color, link=None, style=None)` — a custom static
15
+ shields.io badge: `shield("Discord", "chat", "5865F2", link=gh_link("wiki"))`.
16
+ - `badges()` — renders every entry in config's `badges:` list (preset names, or
17
+ `{preset: ..., **opts}` / `{shield: {...}}` dicts) plus anything under
18
+ `badges_custom:`, in one row.
19
+ - `donate_badges()` — same, for config's `donate:` list.
20
+ - `badges_extra` / `donate_extra` block hooks — add a badge to the row without
21
+ editing the config list:
22
+ `{% block badges_extra %} {{ shield("docs", "latest", "success") }}{% endblock %}`
23
+ - Pass `style=` to any badge helper, or set `badges_style:` in config, to apply a
24
+ shields.io style (`flat-square`, etc.) to everything.
25
+
26
+ ## Images
27
+
28
+ - `screenshot(name, alt=None, width=None)` — finds `docs/screenshots/{name}.{png,jpg,gif,webp,svg}`
29
+ (dir configurable via `screenshots.dir`). If `{name}-dark.*` and `{name}-light.*`
30
+ both exist, renders a theme-aware pair using GitHub's `#gh-light-mode-only` /
31
+ `#gh-dark-mode-only` markdown fragments (or an HTML `<picture>` if
32
+ `screenshots.style: html` / `html=True` via a wider call, or `width=` is set,
33
+ since markdown can't express width).
34
+ - `screenshots(columns=2, order=None, captions=None, subdir=None)` — a gallery
35
+ table of every image in the screenshots dir. `order=["main", "settings"]` fixes
36
+ ordering; `captions={"main": "Main window"}` or a `captions.yaml` file in the
37
+ folder supplies captions.
38
+ - `has_screenshots()` — boolean, for conditionally rendering a screenshots section.
39
+ - `image(path, alt="", width=None)` — an explicit image (local path or URL), no
40
+ discovery.
41
+ - `logo(width=None, alt=None, name="logo")` — theme-aware logo from
42
+ `docs/logo.{png,svg,...}` (or `logo-dark`/`logo-light` pair).
43
+ - `video(name, width=None, alt=None)` — embeds a video/gif from the screenshots dir.
44
+ - `unsplash(photo, alt=None, width=1200, height=None, credit=None, user=None, photo_id=None, link=None, quality=80, html=False)` —
45
+ hero image from Unsplash's CDN. `photo` is a photo id like
46
+ `"photo-1518770660439-4636190af475"` or a full `images.unsplash.com` URL.
47
+ **Always pass `credit=` and `user=`** — Unsplash's license requires attribution;
48
+ omitting them renders the image with a `warn()` and no attribution line. `banner:`
49
+ in config renders one automatically above the title via the same helper.
50
+
51
+ Image helpers emit plain markdown by default (no `<picture>`/`<img>`), and only
52
+ fall back to HTML when markdown can't express what was asked (a `width=`, an
53
+ explicit `html=True`).
54
+
55
+ ## Structure
56
+
57
+ - `toc(min_level=2, max_level=3)` — table of contents built from the markdown
58
+ headings that appear *below* this call in the rendered output.
59
+ - `changelog(n=1)` — the newest `n` entries from `CHANGELOG.md` /
60
+ `CHANGES.md` / `HISTORY.md` (Keep-a-Changelog `##` headings), with heading levels
61
+ shifted to nest under the calling context.
62
+
63
+ ## Pulling in files and command output
64
+
65
+ - `include_file(path)` — raw contents of a file, relative to repo root.
66
+ - `code_block(path, language=None)` — `include_file` wrapped in a fenced code
67
+ block; language defaults to the file extension.
68
+ - `snippet(path, start, end, language=None, dedent=True)` — the lines between the
69
+ first line containing `start` and the first line at/after it containing `end`,
70
+ fenced. Useful for pulling a marked region out of a source file instead of the
71
+ whole thing.
72
+ - `cli_help(command, language="text", strip_ansi=True)` — runs `command` (shell-split,
73
+ no shell interpolation) via subprocess and fences stdout/stderr.
74
+ **Requires `allow_exec: true` in config** — raises `PermissionError` otherwise,
75
+ since it executes code during render.
76
+
77
+ ## Tables
78
+
79
+ - `config_table(path, section=None, headers=("Key", "Value"))` — flattens a
80
+ YAML/TOML/JSON file (optionally a dotted `section=`) into a two-column markdown
81
+ table.
82
+ - `env_table(path=".env.example")` — parses `KEY=value` lines (using preceding `#`
83
+ comment lines as descriptions) into a Variable/Default/Description table.
84
+ - `entry_points_table()` — table of `[project.scripts]` from `pyproject.toml`.
85
+
86
+ ## Links
87
+
88
+ - `gh_link(path="", text=None)` — `{project.owner}/{project.repo}`-relative GitHub
89
+ URL, e.g. `gh_link("issues", "Issues")`. Needs `project.owner`/`project.repo` set
90
+ or autodetected from the git remote.
91
+ - `spdx_link(license_id=None)` — link to the SPDX page for the project's license
92
+ (or an explicit id).
93
+ - `my_ha_link(redirect, text=None, **params)` — a "My Home Assistant" redirect
94
+ button/link, e.g. `my_ha_link("hacs_repository", owner=..., repository=...)`.
95
+
96
+ ## Layout
97
+
98
+ - `callout(kind, text)` — a GitHub alert (`kind` is `note`/`tip`/`important`/
99
+ `warning`/`caution`).
100
+ - `details(summary, body, open=False)` — a `<details>` collapsible.
101
+ - `center(content)` — centers a block of markdown/HTML.
102
+ - `columns(cells, align="center")` — lays out a list of markdown cells
103
+ side-by-side (as an HTML table row).
104
+ - `contributors(logins=None, size=64)` — avatar grid; `logins` defaults to
105
+ contributors autodetected from the repo.
106
+
107
+ ## Ecosystem-specific
108
+
109
+ - `flow_install_cmd()` — Flow Launcher plugin install command.
110
+ - `mc_versions()`, `mod_dependencies()` — Minecraft mod metadata tables (from
111
+ Gradle `gradle.properties`).
112
+ - `related_repos()` — table from config's `related:` list
113
+ (`[{repo: other-tool, description: ...}]`).
114
+ - `pyversions_list(sep=", ")` — joined list of supported Python versions.
115
+
116
+ ## Build metadata
117
+
118
+ - `git_sha(short=True)`, `git_tag()`, `today()` — current commit/tag/date. These
119
+ change on every render, so a checked-in `README.md` that used them will always
120
+ show as stale to `readwright check` unless re-rendered immediately before the
121
+ check (e.g. in a release job). Avoid them in a README that's committed and
122
+ linted by CI; fine for a render step that runs at publish time.
123
+
124
+ ## Context available in every template
125
+
126
+ - `project.*` — `name`, `owner`, `repo`, `tagline`, `pypi`, `npm`, `license`,
127
+ `ci_workflow`, plus anything autodetected from the git remote / `LICENSE` /
128
+ manifest file. `gh_link()` and badge presets read from here.
129
+ - `vars.*` — free-form values from config's `vars:` map, for anything
130
+ project-specific that doesn't fit elsewhere.
@@ -0,0 +1,85 @@
1
+ # AGENTS.md
2
+
3
+ readwright is a Python CLI that renders GitHub `README.md` files from Jinja2 templates
4
+ (`README.md.j2` + `readme.yaml`), with badge, screenshot, TOC, and changelog helpers.
5
+ Package lives under `src/readwright/`; console entry point is `readwright.cli:app`
6
+ (Typer). Python >=3.11, dependency/build managed with `uv` + `hatchling`.
7
+
8
+ ## Setup
9
+
10
+ ```sh
11
+ uv sync --group dev
12
+ ```
13
+
14
+ ## Running things
15
+
16
+ Always run tools through `uv run` (or `uv run tox -e <env>`) so the project's own venv
17
+ and locked dependencies are used, not whatever's on PATH.
18
+
19
+ ```sh
20
+ uv run pytest # run the test suite
21
+ uv run pytest tests/test_cli.py # single file
22
+ uv run ruff check src tests # lint
23
+ uv run ruff format src tests # format
24
+ uv run tox # full matrix: py311, py312, py313, lint
25
+ uv run tox -e lint # lint env only (ruff check + ruff format --check)
26
+ uv run readwright render # regenerate README.md from README.md.j2 + readme.yaml
27
+ uv run readwright check # fail with a diff if README.md is stale vs. the template
28
+ ```
29
+
30
+ `tests/golden/` holds golden-file fixtures for renderer output — if you touch
31
+ `renderer.py`, `helpers.py`, or any template partial, check whether golden files need
32
+ regenerating rather than hand-editing expected output.
33
+
34
+ ## Before committing
35
+
36
+ - `pre-commit` is configured (`.pre-commit-config.yaml`): gitleaks, standard hygiene
37
+ hooks, and `ruff`/`ruff-format` run on every commit; `pytest` and
38
+ `readwright check` run on `pre-push`. Run `uv run pre-commit run --all-files` if you
39
+ want to check before pushing without waiting for the hook.
40
+ - **`README.md` is generated — never edit it directly.** Edit `README.md.j2` (the
41
+ Jinja2 template) and/or `readme.yaml` (the config), then run
42
+ `uv run readwright render` to regenerate `README.md`. The file itself carries a
43
+ `<!-- generated by readwright -->` marker; editing it by hand will be silently
44
+ overwritten and will fail the `readwright check` pre-push hook / CI.
45
+ - Keep `ruff` clean: `select = ["E", "F", "I", "UP", "B", "SIM"]`, line length 100
46
+ (see `pyproject.toml`).
47
+ - This project versions with hand-bumped `pyproject.toml` (no release-please). Bump
48
+ `version` yourself for a release-worthy change — patch for fixes, minor for new
49
+ features/helpers — and follow Conventional Commits (`feat:`, `fix:`, `chore:`, ...).
50
+
51
+ ## Layout
52
+
53
+ - `src/readwright/cli.py` — Typer commands: `init`, `render`, `check`, `badges`,
54
+ `blocks`, `show`, `skill`, `completion`.
55
+ - `src/readwright/renderer.py` — Jinja2 environment setup and rendering pipeline.
56
+ - `src/readwright/helpers.py`, `badges.py`, `images.py`, `toc.py`, `changelog.py`,
57
+ `metadata.py` — the template helper functions exposed to `README.md.j2`
58
+ (`badge()`, `screenshot()`, `toc()`, `changelog()`, `project.*`, etc.) and repo
59
+ metadata autodetection (git remote, `LICENSE`, manifest files like
60
+ `pyproject.toml`/`package.json`/`Cargo.toml`/`go.mod`/`*.csproj`).
61
+ - `src/readwright/config.py` — `readme.yaml` / `[tool.readme]` config model
62
+ (pydantic).
63
+ - `src/readwright/templates/` — packaged `base.md.j2` and partials that a project's
64
+ own `README.md.j2` extends/overrides.
65
+ - `examples/` — worked example projects (`kitchen-sink`, `rust-cli`, `go-cli`,
66
+ `dotnet-tool`, `node-cli`, `config-only`) exercising every helper; useful as
67
+ reference when adding or changing a helper's behavior.
68
+ - `action.yml` — GitHub Action wrapper for `readwright check`/`render` in CI.
69
+ - `.agents/skills/readwright/` — the agent skill (`SKILL.md` + `helpers.md`) that
70
+ documents the render/check workflow, config keys and template helpers for coding
71
+ agents. `.claude/skills/readwright` is a symlink to it, and hatch `force-include`s
72
+ it into the wheel as `readwright/.agents/skills/readwright/`; `readwright skill
73
+ --install` copies it out again (in the dev checkout the command falls back to the
74
+ repo-root directory). When a helper, config
75
+ key, CLI flag or block is added or changed, update the skill in the same change.
76
+
77
+ ## Testing conventions
78
+
79
+ - `tests/` mirrors `src/readwright/` module-for-module (`test_badges.py`,
80
+ `test_renderer.py`, etc.) plus `test_examples.py`, which renders the projects
81
+ under `examples/` and is a good smoke check when changing template helpers or the
82
+ renderer.
83
+ - New template helpers should get both a unit test and, where relevant, coverage
84
+ in `examples/kitchen-sink` since the README documents the full helper set from
85
+ that project's usage.
@@ -0,0 +1,18 @@
1
+ # CLAUDE.md
2
+
3
+ See `AGENTS.md` for project layout, setup, and commands — it applies here too.
4
+
5
+ ## Claude-specific notes
6
+
7
+ - `README.md` is a generated file (from `README.md.j2` + `readme.yaml`). If a task
8
+ touches the README, edit the template/config and run `uv run readwright render`;
9
+ never hand-edit `README.md` itself.
10
+ - After changing anything under `src/readwright/templates/`, `helpers.py`,
11
+ `badges.py`, `images.py`, `toc.py`, or `changelog.py`, run
12
+ `uv run pytest tests/test_examples.py` — it renders every project under
13
+ `examples/` and is the fastest way to catch a broken helper across real usage.
14
+ - Prefer `uv run tox -e lint` over invoking `ruff` directly when you want the same
15
+ check CI runs (`ruff check` + `ruff format --check`, no auto-fix).
16
+ - This repo is dogfooding itself: `readwright`'s own `README.md.j2`/`readme.yaml`
17
+ are a real usage example of the tool, not just project docs — check them for
18
+ helper usage patterns before asking "how do I use X helper".
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: readwright
3
- Version: 0.3.0
3
+ Version: 0.5.0
4
4
  Summary: Render GitHub READMEs from Jinja2 templates with badge and screenshot helpers
5
5
  Project-URL: Homepage, https://github.com/Garulf/readwright
6
6
  Project-URL: Issues, https://github.com/Garulf/readwright/issues
@@ -36,6 +36,8 @@ Render GitHub READMEs from Jinja2 templates with badge and screenshot helpers.
36
36
  - [Template helpers](#template-helpers)
37
37
  - [Configuration](#configuration)
38
38
  - [pre-commit and GitHub Actions](#pre-commit-and-github-actions)
39
+ - [Shell completion](#shell-completion)
40
+ - [Agent skill](#agent-skill)
39
41
  - [Contributing](#contributing)
40
42
  - [License](#license)
41
43
 
@@ -82,7 +84,7 @@ Run `{{ project.name }} --help`.
82
84
  ```
83
85
 
84
86
  See [`examples/`](https://github.com/Garulf/readwright/tree/main/examples) for a kitchen-sink project using every helper,
85
- plus Minecraft mod, HACS card and Flow Launcher plugin examples.
87
+ plus Rust, Go, .NET and Node examples showing how the install section adapts per language.
86
88
 
87
89
  ## Template helpers
88
90
 
@@ -167,18 +169,44 @@ stays reproducible in CI. `readwright render --user-config` merges them ad hoc.
167
169
  ```yaml
168
170
  # .pre-commit-config.yaml
169
171
  - repo: https://github.com/Garulf/readwright
170
- rev: v0.3.0
172
+ rev: v0.5.0
171
173
  hooks:
172
174
  - id: readwright-check
173
175
  ```
174
176
 
175
177
  ```yaml
176
178
  # .github/workflows/ci.yml
177
- - uses: Garulf/readwright@v0.3.0
179
+ - uses: Garulf/readwright@v0.5.0
178
180
  with:
179
181
  mode: check # or render
180
182
  ```
181
183
 
184
+ ## Shell completion
185
+
186
+ `readwright completion <shell>` prints a completion script for bash, zsh, fish or PowerShell.
187
+ It completes subcommands, options and the template names `readwright show` accepts.
188
+
189
+ ```sh
190
+ eval "$(readwright completion bash)" # add to ~/.bashrc
191
+ eval "$(readwright completion zsh)" # add to ~/.zshrc, after compinit
192
+ readwright completion fish > ~/.config/fish/completions/readwright.fish
193
+ ```
194
+
195
+ ## Agent skill
196
+
197
+ The repo ships an [agent skill](https://agentskills.io) at `.agents/skills/readwright/`
198
+ that teaches coding agents (Claude Code, Codex, Copilot CLI, Gemini CLI, ...) the
199
+ render/check workflow, the config keys and every template helper, so they edit
200
+ `README.md.j2` instead of the generated `README.md`. Claude Code picks it up from
201
+ this repo automatically via `.claude/skills/readwright`; the same directory is
202
+ bundled inside the wheel, so any project can install it:
203
+
204
+ ```sh
205
+ readwright skill --install # copies it to ./.agents/skills/readwright
206
+ readwright skill --install --dest ~/.claude/skills # or a user-level skills directory
207
+ readwright skill # just print where the bundled copy lives
208
+ ```
209
+
182
210
  ## Contributing
183
211
 
184
212
  Issues and pull requests are welcome at [Garulf/readwright](https://github.com/Garulf/readwright).
@@ -10,6 +10,8 @@ Render GitHub READMEs from Jinja2 templates with badge and screenshot helpers.
10
10
  - [Template helpers](#template-helpers)
11
11
  - [Configuration](#configuration)
12
12
  - [pre-commit and GitHub Actions](#pre-commit-and-github-actions)
13
+ - [Shell completion](#shell-completion)
14
+ - [Agent skill](#agent-skill)
13
15
  - [Contributing](#contributing)
14
16
  - [License](#license)
15
17
 
@@ -56,7 +58,7 @@ Run `{{ project.name }} --help`.
56
58
  ```
57
59
 
58
60
  See [`examples/`](https://github.com/Garulf/readwright/tree/main/examples) for a kitchen-sink project using every helper,
59
- plus Minecraft mod, HACS card and Flow Launcher plugin examples.
61
+ plus Rust, Go, .NET and Node examples showing how the install section adapts per language.
60
62
 
61
63
  ## Template helpers
62
64
 
@@ -141,18 +143,44 @@ stays reproducible in CI. `readwright render --user-config` merges them ad hoc.
141
143
  ```yaml
142
144
  # .pre-commit-config.yaml
143
145
  - repo: https://github.com/Garulf/readwright
144
- rev: v0.3.0
146
+ rev: v0.5.0
145
147
  hooks:
146
148
  - id: readwright-check
147
149
  ```
148
150
 
149
151
  ```yaml
150
152
  # .github/workflows/ci.yml
151
- - uses: Garulf/readwright@v0.3.0
153
+ - uses: Garulf/readwright@v0.5.0
152
154
  with:
153
155
  mode: check # or render
154
156
  ```
155
157
 
158
+ ## Shell completion
159
+
160
+ `readwright completion <shell>` prints a completion script for bash, zsh, fish or PowerShell.
161
+ It completes subcommands, options and the template names `readwright show` accepts.
162
+
163
+ ```sh
164
+ eval "$(readwright completion bash)" # add to ~/.bashrc
165
+ eval "$(readwright completion zsh)" # add to ~/.zshrc, after compinit
166
+ readwright completion fish > ~/.config/fish/completions/readwright.fish
167
+ ```
168
+
169
+ ## Agent skill
170
+
171
+ The repo ships an [agent skill](https://agentskills.io) at `.agents/skills/readwright/`
172
+ that teaches coding agents (Claude Code, Codex, Copilot CLI, Gemini CLI, ...) the
173
+ render/check workflow, the config keys and every template helper, so they edit
174
+ `README.md.j2` instead of the generated `README.md`. Claude Code picks it up from
175
+ this repo automatically via `.claude/skills/readwright`; the same directory is
176
+ bundled inside the wheel, so any project can install it:
177
+
178
+ ```sh
179
+ readwright skill --install # copies it to ./.agents/skills/readwright
180
+ readwright skill --install --dest ~/.claude/skills # or a user-level skills directory
181
+ readwright skill # just print where the bundled copy lives
182
+ ```
183
+
156
184
  ## Contributing
157
185
 
158
186
  Issues and pull requests are welcome at [Garulf/readwright](https://github.com/Garulf/readwright).
@@ -37,7 +37,7 @@ Run `{{ project.name }} --help`.
37
37
  ```
38
38
 
39
39
  See [`examples/`]({{ gh_link("tree/main/examples") }}) for a kitchen-sink project using every helper,
40
- plus Minecraft mod, HACS card and Flow Launcher plugin examples.
40
+ plus Rust, Go, .NET and Node examples showing how the install section adapts per language.
41
41
 
42
42
  ## Template helpers
43
43
 
@@ -134,4 +134,30 @@ stays reproducible in CI. `readwright render --user-config` merges them ad hoc.
134
134
  mode: check # or render
135
135
  ```
136
136
 
137
+ ## Shell completion
138
+
139
+ `readwright completion <shell>` prints a completion script for bash, zsh, fish or PowerShell.
140
+ It completes subcommands, options and the template names `readwright show` accepts.
141
+
142
+ ```sh
143
+ eval "$(readwright completion bash)" # add to ~/.bashrc
144
+ eval "$(readwright completion zsh)" # add to ~/.zshrc, after compinit
145
+ readwright completion fish > ~/.config/fish/completions/readwright.fish
146
+ ```
147
+
148
+ ## Agent skill
149
+
150
+ The repo ships an [agent skill](https://agentskills.io) at `.agents/skills/readwright/`
151
+ that teaches coding agents (Claude Code, Codex, Copilot CLI, Gemini CLI, ...) the
152
+ render/check workflow, the config keys and every template helper, so they edit
153
+ `README.md.j2` instead of the generated `README.md`. Claude Code picks it up from
154
+ this repo automatically via `.claude/skills/readwright`; the same directory is
155
+ bundled inside the wheel, so any project can install it:
156
+
157
+ ```sh
158
+ readwright skill --install # copies it to ./.agents/skills/readwright
159
+ readwright skill --install --dest ~/.claude/skills # or a user-level skills directory
160
+ readwright skill # just print where the bundled copy lives
161
+ ```
162
+
137
163
  {% endblock %}
@@ -1,15 +1,17 @@
1
1
  # readwright examples
2
2
 
3
- Each directory is a self-contained fake project with a `readme.yaml`, a `README.md.j2` and the
4
- `README.md` that `readwright render` produces from them. Run `readwright render` inside one to regenerate.
3
+ Each directory is a self-contained fake project with a `readme.yaml` (some also have a `README.md.j2`)
4
+ and the `README.md` that `readwright render` produces from them. Run `readwright render` inside one to
5
+ regenerate.
5
6
 
6
7
  | Example | Shows |
7
8
  | --- | --- |
8
9
  | [kitchen-sink](kitchen-sink/) | Every general helper: logo/center header, badge presets + custom + donation badges with a global style, toc, screenshots with captions and dark/light variants, subdir gallery, `include_file`, `cli_help`, `snippet`, `details`, `callout`, `config_table`, `env_table`, `entry_points_table`, `columns`, `video`, `changelog`, `gh_link`, `related_repos`, `contributors`, `git_sha`/`git_tag`/`today`, `spdx_link`, an `unsplash()` hero image, a repo-local partial override |
9
10
  | [config-only](config-only/) | No template at all: a fully annotated `readme.yaml` using every config key (including an Unsplash `banner:`), rendered by the packaged `base.md.j2`. Read it as the config reference |
10
- | [minecraft-mod](minecraft-mod/) | Gradle/NeoForge detection, Unsplash `banner:`, `modrinth`/`curseforge` badges, `mc_versions()`, `mod_dependencies()` |
11
- | [ha-card](ha-card/) | `hacs.json` detection, `unsplash()` from an image URL, `hacs`/`ha-version` badges, `my_ha_link()`, `code_block()` |
12
- | [flow-plugin](flow-plugin/) | Flow Launcher `plugin.json` detection and the `pm install` snippet |
11
+ | [rust-cli](rust-cli/) | `Cargo.toml` detection and the `cargo install` snippet; a custom `{shield: ...}` badge for crates.io, since there's no built-in preset |
12
+ | [go-cli](go-cli/) | `go.mod` detection and the `go install ...@latest` snippet |
13
+ | [dotnet-tool](dotnet-tool/) | `*.csproj` detection (`PackAsTool`) and the `dotnet tool install --global` snippet |
14
+ | [node-cli](node-cli/) | `package.json` detection, the `npm install` snippet and the `npm` badge preset |
13
15
 
14
16
  The kitchen sink uses `git_sha()` and `today()`, so its committed `README.md` will always be a little
15
17
  behind; that is deliberate, to show why those helpers are a poor fit for `readwright check`.
@@ -0,0 +1,10 @@
1
+ <Project Sdk="Microsoft.NET.Sdk">
2
+ <PropertyGroup>
3
+ <TargetFramework>net8.0</TargetFramework>
4
+ <PackAsTool>true</PackAsTool>
5
+ <PackageId>DotTool.Cli</PackageId>
6
+ <Version>2.1.0</Version>
7
+ <Description>A .NET global tool for scaffolding project templates</Description>
8
+ <PackageLicenseExpression>MIT</PackageLicenseExpression>
9
+ </PropertyGroup>
10
+ </Project>
@@ -0,0 +1,20 @@
1
+ <!-- generated by readwright from base.md.j2; edit the template, not this file -->
2
+ # DotTool.Cli
3
+
4
+ A .NET global tool for scaffolding project templates
5
+
6
+ [![License](https://img.shields.io/github/license/octocat/dottool)](https://github.com/octocat/dottool/blob/main/LICENSE) [![CI](https://img.shields.io/github/actions/workflow/status/octocat/dottool/ci.yml)](https://github.com/octocat/dottool/actions/workflows/ci.yml) [![Release](https://img.shields.io/github/v/release/octocat/dottool)](https://github.com/octocat/dottool/releases/latest) [![version](https://img.shields.io/badge/version-2.1.0-informational)](https://github.com/octocat/dottool) [![nuget](https://img.shields.io/badge/nuget-v2.1.0-004880?logo=nuget)](https://www.nuget.org/packages/DotTool.Cli)
7
+
8
+ ## Installation
9
+
10
+ ```sh
11
+ dotnet tool install --global DotTool.Cli
12
+ ```
13
+
14
+ ## Contributing
15
+
16
+ Issues and pull requests are welcome at [octocat/dottool](https://github.com/octocat/dottool).
17
+
18
+ ## License
19
+
20
+ MIT
@@ -0,0 +1,7 @@
1
+ badges:
2
+ - license
3
+ - {preset: ci, workflow: ci.yml}
4
+ - github-release
5
+ - version
6
+ - {shield: {label: nuget, message: v2.1.0, color: 004880, logo: nuget, link: https://www.nuget.org/packages/DotTool.Cli}}
7
+ project: {owner: octocat, repo: dottool}