tomato·bazeldocs v0 · latest
Docs/Reference/Modules/rules_readme

rules_readme

README-shaped sugar over rules_markdown: templated READMEs materialized into the tree with a drift gate

Latest0.0.3
Versions3
CategoryBazel rules
MaintainersMatt Marshall
Registryhttps://registry.tbzl.dev/modules/rules_readme/
Sourcegithub.com/tomato-bazel/rules_readme
MODULE.bazelstarlark
bazel_dep(name = "rules_readme", version = "0.0.3")

View source & releases on GitHub ↗

README-shaped sugar over rules_markdown. Compose a templated README from per-section markdown_fragment targets and materialize it into the source tree, with a drift gate — the dominant docs use case in one rule.

Install

bazel_dep(name = "rules_readme", version = "0.0.1")

Usage

load("@rules_readme//readme:defs.bzl", "readme", "markdown_fragment")

markdown_fragment(name = "overview", src = "overview.md", title = "Overview", weight = 0)
markdown_fragment(name = "repos",    src = "repos.md",    title = "Repositories", weight = 10)

readme(
    name = "readme",
    template = "README.md.tmpl",        # has <!-- TOC --> and <!-- FRAGMENTS -->
    fragments = [":overview", ":repos"],
    # write_to defaults to "README.md" -> creates readme.write + readme.write_test
)
bazel run  //:readme.write        # regenerate README.md in the tree
bazel test //:readme.write_test   # CI drift gate

readme() is the dominant-case macro; reach for markdown_document (re-exported here, and in rules_markdown) when you want a non-README doc or to opt out of materialization (write_to = None). Deep links, TOC, and the fragment model are all rules_markdown — see its README.

Status

0.0.1. See the CHANGELOG.

Usage#

Real usage, taken from the module’s examples/.

examples/profile/BUILD.bazel

load("//readme:defs.bzl", "markdown_fragment", "readme")

markdown_fragment(
    name = "overview",
    src = "overview.md",
    title = "Overview",
    weight = 0,
)

markdown_fragment(
    name = "repos",
    src = "repos.md",
    title = "Repositories",
    weight = 10,
)

# readme() defaults write_to = "README.md", so this auto-creates:
#   bazel run  //examples/profile:readme_doc.write        (materialize README.md)
#   bazel test //examples/profile:readme_doc.write_test   (drift gate)
#
# Named readme_doc, NOT readme: markdown_document renders to `<name>.md`, so a
# target named `readme` produces `readme.md` alongside the materialized
# `README.md`. Those are two files on Linux and one on macOS, where the build
# then fails with an opaque "Could not copy inputs into sandbox ... (File
# exists)". readme() now rejects that collision at load time.
readme(
    name = "readme_doc",
    fragments = [
        ":overview",
        ":repos",
    ],
    template = "README.md.tmpl",
)

Rules & providers#

Generated with Stardoc from the module's .bzl sources.

from docs/defs.md

Public API for rules_readme — README-shaped sugar over rules_markdown.

load("@rules_readme//readme:defs.bzl", "readme", "markdown_fragment")

markdown_fragment

load("@rules_readme//readme:defs.bzl", "markdown_fragment")

markdown_fragment(name, deps, src, anchor, classifiers, content, level, slot, title, weight)

Declare one composable markdown fragment (a section of a document).

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsChild fragments folded in transitively.List of labelsoptional[]
srcThe fragment body (.md). Mutually exclusive with content.LabeloptionalNone
anchorExplicit deep-link handle (defaults to the target name). Reference it elsewhere as mdref:<handle>.Stringoptional""
classifiersFree-form classifiers (e.g. category/section); exposed in fragment metadata.List of stringsoptional[]
contentInline fragment body. Mutually exclusive with src.Stringoptional""
levelHeading level for title (default 2 -> ##).Integeroptional2
slotTarget a named template placeholder <!-- FRAGMENTS:<slot> --> (for generated content placed at a specific spot). Default: the unnamed <!-- FRAGMENTS -->.Stringoptional""
titleSection heading text. If set, md_gen injects a level heading; it’s also the deep-link target.Stringoptional""
weightSort key within the document (ascending).Integeroptional0

markdown_document

load("@rules_readme//readme:defs.bzl", "markdown_document")

markdown_document(name, out, template, fragments, roots, toc, link_check, write_to, **kwargs)

Aggregate fragments into one rendered markdown document.

PARAMETERS

NameDescriptionDefault Value
nametarget name.none
outoutput filename (defaults to <name>.md).None
templateoptional prose template with <!-- FRAGMENTS --> + <!-- TOC -->.None
fragmentsfragment targets to compose.[]
rootsarbitrary targets whose graph contributes fragments (via the aspect).[]
tocemit a table of contents.True
link_checkfail on a dangling mdref: deep link.True
write_toif set (a source-relative path), also create <name>.write (bazel run materializes the doc into the tree) + <name>.write_test (drift gate), via write_source_files.None
kwargsforwarded (visibility, tags, …).none

readme

load("@rules_readme//readme:defs.bzl", "readme")

readme(name, template, fragments, roots, toc, link_check, write_to, **kwargs)

Render a templated README from fragments and materialize it into the tree.

A thin façade over markdown_document with README defaults. Because materialize-to-source is the dominant case, write_to defaults to "README.md" — so readme(...) creates <name>.write (bazel run materializes the README) + <name>.write_test (the drift gate) out of the box, via write_source_files. Pass write_to = None to opt out (you then just get the rendered file in bazel-bin + MarkdownDocInfo).

PARAMETERS

NameDescriptionDefault Value
nametarget name.none
templateprose template with <!-- FRAGMENTS --> (required) and an optional <!-- TOC --> marker.none
fragmentsfragment targets to compose (ordered by their weight).[]
rootsarbitrary targets whose graph contributes fragments.[]
tocemit a table of contents.True
link_checkfail the build on a dangling mdref: deep link.True
write_tosource-relative path to materialize into (default "README.md"); None to skip materialization."README.md"
kwargsforwarded (visibility, tags, …).none

Conformance#

No gate findings. 15 contested atoms. See how gating works or the full report.

Contested atoms

Third-party modules where this module resolves a different version than others do. Not a violation of anything this module did — it is the actionable form of a registry-level convergence finding, and the sentence a maintainer can act on.

AtomResolved hereElsewhere
apple_support 1.24.2 2.2.0 ×1
aspect_bazel_lib 2.22.5 2.8.1 ×1
bazel_lib 3.0.0 3.2.2 ×17
bazel_skylib 1.8.2 1.9.0 ×2
gawk 5.3.2.bcr.1 5.3.2.bcr.3 ×17
jq.bzl 0.1.0 0.4.0 ×17
nlohmann_json 3.6.1 3.12.0.bcr.1 ×1
package_metadata 0.0.2 0.0.5 ×3
protobuf 33.4 34.0.bcr.1 ×2
rules_jvm_external 6.7 6.8 ×4
rules_python 1.7.0 2.0.1 ×1
rules_swift 3.1.2 3.6.1 ×1
tar.bzl 0.5.1 0.10.4 ×170.6.0 ×1
upb 0.0.0-20220923-a547704 0.0.0-20230516-61a97ef ×1
yq.bzl 0.1.1 0.3.4 ×17

Dependencies#

rules_readme in the registry graph — what it depends on (left) and what depends on it (right).

Depends on

platforms1.0.0bazel_skylib1.8.2aspect_bazel_lib2.22.5rules_markdown0.0.3rules_shell0.6.1devstardoc0.7.2dev

Used by (2 in the registry)

Versions#

3 published versions, newest first. Each resolves to an immutable, integrity-checked archive.

VersionIntegrity (sha256)Source archive
0.0.3 latest qThp++srGfGfSk3h… tag archive ↗
0.0.2 /tmmehPERgGQ8J2M… tag archive ↗
0.0.1 nGXvvYmWNwAulOGN… tag archive ↗

Changelog#

All notable changes to rules_readme.

0.0.3

Additive — no migration needed.

Added

  • Bumps rules_markdown to 0.0.3 — named template slots (markdown_fragment(slot = "x")<!-- FRAGMENTS:x -->) now flow through readme() / markdown_fragment.

0.0.2

Additive — no migration needed.

Added

  • Stardoc reference docs (//docs, bazel run //docs:update) + a bzl_library.
  • Bumps rules_markdown to 0.0.2.

0.0.1

Initial release.

Added

  • readme — a thin façade over rules_markdown’s markdown_document with README defaults: write_to defaults to "README.md", so readme(...) creates <name>.write (materialize) + <name>.write_test (drift gate) out of the box via write_source_files. Pass write_to = None to opt out.
  • Re-exports markdown_fragment + markdown_document so a consumer can load the whole README surface from one place.

← All modules