asciidoctor-html 0.1.5 → 0.1.7

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.
Binary file
Binary file
Binary file
Binary file
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "asciidoctor"
4
- require "pathname"
5
4
 
6
5
  module Asciidoctor
7
6
  module Html
@@ -8,7 +8,9 @@ require_relative "converter"
8
8
  require_relative "ref_tree_processor"
9
9
  require_relative "cref_inline_macro"
10
10
  require_relative "bi_inline_macro"
11
+ require_relative "sc_inline_macro"
11
12
  require_relative "template"
13
+ require_relative "pagination"
12
14
 
13
15
  module Asciidoctor
14
16
  module Html
@@ -21,6 +23,7 @@ module Asciidoctor
21
23
  Asciidoctor::Extensions.register do
22
24
  tree_processor RefTreeProcessor
23
25
  inline_macro CrefInlineMacro
26
+ inline_macro ScInlineMacro
24
27
  inline_macro BiInlineMacro
25
28
  end
26
29
 
@@ -29,7 +32,9 @@ module Asciidoctor
29
32
  "stem" => "latexmath",
30
33
  "hide-uri-scheme" => true,
31
34
  "source-highlighter" => "highlight.js",
32
- "imagesdir" => IMG_PATH
35
+ "imagesdir" => IMG_PATH,
36
+ "dollar" => "$",
37
+ "parskip" => %(<span class="parskip"></span><br>)
33
38
  }.freeze
34
39
 
35
40
  DEFAULT_OPTS = {
@@ -39,7 +44,12 @@ module Asciidoctor
39
44
  }.freeze
40
45
 
41
46
  # Template data to be processed by each document
42
- TData = Struct.new("TData", :chapnum, :chaptitle)
47
+ TData = Struct.new("TData",
48
+ :chapprefix,
49
+ :chaptitle,
50
+ :chapheading,
51
+ :chapsubheading,
52
+ :index)
43
53
 
44
54
  # opts:
45
55
  # - title
@@ -55,6 +65,7 @@ module Asciidoctor
55
65
  @author = ERB::Escape.html_escape opts[:author]
56
66
  @date = opts.include?(:date) ? Date.parse(opts[:date]) : Date.today
57
67
  @se_id = opts[:se_id]
68
+ @base_url = opts[:base_url]
58
69
  @chapname = opts[:chapname]
59
70
  @refs = {} # Hash(docname => Hash(id => reftext))
60
71
  @templates = {} # Hash(docname => TData)
@@ -81,15 +92,22 @@ module Asciidoctor
81
92
  # - chapters: array of filenames
82
93
  # - appendices: array of filenames
83
94
  # - outdir: directory to write the converted html files to
84
- def write(chapters, appendices, outdir)
95
+ def write(chapters, appendices, outdir, sitemap: false)
96
+ needs_sitemap = sitemap && @base_url
97
+ entries = [] # for sitemap
85
98
  read(chapters, appendices).each do |name, html|
86
- File.write("#{outdir}/#{name}.html", html)
99
+ filename = "#{name}.html"
100
+ File.write("#{outdir}/#{filename}", html)
101
+ entries << Template.sitemap_entry("#{@base_url}#{filename}") if needs_sitemap
87
102
  end
88
103
  File.write("#{outdir}/#{SEARCH_PAGE}", search_page(@se_id)) if @se_id
104
+ File.write("#{outdir}/sitemap.xml", Template.sitemap(entries)) if needs_sitemap
89
105
  end
90
106
 
91
107
  private
92
108
 
109
+ include Pagination
110
+
93
111
  def search_page(se_id)
94
112
  content = <<~HTML
95
113
  <script async src="https://cse.google.com/cse.js?cx=#{se_id}"></script>
@@ -102,7 +120,6 @@ module Asciidoctor
102
120
  short_title: @short_title,
103
121
  author: @author,
104
122
  date: @date,
105
- chapnum: "",
106
123
  chaptitle: "Search",
107
124
  langs: []
108
125
  )
@@ -122,50 +139,59 @@ module Asciidoctor
122
139
  end
123
140
 
124
141
  def chapter(filename, idx)
125
- numeral = idx.to_s
126
- doc = parse_file filename, @chapname, numeral
127
- chaptitle = doctitle doc
128
- chapref = idx.zero? ? chaptitle : chapref_default(@chapname, numeral)
129
- chapnum = idx.zero? ? "" : numeral
130
- process_doc key(filename), doc, chapnum:, chaptitle:, chapref:
142
+ key = key filename
143
+ index = @templates.dig(key, :index) || idx
144
+ chapnum = index.to_s
145
+ doc = parse_file filename, @chapname, chapnum
146
+ chapsubheading = doctitle doc
147
+ chapref = index.zero? ? chapsubheading : chapref_default(@chapname, chapnum)
148
+ tdata = TData.new(
149
+ chapprefix: index.zero? ? "" : chapnum,
150
+ chaptitle: chapsubheading,
151
+ chapheading: (chapref unless index.zero?),
152
+ chapsubheading:,
153
+ index:
154
+ )
155
+ process_doc key, doc, tdata, chapref
131
156
  end
132
157
 
133
158
  def appendix(filename, idx, num_appendices)
159
+ key = key filename
160
+ index = @templates.dig(key, :index) || idx
134
161
  chapname = "Appendix"
135
- numeral = ("a".."z").to_a[idx].upcase
136
- doc = parse_file filename, chapname, numeral
137
- chapref = num_appendices == 1 ? chapname : chapref_default(chapname, numeral)
138
- chapnum = ""
139
- chaptitle = Template.appendix_title chapname, numeral, doctitle(doc), num_appendices
140
- process_doc key(filename), doc, chapnum:, chaptitle:, chapref:
162
+ chapnum = ("a".."z").to_a[index].upcase
163
+ doc = parse_file filename, chapname, chapnum
164
+ chapsubheading = doctitle doc
165
+ chapref = num_appendices == 1 ? chapname : chapref_default(chapname, chapnum)
166
+ tdata = TData.new(
167
+ chapprefix: "",
168
+ chaptitle: Template.appendix_title(chapname, chapnum, chapsubheading, num_appendices),
169
+ chapheading: chapref,
170
+ chapsubheading:,
171
+ index:
172
+ )
173
+ process_doc key, doc, tdata, chapref
141
174
  end
142
175
 
143
176
  def key(filename)
144
177
  Pathname(filename).basename.sub_ext("").to_s
145
178
  end
146
179
 
147
- # opts:
148
- # - chapnum
149
- # - chaptitle
150
- # - chapref
151
- def process_doc(key, doc, opts)
180
+ def process_doc(key, doc, tdata, chapref)
152
181
  val = doc.catalog[:refs].transform_values(&method(:reftext)).compact
153
- val["chapref"] = opts[:chapref]
182
+ val["chapref"] = chapref
154
183
  @refs[key] = val
155
- @templates[key] = TData.new(
156
- chapnum: opts[:chapnum],
157
- chaptitle: opts[:chaptitle]
158
- )
184
+ @templates[key] = tdata
159
185
  doc
160
186
  end
161
187
 
162
- def parse_file(filename, chapname, numeral)
163
- attributes = { "chapnum" => numeral, "chapname" => chapname }.merge DOCATTRS
188
+ def parse_file(filename, chapname, chapnum)
189
+ attributes = { "chapnum" => chapnum, "chapname" => chapname }.merge DOCATTRS
164
190
  Asciidoctor.load_file filename, safe: :unsafe, attributes:
165
191
  end
166
192
 
167
- def chapref_default(chapname, numeral)
168
- "#{ERB::Escape.html_escape chapname} #{numeral}"
193
+ def chapref_default(chapname, chapnum)
194
+ "#{ERB::Escape.html_escape chapname} #{chapnum}"
169
195
  end
170
196
 
171
197
  def reftext(node)
@@ -194,7 +220,7 @@ module Asciidoctor
194
220
  items = @templates.map do |k, td|
195
221
  active = (k == active_key)
196
222
  subnav = active && doc ? outline(doc) : ""
197
- navtext = Template.nav_text td.chapnum, td.chaptitle
223
+ navtext = Template.nav_text td.chapprefix, td.chaptitle
198
224
  Template.nav_item "#{k}.html", navtext, subnav, active:
199
225
  end
200
226
  return items unless @se_id
@@ -209,7 +235,7 @@ module Asciidoctor
209
235
  def build_template(key, doc)
210
236
  tdata = @templates[key]
211
237
  nav_items = nav_items key, doc
212
- content = ERB.new(doc.convert).result(binding)
238
+ content = "#{ERB.new(doc.convert).result(binding)}\n#{pagination key}"
213
239
  Template.html(
214
240
  content,
215
241
  nav_items,
@@ -217,10 +243,11 @@ module Asciidoctor
217
243
  short_title: @short_title,
218
244
  author: @author,
219
245
  date: @date,
220
- chapnum: tdata.chapnum,
246
+ description: doc.attr("description"),
221
247
  chaptitle: tdata.chaptitle,
222
- langs: langs(doc),
223
- nav: (nav_items.size > 1)
248
+ chapheading: tdata.chapheading,
249
+ chapsubheading: tdata.chapsubheading,
250
+ langs: langs(doc)
224
251
  )
225
252
  end
226
253
  end
@@ -37,7 +37,8 @@ module Asciidoctor
37
37
  begin
38
38
  config = Psych.safe_load_file config_file
39
39
  rescue StandardError
40
- puts "Error opening configuration file #{config_file}"
40
+ puts "Error opening configuration file\n #{config_file}"
41
+ puts
41
42
  exit 1
42
43
  end
43
44
  config_dir = Pathname(config_file).dirname
@@ -53,28 +54,38 @@ module Asciidoctor
53
54
  config
54
55
  end
55
56
 
56
- def self.setup_outdir(outdir)
57
- assets_dir = "#{outdir}/#{ASSETS_PATH}"
58
- FileUtils.mkdir_p assets_dir unless File.directory?(assets_dir)
57
+ def self.setup_outdir(srcdir, outdir)
58
+ assets_out = "#{outdir}/#{ASSETS_PATH}"
59
+ FileUtils.mkdir_p assets_out unless File.directory?(assets_out)
60
+ %W[#{IMG_PATH} #{CSS_PATH} #{FAVICON_PATH}].each do |p|
61
+ dir = "#{srcdir}/#{p}"
62
+ next unless Dir.exist?(dir)
63
+
64
+ puts "Copying\n #{dir}\nto\n #{assets_out}"
65
+ puts
66
+ FileUtils.cp_r dir, assets_out
67
+ end
59
68
  rootdir = File.absolute_path "#{__dir__}/../../.."
60
69
  %W[#{CSS_PATH} #{FAVICON_PATH}].each do |p|
61
70
  dir = "#{outdir}/#{p}"
62
71
  next if Dir.exist?(dir)
63
72
 
64
- puts "Generating #{dir}"
65
- FileUtils.cp_r "#{rootdir}/#{p}", assets_dir
73
+ puts "Putting default '#{p}' files in\n #{dir}"
74
+ puts
75
+ FileUtils.cp_r "#{rootdir}/#{p}", assets_out
66
76
  end
67
77
  end
68
78
 
69
79
  def self.generate_webmanifest(outdir, name, short_name)
70
80
  filename = "#{outdir}/#{FAVICON_PATH}/site.webmanifest"
71
- puts "Generating #{filename}"
81
+ puts "Generating\n #{filename}"
82
+ puts
72
83
  File.write filename, Webmanifest.generate(name, short_name)
73
84
  end
74
85
 
75
86
  def self.generate_bookopts(config)
76
87
  book_opts = {}
77
- %i[title short_title author date se_id chapname].each do |opt|
88
+ %i[title short_title author date se_id base_url chapname].each do |opt|
78
89
  key = opt.to_s
79
90
  book_opts[opt] = config[key] if config.include?(key)
80
91
  end
@@ -86,25 +97,29 @@ module Asciidoctor
86
97
  opts ||= parse_opts
87
98
  config = read_config opts[:"config-file"]
88
99
  outdir = config["outdir"]
100
+ srcdir = config["srcdir"]
89
101
  book_opts = generate_bookopts config
90
- setup_outdir outdir
102
+ setup_outdir srcdir, outdir
91
103
  generate_webmanifest outdir, book_opts[:title], book_opts[:short_title]
92
104
  book = Book.new book_opts
93
- puts "Writing book to #{outdir}"
94
- book.write config["chapters"], config["appendices"], config["outdir"]
105
+ puts "Writing book to\n #{outdir}"
106
+ puts
107
+ book.write config["chapters"], config["appendices"], outdir, sitemap: true
95
108
  return unless opts[:watch]
96
109
 
97
- Filewatcher.new("#{config["srcdir"]}/*.adoc").watch do |changes|
110
+ Filewatcher.new("#{srcdir}/*.adoc").watch do |changes|
98
111
  chapters = []
99
112
  appendices = []
100
113
  changes.each_key do |filename|
101
- puts "Detected change in #{filename}"
114
+ puts "Detected change in\n #{filename}"
115
+ puts
102
116
  chapters.append(filename) if config["chapters"].include?(filename)
103
117
  appendices.append(filename) if config["appendices"].include?(filename)
104
118
  end
105
119
  puts "Regenerating book:"
106
- puts " Chapters: #{chapters.map { |c| Pathname(c).basename }.join ", "}" unless chapters.empty?
107
- puts " Appendices: #{appendices.map { |a| Pathname(a).basename }.join ", "}" unless appendices.empty?
120
+ puts " Chapters: #{chapters.map { |c| Pathname(c).basename }.join ", "}" unless chapters.empty?
121
+ puts " Appendices: #{appendices.map { |a| Pathname(a).basename }.join ", "}" unless appendices.empty?
122
+ puts
108
123
  book.write chapters, appendices, config["outdir"]
109
124
  end
110
125
  end
@@ -4,6 +4,7 @@ require "asciidoctor"
4
4
  require_relative "list"
5
5
  require_relative "utils"
6
6
  require_relative "figure"
7
+ require_relative "table"
7
8
 
8
9
  module Asciidoctor
9
10
  module Html
@@ -33,7 +34,8 @@ module Asciidoctor
33
34
  document = node.document
34
35
  level = node.level
35
36
  show_sectnum = node.numbered && level <= (document.attr("sectnumlevels") || 1).to_i
36
- tag_name = %(h#{[level + 2, 6].min})
37
+ tag_level = [level == 1 ? level + 1 : level + 2, 6].min
38
+ tag_name = %(h#{tag_level})
37
39
  sectnum = show_sectnum ? %(<span class="title-mark">#{node.sectnum ""}</span>) : ""
38
40
  content = %(<#{tag_name}>#{sectnum}#{node.title}</#{tag_name}>\n#{node.content})
39
41
  Utils.wrap_node content, node, :section
@@ -66,7 +68,8 @@ module Asciidoctor
66
68
  else "exclamation-lg"
67
69
  end
68
70
  icon = %(<div class="icon"><i class="bi bi-#{icon_class}"></i></div>)
69
- content = %(#{icon}\n#{Utils.display_title node, needs_prefix: false}#{node.content})
71
+ content = node.blocks? ? node.content : "<p>#{node.content}</p>"
72
+ content = %(#{icon}\n#{Utils.display_title node}#{content})
70
73
  Utils.wrap_id_classes content, node.id, "admonition admonition-#{name}"
71
74
  end
72
75
 
@@ -81,7 +84,7 @@ module Asciidoctor
81
84
  open, close = BLOCK_MATH_DELIMITERS[node.style.to_sym]
82
85
  equation = node.content || ""
83
86
  equation = "#{open}#{equation}#{close}" unless (equation.start_with? open) && (equation.end_with? close)
84
- classes = ["stem"]
87
+ classes = ["stem", node.role].compact
85
88
  if node.option? "numbered"
86
89
  equation = %(<div class="equation">\n#{equation}\n</div> <!-- .equation -->)
87
90
  equation = %(#{equation}\n<div class="equation-number">#{node.reftext}</div>)
@@ -123,25 +126,31 @@ module Asciidoctor
123
126
  pre_open = %(<pre#{%( class="nowrap") if nowrap}>)
124
127
  pre_close = "</pre>"
125
128
  end
126
- needs_prefix = node.option? "numbered"
127
- title = Utils.display_title(node, needs_prefix:)
129
+ title = Utils.display_title(node)
128
130
  content = title + pre_open + node.content + pre_close
129
131
  Utils.wrap_node content, node
130
132
  end
131
133
 
134
+ def convert_literal(node)
135
+ nowrap = !(node.document.attr? "prewrap") || (node.option? "nowrap")
136
+ pre = %(<pre#{%( class="nowrap") if nowrap}>#{node.content}</pre>)
137
+ title = Utils.display_title(node)
138
+ Utils.wrap_node "#{title}#{pre}", node
139
+ end
140
+
132
141
  def convert_open(node)
133
142
  collapsible = node.option? "collapsible"
134
143
  title = if collapsible
135
144
  %(<summary>#{node.title || "Details"}</summary>\n)
136
145
  else
137
- Utils.display_title(node, needs_prefix: false)
146
+ Utils.display_title(node)
138
147
  end
139
148
  tag_name = collapsible ? :details : :div
140
149
  Utils.wrap_node(title + node.content, node, tag_name)
141
150
  end
142
151
 
143
152
  def convert_example(node)
144
- Utils.wrap_node_with_title node.content, node, needs_prefix: true
153
+ Utils.wrap_node_with_title node.content, node
145
154
  end
146
155
 
147
156
  def convert_image(node)
@@ -151,6 +160,8 @@ module Asciidoctor
151
160
 
152
161
  def convert_inline_image(node)
153
162
  target = node.target
163
+ return read_svg_contents(node, target) if node.option?("inline")
164
+
154
165
  mark = node.parent.attr "mark"
155
166
  title_attr = node.attr? "title"
156
167
  if mark # The image is part of a figlist
@@ -169,7 +180,6 @@ module Asciidoctor
169
180
  end
170
181
 
171
182
  def convert_colist(node)
172
- node.style = "arabic-circled"
173
183
  List.convert node
174
184
  end
175
185
 
@@ -196,18 +206,59 @@ module Asciidoctor
196
206
  end
197
207
 
198
208
  def convert_inline_anchor(node)
199
- if node.type == :xref && !node.text
209
+ node_text = node.text
210
+ if node.type == :xref
200
211
  target = node.document.catalog[:refs][node.attr("refid")]
201
- if target&.inline?
202
- text = target.text
203
- return %(<a href="#{node.target}">#{text}</a>) if text&.match?(/\A<i class="bi/)
212
+ if target&.inline? && target.parent&.parent&.style == "bibliography"
213
+ reftext = target.reftext
214
+ if node_text
215
+ /\A\[(?<numeral>\d+)\]\z/ =~ reftext
216
+ reftext = if numeral
217
+ "[#{numeral}, #{node_text}]"
218
+ else
219
+ "#{reftext}, #{node_text}"
220
+ end
221
+ end
222
+ return Utils.popover_button(reftext, target.id, "bibref")
223
+ end
204
224
 
205
- list_style = target.parent&.parent&.style
206
- return Utils.popover_button(target.reftext, target.id, "bibref") if list_style == "bibliography"
225
+ if !node_text && (text = target&.inline? ? target&.text : target&.attr("reftext"))
226
+ subs = %i[specialcharacters quotes replacements macros]
227
+ return %(<a href="#{node.target}">#{node.apply_subs text, subs}</a>)
207
228
  end
208
229
  end
209
230
  super
210
231
  end
232
+
233
+ def convert_table(node)
234
+ classes = ["table", node.role].compact
235
+ classes << "table-striped" if node.option? "striped"
236
+ classes << "table-bordered" if node.option? "bordered"
237
+ classes << "table-sm" if node.option? "compact"
238
+ classes << "table-v#{node.attr "valign"}" if node.attr?("valign")
239
+ classes << "table-h#{node.attr "halign"}" if node.attr?("halign")
240
+ width_attribute = ""
241
+ if (autowidth = node.option? "autowidth") && !(node.attr? "width")
242
+ classes << "table-fit"
243
+ elsif (tablewidth = node.attr "width")
244
+ width_attribute = %( width="#{tablewidth}%")
245
+ end
246
+ result = [%(<table#{Utils.id_class_attr_str node.id, classes.join(" ")}#{width_attribute}>)]
247
+ result << %(<caption class="table-title">#{Utils.display_title_prefix node}#{node.title}</caption>)
248
+ if node.attr("rowcount").positive? && node.attr?("cols")
249
+ result << "<colgroup>"
250
+ if autowidth
251
+ result += (Array.new node.columns.size, %(<col>))
252
+ else
253
+ node.columns.each do |col|
254
+ result << (col.option?("autowidth") ? %(<col>) : %(<col style="width:#{col.attr "colpcwidth"}%;">))
255
+ end
256
+ end
257
+ result << "</colgroup>"
258
+ end
259
+ result << "#{Table.display_rows(node)}</table>"
260
+ Utils.wrap_id_classes result.join("\n"), nil, "table-responsive"
261
+ end
211
262
  end
212
263
  end
213
264
  end
@@ -6,6 +6,8 @@ module Asciidoctor
6
6
  # Mixed into the Converter class.
7
7
  module Figure
8
8
  def display_image(node, target, title_attr: false)
9
+ return read_svg_contents(node, target) if node.option?("inline")
10
+
9
11
  attrs = image_attrs(node, title_attr:)
10
12
  %(<img src="#{node.image_uri target}" #{attrs}#{@void_element_slash}>)
11
13
  end
@@ -29,9 +31,9 @@ module Asciidoctor
29
31
 
30
32
  def convert_figlist(node)
31
33
  result = node.items.map do |item|
32
- %(<li#{Utils.id_class_attr_str item.id}><figure>\n#{item.text}\n</figure></li>)
34
+ %(<li#{Utils.id_class_attr_str item.id, item.role}><figure>\n#{item.text}\n</figure></li>)
33
35
  end
34
- content = Utils.wrap_id_classes result.join("\n"), nil, "figlist loweralpha", :ol
36
+ content = Utils.wrap_id_classes result.join("\n"), nil, "figlist", :ol
35
37
  title = %(<div class="figlist-title">#{Utils.display_title_prefix(node)}#{node.title}</div>)
36
38
  classes = ["figlist-wrapper", node.role].compact.join(" ")
37
39
  Utils.wrap_id_classes %(#{content}#{title}), node.id, classes
@@ -46,53 +46,60 @@ module Asciidoctor
46
46
  }.freeze
47
47
 
48
48
  PLUGIN = <<~JS
49
- function toggleCopyIcon(copyIcon) {
50
- copyIcon.classList.toggle("bi-clipboard");
51
- copyIcon.classList.toggle("bi-clipboard-check");
52
- }
53
- hljs.addPlugin({
54
- "after:highlightElement": function({ el, result, text }) {
55
- const wrapper = el.parentElement; // pre element
56
- if(wrapper == null) { return; }
49
+ (function() {
50
+ function canHover() {
51
+ return matchMedia('(hover: hover)').matches &&
52
+ matchMedia('(pointer: fine)').matches;
53
+ }
54
+ function toggleCopyIcon(copyIcon) {
55
+ copyIcon.classList.toggle('bi-clipboard');
56
+ copyIcon.classList.toggle('bi-clipboard-check');
57
+ }
58
+ hljs.addPlugin({
59
+ 'after:highlightElement': function({ el, result, text }) {
60
+ let cbText = text
61
+ const wrapper = el.parentElement; // pre element
62
+ if(wrapper == null) { return; }
57
63
 
58
- const overlay = document.createElement("div");
59
- overlay.classList.add("copy-button");
60
- overlay.textContent = result.language.toUpperCase() + ' ';
64
+ const overlay = document.createElement('div');
65
+ overlay.classList.add('copy-button');
66
+ overlay.textContent = result.language.toUpperCase() + ' ';
61
67
 
62
- const copyButton = document.createElement("button");
63
- copyButton.classList.add("btn");
64
- copyButton.setAttribute("type", "button");
65
- copyButton.setAttribute("data-bs-toggle", "tooltip");
66
- copyButton.setAttribute("data-bs-title", "Copy to clipboard");
67
- if(!touch) {bootstrap.Tooltip.getOrCreateInstance(copyButton);}
68
+ const copyButton = document.createElement('button');
69
+ copyButton.classList.add('btn');
70
+ copyButton.setAttribute('type', 'button');
71
+ copyButton.setAttribute('data-bs-toggle', 'tooltip');
72
+ copyButton.setAttribute('data-bs-title', 'Copy to clipboard');
73
+ if(canHover()) bootstrap.Tooltip.getOrCreateInstance(copyButton);
68
74
 
69
- const copyIcon = document.createElement("i");
70
- copyIcon.classList.add("bi", "bi-clipboard");
75
+ const copyIcon = document.createElement('i');
76
+ copyIcon.classList.add('bi', 'bi-clipboard');
71
77
 
72
- copyButton.append(copyIcon);
73
- overlay.append(copyButton);
78
+ copyButton.append(copyIcon);
79
+ overlay.append(copyButton);
74
80
 
75
- copyButton.onclick = function() {
76
- navigator.clipboard.writeText(text);
77
- if(!copyIcon.classList.contains("bi-clipboard-check")) {
78
- toggleCopyIcon(copyIcon);
79
- setTimeout(() => { toggleCopyIcon(copyIcon); }, 1500);
80
- }
81
- };
81
+ copyButton.addEventListener('click', function() {
82
+ navigator.clipboard.writeText(cbText);
83
+ if(!copyIcon.classList.contains('bi-clipboard-check')) {
84
+ toggleCopyIcon(copyIcon);
85
+ setTimeout(() => { toggleCopyIcon(copyIcon); }, 1500);
86
+ }
87
+ });
82
88
 
83
- // Append the copy button to the wrapper
84
- wrapper.appendChild(overlay);
89
+ // Append the copy button to the wrapper
90
+ wrapper.appendChild(overlay);
85
91
 
86
- // Find and replace inline callouts
87
- const rgx = /[\u2460-\u2468]/gu;
88
- if(text.match(rgx)) {
89
- text = text.replaceAll(rgx, "");
90
- el.innerHTML = el.innerHTML.replaceAll(rgx, (match) => {
91
- return '<i class="bi bi-' + (match.charCodeAt() - 9311) + '-circle"></i>';
92
- });
92
+ // Find and replace inline callouts
93
+ const rgx = /[\u2460-\u2468]/gu;
94
+ if(text.match(rgx)) {
95
+ cbText = text.replaceAll(rgx, '');
96
+ el.innerHTML = el.innerHTML.replaceAll(rgx, (match) => {
97
+ return '<i class="hljs-comment bi bi-' + (match.charCodeAt() - 9311) + '-circle"></i>';
98
+ });
99
+ }
93
100
  }
94
- }
95
- });
101
+ });
102
+ })();
96
103
  JS
97
104
  end
98
105
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Asciidoctor
4
4
  module Html
5
- # Helper functions for the list conversion.
5
+ # Helper functions for the list conversion
6
6
  module List
7
7
  def self.convert(node, tag_name = :ol)
8
8
  depth = node.attr "list-depth"
@@ -11,8 +11,7 @@ module Asciidoctor
11
11
  classes = [
12
12
  "list",
13
13
  "list-#{node.context}",
14
- "level-#{level}",
15
- flat ? "pseudocode" : node.style,
14
+ ("level-#{level} pseudocode" if flat),
16
15
  node.role
17
16
  ].compact
18
17
  classes << "checklist" if node.option?("checklist")
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor
4
+ module Html
5
+ # Mixin to add pagination support to Book class
6
+ module Pagination
7
+ # Pagination item
8
+ PagItem = Struct.new("PagItem", :url, :title)
9
+
10
+ def display_paginator(prv, nxt)
11
+ <<~HTML
12
+ <div class="paginator-wrapper">
13
+ <div class="d-inline-block">
14
+ <div class="paginator">
15
+ #{%(<a href="#{prv.url}">&laquo; #{prv.title}</a>) if prv}
16
+ #{%(<span class="blank">&nbsp;</span>) unless prv && nxt}
17
+ #{%(<a href="#{nxt.url}">#{nxt.title} &raquo;</a>) if nxt}
18
+ </div>
19
+ </div>
20
+ </div>
21
+ HTML
22
+ end
23
+
24
+ def prv_nxt(keys, idx)
25
+ pagitems = []
26
+ [idx - 1, idx + 1].each do |i|
27
+ if i.between?(0, keys.size - 1)
28
+ key = keys[i]
29
+ ref = @refs[key]
30
+ pagitems << PagItem.new(
31
+ url: "#{key}.html",
32
+ title: ref["chapref"]
33
+ )
34
+ else
35
+ pagitems << nil
36
+ end
37
+ end
38
+ display_paginator(*pagitems)
39
+ end
40
+
41
+ def pagination(key = -1)
42
+ keys = @refs.keys
43
+ idx = keys.find_index key
44
+ return "" unless idx
45
+
46
+ prv_nxt keys, idx
47
+ end
48
+ end
49
+ end
50
+ end