philiprehberger-html_builder 0.7.0 → 0.9.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a1ed5d63b82c40002240f74e0f808a5e62926efd8b55a0c52b482d804a23bab
4
- data.tar.gz: 814fd3cf20cf2cf358f25e38d14dcf9f02e84e32827a584c0c94a947d4404f48
3
+ metadata.gz: 56b6f4a4c8e09045d724f5f67b3f8cec1e87fc2daddd397e04604cf13bcd33d8
4
+ data.tar.gz: 1b820c958ea1cafe11fa4aa415fb76b17aebef39aa611b6f100dedcdf01f2411
5
5
  SHA512:
6
- metadata.gz: 0e0214af812ff0754349ee79c494f544f34b6b5a16852387d3c51c30b1580c7e88f75d0392f4761dacf754c91722cc83015f95131f065c60eaa073df64453217
7
- data.tar.gz: eb761b219b3a40319752ba84628ed2a7a88f0ea423581619a641a98932a3c39f8deabb83edb077be8c0319436d60f7ccac2f53f5acaa6e63cb5d469e4d04b271
6
+ metadata.gz: '0398ad1acd04f45d1e28dc890a8436e01d42b9ed4e9bab2f0ee6d8e278d505016f74bee609c8743a0f8e3d69c111b3e03c83e9e2779bcb7437a51f7167183e1a'
7
+ data.tar.gz: 693dbcc9294f41267f54e66ef5c9a082f24c1a222d4db7d3c648623a392cf8ca6e6a80ac7fea0c944eb080c87ef598fba5b1292829ac4cc6825495bbbe54f1c3
data/CHANGELOG.md CHANGED
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.9.0] - 2026-05-30
11
+
12
+ ### Added
13
+ - `HtmlBuilder.data(**attrs)` helper to build `data-*` attribute hashes, mirroring the existing `aria` helper
14
+
15
+ ### Fixed
16
+ - Bug report issue template now includes a required `gem-version` field and marks `ruby-version` as required, matching the standard template
17
+
18
+ ## [0.8.0] - 2026-05-20
19
+
20
+ ### Added
21
+ - `Builder#capture { ... }` — render a block in an isolated scope and return the HTML as a string without appending to the current document. Inherits previously defined components, so component reuse works inside captured fragments. Pairs naturally with `Builder#raw` for inserting the captured HTML into the document.
22
+ - Card image reference in the README for registry-side rendering
23
+
10
24
  ## [0.7.0] - 2026-04-26
11
25
 
12
26
  ### Added
data/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
  [![Gem Version](https://badge.fury.io/rb/philiprehberger-html_builder.svg)](https://rubygems.org/gems/philiprehberger-html_builder)
5
5
  [![Last updated](https://img.shields.io/github/last-commit/philiprehberger/rb-html-builder)](https://github.com/philiprehberger/rb-html-builder/commits/main)
6
6
 
7
+ ![philiprehberger-html_builder](https://raw.githubusercontent.com/philiprehberger/rb-html-builder/main/package-card.webp)
8
+
7
9
  Programmatic HTML builder with tag DSL, auto-escaping, form helpers, components, and output formatting
8
10
 
9
11
  ## Requirements
@@ -181,9 +183,14 @@ Philiprehberger::HtmlBuilder.build do
181
183
  aria(label: 'Save', expanded: false, describedby: nil)
182
184
  end
183
185
  # => { 'aria-label' => 'Save', 'aria-expanded' => 'false' }
186
+
187
+ Philiprehberger::HtmlBuilder.build do
188
+ data(controller: 'menu', modal_target: 'dialog', open: true)
189
+ end
190
+ # => { 'data-controller' => 'menu', 'data-modal-target' => 'dialog', 'data-open' => 'true' }
184
191
  ```
185
192
 
186
- `merge_attrs` joins `:class` values with a single space and `:style` values with `'; '`. Other keys follow last-write-wins, and input hashes are not mutated. `aria` converts snake_case keys to `aria-kebab-case` string keys, stringifies values, and omits keys whose value is `nil`.
193
+ `merge_attrs` joins `:class` values with a single space and `:style` values with `'; '`. Other keys follow last-write-wins, and input hashes are not mutated. `aria` converts snake_case keys to `aria-kebab-case` string keys, stringifies values, and omits keys whose value is `nil`. `data` mirrors `aria` for the `data-*` attribute namespace.
187
194
 
188
195
  ### CSS Class Helpers
189
196
 
@@ -198,6 +205,25 @@ end
198
205
  # => <div class="btn btn-lg active">Click me</div>
199
206
  ```
200
207
 
208
+ ### Capturing Fragments
209
+
210
+ Render a block in a separate scope and capture the HTML as a string instead of appending it to the document. Useful when the same fragment is needed in more than one place or as a value:
211
+
212
+ ```ruby
213
+ Philiprehberger::HtmlBuilder.build do
214
+ badge = capture { strong 'NEW', class: 'badge' }
215
+ article do
216
+ h2 'Headline'
217
+ raw badge
218
+ p 'Body text'
219
+ raw badge
220
+ end
221
+ end
222
+ # => <article><h2>Headline</h2><strong class="badge">NEW</strong><p>Body text</p><strong class="badge">NEW</strong></article>
223
+ ```
224
+
225
+ `capture` inherits any components defined on the parent builder, so component reuse works inside captured fragments.
226
+
201
227
  ### Fragment Caching
202
228
 
203
229
  Cache rendered block results by key. On subsequent calls with the same key, the cached HTML is returned without re-executing the block:
@@ -348,7 +374,9 @@ Philiprehberger::HtmlBuilder.merge(header, body, footer)
348
374
  | `Builder#class_names(*args)` | Build a conditional CSS class string from strings and hashes |
349
375
  | `Builder#merge_attrs(*hashes)` | Merge attribute hashes, concatenating `:class` (space) and `:style` (`'; '`) values |
350
376
  | `Builder#aria(**pairs)` | Build an ARIA attribute hash from snake_case keys (rendered as `aria-kebab-case`); omits nil values |
377
+ | `Builder#data(**attrs)` | Build a `data-*` attribute hash from snake_case keys (rendered as `data-kebab-case`); omits nil values |
351
378
  | `Builder#cache(key) { ... }` | Cache rendered block output by key; return cached HTML on repeat calls |
379
+ | `Builder#capture { ... }` | Render the block in an isolated scope and return its HTML string (no append) |
352
380
  | `Escape.html(value)` | Escape HTML special characters in a string |
353
381
 
354
382
  ## Development
@@ -308,6 +308,47 @@ module Philiprehberger
308
308
  result
309
309
  end
310
310
 
311
+ # Build a `data-*` attribute hash from keyword pairs
312
+ #
313
+ # snake_case keys are converted to `data-kebab-case` string keys. Values are
314
+ # converted to strings. Keys whose value is `nil` are omitted from the result.
315
+ # String keys are passed through with a `data-` prefix and underscores
316
+ # converted to dashes (e.g. `"modal-target"` becomes `"data-modal-target"`).
317
+ #
318
+ # @param attrs [Hash] keyword pairs to convert into `data-*` attributes
319
+ # @return [Hash<String, String>] hash with `"data-*"` string keys and string values
320
+ def data(**attrs)
321
+ result = {}
322
+ attrs.each do |key, value|
323
+ next if value.nil?
324
+
325
+ result["data-#{key.to_s.tr('_', '-')}"] = value.to_s
326
+ end
327
+ result
328
+ end
329
+
330
+ # Render a block in an isolated builder scope and return the HTML string
331
+ # without appending anything to the current document.
332
+ #
333
+ # Useful for template helpers that need to compute a fragment once and
334
+ # then insert it in multiple places (e.g. via {#raw}) or pass it as a
335
+ # string attribute (e.g. ``title:`` containing a small piece of escaped
336
+ # markup) — none of which can be expressed with the regular tag DSL
337
+ # because every tag method side-effects into the current scope.
338
+ #
339
+ # @yield block evaluated against a fresh builder; the same DSL methods
340
+ # (tags, `text`, `raw`, components, etc.) are available
341
+ # @return [String] the captured HTML (minified)
342
+ # @raise [Error] if no block is given
343
+ def capture(&block)
344
+ raise Error, 'a block is required for capture' unless block
345
+
346
+ nested = Builder.new
347
+ @components.each { |name, b| nested.instance_variable_get(:@components)[name] = b }
348
+ nested.instance_eval(&block)
349
+ nested.to_html
350
+ end
351
+
311
352
  # Cache a rendered block result by key
312
353
  #
313
354
  # On the first call with a given key, the block is executed, its rendered
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Philiprehberger
4
4
  module HtmlBuilder
5
- VERSION = '0.7.0'
5
+ VERSION = '0.9.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: philiprehberger-html_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philip Rehberger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-27 00:00:00.000000000 Z
11
+ date: 2026-05-31 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Build HTML programmatically using a clean tag DSL with nested blocks,
14
14
  automatic content escaping, void element support, and attribute hashes.