asciidoctor-lists-extended 1.0.0 → 1.0.1
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c1f0396e93370444193a1258530dd32f81db35dddaedc4c911a31655d94d5e2c
|
|
4
|
+
data.tar.gz: bbd4f0412e6b11fcfc1bb39b38a2cd9932c8738a740d8c6b693f4185c03c0566
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9970ef9f04375ee8e446abb219171880806ac09bdc09f1909f0830eda569e37191188cd195813185339e56b31ccaaf6446f835415f77d5adaf912b6bf032aee3
|
|
7
|
+
data.tar.gz: fe43e888bba80b85b9212f24df7bed543224e510f22e4b40aefd754eeacf27b0e5e22220d2bc9a3d70e684dacab1e00d49ab120547b74382b6ad9bdc86bda824
|
data/README.adoc
CHANGED
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
= asciidoctor-lists-extended
|
|
2
2
|
:toc: left
|
|
3
3
|
:toclevels: 2
|
|
4
|
-
:source-highlighter:
|
|
4
|
+
:source-highlighter: highlight.js
|
|
5
5
|
|
|
6
6
|
A converter-aware asciidoctor extension that generates a *List of Figures*, *List of Tables*, *List of Listings*, and *List of Examples* — or any custom captioned block type.
|
|
7
7
|
|
|
8
8
|
Replaces and supersedes `asciidoctor-pdf-lofte`.
|
|
9
9
|
Compatible with the `asciidoctor-lists` macro syntax.
|
|
10
10
|
|
|
11
|
+
== Preview
|
|
12
|
+
|
|
13
|
+
.Table of Contents with List of Figures, List of Tables, and List of Examples entries
|
|
14
|
+
image::test/images/toc.png[PDF Table of Contents showing list entries,pdfwidth=100%]
|
|
15
|
+
|
|
16
|
+
.List of Figures — dot-leader style matching the ToC
|
|
17
|
+
image::test/images/lof.png[List of Figures rendered in PDF front matter,pdfwidth=100%]
|
|
18
|
+
|
|
19
|
+
.List of Listings
|
|
20
|
+
image::test/images/lol.png[List of Listings rendered in PDF front matter,pdfwidth=100%]
|
|
21
|
+
|
|
22
|
+
.List of Examples
|
|
23
|
+
image::test/images/loe.png[List of Examples rendered in PDF front matter,pdfwidth=100%]
|
|
24
|
+
|
|
25
|
+
.PDF bookmark outline showing list entries
|
|
26
|
+
image::test/images/pdf-outline.png[PDF bookmark outline panel,pdfwidth=100%]
|
|
27
|
+
|
|
11
28
|
== Features
|
|
12
29
|
|
|
13
30
|
* Works with *HTML5* (xref links) and *asciidoctor-pdf* (dot-leader style matching the ToC)
|
|
@@ -47,13 +64,13 @@ asciidoctor -r /path/to/lib/asciidoctor-lists-extended.rb document.adoc
|
|
|
47
64
|
:toc:
|
|
48
65
|
:doctype: book
|
|
49
66
|
|
|
50
|
-
|
|
67
|
+
== List of Figures <1>
|
|
51
68
|
list-of::image[] <2>
|
|
52
69
|
|
|
53
|
-
|
|
70
|
+
== List of Tables
|
|
54
71
|
list-of::table[]
|
|
55
72
|
|
|
56
|
-
|
|
73
|
+
== Chapter 1
|
|
57
74
|
|
|
58
75
|
.My Architecture Diagram <3>
|
|
59
76
|
image::arch.png[]
|
|
@@ -165,7 +182,7 @@ In PDF mode the extension hooks into `asciidoctor-pdf`'s ToC allocation/renderin
|
|
|
165
182
|
All lists are placed in the *front matter* (directly after the ToC) regardless of where the `list-of::` macros appear in the source.
|
|
166
183
|
The macro order in the source determines the order of the lists in the front matter.
|
|
167
184
|
|
|
168
|
-
You can place
|
|
185
|
+
You can place `list-of::` macros inside any subsection to generate *section-scoped* lists.
|
|
169
186
|
The scope is determined automatically from where the macro appears in the document hierarchy:
|
|
170
187
|
|
|
171
188
|
[cols="1,2"]
|
|
@@ -176,30 +193,41 @@ The scope is determined automatically from where the macro appears in the docume
|
|
|
176
193
|
e.g. a front-matter `== List of Figures`
|
|
177
194
|
|*Document-wide* — collects all matching elements in the entire document.
|
|
178
195
|
|
|
179
|
-
|Inside a subsection (`=== …`)
|
|
196
|
+
|Inside a subsection (`=== …`) +
|
|
180
197
|
e.g. `=== Chapter 1 Figures` inside `== Chapter 1`
|
|
181
|
-
|*
|
|
198
|
+
|*Section-scoped* — collects only elements placed inside that same subsection.
|
|
182
199
|
|===
|
|
183
200
|
|
|
184
|
-
|
|
201
|
+
[IMPORTANT]
|
|
202
|
+
====
|
|
203
|
+
For section-scoped lists, place the captioned content *before* the `list-of::` macros
|
|
204
|
+
within the subsection.
|
|
205
|
+
This ensures all entries have already been rendered when the list runs, so page numbers
|
|
206
|
+
show correctly (no `?`).
|
|
207
|
+
====
|
|
208
|
+
|
|
209
|
+
.Example: global list plus a per-section list
|
|
185
210
|
[source,asciidoc]
|
|
186
211
|
----
|
|
187
|
-
|
|
212
|
+
== List of Figures <1>
|
|
188
213
|
list-of::image[]
|
|
189
214
|
|
|
190
|
-
|
|
215
|
+
== Chapter 1
|
|
191
216
|
|
|
192
|
-
|
|
193
|
-
image::arch.png[]
|
|
217
|
+
=== Chapter 1 Figures <2>
|
|
194
218
|
|
|
195
|
-
|
|
196
|
-
|
|
219
|
+
.Overview Diagram <3>
|
|
220
|
+
image::arch.png[]
|
|
197
221
|
|
|
198
222
|
.Detailed Flow
|
|
199
223
|
image::flow.png[]
|
|
224
|
+
|
|
225
|
+
list-of::image[] <4>
|
|
200
226
|
----
|
|
201
|
-
<1> Document-wide: collects all images.
|
|
202
|
-
<2>
|
|
227
|
+
<1> Document-wide: collects all images across the entire document.
|
|
228
|
+
<2> Subsection that owns both the content and the scoped list.
|
|
229
|
+
<3> Captioned images placed *before* the macro so page numbers are resolved.
|
|
230
|
+
<4> Section-scoped: collects only images placed inside `=== Chapter 1 Figures`.
|
|
203
231
|
|
|
204
232
|
=== Styling
|
|
205
233
|
|
|
@@ -250,19 +278,19 @@ The containing section and heading are rendered normally.
|
|
|
250
278
|
:table-caption: Table
|
|
251
279
|
:listing-caption: Listing
|
|
252
280
|
|
|
253
|
-
|
|
281
|
+
== List of Figures
|
|
254
282
|
list-of::image[] <1>
|
|
255
283
|
|
|
256
|
-
|
|
284
|
+
== List of Tables
|
|
257
285
|
list-of::table[hide_empty_section] <2>
|
|
258
286
|
|
|
259
|
-
|
|
287
|
+
== List of Code Examples
|
|
260
288
|
list-of::listing[title="Code Examples"] <3>
|
|
261
289
|
|
|
262
|
-
|
|
290
|
+
== List of Appendix Examples
|
|
263
291
|
list-of::example[exclude_from_outline] <4>
|
|
264
292
|
|
|
265
|
-
|
|
293
|
+
== Chapter 1: Architecture
|
|
266
294
|
|
|
267
295
|
.System Overview
|
|
268
296
|
image::arch.png[]
|
|
@@ -332,10 +360,10 @@ The `list-of::` macros render as `<ul>` lists with `<a href="#…">` links.
|
|
|
332
360
|
|
|
333
361
|
|`:lof-title: List of Figures` +
|
|
334
362
|
`:lot-title: List of Tables`
|
|
335
|
-
|
|
363
|
+
|`== List of Figures` +
|
|
336
364
|
`list-of::image[]` +
|
|
337
365
|
+
|
|
338
|
-
|
|
366
|
+
`== List of Tables` +
|
|
339
367
|
`list-of::table[]`
|
|
340
368
|
|
|
341
369
|
|`:include-lists-in-toc:`
|
|
@@ -64,13 +64,7 @@ module Asciidoctor
|
|
|
64
64
|
def scope_node_for(block, document)
|
|
65
65
|
node = block.parent
|
|
66
66
|
return document unless node.respond_to?(:context) && node.context == :section
|
|
67
|
-
node.parent.context == :document ? document :
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def chapter_ancestor(section)
|
|
71
|
-
node = section
|
|
72
|
-
node = node.parent while node.parent&.context == :section
|
|
73
|
-
node
|
|
67
|
+
node.parent.context == :document ? document : node
|
|
74
68
|
end
|
|
75
69
|
|
|
76
70
|
# Parse AsciiDoc source lines in the context of +parent+, returning the
|
|
@@ -29,7 +29,8 @@ module Asciidoctor
|
|
|
29
29
|
super
|
|
30
30
|
@list_extents = {} # UUID → Extent (front-matter lists only)
|
|
31
31
|
@list_configs_ordered = [] # front-matter list configs in document order
|
|
32
|
-
@inline_list_configs = {} # UUID → config for
|
|
32
|
+
@inline_list_configs = {} # UUID → config for section-scoped inline lists
|
|
33
|
+
@inline_render_positions = {} # UUID → deferred render position (page + cursor)
|
|
33
34
|
@inline_num_front_matter_pages = 0 # saved from ink_toc for inline page-number math
|
|
34
35
|
@rendering_list = false
|
|
35
36
|
@list_toc_insert_idx = 0
|
|
@@ -89,7 +90,29 @@ module Asciidoctor
|
|
|
89
90
|
@list_toc_insert_idx += 1
|
|
90
91
|
end
|
|
91
92
|
|
|
92
|
-
super
|
|
93
|
+
result = super
|
|
94
|
+
|
|
95
|
+
# Phase 2: render deferred inline section-scoped lists.
|
|
96
|
+
# traverse doc has completed before ink_toc is called, so all
|
|
97
|
+
# pdf-page-start attributes are now set and page numbers are real.
|
|
98
|
+
unless @inline_render_positions.empty?
|
|
99
|
+
@inline_render_positions.each_value do |pos|
|
|
100
|
+
go_to_page pos[:page]
|
|
101
|
+
move_cursor_to pos[:cursor]
|
|
102
|
+
entries = get_list_entries(pos[:config][:scope_node], pos[:config][:element])
|
|
103
|
+
next if entries.empty?
|
|
104
|
+
entries.each { |e| e.level = 2 if e.title }
|
|
105
|
+
begin
|
|
106
|
+
@rendering_list = true
|
|
107
|
+
ink_toc_level entries, pos[:num_levels], pos[:dot_leader], num_front_matter_pages
|
|
108
|
+
ensure
|
|
109
|
+
@rendering_list = false
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
go_to_page page_count
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
result
|
|
93
116
|
end
|
|
94
117
|
|
|
95
118
|
# -----------------------------------------------------------------------
|
|
@@ -122,19 +145,69 @@ module Asciidoctor
|
|
|
122
145
|
# cursor position without a heading (the enclosing === section provides
|
|
123
146
|
# the heading) and without any page break before or after.
|
|
124
147
|
# All other paragraphs delegate to super unchanged.
|
|
148
|
+
# -----------------------------------------------------------------------
|
|
149
|
+
# convert_paragraph override
|
|
150
|
+
# -----------------------------------------------------------------------
|
|
151
|
+
# Intercepts UUID placeholder paragraphs for section-scoped inline lists.
|
|
152
|
+
#
|
|
153
|
+
# Rendering strategy (two-phase):
|
|
154
|
+
# Phase 1 — body rendering (here, scratch? may be true or false):
|
|
155
|
+
# • When scratch? is true: call ink_toc_level in scratch mode so Prawn
|
|
156
|
+
# measures the correct space for page-break decisions.
|
|
157
|
+
# • When scratch? is false: dry-run the list to measure its height,
|
|
158
|
+
# reserve that space in the document by advancing the cursor, and
|
|
159
|
+
# record the page + cursor position in @inline_render_positions.
|
|
160
|
+
# No visible content is written yet.
|
|
161
|
+
#
|
|
162
|
+
# Phase 2 — ink_toc (called by asciidoctor-pdf AFTER traverse doc):
|
|
163
|
+
# By the time ink_toc runs all pdf-page-start attributes have been set.
|
|
164
|
+
# For each saved position, navigate there and render with real dot leaders
|
|
165
|
+
# and page numbers. See ink_toc below.
|
|
125
166
|
def convert_paragraph(node)
|
|
126
167
|
if node.content_model == :simple && node.lines.size == 1 &&
|
|
127
168
|
(config = @inline_list_configs[node.lines[0]])
|
|
169
|
+
uuid = node.lines[0]
|
|
128
170
|
entries = get_list_entries(config[:scope_node], config[:element])
|
|
171
|
+
|
|
129
172
|
unless entries.empty?
|
|
130
173
|
entries.each { |e| e.level = 2 if e.title }
|
|
131
|
-
num_levels =
|
|
174
|
+
num_levels = @theme.toc_levels || 2
|
|
132
175
|
dot_leader = build_dot_leader_config(num_levels)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
176
|
+
|
|
177
|
+
if scratch?
|
|
178
|
+
# Scratch pass (e.g. heading orphan detection): measure space only.
|
|
179
|
+
begin
|
|
180
|
+
@rendering_list = true
|
|
181
|
+
ink_toc_level entries, num_levels, dot_leader, 0
|
|
182
|
+
ensure
|
|
183
|
+
@rendering_list = false
|
|
184
|
+
end
|
|
185
|
+
else
|
|
186
|
+
# Real pass: measure via dry_run, reserve blank space, save position.
|
|
187
|
+
extent = dry_run(onto: self) do
|
|
188
|
+
begin
|
|
189
|
+
@rendering_list = true
|
|
190
|
+
ink_toc_level entries, num_levels, dot_leader, 0
|
|
191
|
+
ensure
|
|
192
|
+
@rendering_list = false
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
save_page = extent.from.page
|
|
197
|
+
save_cursor = extent.from.cursor
|
|
198
|
+
|
|
199
|
+
# Reserve the space without rendering any content.
|
|
200
|
+
extent.each_page { |first_page| start_new_page unless first_page }
|
|
201
|
+
move_cursor_to extent.to.cursor
|
|
202
|
+
|
|
203
|
+
@inline_render_positions[uuid] = {
|
|
204
|
+
config: config,
|
|
205
|
+
entries: entries,
|
|
206
|
+
num_levels: num_levels,
|
|
207
|
+
dot_leader: dot_leader,
|
|
208
|
+
page: save_page,
|
|
209
|
+
cursor: save_cursor,
|
|
210
|
+
}
|
|
138
211
|
end
|
|
139
212
|
end
|
|
140
213
|
return
|
|
@@ -134,24 +134,16 @@ module Asciidoctor
|
|
|
134
134
|
# Determine the collection scope for a list-of:: UUID placeholder block.
|
|
135
135
|
#
|
|
136
136
|
# Rule: if the macro's parent section is a top-level section (its parent is
|
|
137
|
-
# the Document), scope is the whole document.
|
|
138
|
-
#
|
|
139
|
-
# the first ancestor section whose parent is the Document.
|
|
137
|
+
# the Document), scope is the whole document. Otherwise, scope is the direct
|
|
138
|
+
# parent section — the macro collects only elements within that subsection.
|
|
140
139
|
#
|
|
141
140
|
# This means front-matter lists (== List of Figures) collect everything, while
|
|
142
|
-
# per-
|
|
143
|
-
#
|
|
141
|
+
# per-section lists (=== Chapter Figures inside == Chapter 1) collect only
|
|
142
|
+
# elements placed inside that same subsection.
|
|
144
143
|
def scope_node_for(block)
|
|
145
144
|
node = block.parent
|
|
146
145
|
return block.document unless node.respond_to?(:context) && node.context == :section
|
|
147
|
-
node.parent.context == :document ? block.document :
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
# Walk up the parent chain to find the first section whose parent is the Document.
|
|
151
|
-
def chapter_ancestor(section)
|
|
152
|
-
node = section
|
|
153
|
-
node = node.parent while node.parent&.context == :section
|
|
154
|
-
node
|
|
146
|
+
node.parent.context == :document ? block.document : node
|
|
155
147
|
end
|
|
156
148
|
|
|
157
149
|
# Safe accessor: use the asciidoctor-pdf constant if available, else fall back.
|