asciidoctor-html 0.1.5 → 0.1.6
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 +4 -4
- data/.rubocop.yml +2 -2
- data/CHANGELOG.md +8 -0
- data/assets/css/styles.css +2 -2
- data/assets/css/styles.css.map +1 -1
- data/assets/favicon/android-chrome-192x192.png +0 -0
- data/assets/favicon/android-chrome-512x512.png +0 -0
- data/assets/favicon/apple-touch-icon.png +0 -0
- data/assets/favicon/favicon-16x16.png +0 -0
- data/assets/favicon/favicon-32x32.png +0 -0
- data/assets/favicon/favicon.ico +0 -0
- data/lib/asciidoctor/html/book.rb +10 -4
- data/lib/asciidoctor/html/cli.rb +2 -2
- data/lib/asciidoctor/html/converter.rb +40 -2
- data/lib/asciidoctor/html/figure.rb +2 -2
- data/lib/asciidoctor/html/highlightjs.rb +1 -1
- data/lib/asciidoctor/html/ref_tree_processor.rb +24 -3
- data/lib/asciidoctor/html/table.rb +37 -0
- data/lib/asciidoctor/html/template.rb +36 -8
- data/lib/asciidoctor/html/utils.rb +2 -6
- metadata +2 -1
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/assets/favicon/favicon.ico
CHANGED
Binary file
|
@@ -55,6 +55,7 @@ module Asciidoctor
|
|
55
55
|
@author = ERB::Escape.html_escape opts[:author]
|
56
56
|
@date = opts.include?(:date) ? Date.parse(opts[:date]) : Date.today
|
57
57
|
@se_id = opts[:se_id]
|
58
|
+
@base_url = opts[:base_url]
|
58
59
|
@chapname = opts[:chapname]
|
59
60
|
@refs = {} # Hash(docname => Hash(id => reftext))
|
60
61
|
@templates = {} # Hash(docname => TData)
|
@@ -81,11 +82,16 @@ module Asciidoctor
|
|
81
82
|
# - chapters: array of filenames
|
82
83
|
# - appendices: array of filenames
|
83
84
|
# - outdir: directory to write the converted html files to
|
84
|
-
def write(chapters, appendices, outdir)
|
85
|
+
def write(chapters, appendices, outdir, sitemap: false)
|
86
|
+
needs_sitemap = sitemap && @base_url
|
87
|
+
entries = [] # for sitemap
|
85
88
|
read(chapters, appendices).each do |name, html|
|
86
|
-
|
89
|
+
filename = "#{name}.html"
|
90
|
+
File.write("#{outdir}/#{filename}", html)
|
91
|
+
entries << Template.sitemap_entry("#{@base_url}#{filename}") if needs_sitemap
|
87
92
|
end
|
88
93
|
File.write("#{outdir}/#{SEARCH_PAGE}", search_page(@se_id)) if @se_id
|
94
|
+
File.write("#{outdir}/sitemap.xml", Template.sitemap(entries)) if needs_sitemap
|
89
95
|
end
|
90
96
|
|
91
97
|
private
|
@@ -217,10 +223,10 @@ module Asciidoctor
|
|
217
223
|
short_title: @short_title,
|
218
224
|
author: @author,
|
219
225
|
date: @date,
|
226
|
+
description: doc.attr("description"),
|
220
227
|
chapnum: tdata.chapnum,
|
221
228
|
chaptitle: tdata.chaptitle,
|
222
|
-
langs: langs(doc)
|
223
|
-
nav: (nav_items.size > 1)
|
229
|
+
langs: langs(doc)
|
224
230
|
)
|
225
231
|
end
|
226
232
|
end
|
data/lib/asciidoctor/html/cli.rb
CHANGED
@@ -74,7 +74,7 @@ module Asciidoctor
|
|
74
74
|
|
75
75
|
def self.generate_bookopts(config)
|
76
76
|
book_opts = {}
|
77
|
-
%i[title short_title author date se_id chapname].each do |opt|
|
77
|
+
%i[title short_title author date se_id base_url chapname].each do |opt|
|
78
78
|
key = opt.to_s
|
79
79
|
book_opts[opt] = config[key] if config.include?(key)
|
80
80
|
end
|
@@ -91,7 +91,7 @@ module Asciidoctor
|
|
91
91
|
generate_webmanifest outdir, book_opts[:title], book_opts[:short_title]
|
92
92
|
book = Book.new book_opts
|
93
93
|
puts "Writing book to #{outdir}"
|
94
|
-
book.write config["chapters"], config["appendices"], config["outdir"]
|
94
|
+
book.write config["chapters"], config["appendices"], config["outdir"], sitemap: true
|
95
95
|
return unless opts[:watch]
|
96
96
|
|
97
97
|
Filewatcher.new("#{config["srcdir"]}/*.adoc").watch do |changes|
|
@@ -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
|
-
|
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 =
|
71
|
+
content = node.blocks? ? node.content : "<p>#{node.content}</p>"
|
72
|
+
content = %(#{icon}\n#{Utils.display_title node, needs_prefix: false}#{content})
|
70
73
|
Utils.wrap_id_classes content, node.id, "admonition admonition-#{name}"
|
71
74
|
end
|
72
75
|
|
@@ -129,6 +132,13 @@ module Asciidoctor
|
|
129
132
|
Utils.wrap_node content, node
|
130
133
|
end
|
131
134
|
|
135
|
+
def convert_literal(node)
|
136
|
+
nowrap = !(node.document.attr? "prewrap") || (node.option? "nowrap")
|
137
|
+
pre = %(<pre#{%( class="nowrap") if nowrap}>#{node.content}</pre>)
|
138
|
+
title = Utils.display_title(node, needs_prefix: false)
|
139
|
+
Utils.wrap_node "#{title}#{pre}", node
|
140
|
+
end
|
141
|
+
|
132
142
|
def convert_open(node)
|
133
143
|
collapsible = node.option? "collapsible"
|
134
144
|
title = if collapsible
|
@@ -208,6 +218,34 @@ module Asciidoctor
|
|
208
218
|
end
|
209
219
|
super
|
210
220
|
end
|
221
|
+
|
222
|
+
def convert_table(node)
|
223
|
+
classes = ["table", node.role].compact
|
224
|
+
classes << "table-striped" if node.option? "striped"
|
225
|
+
classes << "table-bordered" if node.option? "bordered"
|
226
|
+
classes << "table-sm" if node.option? "compact"
|
227
|
+
width_attribute = ""
|
228
|
+
if (autowidth = node.option? "autowidth") && !(node.attr? "width")
|
229
|
+
classes << "table-fit"
|
230
|
+
elsif (tablewidth = node.attr "width")
|
231
|
+
width_attribute = %( width="#{tablewidth}%")
|
232
|
+
end
|
233
|
+
result = [%(<table#{Utils.id_class_attr_str node.id, classes.join(" ")}#{width_attribute}>)]
|
234
|
+
result << %(<caption class="table-title">#{Utils.display_title_prefix node}#{node.title}</caption>)
|
235
|
+
if node.attr("rowcount").positive?
|
236
|
+
result << "<colgroup>"
|
237
|
+
if autowidth
|
238
|
+
result += (Array.new node.columns.size, %(<col>))
|
239
|
+
else
|
240
|
+
node.columns.each do |col|
|
241
|
+
result << (col.option?("autowidth") ? %(<col>) : %(<col style="width:#{col.attr "colpcwidth"}%;">))
|
242
|
+
end
|
243
|
+
end
|
244
|
+
result << "</colgroup>"
|
245
|
+
end
|
246
|
+
result << "#{Table.display_rows(node)}</table>"
|
247
|
+
Utils.wrap_id_classes result.join("\n"), nil, "table-responsive"
|
248
|
+
end
|
211
249
|
end
|
212
250
|
end
|
213
251
|
end
|
@@ -29,9 +29,9 @@ module Asciidoctor
|
|
29
29
|
|
30
30
|
def convert_figlist(node)
|
31
31
|
result = node.items.map do |item|
|
32
|
-
%(<li#{Utils.id_class_attr_str item.id}><figure>\n#{item.text}\n</figure></li>)
|
32
|
+
%(<li#{Utils.id_class_attr_str item.id, item.role}><figure>\n#{item.text}\n</figure></li>)
|
33
33
|
end
|
34
|
-
content = Utils.wrap_id_classes result.join("\n"), nil, "figlist
|
34
|
+
content = Utils.wrap_id_classes result.join("\n"), nil, "figlist", :ol
|
35
35
|
title = %(<div class="figlist-title">#{Utils.display_title_prefix(node)}#{node.title}</div>)
|
36
36
|
classes = ["figlist-wrapper", node.role].compact.join(" ")
|
37
37
|
Utils.wrap_id_classes %(#{content}#{title}), node.id, classes
|
@@ -88,7 +88,7 @@ module Asciidoctor
|
|
88
88
|
if(text.match(rgx)) {
|
89
89
|
text = text.replaceAll(rgx, "");
|
90
90
|
el.innerHTML = el.innerHTML.replaceAll(rgx, (match) => {
|
91
|
-
return '<i class="bi bi-' + (match.charCodeAt() - 9311) + '-circle"></i>';
|
91
|
+
return '<i class="hljs-comment bi bi-' + (match.charCodeAt() - 9311) + '-circle"></i>';
|
92
92
|
});
|
93
93
|
}
|
94
94
|
}
|
@@ -91,15 +91,33 @@ module Asciidoctor
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def ref_li_mark(mark, depth, style = nil)
|
94
|
-
return
|
94
|
+
return mark.to_s unless style
|
95
95
|
|
96
|
-
|
96
|
+
case li_style depth, style
|
97
|
+
when "mark-square-brackets" then "[#{mark}]"
|
98
|
+
when "mark-round-brackets" then "(#{mark})"
|
99
|
+
else mark.to_s
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def li_style(depth, list_style)
|
104
|
+
return "mark-square-brackets" if list_style == "bibliography"
|
105
|
+
return "mark-round-brackets" if list_style == "figlist"
|
106
|
+
|
107
|
+
case depth
|
108
|
+
when 1, 3 then "mark-round-brackets"
|
109
|
+
else "mark-dot"
|
110
|
+
end
|
97
111
|
end
|
98
112
|
|
99
113
|
def offset(list)
|
100
114
|
list.attr?("start") ? (list.attr("start").to_i - 1) : 0
|
101
115
|
end
|
102
116
|
|
117
|
+
def shift(list)
|
118
|
+
list.attr?("shift") ? list.attr("shift").to_i : 0
|
119
|
+
end
|
120
|
+
|
103
121
|
# Finds an anchor at the start of item.text and updates
|
104
122
|
# its reftext to that of item's if necessary.
|
105
123
|
def register_reftext!(item, reftext)
|
@@ -121,11 +139,14 @@ module Asciidoctor
|
|
121
139
|
block.set_attr("flat-style", true)
|
122
140
|
else
|
123
141
|
offset = offset block
|
142
|
+
shift = shift block
|
124
143
|
style = block.style
|
144
|
+
d = (style == "figlist" ? 1 : depth) + shift
|
145
|
+
role = li_style d, style
|
125
146
|
block.items.each_with_index do |item, idx|
|
126
|
-
d = style == "figlist" ? 1 : depth
|
127
147
|
mark = li_mark(d, idx + offset)
|
128
148
|
item.set_attr "mark", mark
|
149
|
+
item.role = role
|
129
150
|
item_reftext = "#{parent_reftext}#{ref_li_mark mark, d, style}"
|
130
151
|
register_reftext! item, item_reftext
|
131
152
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Asciidoctor
|
4
|
+
module Html
|
5
|
+
# Helpers for the table conversion
|
6
|
+
module Table
|
7
|
+
def self.display_row(tsec, row)
|
8
|
+
result = ["<tr>"]
|
9
|
+
row.each do |cell|
|
10
|
+
cell_content = if tsec == :head
|
11
|
+
cell.text
|
12
|
+
elsif cell.style == :literal
|
13
|
+
"<pre>#{cell.text}</pre>"
|
14
|
+
else
|
15
|
+
cell.content.join "\n"
|
16
|
+
end
|
17
|
+
cell_tag_name = (tsec == :head || cell.style == :header ? %(th scope="col") : "td")
|
18
|
+
cell_class_attribute = %( class="halign-#{cell.attr "halign"} align-#{cell.attr "valign"}")
|
19
|
+
cell_colspan_attribute = cell.colspan ? %( colspan="#{cell.colspan}") : ""
|
20
|
+
cell_rowspan_attribute = cell.rowspan ? %( rowspan="#{cell.rowspan}") : ""
|
21
|
+
cell_attributes = "#{cell_class_attribute}#{cell_colspan_attribute}#{cell_rowspan_attribute}"
|
22
|
+
result << %(<#{cell_tag_name}#{cell_attributes}>#{cell_content}</#{cell_tag_name}>)
|
23
|
+
end
|
24
|
+
result << "</tr>"
|
25
|
+
result.join "\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.display_rows(node)
|
29
|
+
node.rows.to_h.map do |tsec, rows|
|
30
|
+
next if rows.empty?
|
31
|
+
|
32
|
+
"<t#{tsec}>\n#{rows.map { |row| display_row(tsec, row) }.join("\n")}\n</t#{tsec}>"
|
33
|
+
end.join("\n")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -40,7 +40,7 @@ module Asciidoctor
|
|
40
40
|
<<~HTML
|
41
41
|
<main class="main">
|
42
42
|
<div class="content-container">
|
43
|
-
<
|
43
|
+
<h1>#{nav_text chapnum, chaptitle}</h1>
|
44
44
|
#{content}
|
45
45
|
#{footer author, year}
|
46
46
|
</div>
|
@@ -48,6 +48,24 @@ module Asciidoctor
|
|
48
48
|
HTML
|
49
49
|
end
|
50
50
|
|
51
|
+
def self.sitemap(entries)
|
52
|
+
<<~XML
|
53
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
54
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
55
|
+
|
56
|
+
#{entries.join "\n"}
|
57
|
+
</urlset>
|
58
|
+
XML
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.sitemap_entry(url)
|
62
|
+
<<~XML
|
63
|
+
<url>
|
64
|
+
<loc>#{url}</loc>
|
65
|
+
</url>
|
66
|
+
XML
|
67
|
+
end
|
68
|
+
|
51
69
|
def self.header(title, short_title, nav: true)
|
52
70
|
nav_btn = if nav
|
53
71
|
<<~HTML
|
@@ -70,7 +88,14 @@ module Asciidoctor
|
|
70
88
|
end
|
71
89
|
|
72
90
|
def self.footer(author, year)
|
73
|
-
|
91
|
+
<<~HTML
|
92
|
+
<footer class="footer">
|
93
|
+
<div class="footer-left">© #{year} #{author}</div>
|
94
|
+
<div class="footer-right">Built with
|
95
|
+
<a href="https://github.com/ravirajani/asciidoctor-html">asciidoctor-html</a>
|
96
|
+
</div>
|
97
|
+
</footer>
|
98
|
+
HTML
|
74
99
|
end
|
75
100
|
|
76
101
|
def self.highlightjs(langs)
|
@@ -79,11 +104,13 @@ module Asciidoctor
|
|
79
104
|
end.join("\n ")
|
80
105
|
end
|
81
106
|
|
82
|
-
def self.head(title, langs)
|
107
|
+
def self.head(title, description, author, langs)
|
83
108
|
<<~HTML
|
84
109
|
<head>
|
85
110
|
<meta charset="utf-8">
|
86
111
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
112
|
+
#{%(<meta name="description" content="#{description}">) if description}
|
113
|
+
#{%(<meta name="author" content="#{author}">) if author}
|
87
114
|
<title>#{title}</title>
|
88
115
|
<link rel="apple-touch-icon" sizes="180x180" href="#{FAVICON_PATH}/apple-touch-icon.png">
|
89
116
|
<link rel="icon" type="image/png" sizes="32x32" href="#{FAVICON_PATH}/favicon-32x32.png">
|
@@ -102,13 +129,14 @@ module Asciidoctor
|
|
102
129
|
# - title: String
|
103
130
|
# - short_title: String
|
104
131
|
# - author: String
|
132
|
+
# - description: String
|
105
133
|
# - date: Date
|
106
|
-
# - nav: Boolean
|
107
134
|
# - chapnum: Int
|
108
135
|
# - chaptitle: String
|
109
136
|
# - langs: Array[String]
|
110
137
|
def self.html(content, nav_items, opts = {})
|
111
|
-
|
138
|
+
nav = (nav_items.size > 1)
|
139
|
+
hash_listener = if nav
|
112
140
|
<<~JS
|
113
141
|
addEventListener('hashchange', function() {
|
114
142
|
collapse = bootstrap.Collapse.getInstance('#sidebar');
|
@@ -121,10 +149,10 @@ module Asciidoctor
|
|
121
149
|
<<~HTML
|
122
150
|
<!DOCTYPE html>
|
123
151
|
<html lang="en">
|
124
|
-
#{head opts[:title], opts[:langs]}
|
152
|
+
#{head opts[:title], opts[:description], opts[:author], opts[:langs]}
|
125
153
|
<body>
|
126
|
-
#{header opts[:title], opts[:short_title], nav:
|
127
|
-
#{sidebar(nav_items) if
|
154
|
+
#{header opts[:title], opts[:short_title], nav:}
|
155
|
+
#{sidebar(nav_items) if nav}
|
128
156
|
#{main content, opts[:chapnum], opts[:chaptitle], opts[:author], opts[:date].year}
|
129
157
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/js/bootstrap.bundle.min.js"
|
130
158
|
integrity="sha384-j1CDi7MgGQ12Z7Qab0qlWQ/Qqz24Gc6BM0thvEMVjHnfYGF0rmFCozFSxQBxwHKO"
|
@@ -48,12 +48,8 @@ module Asciidoctor
|
|
48
48
|
|
49
49
|
def self.wrap_node(content, node, tag_name = :div)
|
50
50
|
base_class = node.context
|
51
|
-
mod = node.
|
52
|
-
mod_class = if mod && mod != base_class.to_s
|
53
|
-
"#{base_class}-#{mod}"
|
54
|
-
else
|
55
|
-
""
|
56
|
-
end
|
51
|
+
mod = node.style
|
52
|
+
mod_class = "#{base_class}-#{mod}" if mod && mod != base_class.to_s
|
57
53
|
classes = [base_class, mod_class, node.role].compact.map(&:to_s).uniq.join(" ").strip
|
58
54
|
wrap_id_classes content, node.id, classes, tag_name
|
59
55
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asciidoctor-html
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ravi Rajani
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- lib/asciidoctor/html/list.rb
|
101
101
|
- lib/asciidoctor/html/popovers.rb
|
102
102
|
- lib/asciidoctor/html/ref_tree_processor.rb
|
103
|
+
- lib/asciidoctor/html/table.rb
|
103
104
|
- lib/asciidoctor/html/template.rb
|
104
105
|
- lib/asciidoctor/html/tree_walker.rb
|
105
106
|
- lib/asciidoctor/html/utils.rb
|