winged-rust 1.0.1

Fast, type-safe HTML DSL and static site generation engine in Rust and WebAssembly
Documentation
# Contributing

Thanks for wanting to help. This document is short on purpose — the repository enforces
most of what matters, so you can find out you are wrong in seconds rather than in review.

## The one command

```bash
./scripts/verify.sh
```

Build, test, clippy, rustfmt, tag-catalog freshness, the golden fixtures, and an end-to-end
smoke test that builds a throwaway crate against your checkout. It is a **superset** of CI,
so if it passes locally, CI passes.

It accumulates failures rather than stopping at the first, so one run tells you everything
that is wrong.

## Setup

```bash
rustup toolchain install stable
rustup target add wasm32-unknown-unknown
cargo install wasm-pack cargo-llvm-cov   # only for the wasm and coverage jobs
```

MSRV is 1.85 (edition 2024). CI tests both stable and the MSRV; a change that needs a newer
compiler needs a deliberate MSRV bump and a CHANGELOG entry.

## Workflow

1. Fork, then branch from `develop` — not `main`.
2. Name the branch `feature/…`, `fix/…` or `docs/…`.
3. Make the change. Add tests.
4. `./scripts/verify.sh`
5. Update `CHANGELOG.md` under `## [Unreleased]`.
6. Pull request against `develop`.

## Commit messages

Prefix with the kind of change, matching Winged-Swift's CHANGELOG vocabulary:

```
Add: comment nodes to the html! macro
Fix: attribute injection through add_class
Change: data_attrs takes an ordered iterator
Docs: explain why escaping is not idempotent
Test: cover the empty-fragment blank-line case
Perf: reserve the output buffer once per render
```

Reference issues in the body (`Refs #12`, `Fixes #12`), not the subject.

## Code

- **Every `pub` item needs a rustdoc comment with a working example.** `missing_docs` is
  denied, and examples are compiled as doctests, so they cannot rot.
- Comments explain *why*. The code already says what.
- `cargo fmt` is the arbiter of layout; `clippy -D warnings` of everything else.
- Prefer a test over a comment asserting something is true.

## Tests

**Assert on rendered strings, not tree shape.**

```rust
// Good — locks in the contract.
assert_eq!(div().add_class("a").render(), r#"<div class="a"></div>"#);

// Bad — locks in the implementation.
assert_eq!(div().add_class("a").attributes()[0].key(), "class");
```

This is not style pedantry: it is why Winged-Swift's test suite survived a complete
internal rewrite in 2.0 without changing.

Reference the Swift test you ported in a doc comment on the test, so the two stay
traceable:

```rust
/// Ports `CSSHelpersTests.testAddClassDoesNotDoubleEscape`.
#[test]
fn chaining_add_class_does_not_double_escape() { … }
```

## Changing markup

`cargo test --test golden` compares four files against Winged-Swift's own fixtures, byte
for byte. If your change alters output, that test fails.

That is the system working. Either the change is wrong, or the fixtures genuinely need
updating:

```bash
WINGED_UPDATE_FIXTURES=1 cargo test --test golden
```

If you regenerate them, **say so in the pull request and explain why**. A fixture diff is
the only place a markup change is visible to a reviewer.

## Adding an element

See the five-step contract in [`AGENTS.md`](AGENTS.md#adding-an-element). Skipping any step
fails `verify.sh`.

## What gets a pull request merged

- `./scripts/verify.sh` passes
- New behaviour has a test that would fail without it
- New public API has rustdoc with an example
- `CHANGELOG.md` updated
- Markup changes are either absent or explained

## Code of conduct

[`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) applies to every interaction in this repository.