asciidoctor-rhrev 1.0.0 → 1.2.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: 7a1ad3cb27fbce5f7a4295c90d2f069407d993230f89e14d6d05e4f34f3d6302
4
- data.tar.gz: 9129908c97d9da8ad0b16028e92e722103db4a865504e357c1c28748eadadbc0
3
+ metadata.gz: ba4b787b526a584c23e8d5c890cfc0459711552efb13b11e483b2847706f018e
4
+ data.tar.gz: 5e740bd4af7144bcc3ad461ddadfc402883354395f372c1336439e87d498547f
5
5
  SHA512:
6
- metadata.gz: 95a202f0e4560c9ce5eb51de3bd53325c44ae41d820c40db2b791ed6438f797f121cc143559ee3ab564b88006156e4724ad6730d9680a95cee464f24885280d6
7
- data.tar.gz: d47b9bf8163523403bf7a41a2c52765eaafcf33b41e33a7737a2801234382b80e13ec9c646ea35dc6ce05bddd3b5afe4cd900a96e50d0d7f8bb13500bd178823
6
+ metadata.gz: 9ad667cf9c86e5462ca177eae98fddad13335354c26083fb15cfe5639630b7044e0e623b7e5b1f5f069fe4689403e6c382246db47c7127aafe89d2f1fa204853
7
+ data.tar.gz: fca906ea2b5256d3d141828ee39ef3298fb9420dbea437f424e6cac633035e8dec6463ca2bdd30c76d86c73e08125bb7620c94fdff4015970cc9b65fa837f764
data/CHANGELOG.adoc ADDED
@@ -0,0 +1,11 @@
1
+ = Changelog
2
+
3
+ == 1.2.0 (2026-07-07)
4
+
5
+ * Fix document-level `-all`/`-cover` entries being ignored for revisions with more than two segments (e.g. `1-2-0`): revisions are now discovered from `*-prevrev` attributes instead of enumerating `major-minor` pairs (PDF and HTML backends)
6
+ * Add PDF change bars: with `:rhrev-change-bars:` set, a vertical bar is inked in the page margin next to every tracked block (section, floating title, example, listing, table, image) marked with the current revision (`revnumber` 1.2 → `rhrev1-2`). Styled via the `rhrev_change_bars` PDF theme category — `color` (default `FF0000`), `width` (default `2`), `offset` (default `16`), and `side` (`outer`/`inner`/`left`/`right`; defaults to `outer` for prepress media, `right` otherwise) — overridable per document with the matching `rhrev-change-bars-*` attributes
7
+
8
+ == 1.0.1 (2026-05-15)
9
+
10
+ * Fix `convert_section` method signature to accept optional `opts` keyword arguments for compatibility with converters that pass them
11
+ * Fix `delete_attr` → `delete_attribute` to use the correct Asciidoctor Document API
data/README.adoc CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  rhrev is a comprehensive revision history tracking system for the AsciiDoc and Antora ecosystems which automatically creates a grouped, formatted table of document changes.
4
4
 
5
- It supports several converters/backends:
5
+ https://baiyibai-antora.gitlab.io
6
+
7
+ == Supported Backends
6
8
 
7
9
  * asciidoctor-pdf
8
10
  +
@@ -19,18 +21,11 @@ image::resources/nodejs-html5-output.png[width=50%]
19
21
  +
20
22
  * Antora-Assembler to asciidoctor-pdf
21
23
 
22
- == Features
24
+ include::doc/modules/ROOT/pages/introduction.adoc[tag=why]
25
+
26
+ include::doc/modules/ROOT/pages/introduction.adoc[tag=features]
23
27
 
24
- * *Automatic revision tracking* with version-based grouping
25
- * *Dynamic version labels* using `:version-label:` attribute
26
- * *Localization support* for multiple languages
27
- * *Export to AsciiDoc* for inclusion in other documents
28
- * *Flexible placement* (auto or manual via macro)
29
- * *Extensive customization* options for styling and formatting
30
- * [PDF] *Clickable page references* that link to actual document locations
31
- * [PDF] *Flexible xrefstyle support* (full, short, basic) for all block types
32
- * [PDF] *Custom captions* for Examples, Tables, Listings, and Figures
33
- * *FAST*
28
+ include::doc/modules/ROOT/pages/introduction.adoc[tag=quick-start]
34
29
 
35
30
  == Inspiration
36
31
 
@@ -42,62 +37,11 @@ This extension draws inspiration from:
42
37
 
43
38
  The goal was to bring similar automated revision tracking capabilities to the Asciidoctor ecosystem, with the added benefit of clickable page references and flexible customization options tailored for PDF technical documentation.
44
39
 
45
- == Quick Start
46
-
47
- === Installation
48
-
49
- The asciidoctor-pdf-rhrev extension is available as a Ruby Gem.
50
-
51
- https://rubygems.org/gems/asciidoctor-pdf-rhrev[^]
52
-
53
- Complete these steps to use:
54
-
55
- . Install the required Gems:
56
- +
57
- [source,bash]
58
- ----
59
- gem install asciidoctor
60
- gem install asciidoctor-pdf
61
- gem install asciidoctor-pdf-rhrev
62
- ----
63
- +
64
- . Render your document:
65
- +
66
- [source,bash]
67
- ----
68
- asciidoctor-pdf -r asciidoctor-pdf-rhrev document.adoc
69
- ----
70
-
71
- === Basic Usage
72
-
73
- [source,asciidoc]
74
- ----
75
- = My Document
76
- :doctype: book
77
- :revnumber: 1.1
78
- :rhrev:
79
- :version-label: Version
80
- // 1.0 Metadata
81
- :1-1-prevrev: 1.0
82
- :1-1-prevrevdate: 2024-02-01
83
- :rhrev1-1-all: Feature update
84
-
85
- [rhrev1-1="Updated introduction"]
86
- == Introduction
87
-
88
- Content here...
89
- ----
90
-
91
40
  == Documentation
92
41
 
93
- See link:USAGE.adoc[] for complete documentation including:
42
+ Full documentation is published at https://baiyibai-antora.gitlab.io.
94
43
 
95
- * Configuration options
96
- * Advanced features
97
- * Localization
98
- * Export functionality
99
- * xrefstyle support
100
- * Examples and use cases
44
+ For configuration details, see link:doc/modules/ROOT/pages/usage.adoc[].
101
45
 
102
46
  == Testing
103
47
 
@@ -114,7 +58,7 @@ This will generate PDFs for all test cases in the `tests/` directory.
114
58
 
115
59
  [source,bash]
116
60
  ----
117
- gem build asciidoctor-pdf-rhrev.gemspec
61
+ gem build asciidoctor-pdf-rhrev.gemspec
118
62
  gem install ./asciidoctor-pdf-rhrev-1.0.0.gem
119
63
  ----
120
64
 
@@ -128,7 +72,7 @@ Contributions welcome! Please ensure all tests pass before submitting changes.
128
72
 
129
73
  == Copyright
130
74
 
131
- Copyright (C) 2025-present 白一百 baiyibai
75
+ Copyright (C) 2025-present 白一百 baiyibai
132
76
 
133
77
  * The image _The «Public Domain Mark» icon from Creative Commons with transparent background._ is in the public domain and taken from: +
134
78
  https://commons.wikimedia.org/wiki/File:Cc-public_domain_mark.svg[^]
data/USAGE.adoc CHANGED
@@ -5,649 +5,10 @@ A comprehensive revision history tracking system for AsciiDoctor and Antora that
5
5
 
6
6
  toc::[]
7
7
 
8
- == Key Features
8
+ include::doc/modules/ROOT/pages/introduction.adoc[tag=why]
9
9
 
10
+ include::doc/modules/ROOT/pages/introduction.adoc[tag=features]
10
11
 
11
- * [x] *Revision Grouping* +
12
- Organize changes by revision number (1-1, 1-2, 2-1, etc.)
13
- * [x] *AST Pre-scanning* +
14
- Collects entries before rendering (like ToC) for accurate page allocation
15
- * [x] *Automatic Page Allocation* +
16
- Properly allocates multi-page tables without overprinting
17
- * [x] *Clickable Page Numbers* +
18
- Page numbers link directly to changed content
19
- * [x] *Bullet Point Lists* +
20
- Changes formatted as proper bullet lists with nesting
21
- * [x] *Bold Headers* +
22
- "Major changes since..." headers are bold and clear
23
- * [x] *Document-Level Entries* +
24
- Special "all" and "cover" page entries
25
- * [x] *Block-Level Tracking* +
26
- Sections, examples, listings, tables, and figures
27
- * [x] *Multiple Placement Options* +
28
- Auto placement or manual with `rhrev::[]` macro
29
- * [x] *Flexible Display* +
30
- Render as section or standalone table
31
- * [x] *Table Styling* +
32
- Control frame, grid, stripes, alignment, and caption
33
- * [x] *Localization* +
34
- Customize all labels and text
35
- * [x] *Export to .adoc* +
36
- Export revision history to separate file
37
- * [x] *Pre/Post Content* +
38
- Add custom content before/after the table
39
- * [x] *TOC-like Syntax* +
40
- Use `:rhrev: macro` just like `:toc: macro`
12
+ include::doc/modules/ROOT/pages/introduction.adoc[tag=quick-start]
41
13
 
42
- == Basic Usage
43
-
44
- [source,asciidoc]
45
- ----
46
- = My Document
47
- :doctype: book
48
- :rhrev:
49
- ----
50
-
51
- === Define Revision Metadata
52
-
53
- [source,asciidoc]
54
- ----
55
- // Revision 1.1 metadata
56
- :1-1-prevrev: 1.0
57
- :1-1-prevrevdate: 2024-01-01
58
- :rhrev1-1-all: * Initial document structure * Added core sections * Setup formatting
59
- :rhrev1-1-cover: * Updated cover design * New logo
60
- ----
61
-
62
- [IMPORTANT]
63
- *All revision attributes must be defined in the document header* - before the first blank line after the document title.
64
- Asciidoctor only loads attributes from the header section.
65
- Attributes that are placed after a blank line do not appear in the revision history.
66
-
67
- .Correct ✅
68
- [source,asciidoc]
69
- ----
70
- = My Document
71
- :doctype: book
72
- :rhrev:
73
- :version-label: Version
74
- // Revision 1.0 metadata
75
- :1-1-prevrev: 1.0
76
- :1-1-prevrevdate: 2024-01-01
77
- :rhrev1-1-all: Initial release
78
-
79
- == Chapter One
80
- ----
81
-
82
- .Incorrect ❌
83
- [source,asciidoc]
84
- ----
85
- = My Document
86
- :doctype: book
87
- :rhrev:
88
- :version-label: Version
89
-
90
- // ❌ This blank line ends the header!
91
- :1-1-prevrev: 1.0 // ❌ These attributes will be IGNORED
92
- :rhrev1-1-all: Initial release // ❌ They won't appear in output
93
-
94
- == Chapter One
95
- ----
96
-
97
- Pro Tip:: Use comments like `// Revision 1.0 metadata` between revision groups instead of blank lines to keep everything in the header while maintaining readability.
98
-
99
- === Mark Content Blocks
100
-
101
- [source,asciidoc]
102
- ----
103
- [rhrev1-1="Created introduction section * Added
104
- overview"]
105
- == Introduction
106
-
107
- Content here...
108
-
109
-
110
- [rhrev1-1="Added installation guide * Included prerequisites"]
111
- [rhrev1-2="Re-ordered the installation steps * Added overview"]
112
- == Getting Started
113
-
114
- More content...
115
- ----
116
-
117
- That's it! The extension performs several actions:
118
-
119
- . Pre-scans the document AST to collect all revision entries
120
- . Allocates proper space for the revision history table
121
- . Renders content normally and capture page numbers
122
- . Fills in the revision history table with actual data and clickable links
123
-
124
- == Understanding Revisions
125
-
126
- Revisions use a hierarchical numbering system: `major-minor` (e.g., 1-1, 1-2, 2-1).
127
-
128
- Each revision groups changes into:
129
-
130
- Document-level "all" entry:: Overall changes for the entire document
131
- Document-level "cover" entry:: Cover page changes (PDF only, not in HTML)
132
- Block-level entries:: Specific changes to sections, examples, etc.
133
-
134
- == Configuration Attributes
135
-
136
- The extension is highly-configurable.
137
-
138
- .Core Settings
139
- [%header,cols="25,75"]
140
- |===
141
- |Attribute
142
- |Description
143
-
144
- |`:rhrev:`
145
- |Enable the feature
146
-
147
- |`:rhrev: macro`
148
- |Enable with macro placement, +
149
- similar to the +
150
- `:toc: macro` +
151
- `toc::[]`
152
-
153
- |`:rhrev-block-type:`
154
- a|
155
- * `section` (default)
156
- * `table`
157
-
158
- |`:rhrev-discrete:`
159
- |Exclude from the Table of Contents +
160
- (`:rhrev-block-type: section` only)
161
-
162
- |`:rhrev-suppress-new-page-after:`
163
- a|Suppress automatic new page after revision history table +
164
-
165
- * Allows content to continue on the same page.
166
-
167
- |`:rhrev-disable-caption:`
168
- a|
169
- * Disable "Table N." caption prefix
170
-
171
- |`:rhrev-table-caption: <Custom Caption>`
172
- |Custom table caption text
173
-
174
- |`:rhrev-description-xrefstyle: basic`
175
- a|Sets the `xrefstyle` inside the description column.
176
-
177
- * `full`
178
- * `short`
179
- * `basic`
180
- * `short basic` +
181
- Like `full`, but without comma, italics, or bold styling.
182
-
183
- |`:rhrev-customization-xrefstyleshort-remove-trailling-period:`
184
- |Removes the trailing period from xrefstyleshort.
185
-
186
- |`:rhrev-initial-handling:`
187
- a|Controls behavior when revnumber is 1.0 or 1
188
-
189
- * `initial-release` (default) - Renders simplified table with "Initial release" text
190
- * `skip` - Completely skip revision history rendering
191
- * `normal` - Render normally even for version 1.0
192
-
193
- |`:rhrev-customization-title:`
194
- a|Custom title for revision history section +
195
- Default: "{version-label} History" +
196
- Set to empty string to suppress title
197
-
198
- |===
199
-
200
- .Localization and Customization
201
- [%header,cols="25,75"]
202
- |===
203
- |Attribute
204
- |Default
205
-
206
- |`:rhrev-table-caption:`
207
- |Custom Caption
208
-
209
- |`:rhrev-localization-page:`
210
- |Page
211
-
212
- |`:rhrev-localization-major-changes:`
213
- |Major changes since
214
-
215
- |`:rhrev-localization-all:`
216
- |All
217
-
218
- |`:rhrev-localization-cover:`
219
- |Cover
220
-
221
- |`:rhrev-localization-initial-release:`
222
- |Initial release
223
-
224
- |`:rhrev-customization-prevrev-include-date:`
225
- a|Include date in revision headers +
226
- When set, date appears after revision: "Version 1.0 2024-01-15" +
227
- When unset, only version: "Version 1.0" (default)
228
-
229
- |`:rhrev-customization-date-format:`
230
- |Date format string for prevrev dates +
231
- Default: %Y-%m-%d +
232
- Example: %B %d, %Y → January 15, 2025
233
-
234
- |`:rhrev-customization-initial-release-text:`
235
- |Text to display for initial release (v1.0) +
236
- Default: Initial Release
237
-
238
- |===
239
-
240
- .Advanced Options
241
- [%header,cols="25,75"]
242
- |===
243
- |Attribute
244
- |Description
245
-
246
- |`:revhistoryprefix:`
247
- a|Override the default attribute prefix +
248
- Default: rhrev +
249
- Example: `:revhistoryprefix: rev` changes `rhrev1-1` to `rev1-1`
250
-
251
- [WARNING]
252
- Changing this value may have adverse effects.
253
-
254
- |`:rhrev-customization-description-format:`
255
- a|Control what appears in description column +
256
- Options:
257
-
258
- * `xref,desc` (default) - Show xref and description
259
- * `xref` - Show only xref
260
- * `desc` - Show only description
261
-
262
- |`:rhrev-debug:`
263
- |Enable debug logging for troubleshooting +
264
- Outputs to stderr or logger
265
-
266
- |===
267
-
268
- .Table Styling
269
- [%header,cols="25,75"]
270
- |===
271
- |Attribute
272
- |Default
273
-
274
- |`:rhrev-table-column-width:`
275
- |30,70
276
-
277
- |`:rhrev-table-frame:`
278
- a|Table frame styling
279
-
280
- * all
281
- * sides
282
- * ends
283
- * none
284
-
285
- |`:rhrev-table-grid:`
286
- a|Table grid styling
287
-
288
- * all
289
- * rows
290
- * cols
291
- * none
292
-
293
- |`:rhrev-table-stripes:`
294
- a|Table stripe styling
295
-
296
- * even
297
- * odd
298
- * none
299
-
300
- |`:rhrev-table-stripes-color:`
301
- a|Table stripe color
302
-
303
- * Hex color for stripes (default: 'EEEEEE')
304
-
305
- |`:rhrev-table-extra-blank-row:`
306
- a|Add blank row at end of table +
307
- (Uses non-breaking spaces for proper height)
308
-
309
- |===
310
-
311
-
312
- The <<table-inserted-row>> attributes allow the author to insert a custom row into the table.
313
- All support full AsciiDoc markup (bold, italic, admonitions, lists, etc.)
314
-
315
- NOTE: Custom first row is supported in both embedded output and exported .adoc files.
316
-
317
- [#table-inserted-row]
318
- .Inserted Row
319
- [%header,cols="25,75"]
320
- |===
321
- |Attribute
322
- |Default
323
-
324
- |`:rhrev-customization-first-row:`
325
- |Content to add to the first row which spans both columns
326
-
327
- |`:rhrev-customization-first-row-left:`
328
- |Content for left cell of first row
329
-
330
- |`:rhrev-customization-first-row-right:`
331
- |Content for right cell of first row
332
-
333
-
334
- |`:rhrev-export-to-file:`
335
- |Enable export to .adoc file
336
-
337
- |`:rhrev-adoc-output:`
338
- |Output filename +
339
- default: revhistory.adoc
340
-
341
- |`:rhrev-export-format:`
342
- a|Export format:
343
-
344
- * 'xref' (default) - exports with the `xref:anchor[page]` macro in the left column
345
- * 'pagerhref' - exports with the `pagerhref:anchor[]` macro in the left column
346
-
347
- NOTE: Antora Assembler beta.15 xref format (`xref:file/path:::anchor[]`) xrefs are automatically converted to standard format (`xref:filename.adoc#anchor[]`) during export
348
-
349
- |===
350
-
351
- === Theme Support
352
-
353
- rhrev supports three asciidoctor theme keys for styling output:
354
-
355
- * `rhrevpage`
356
- * `rhrevdescription`
357
- * `pagerhref`
358
-
359
- == Initial Release Handling
360
-
361
- When `:revnumber:` is set to `1.0` or `1`, the extension provides special handling:
362
-
363
- .Default Behavior (`:rhrev-initial-handling: initial-release`)
364
- Renders a simplified table with "Initial release" text instead of showing empty revision history.
365
-
366
- [source,asciidoc]
367
- ----
368
- = My Document
369
- :revnumber: 1.0
370
- :rhrev:
371
- :rhrev-initial-handling: initial-release
372
- ----
373
-
374
- This produces a clean table showing:
375
-
376
- [cols="30,70"]
377
- |===
378
- a|*Page* | a|*Initial release*
379
- | {nbsp} | {nbsp}
380
- |===
381
-
382
- .Skip Rendering (`:rhrev-initial-handling: skip`)
383
- Completely skip revision history rendering for initial release.
384
-
385
- Use `:rhrev: macro` to avoid a blank page being inserted at the beginning of the document.
386
-
387
- [source,asciidoc]
388
- ----
389
- :revnumber: 1.0
390
- :rhrev: macro
391
- :rhrev-initial-handling: skip
392
- ----
393
-
394
- .Normal Rendering (`:rhrev-initial-handling: normal`)
395
- Render revision history normally even for version 1.0:
396
-
397
- [source,asciidoc]
398
- ----
399
- :revnumber: 1.0
400
- :rhrev:
401
- :rhrev-initial-handling: normal
402
- :1-0-prevrev: 0.9
403
- :rhrev1-0-all: First stable release
404
- ----
405
-
406
- == Manual Mode (`:rhrev: manual`)
407
-
408
- Manual mode allows authors to hand-craft revision history tables, while still leveraging the rhrev extension's anchor cataloging functionality.
409
- This allows authors to use the `pagerhref` macro to resolve page numbers, which eliminates the need to manually track page numbers.
410
-
411
- Use manual mode when these requirements are needed:
412
-
413
- * *Full control* over table structure and formatting
414
- * *Custom grouping* of changes by version/date
415
- * *Flexible layout* not constrained by auto-generation
416
- * *Clickable page number links* via `pagerhref` macro
417
-
418
- What it does not do:
419
-
420
- * Does *NOT* build a revision history table
421
- * Does *NOT* collect or process revision attributes
422
- * Does *NOT* create automatic revision entries
423
-
424
-
425
- === Usage Example
426
-
427
- [source,asciidoc]
428
- ----
429
- = My Document
430
- :doctype: book
431
- :rhrev: manual
432
-
433
- == Revision History
434
-
435
- .Version History
436
- [cols="1,3"]
437
- |===
438
- |Page
439
- |Changes
440
-
441
- a|pagerhref:_introduction[]
442
- a| xref:_introduction[Introduction]
443
-
444
- * Created new section
445
-
446
- a|pagerhref:_features[]
447
- a|xref:_features[Features]
448
-
449
- * Added advanced features
450
-
451
- |===
452
-
453
- == Introduction
454
-
455
- Content here...
456
-
457
- == Features
458
-
459
- More content...
460
- ----
461
-
462
- === How pagerhref Works
463
-
464
- The `pagerhref:anchor[]` macro uses *deferred rendering* to resolve both forward and backward references:
465
-
466
- 1. *First Pass*: Tables with `pagerhref` macros are measured and space is allocated
467
- 2. *Cataloging*: All sections/blocks with anchors are cataloged with their page numbers during rendering
468
- 3. *Re-rendering*: After document rendering completes, tables are re-rendered with actual page numbers
469
- 4. *Result*: Clickable page number links that work for all references
470
-
471
- === Benefits vs. Auto Mode
472
-
473
- [cols="1,2,2"]
474
- |===
475
- | Aspect | Auto Mode | Manual Mode
476
-
477
- | Table Generation
478
- | Automatic
479
- | Hand-crafted
480
-
481
- | Flexibility
482
- | Structured format
483
- | Complete control
484
-
485
- | Page Links
486
- | Automatic
487
- | Via `pagerhref` macro
488
-
489
- | Best For
490
- | Standard revision tracking
491
- | Custom layouts, specific requirements
492
- |===
493
-
494
- == Usage Examples
495
-
496
- Refer to the /tests folder to see real examples.
497
-
498
- == Troubleshooting
499
-
500
- * Page numbers show as "???"
501
- ** Ensure images resolve
502
-
503
- * Bullets render as asterisks
504
- ** Check for syntax errors in bullet formatting
505
- ** Ensure asterisks have spaces: `* item` not `*item`
506
- ** Nested bullets need multiple asterisks: `** nested`
507
-
508
- == Antora Assembler (PDF Extension) Compatibility and Configuration
509
-
510
- Using the rhrev extension with either the default embedded, `rhrev: ''` or `macro` mode requires no additional configuration.
511
-
512
- Using `rhrev: manual` mode with content which contains the `rhrev-export-format: pagerhref` requires additional steps:
513
-
514
- . [`antora-assembler.yml`] Add the rhrev extension as the last item (`-r `) in the `build/command`. +
515
- This is required to ensure the extension overrides the table rendering so that it can provide page numbers to the catalog.
516
- . [`antora-playbook.yml`] Add the Antora-Assembler `antora-rhrev-assembler-pagerhref.js` script to the `antora/extensions` section. +
517
- This extension overwrites the pagerhref macros in exported in the assembly file to allow page lookup in the catalog.
518
-
519
- The recommended approach is to add some rhrev entires in the document, export the revision history to an .adoc file, and then examine it to see how to copy and re-import the content.
520
-
521
- == Antora Usage
522
-
523
- Until the extension is available on npm or yarn, the extensions must be manually configured in the `antora-playbook.yml` file.
524
-
525
- . Add these lines to the `antora-playbook.yml`:
526
- +
527
- [source,yaml]
528
- ----
529
- asciidoc:
530
- extensions:
531
- - ./antora-extension/antora-rhrev-asciidoc.js
532
- antora:
533
- extensions:
534
- - '@antora/pdf-extension'
535
- # Select only one
536
- - require: ./antora-extension/antora-rhrev-html.js
537
- - require: ./antora-extension/antora-rhrev-placeholder.js
538
- # Required if using rhrev: manual w/pagerhref macros:
539
- - require: ./antora-extension/antora-rhrev-assembler-pagerhref.js
540
- ----
541
- +
542
- . Add the desired configuration settings into the appropriate .yml file; antora-assembler.yml for PDF and antora-playbook.yml for HTML.
543
- . For best results, use the `rhrev: macro` attribute in the document.
544
-
545
- == The Tao of Revision History
546
-
547
- === Writing Good Revision Descriptions
548
-
549
- A good revision history is not a list of "updated" and "fixed bugs."
550
- It's a narrative that respects the reader's time and helps them understand what changed without comparing two versions.
551
-
552
- . Use simple past tense verbs with specificity
553
- ** [x] "Added OAuth 2.0 authentication"
554
- ** [x] "Changed timeout from 30s to 60s"
555
- ** [x] "Removed deprecated API endpoints"
556
- ** ❌ "Updated authentication"
557
- ** ❌ "Fixed issues"
558
- ** ❌ "Improvements made"
559
- . Describe the transition (from → to):
560
- ** [x] "Changed default port from 8080 to 3000"
561
- ** [x] "Renamed 'config.yaml' to 'settings.yaml'
562
- ** ❌ "Port updated"
563
- ** ❌ "Config file changed"
564
- . Keep simple styling and avoid too many hyperlinks.
565
- . Keep changes next to the context.
566
-
567
- === Why Use Block Attributes?
568
-
569
- When placed `[rhrev1-2="Added validation"]` directly on a section about user input, the editor immediately knows WHAT was validated and WHERE. This is better than a separate changelog that says "Added validation" with no context.
570
-
571
- The problem with separate changelogs::
572
-
573
- * The author must remember what changed
574
- * The reader must hunt through document to find the change
575
- * Vague entries like "updated section 3.2" are useless
576
- * Maintaining two files is error-prone
577
-
578
- The solution with inline attributes::
579
-
580
- * The change description is right at the change location
581
- * This forces author to think about the change while making it
582
- * The reader gets a descriptive preview of the change in advance
583
- * There is a single source of truth
584
-
585
- == The Frustration This Avoids
586
-
587
- When maintaining a 200-page technical manual, tracking changes in a separate file becomes a nightmare:
588
-
589
- * "Which section did I update?"
590
- * "Was it the API reference or the examples?"
591
- * "What exactly changed in chapter 5?"
592
-
593
- With inline `[rhrev]` attributes, the change description lives with the change.
594
-
595
-
596
- === Document-Level vs Block-Level Entries
597
-
598
- Document-level "all" Entries::
599
-
600
- * Structural changes (added new chapter, reorganized sections)
601
- * Format updates (changed heading styles, updated templates)
602
- * Global find-replace operations
603
- * Overall improvements that touch many places
604
-
605
- Block-level Entries:::
606
-
607
- * Specific content changes (added example, updated diagram)
608
- * Localized fixes (corrected formula, fixed typo)
609
- * New content (added section on X)
610
- * Targeted updates (revised explanation of Y)
611
-
612
- === The Asterisk System
613
-
614
- Asterisks create hierarchy in the changes:
615
-
616
- [source,asciidoc]
617
- ----
618
- :rhrev1-2-all: Added security chapter * Authentication ** OAuth 2.0 ** API keys * Authorization ** Role-based access ** Permissions
619
- ----
620
-
621
- This renders as:
622
-
623
- * Added security chapter
624
- * Authentication
625
- ** OAuth 2.0
626
- ** API keys
627
- * Authorization
628
- ** Role-based access
629
- ** Permissions
630
-
631
- One bullet per change, subbullets for more detail
632
-
633
- === Minimal Styling is Better
634
-
635
- Revision histories should be scannable, not distracting:
636
-
637
- * Plain text is best for change descriptions
638
- * Bold headers (automatic) help separate revisions
639
- * Bullet points (automatic) organize changes
640
- * Clickable page numbers (automatic) for navigation
641
- * That's it. No colors, no icons, no fancy formatting.
642
-
643
- The goal is clarity, not decoration. Your readers are looking for information, not entertainment.
644
-
645
- === Teaching Better Documentation
646
-
647
- This extension teaches authors to think more deeply about their changes:
648
-
649
- * What exactly changed?
650
- * Why did it change?
651
- * How would I explain this to someone who doesn't have the previous version?
652
-
653
- This discipline improves documentation quality overall.
14
+ include::doc/modules/ROOT/pages/usage.adoc[tag=content]
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor
4
+ module PDF
5
+ module Rhrev
6
+ # Inks a vertical change bar in the page margin next to blocks marked
7
+ # with the current revision (revnumber 1.2 => attribute rhrev1-2).
8
+ # Enabled by the rhrev-change-bars document attribute.
9
+ #
10
+ # Styling comes from the PDF theme by default (rhrev_change_bars category:
11
+ # color, width, offset, side), overridable per document via the
12
+ # rhrev-change-bars-color/-width/-offset/-side attributes.
13
+ module ChangeBars
14
+ def init_change_bars doc
15
+ @change_bar_attr = nil
16
+ @change_bar_settings = nil
17
+ return unless doc.attr? 'rhrev-change-bars'
18
+ # Without a revnumber there is no "current" revision to match
19
+ return unless (revnumber = doc.attr 'revnumber')
20
+ @change_bar_attr = %(#{@revision_prefix}#{revnumber.to_s.tr '.', '-'})
21
+ # Capture attribute values only; holding the Document in an ivar here
22
+ # would leak it into the scratch prototype, which must stay marshalable
23
+ @change_bar_overrides = {
24
+ color: (doc.attr 'rhrev-change-bars-color'),
25
+ width: (doc.attr 'rhrev-change-bars-width'),
26
+ offset: (doc.attr 'rhrev-change-bars-offset'),
27
+ side: (doc.attr 'rhrev-change-bars-side'),
28
+ }
29
+ @change_bar_starts = {}
30
+ end
31
+
32
+ # Resolved lazily on first ink: the theme (and @media/@folio_placement)
33
+ # are not loaded yet when init_change_bars runs; upstream
34
+ # convert_document sets them up after rhrev's pre-super initialization.
35
+ # Precedence: document attribute > theme key > built-in default.
36
+ def change_bar_settings
37
+ @change_bar_settings ||= begin
38
+ overrides = @change_bar_overrides || {}
39
+ theme = @theme
40
+ side = overrides[:side] || theme&.rhrev_change_bars_side ||
41
+ (@media == 'prepress' ? 'outer' : 'right')
42
+ {
43
+ color: (overrides[:color] || theme&.rhrev_change_bars_color || 'FF0000').to_s.delete_prefix('#').upcase,
44
+ width: (overrides[:width] || theme&.rhrev_change_bars_width || 2).to_f,
45
+ offset: (overrides[:offset] || theme&.rhrev_change_bars_offset || 16).to_f,
46
+ side: side.to_s,
47
+ }
48
+ end
49
+ end
50
+
51
+ def change_bar? node
52
+ @change_bar_attr && node.respond_to?(:attributes) &&
53
+ node.attributes && (node.attributes.key? @change_bar_attr)
54
+ end
55
+
56
+ def record_change_bar_start node
57
+ @change_bar_starts[node] = { page: page_number, cursor: cursor }
58
+ end
59
+
60
+ def take_change_bar_start node
61
+ @change_bar_starts&.delete node
62
+ end
63
+
64
+ # The offset measures the gap between the text edge and the near edge
65
+ # of the bar. Sides recto/verso are determined by the physical page
66
+ # number (honoring pdf-folio-placement inversion), matching prepress
67
+ # physical folio placement.
68
+ def change_bar_x pgnum, settings
69
+ case settings[:side]
70
+ when 'right'
71
+ on_right = true
72
+ when 'outer', 'inner'
73
+ recto = (page_side pgnum, @folio_placement && @folio_placement[:inverted]) == :recto
74
+ on_right = settings[:side] == 'outer' ? recto : !recto
75
+ end
76
+ on_right ? bounds.right + settings[:offset] : bounds.left - settings[:offset] - settings[:width]
77
+ end
78
+
79
+ # Paints the bar page by page; from/to are { page:, cursor: }.
80
+ # Called immediately after the block is rendered, so all spanned pages exist.
81
+ def ink_change_bar from, to
82
+ return if scratch? || from.nil? || to.nil?
83
+ return if to[:page] < from[:page]
84
+ return if to[:page] == from[:page] && to[:cursor] >= from[:cursor]
85
+ settings = change_bar_settings
86
+ float do
87
+ (from[:page]..to[:page]).each do |pgnum|
88
+ go_to_page pgnum unless page_number == pgnum
89
+ top = pgnum == from[:page] ? from[:cursor] : bounds.top
90
+ bottom = pgnum == to[:page] ? to[:cursor] : 0
91
+ next if (height = top - bottom) <= 0
92
+ bounding_box [(change_bar_x pgnum, settings), top], width: settings[:width], height: height do
93
+ fill_bounds settings[:color]
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ def ink_change_bar_for_extent extent
100
+ return unless extent
101
+ ink_change_bar({ page: extent.from.page, cursor: extent.from.cursor },
102
+ { page: extent.to.page, cursor: extent.to.cursor })
103
+ end
104
+
105
+ # Examples and listings are arranged blocks: the extent yielded here is
106
+ # exact across page breaks. Tables and images never reach this hook with
107
+ # their own node, so they are handled in the converter overrides instead.
108
+ def arrange_block node, &block
109
+ if @change_bar_attr && !scratch? &&
110
+ (node.context == :example || node.context == :listing) && (change_bar? node)
111
+ super node do |extent|
112
+ if scratch?
113
+ # measurement pass: upstream instance_execs this wrapper on the scratch
114
+ # document, so re-bind the original block to it the same way
115
+ instance_exec(&block)
116
+ else
117
+ block.call extent
118
+ ink_change_bar_for_extent extent
119
+ end
120
+ end
121
+ else
122
+ super
123
+ end
124
+ end
125
+
126
+ # The heading ink methods run after arrange_heading / start_new_chapter
127
+ # have settled the page, so this is the first accurate start position.
128
+ def ink_general_heading node, title, opts = {}
129
+ record_change_bar_start node if @change_bar_attr && !scratch? && (change_bar? node)
130
+ super
131
+ end
132
+
133
+ def ink_chapter_title node, title, opts = {}
134
+ record_change_bar_start node if @change_bar_attr && !scratch? && (change_bar? node)
135
+ super
136
+ end
137
+
138
+ # Upstream defines ink_part_title as an alias copy of ink_chapter_title,
139
+ # so it must be overridden separately
140
+ def ink_part_title node, title, opts = {}
141
+ record_change_bar_start node if @change_bar_attr && !scratch? && (change_bar? node)
142
+ super
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
@@ -5,6 +5,7 @@ require_relative 'catalog'
5
5
  require_relative 'renderer'
6
6
  require_relative 'exporter'
7
7
  require_relative 'processors'
8
+ require_relative 'change_bars'
8
9
 
9
10
  module Asciidoctor
10
11
  module PDF
@@ -19,6 +20,7 @@ module Asciidoctor
19
20
  include Helpers
20
21
  include Renderer
21
22
  include Exporter
23
+ include ChangeBars
22
24
 
23
25
  def initialize *args
24
26
  super
@@ -37,7 +39,8 @@ module Asciidoctor
37
39
 
38
40
  def convert_document node
39
41
  @revision_prefix = node.attr 'revhistoryprefix', 'rhrev'
40
-
42
+ init_change_bars node
43
+
41
44
  # Check if we're in manual mode (pagerhref support needed)
42
45
  @manual_mode = node.attr('rhrev') == 'manual'
43
46
 
@@ -67,7 +70,7 @@ module Asciidoctor
67
70
  result
68
71
  end
69
72
 
70
- def convert_section node
73
+ def convert_section node, opts = {}
71
74
  # Skip collect during render if prescan already did it
72
75
  collect_revision_entries node unless @prescan_complete
73
76
  update_revision_entry_metadata node
@@ -86,8 +89,13 @@ module Asciidoctor
86
89
  # Link destination to page for revision history
87
90
  revision_history.link_dest_to_page node.id, page_number, 1, y: cursor
88
91
  end
89
-
90
- super
92
+
93
+ result = super
94
+ # Start position was captured at heading-ink time (after any page advance)
95
+ if @change_bar_attr && !scratch? && (start_pos = take_change_bar_start node)
96
+ ink_change_bar start_pos, { page: page_number, cursor: cursor }
97
+ end
98
+ result
91
99
  end
92
100
 
93
101
  def convert_table node
@@ -112,8 +120,17 @@ module Asciidoctor
112
120
  if has_pagerhref
113
121
  allocate_pagerhref_table_extent node
114
122
  else
123
+ # Skip recording when the upstream table-container rewrap will trigger
124
+ # (condition replicated from asciidoctor-pdf convert_table); the
125
+ # re-entrant conversion of the attribute-preserving dup records instead
126
+ if @change_bar_attr && !scratch? && (change_bar? node) &&
127
+ !(!at_page_top? && ((node.option? 'unbreakable') ||
128
+ ((node.option? 'breakable') && (node.id || node.title?))))
129
+ bar_from = { page: page_number, cursor: cursor }
130
+ end
115
131
  result = super
116
132
  catalog_block_anchor node
133
+ ink_change_bar bar_from, { page: page_number, cursor: cursor } if bar_from
117
134
  result
118
135
  end
119
136
  end
@@ -122,8 +139,19 @@ module Asciidoctor
122
139
  # Skip collect during render if prescan already did it
123
140
  collect_revision_entries node unless @prescan_complete
124
141
  update_revision_entry_metadata node
142
+ # PDF targets import whole pages; there is no cursor flow to mark
143
+ if @change_bar_attr && !scratch? && (change_bar? node) &&
144
+ !((node.attr 'target').to_s.downcase.end_with? '.pdf')
145
+ bar_from = { page: page_number, cursor: cursor }
146
+ end
125
147
  result = super
126
148
  catalog_block_anchor node
149
+ if bar_from
150
+ bar_to = { page: page_number, cursor: cursor }
151
+ # Images never split; a page change means the image moved wholesale
152
+ bar_from = { page: bar_to[:page], cursor: bounds.top } if bar_to[:page] > bar_from[:page]
153
+ ink_change_bar bar_from, bar_to
154
+ end
127
155
  result
128
156
  end
129
157
 
@@ -151,6 +179,9 @@ module Asciidoctor
151
179
  update_revision_entry_metadata node
152
180
  result = super
153
181
  catalog_block_anchor node
182
+ if @change_bar_attr && !scratch? && (start_pos = take_change_bar_start node)
183
+ ink_change_bar start_pos, { page: page_number, cursor: cursor }
184
+ end
154
185
  result
155
186
  end
156
187
 
@@ -390,23 +421,23 @@ module Asciidoctor
390
421
  def collect_document_level_entries doc
391
422
  return if @document_entries_collected
392
423
  @document_entries_collected = true
393
-
394
- (0..9).each do |major|
395
- (0..9).each do |minor|
396
- revision = "#{major}-#{minor}"
397
- prevrev_attr = "#{revision}-prevrev"
398
-
399
- if doc.attr(prevrev_attr)
400
- all_attr_name = "#{@revision_prefix}#{revision}-all"
401
- if (all_value = doc.attr(all_attr_name))
402
- revision_history.add_all_entry revision, all_value
403
- end
404
-
405
- cover_attr_name = "#{@revision_prefix}#{revision}-cover"
406
- if (cover_value = doc.attr(cover_attr_name))
407
- revision_history.add_cover_entry revision, cover_value
408
- end
409
- end
424
+
425
+ # Discover revisions from *-prevrev attributes so any number of
426
+ # segments works (1-1, 1-2-0, ...), not just major-minor
427
+ doc.attributes.each_key do |key|
428
+ key_str = key.to_s
429
+ next unless key_str.end_with?('-prevrev')
430
+ revision = key_str.delete_suffix('-prevrev')
431
+ next unless revision.match?(/\A\d+(?:-\d+)*\z/)
432
+
433
+ all_attr_name = "#{@revision_prefix}#{revision}-all"
434
+ if (all_value = doc.attr(all_attr_name))
435
+ revision_history.add_all_entry revision, all_value
436
+ end
437
+
438
+ cover_attr_name = "#{@revision_prefix}#{revision}-cover"
439
+ if (cover_value = doc.attr(cover_attr_name))
440
+ revision_history.add_cover_entry revision, cover_value
410
441
  end
411
442
  end
412
443
  end
@@ -345,7 +345,7 @@ module Asciidoctor
345
345
  if saved_caption
346
346
  doc.set_attr 'table-caption', saved_caption
347
347
  else
348
- doc.delete_attr 'table-caption'
348
+ doc.delete_attribute 'table-caption'
349
349
  end
350
350
  end
351
351
  end
@@ -155,20 +155,20 @@ module Asciidoctor
155
155
  prefix = doc.attr 'revhistoryprefix', 'rhrev'
156
156
 
157
157
  # Collect document-level entries (-all)
158
- (0..9).each do |major|
159
- (0..9).each do |minor|
160
- revision = "#{major}-#{minor}"
161
- prevrev_attr = "#{revision}-prevrev"
162
-
163
- if doc.attr(prevrev_attr)
164
- all_attr_name = "#{prefix}#{revision}-all"
165
- if (all_value = doc.attr(all_attr_name))
166
- catalog.add_all_entry revision, all_value
167
- end
168
-
169
- # Skip -cover entries for HTML
170
- end
158
+ # Discover revisions from *-prevrev attributes so any number of
159
+ # segments works (1-1, 1-2-0, ...), not just major-minor
160
+ doc.attributes.each_key do |key|
161
+ key_str = key.to_s
162
+ next unless key_str.end_with?('-prevrev')
163
+ revision = key_str.delete_suffix('-prevrev')
164
+ next unless revision.match?(/\A\d+(?:-\d+)*\z/)
165
+
166
+ all_attr_name = "#{prefix}#{revision}-all"
167
+ if (all_value = doc.attr(all_attr_name))
168
+ catalog.add_all_entry revision, all_value
171
169
  end
170
+
171
+ # Skip -cover entries for HTML
172
172
  end
173
173
 
174
174
  # Collect block-level entries by scanning document
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-rhrev
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - 白一百 baiyibai
@@ -31,12 +31,14 @@ executables: []
31
31
  extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
+ - CHANGELOG.adoc
34
35
  - LICENSE
35
36
  - README.adoc
36
37
  - USAGE.adoc
37
38
  - lib/asciidoctor-rhrev.rb
38
39
  - lib/asciidoctor/rhrev.rb
39
40
  - lib/asciidoctor/rhrev/catalog.rb
41
+ - lib/asciidoctor/rhrev/change_bars.rb
40
42
  - lib/asciidoctor/rhrev/converter.rb
41
43
  - lib/asciidoctor/rhrev/exporter.rb
42
44
  - lib/asciidoctor/rhrev/helpers.rb
@@ -63,7 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
63
65
  - !ruby/object:Gem::Version
64
66
  version: '0'
65
67
  requirements: []
66
- rubygems_version: 3.6.7
68
+ rubygems_version: 3.6.9
67
69
  specification_version: 4
68
70
  summary: Comprehensive revision history tracking extension for asciidoctor and asciidoctor-pdf
69
71
  test_files: []