Skip to content

feat(page): normalize the authoring API — positional Header title, no more parens gotcha - #27

Merged
mhenrixon merged 1 commit into
mainfrom
issue-10-normalize-authoring-api
Jul 3, 2026
Merged

feat(page): normalize the authoring API — positional Header title, no more parens gotcha#27
mhenrixon merged 1 commit into
mainfrom
issue-10-normalize-authoring-api

Conversation

@mhenrixon

Copy link
Copy Markdown
Collaborator

Closes #10. Part of #8 (Phase 1).

Problem

The kit's constructor conventions were inconsistent and the inconsistency was user-facing:

  • Section.new(title, …) / Code.new(source, …) took their main argument positionally, but Header.new(title:, …) required a kwarg — DocsUI::Header("My guide") raised ArgumentError.
  • Prose / Example take no positional args, so DocsUI::Prose do … end is a Ruby SyntaxError (it parses as a constant reference). The gem papered over this with a whole "the one syntax rule that bites everyone" docs section.

What changed

One convention: the primary argument is positional; modifiers are keyword arguments.

Before After
DocsUI::Header(title: "T", eyebrow: "E") DocsUI::Header("T", eyebrow: "E")
DocsUI::Prose() do … end prose do … end (page helper)
DocsUI::Example() do |ex| … end example do |ex| … end (page helper)
  • Header takes a positional titleinitialize(title = nil, eyebrow: nil, **opts). The legacy title: kwarg still works (silent compat, no deprecation warning); the positional wins if both are given. Existing consumer sites that call Header(title:) keep rendering verbatim.
  • New lowercase page helpers prose / example (alongside the existing md). A lowercase method takes a block without parens, so the parens-with-blocks trap structurally cannot occur. The kit forms DocsUI::Prose() / DocsUI::Example() stay valid forever — nothing is removed.
  • The helpers live in a new DocsUI::PageHelpers module mixed into DocsUI::Page. Extracting them into a module (rather than defining them inline on Page) makes them unit-testable against a bare Phlex host — DocsUI::Page includes Phlex::Rails::Helpers::Routes and cannot load in the standalone suite.
  • The gem's own docs pages adopt the helpers; the dedicated "parens gotcha" section shrinks to a footnote. README gains an authoring convention section.

Why a module instead of inline methods

DocsUI::Page references Rails.application.routes at class-load time (via the Routes helper), so it cannot be loaded in the gem's Rails-free spec suite. A global Rails stub was ruled out — two code paths (icon.rb and the install generator) branch on defined?(Rails) and specs depend on Rails being absent under the random-ordered suite. Extracting the helpers into a module tests the real helper bodies without loading Page and without global-state pollution. (It also fixed a latent weakness in markdown_spec that was re-implementing md rather than exercising it.)

Test coverage

  • spec/docs_ui/header_spec.rb — positional title, eyebrow, lead block; legacy title: kwarg renders identically to the positional form (backwards-compat proof); positional wins when both are given.
  • spec/docs_ui/page_helpers_spec.rbprose / example / md render the Prose wrapper / Example tabs / Markdown, exercising the real PageHelpers module through a bare Phlex host.
  • spec/docs_ui/markdown_spec.rb — the md delegation test now includes the real module.

header.rb and page_helpers.rb are at 100% line coverage.

Verification

  • bundle exec rake — rspec 103 examples, 0 failures; rubocop 42 files, no offenses
  • Grep gate: no live DocsUI::Prose() / DocsUI::Example() in the gem's docs pages (only code { "…" } API references remain, which document that the kit form stays valid)
  • Backwards compatible: Header(title:) covered by spec; no consumer-site call site changes required
  • No new emitted CSS classes (Prose/Example classes already scanned) — no Tailwind @source change needed

Out of scope (per the issue)

  • Renaming any component or removing the kit-form calls (DocsUI::Prose() stays valid).
  • Callout / OnThisPage signature changes.

…ose/example helpers

## Summary

One consistent convention across the kit: the primary argument is positional,
modifiers are keyword arguments — and the everyday authoring path no longer hits
the Ruby parens-with-blocks SyntaxError.

- `DocsUI::Header` takes the title positionally (`Header("Installation")`),
  matching Section/Code. The legacy `title:` kwarg still works (silent compat,
  no deprecation); the positional wins if both are given.
- New lowercase, block-friendly page helpers `prose { … }` and `example { |ex| … }`
  (alongside the existing `md`), extracted into `DocsUI::PageHelpers` and mixed
  into `DocsUI::Page`. A lowercase method takes a block without parens, so the
  gotcha structurally cannot occur. The kit forms `DocsUI::Prose()` /
  `DocsUI::Example()` stay valid forever.
- The gem's own docs pages adopt the helpers; the dedicated "parens gotcha"
  section shrinks to a footnote. README documents the convention.

`PageHelpers` is a module (not methods inline on Page) so the helpers are
unit-testable against a bare Phlex host — `DocsUI::Page` includes
Phlex::Rails::Helpers::Routes and cannot load in the standalone suite.

## Test Coverage

- spec/docs_ui/header_spec.rb: positional title, eyebrow, lead block; legacy
  `title:` kwarg renders identically (backwards-compat proof); positional wins
  when both given.
- spec/docs_ui/page_helpers_spec.rb: `prose`/`example`/`md` render the expected
  Prose wrapper / Example tabs / Markdown against a bare Phlex host exercising the
  REAL PageHelpers module.
- spec/docs_ui/markdown_spec.rb: the `md` delegation test now includes the real
  PageHelpers module instead of re-implementing `md`.

## Verification

- [x] bundle exec rake (rspec 103 examples, 0 failures; rubocop 42 files clean)
- [x] header.rb + page_helpers.rb: 100% line coverage
- [x] grep gate: no live DocsUI::Prose()/Example() in gem docs (only code{} API references remain)
- [x] backwards compatible: `Header(title:)` covered by spec; existing consumer sites unchanged

Refs #10
@mhenrixon mhenrixon self-assigned this Jul 3, 2026
@mhenrixon
mhenrixon merged commit e57fef1 into main Jul 3, 2026
3 checks passed
@mhenrixon mhenrixon added the enhancement New feature or request label Jul 3, 2026
@mhenrixon
mhenrixon deleted the issue-10-normalize-authoring-api branch July 4, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(page): normalize the authoring API — positional Header title, no more parens gotcha

1 participant