asciidoctor-html 2.1.6 → 2.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 +4 -4
- data/.rubocop.yml +4 -1
- data/CHANGELOG.md +11 -0
- data/Rakefile +12 -2
- data/assets/css/jupyterlite.css +1 -1
- data/assets/css/styles.css +2 -2
- data/lib/asciidoctor/html/book.rb +13 -5
- data/lib/asciidoctor/html/book_template.rb +26 -10
- data/lib/asciidoctor/html/cache_buster.rb +65 -0
- data/lib/asciidoctor/html/cli.rb +11 -14
- data/lib/asciidoctor/html/converter.rb +1 -1
- data/lib/asciidoctor/html/flip.rb +23 -2
- data/lib/asciidoctor/html/jupyterlite.rb +13 -8
- data/lib/asciidoctor/html/reuse_block_macro.rb +39 -0
- data/lib/asciidoctor/html/search.rb +1 -1
- data/lib/asciidoctor/html/subnav_block_macro.rb +3 -2
- data/lib/asciidoctor/html/utils.rb +11 -1
- data/lib/asciidoctor/html/version.rb +1 -1
- data/lib/asciidoctor/html.rb +1 -0
- data/lib/minitest/html_plugin.rb +0 -2
- metadata +6 -9
- data/exe/build-jupyterlite +0 -35
- data/jupyterlite/content/data/matplotlib.png +0 -0
- data/jupyterlite/content/pyodide/matplotlib.ipynb +0 -113
- data/jupyterlite/content/python.ipynb +0 -721
|
@@ -9,6 +9,7 @@ require_relative "cref_inline_macro"
|
|
|
9
9
|
require_relative "bi_inline_macro"
|
|
10
10
|
require_relative "text_inline_macro"
|
|
11
11
|
require_relative "subnav_block_macro"
|
|
12
|
+
require_relative "reuse_block_macro"
|
|
12
13
|
require_relative "book_template"
|
|
13
14
|
require_relative "pagination"
|
|
14
15
|
require_relative "search"
|
|
@@ -27,6 +28,7 @@ module Asciidoctor
|
|
|
27
28
|
inline_macro TextInlineMacro
|
|
28
29
|
inline_macro BiInlineMacro
|
|
29
30
|
block_macro SubnavBlockMacro
|
|
31
|
+
block_macro ReuseBlockMacro
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
DOCATTRS = {
|
|
@@ -62,12 +64,14 @@ module Asciidoctor
|
|
|
62
64
|
# - authors
|
|
63
65
|
# - chapname
|
|
64
66
|
# - base_url
|
|
67
|
+
# - repl_url
|
|
65
68
|
def initialize(opts = {})
|
|
66
69
|
opts = DEFAULT_OPTS.merge opts
|
|
67
70
|
@title = ERB::Escape.html_escape opts[:title]
|
|
68
71
|
@short_title = ERB::Escape.html_escape opts[:short_title]
|
|
69
72
|
@authors = opts[:authors]
|
|
70
73
|
@base_url = opts[:base_url]
|
|
74
|
+
@repl_url = opts[:repl_url]
|
|
71
75
|
@chapname = opts[:chapname]
|
|
72
76
|
@search_index = {} # Hash(docname => Array[SearchData])
|
|
73
77
|
@refs = {} # Hash(docname => Hash(id => reftext))
|
|
@@ -176,7 +180,11 @@ module Asciidoctor
|
|
|
176
180
|
end
|
|
177
181
|
|
|
178
182
|
def parse_file(filename, chapname, chapnum)
|
|
179
|
-
attributes = {
|
|
183
|
+
attributes = {
|
|
184
|
+
"chapnum" => chapnum,
|
|
185
|
+
"chapname" => chapname,
|
|
186
|
+
"repl-url" => @repl_url
|
|
187
|
+
}.merge DOCATTRS
|
|
180
188
|
Asciidoctor.load_file filename, safe: :unsafe, attributes:
|
|
181
189
|
end
|
|
182
190
|
|
|
@@ -185,7 +193,7 @@ module Asciidoctor
|
|
|
185
193
|
end
|
|
186
194
|
|
|
187
195
|
def reftext(node)
|
|
188
|
-
|
|
196
|
+
Utils.reftext node
|
|
189
197
|
end
|
|
190
198
|
|
|
191
199
|
def display_authors(doc = nil)
|
|
@@ -220,7 +228,7 @@ module Asciidoctor
|
|
|
220
228
|
line_number += 1
|
|
221
229
|
items << BookTemplate.nav_item(url, "#{prefix}#{section.title}", line_number:)
|
|
222
230
|
end
|
|
223
|
-
return
|
|
231
|
+
return unless items.size > 1
|
|
224
232
|
|
|
225
233
|
"<ul>#{items.join "\n"}</ul>"
|
|
226
234
|
end
|
|
@@ -240,7 +248,7 @@ module Asciidoctor
|
|
|
240
248
|
def nav_items(active_key = -1, doc = nil)
|
|
241
249
|
items = @templates.map do |k, td|
|
|
242
250
|
active = (k == active_key)
|
|
243
|
-
subnav = active && doc ? outline(k, doc, absolute: false) :
|
|
251
|
+
subnav = active && doc ? outline(k, doc, absolute: false) : td.outline
|
|
244
252
|
navtext = BookTemplate.nav_text td.chapprefix, td.chaptitle
|
|
245
253
|
BookTemplate.nav_item "#{k}.html", navtext, subnav, active:
|
|
246
254
|
end
|
|
@@ -261,7 +269,7 @@ module Asciidoctor
|
|
|
261
269
|
BookTemplate.html(
|
|
262
270
|
content,
|
|
263
271
|
nav_items,
|
|
264
|
-
has_subnav: !outline.
|
|
272
|
+
has_subnav: !outline.nil?,
|
|
265
273
|
has_live: doc.attr?("live"),
|
|
266
274
|
title: @title,
|
|
267
275
|
short_title: @short_title,
|
|
@@ -18,10 +18,26 @@ module Asciidoctor
|
|
|
18
18
|
</button>
|
|
19
19
|
HTML
|
|
20
20
|
|
|
21
|
-
def self.nav_item(target, text, content =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
def self.nav_item(target, text, content = nil, active: false, line_number: 0)
|
|
22
|
+
if content
|
|
23
|
+
id = target.sub(/\.html$/, "-subnav").tr ".", "-"
|
|
24
|
+
show_class = " show" if active
|
|
25
|
+
subnav = %(<div class="collapse#{show_class}" id="#{id}">\n#{content}\n</div>)
|
|
26
|
+
toggle = <<~HTML
|
|
27
|
+
<button class="btn subnav-toggle#{" collapsed" unless active}"
|
|
28
|
+
type="button"
|
|
29
|
+
data-bs-toggle="collapse"
|
|
30
|
+
data-bs-target="##{id}"
|
|
31
|
+
aria-expanded="#{active ? "true" : "false"}"
|
|
32
|
+
aria-controls="#{id}">
|
|
33
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="caret" viewBox="0 0 16 16">
|
|
34
|
+
<path d="M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z"/>
|
|
35
|
+
</svg>
|
|
36
|
+
</button>
|
|
37
|
+
HTML
|
|
38
|
+
end
|
|
39
|
+
active_class = %( class="active") if active
|
|
40
|
+
link = %(<a href="#{target}">#{text}</a>#{toggle})
|
|
25
41
|
live_attr = Utils.line_number_attr(line_number, live: line_number.positive?)
|
|
26
42
|
%(<li#{active_class}#{live_attr}>#{link}#{subnav}</li>\n)
|
|
27
43
|
end
|
|
@@ -186,12 +202,12 @@ module Asciidoctor
|
|
|
186
202
|
#{%(<meta name="description" content="#{opts[:description]}">) if opts[:description]}
|
|
187
203
|
#{%(<meta name="author" content="#{opts[:authors]}">) if opts[:authors]}
|
|
188
204
|
<title>#{opts[:title]}</title>
|
|
189
|
-
<link rel="icon" type="image/png" href="#{FAVICON_PATH}/favicon-96x96.png" sizes="96x96"
|
|
190
|
-
<link rel="icon" type="image/svg+xml" href="#{FAVICON_PATH}/favicon.svg"
|
|
191
|
-
<link rel="shortcut icon" href="#{FAVICON_PATH}/favicon.ico"
|
|
192
|
-
<link rel="apple-touch-icon" sizes="180x180" href="#{FAVICON_PATH}/apple-touch-icon.png"
|
|
193
|
-
<meta name="apple-mobile-web-app-title" content="#{opts[:short_title]}"
|
|
194
|
-
<link rel="manifest" href="site.webmanifest"
|
|
205
|
+
<link rel="icon" type="image/png" href="#{FAVICON_PATH}/favicon-96x96.png" sizes="96x96">
|
|
206
|
+
<link rel="icon" type="image/svg+xml" href="#{FAVICON_PATH}/favicon.svg">
|
|
207
|
+
<link rel="shortcut icon" href="#{FAVICON_PATH}/favicon.ico">
|
|
208
|
+
<link rel="apple-touch-icon" sizes="180x180" href="#{FAVICON_PATH}/apple-touch-icon.png">
|
|
209
|
+
<meta name="apple-mobile-web-app-title" content="#{opts[:short_title]}">
|
|
210
|
+
<link rel="manifest" href="site.webmanifest">
|
|
195
211
|
<link rel="stylesheet" href="#{CSS_PATH}/styles.css">
|
|
196
212
|
#{highlightjs(opts)}
|
|
197
213
|
<script>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "pathname"
|
|
4
|
+
require "zlib"
|
|
5
|
+
require "strscan"
|
|
6
|
+
|
|
7
|
+
module Asciidoctor
|
|
8
|
+
module Html
|
|
9
|
+
# Postprocess site with cachebusting paths
|
|
10
|
+
module CacheBuster
|
|
11
|
+
AssetData = Struct.new("AssetData", :filehash, :newpath)
|
|
12
|
+
|
|
13
|
+
def self.process(outdir)
|
|
14
|
+
puts "-- Begin cache busting --"
|
|
15
|
+
puts
|
|
16
|
+
cache = {} # assetpath => {:filehash,:newpath}
|
|
17
|
+
glob = ["**/*.html", "*.webmanifest"]
|
|
18
|
+
Pathname(outdir).glob(glob) do |filepath|
|
|
19
|
+
puts "Processing"
|
|
20
|
+
puts " #{filepath}"
|
|
21
|
+
scanner = StringScanner.new(filepath.read)
|
|
22
|
+
rgx = %r{"((?<prefix>[\./]*?#{ASSETS_PATH}/.+?)(?<hash>\.|\.[a-f0-9]{8}\.)(?<ext>[a-z]+?))"}
|
|
23
|
+
buffer = []
|
|
24
|
+
while (scanned = scanner.scan_until(rgx))
|
|
25
|
+
matched = scanner.matched
|
|
26
|
+
buffer << scanned[0, scanned.size - matched.size]
|
|
27
|
+
matchedpath = Pathname(matched[1..-2])
|
|
28
|
+
assetpath = filepath.dirname / matchedpath
|
|
29
|
+
if assetpath.file?
|
|
30
|
+
assetpath = assetpath.realpath
|
|
31
|
+
captures = scanner.named_captures
|
|
32
|
+
cache[assetpath] ||= AssetData.new
|
|
33
|
+
assetdata = cache[assetpath]
|
|
34
|
+
assetdata.filehash ||= format("%08x", Zlib.crc32(assetpath.read))
|
|
35
|
+
new_hash = assetdata.filehash
|
|
36
|
+
found_hash = captures["hash"][1..-2] unless captures["hash"] == "."
|
|
37
|
+
if new_hash == found_hash
|
|
38
|
+
buffer << matched
|
|
39
|
+
else
|
|
40
|
+
new_name = "#{captures["prefix"]}.#{new_hash}.#{captures["ext"]}"
|
|
41
|
+
buffer << %("#{new_name}")
|
|
42
|
+
assetdata.newpath = filepath.dirname / Pathname(new_name)
|
|
43
|
+
end
|
|
44
|
+
else
|
|
45
|
+
buffer << matched
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
buffer << scanner.rest
|
|
49
|
+
filepath.write buffer.join
|
|
50
|
+
end
|
|
51
|
+
cache.each_pair do |assetpath, assetdata|
|
|
52
|
+
next unless assetdata.newpath
|
|
53
|
+
|
|
54
|
+
puts
|
|
55
|
+
puts "Renaming:"
|
|
56
|
+
puts " #{assetpath}"
|
|
57
|
+
puts "->#{assetdata.newpath}"
|
|
58
|
+
assetpath.rename(assetdata.newpath)
|
|
59
|
+
end
|
|
60
|
+
puts
|
|
61
|
+
puts "-- End cache busting --"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
data/lib/asciidoctor/html/cli.rb
CHANGED
|
@@ -8,7 +8,7 @@ require "psych"
|
|
|
8
8
|
require_relative "book"
|
|
9
9
|
require_relative "webmanifest"
|
|
10
10
|
require_relative "version"
|
|
11
|
-
require_relative "
|
|
11
|
+
require_relative "cache_buster"
|
|
12
12
|
|
|
13
13
|
module Asciidoctor
|
|
14
14
|
module Html
|
|
@@ -16,6 +16,7 @@ module Asciidoctor
|
|
|
16
16
|
module CLI
|
|
17
17
|
DEFAULT_OPTIONS = {
|
|
18
18
|
"config-file": "config.yml",
|
|
19
|
+
"bust-cache": false,
|
|
19
20
|
watch: false
|
|
20
21
|
}.freeze
|
|
21
22
|
|
|
@@ -29,6 +30,8 @@ module Asciidoctor
|
|
|
29
30
|
OptionParser.new do |parser|
|
|
30
31
|
parser.on("-w", "--watch",
|
|
31
32
|
"Watch for file changes in SRCDIR. Default: unset")
|
|
33
|
+
parser.on("-b", "--bust-cache",
|
|
34
|
+
"Modify asset names for cache busting. Default: #{options[:"bust-cache"]}")
|
|
32
35
|
parser.on("-c", "--config-file CONFIG",
|
|
33
36
|
"Location of config file. Default: #{options[:"config-file"]}")
|
|
34
37
|
parser.on("-v", "--version", "Print version and exit.")
|
|
@@ -54,11 +57,10 @@ module Asciidoctor
|
|
|
54
57
|
"#{config["srcdir"]}/#{f}"
|
|
55
58
|
end
|
|
56
59
|
end
|
|
57
|
-
config["jupyterlite"] = config["jupyterlite"] || false
|
|
58
60
|
config
|
|
59
61
|
end
|
|
60
62
|
|
|
61
|
-
def self.setup_outdir(srcdir, outdir
|
|
63
|
+
def self.setup_outdir(rootdir, srcdir, outdir)
|
|
62
64
|
assets_out = "#{outdir}/#{ASSETS_PATH}"
|
|
63
65
|
FileUtils.mkdir_p assets_out unless File.directory?(assets_out)
|
|
64
66
|
%W[#{IMG_PATH} #{CSS_PATH} #{FAVICON_PATH}].each do |p|
|
|
@@ -69,7 +71,6 @@ module Asciidoctor
|
|
|
69
71
|
puts
|
|
70
72
|
FileUtils.cp_r dir, assets_out
|
|
71
73
|
end
|
|
72
|
-
rootdir = File.absolute_path "#{__dir__}/../../.."
|
|
73
74
|
%W[#{CSS_PATH} #{FAVICON_PATH}].each do |p|
|
|
74
75
|
dir = "#{outdir}/#{p}"
|
|
75
76
|
next if Dir.exist?(dir)
|
|
@@ -78,7 +79,6 @@ module Asciidoctor
|
|
|
78
79
|
puts
|
|
79
80
|
FileUtils.cp_r "#{rootdir}/#{p}", assets_out
|
|
80
81
|
end
|
|
81
|
-
build_jupyterlite(rootdir, outdir) if jupyterlite
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
def self.generate_webmanifest(outdir, name, short_name)
|
|
@@ -90,7 +90,7 @@ module Asciidoctor
|
|
|
90
90
|
|
|
91
91
|
def self.generate_bookopts(config)
|
|
92
92
|
book_opts = {}
|
|
93
|
-
%i[title short_title authors base_url chapname].each do |opt|
|
|
93
|
+
%i[title short_title authors base_url chapname repl_url].each do |opt|
|
|
94
94
|
key = opt.to_s
|
|
95
95
|
book_opts[opt] = config[key] if config.include?(key)
|
|
96
96
|
end
|
|
@@ -98,13 +98,6 @@ module Asciidoctor
|
|
|
98
98
|
book_opts
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
-
def self.build_jupyterlite(rootdir, outdir)
|
|
102
|
-
jupyterlite_outdir = "#{outdir}/#{Jupyterlite::PATH}"
|
|
103
|
-
return if File.directory?(jupyterlite_outdir)
|
|
104
|
-
|
|
105
|
-
system %(#{rootdir}/exe/build-jupyterlite -o "#{jupyterlite_outdir}" "#{rootdir}/#{Jupyterlite::PATH}")
|
|
106
|
-
end
|
|
107
|
-
|
|
108
101
|
def self.run(opts = nil)
|
|
109
102
|
opts ||= parse_opts
|
|
110
103
|
if opts[:version]
|
|
@@ -114,15 +107,19 @@ module Asciidoctor
|
|
|
114
107
|
config = read_config opts[:"config-file"]
|
|
115
108
|
outdir = config["outdir"]
|
|
116
109
|
srcdir = config["srcdir"]
|
|
110
|
+
rootdir = File.absolute_path "#{__dir__}/../../.."
|
|
117
111
|
book_opts = generate_bookopts config
|
|
118
|
-
setup_outdir srcdir, outdir
|
|
112
|
+
setup_outdir rootdir, srcdir, outdir
|
|
119
113
|
generate_webmanifest outdir, book_opts[:title], book_opts[:short_title]
|
|
120
114
|
book = Book.new book_opts
|
|
121
115
|
puts "Writing book to\n #{outdir}"
|
|
122
116
|
puts
|
|
123
117
|
book.write config["chapters"], config["appendices"], outdir, sitemap: true
|
|
118
|
+
CacheBuster.process(outdir) if opts[:"bust-cache"]
|
|
124
119
|
return unless opts[:watch]
|
|
125
120
|
|
|
121
|
+
puts "Watching for changes to chapters and appendices..."
|
|
122
|
+
puts
|
|
126
123
|
Filewatcher.new("#{srcdir}/*.adoc").watch do |changes|
|
|
127
124
|
chapters = []
|
|
128
125
|
appendices = []
|
|
@@ -84,7 +84,7 @@ module Asciidoctor
|
|
|
84
84
|
|
|
85
85
|
def convert_sidebar(node)
|
|
86
86
|
classes = ["aside", node.role].compact.join(" ")
|
|
87
|
-
title = node.title? ? %(<
|
|
87
|
+
title = node.title? ? %(<div class="aside-title">#{node.title}</div>\n) : ""
|
|
88
88
|
content = "#{title}#{node.content}"
|
|
89
89
|
%(<aside#{Utils.id_class_attr_str node.id, classes}>\n#{content}\n</aside>\n)
|
|
90
90
|
end
|
|
@@ -24,7 +24,7 @@ module Asciidoctor
|
|
|
24
24
|
const chapheading = page.querySelector('.chapheading');
|
|
25
25
|
const chaptitle = page.querySelector('.chaptitle');
|
|
26
26
|
|
|
27
|
-
const nav = document.querySelectorAll('#sidebar nav > ul > li.active
|
|
27
|
+
const nav = document.querySelectorAll('#sidebar nav > ul > li.active ul li');
|
|
28
28
|
|
|
29
29
|
let currentId = "page";
|
|
30
30
|
focusEl.querySelectorAll(':scope > .flip').forEach(el => {
|
|
@@ -92,6 +92,25 @@ module Asciidoctor
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
function reuseElements() {
|
|
96
|
+
focusEl.querySelectorAll(':scope > .flip.d-block .reuse').forEach(target => {
|
|
97
|
+
const link = target && target.querySelector('a.reuse-link');
|
|
98
|
+
if(!link) return;
|
|
99
|
+
|
|
100
|
+
const source = document.getElementById(link.hash.substring(1));
|
|
101
|
+
let reuse = source && source.parentElement;
|
|
102
|
+
if(!reuse) return;
|
|
103
|
+
|
|
104
|
+
if(!reuse.classList.contains('reuse')) {
|
|
105
|
+
reuse = document.createElement('div');
|
|
106
|
+
reuse.classList.add('reuse');
|
|
107
|
+
source.replaceWith(reuse);
|
|
108
|
+
}
|
|
109
|
+
reuse.replaceChildren(...target.children);
|
|
110
|
+
target.replaceChildren(source);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
95
114
|
function flip(e) {
|
|
96
115
|
if(!page.classList.contains('multi')) {
|
|
97
116
|
focusOnLoad();
|
|
@@ -128,6 +147,8 @@ module Asciidoctor
|
|
|
128
147
|
}
|
|
129
148
|
}
|
|
130
149
|
|
|
150
|
+
reuseElements();
|
|
151
|
+
|
|
131
152
|
nav.forEach(el => {
|
|
132
153
|
const a = el.querySelector('a');
|
|
133
154
|
a && a.hash && el.classList.toggle('active', id == a.hash.substring(1));
|
|
@@ -135,7 +156,7 @@ module Asciidoctor
|
|
|
135
156
|
|
|
136
157
|
ADHT.nudgeMenuBtn();
|
|
137
158
|
|
|
138
|
-
const scrollEl =
|
|
159
|
+
const scrollEl = isPresentation ? main : page;
|
|
139
160
|
if(target == section) {
|
|
140
161
|
scrollEl.scrollTo({
|
|
141
162
|
top: 0,
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "utils"
|
|
4
|
+
|
|
3
5
|
module Asciidoctor
|
|
4
6
|
module Html
|
|
5
7
|
# Jupyterlite library
|
|
6
8
|
module Jupyterlite
|
|
7
|
-
PATH = "jupyterlite"
|
|
8
|
-
REPL_PATH = "repl/index.html"
|
|
9
|
-
|
|
10
9
|
CONFIG = {
|
|
11
10
|
toolbar: true,
|
|
12
11
|
kernel: "python",
|
|
@@ -21,7 +20,7 @@ module Asciidoctor
|
|
|
21
20
|
def self.repl_path_with_options(node)
|
|
22
21
|
query_string = ["code=#{URI.encode_uri_component node.content}"]
|
|
23
22
|
query_string << CONFIG.merge(
|
|
24
|
-
{ promptCellPosition: node.attr("prompt-position", "
|
|
23
|
+
{ promptCellPosition: node.attr("prompt-position", "top") }
|
|
25
24
|
).map do |k, v|
|
|
26
25
|
value = if v == true
|
|
27
26
|
1
|
|
@@ -32,20 +31,26 @@ module Asciidoctor
|
|
|
32
31
|
end
|
|
33
32
|
"#{k}=#{URI.encode_uri_component value}"
|
|
34
33
|
end
|
|
35
|
-
"#{
|
|
34
|
+
"#{node.document.attr "repl-url"}?#{query_string.join "&"}"
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
def self.html(node)
|
|
38
|
+
error_msg = "Set a <code>repl_url</code> in your <code>config.yaml</code>."
|
|
39
|
+
return Utils.show_error(error_msg) unless node.document.attr("repl-url")
|
|
40
|
+
|
|
39
41
|
cell_id = "jupyter-cell-frame-#{node.attr "jupyter-cell-id"}"
|
|
40
|
-
|
|
42
|
+
styles = []
|
|
43
|
+
styles << "height:#{node.attr "height"}px;" if node.attr?("height")
|
|
44
|
+
styles << "width:#{node.attr "width"}px;" if node.attr?("width")
|
|
45
|
+
style_attr = %( style="#{styles.join}") unless styles.empty?
|
|
41
46
|
<<~HTML
|
|
42
|
-
<div id="#{cell_id}"#{
|
|
47
|
+
<div id="#{cell_id}"#{style_attr} class="jupyter-cell"></div>
|
|
43
48
|
<script>
|
|
44
49
|
(function(){
|
|
45
50
|
const cell = document.getElementById('#{cell_id}');
|
|
46
51
|
addEventListener('load', () => {
|
|
47
52
|
const frame = document.createElement('iframe');
|
|
48
|
-
frame.src = '#{
|
|
53
|
+
frame.src = '#{repl_path_with_options node}';
|
|
49
54
|
frame.width = '100%';
|
|
50
55
|
frame.height = '100%';
|
|
51
56
|
cell.appendChild(frame);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "asciidoctor"
|
|
4
|
+
require_relative "utils"
|
|
5
|
+
|
|
6
|
+
module Asciidoctor
|
|
7
|
+
module Html
|
|
8
|
+
# Reuse blocks, especially useful in multi mode
|
|
9
|
+
class ReuseBlockMacro < Asciidoctor::Extensions::BlockMacroProcessor
|
|
10
|
+
use_dsl
|
|
11
|
+
|
|
12
|
+
named :reuse
|
|
13
|
+
name_positional_attributes "reftext"
|
|
14
|
+
|
|
15
|
+
def process(parent, target, attrs)
|
|
16
|
+
if target.empty?
|
|
17
|
+
content = Utils.show_error "Missing target."
|
|
18
|
+
else
|
|
19
|
+
el = parent.document.catalog[:refs][target]
|
|
20
|
+
reftext = el && (attrs["reftext"] || Utils.reftext(el))
|
|
21
|
+
title = %(<div class="block-title">#{parent.apply_subs attrs["title"]}</div>) if attrs.include?("title")
|
|
22
|
+
content = if reftext
|
|
23
|
+
id = %( id="#{attrs["id"]}") if attrs.include?("id")
|
|
24
|
+
classes = %( #{attrs["role"]}) if attrs.include?("role")
|
|
25
|
+
<<~HTML
|
|
26
|
+
<div#{id} class="reuse#{classes}">
|
|
27
|
+
#{title}
|
|
28
|
+
<p><a class="reuse-link" href="##{target}">#{reftext}</a></p>
|
|
29
|
+
</div>
|
|
30
|
+
HTML
|
|
31
|
+
else
|
|
32
|
+
Utils.show_error "Invalid ID."
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
create_pass_block parent, content, attrs, subs: nil
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -23,7 +23,7 @@ module Asciidoctor
|
|
|
23
23
|
</form>
|
|
24
24
|
</div>
|
|
25
25
|
<div id="search-results-container" class="hidden">
|
|
26
|
-
<
|
|
26
|
+
<div class="h4 search-matches-title">Found <span id="search-nmatches">0 matches</span></div>
|
|
27
27
|
<ul id="search-results" class="search-results list-group list-group-flush"></ul>
|
|
28
28
|
</div>
|
|
29
29
|
HTML
|
|
@@ -14,13 +14,14 @@ module Asciidoctor
|
|
|
14
14
|
|
|
15
15
|
def process(parent, target, attrs)
|
|
16
16
|
doc_key = Pathname(target).sub_ext "" unless target.empty?
|
|
17
|
-
title = %(<
|
|
17
|
+
title = %(<div class="block-title">#{parent.apply_subs attrs["title"]}</div>) if attrs.include?("title")
|
|
18
18
|
bordered_class = " bordered" if attrs.include?("border")
|
|
19
19
|
border_width = attrs["border"].to_i if bordered_class
|
|
20
20
|
style = %( style="border-top-width: #{border_width}px; border-bottom-width: #{border_width}px;") if border_width
|
|
21
21
|
roles = " #{attrs["role"]}" if attrs.include?("role")
|
|
22
|
+
id_attr = %( id="#{attrs["id"]}") if attrs.include?("id")
|
|
22
23
|
content = <<~HTML
|
|
23
|
-
<div class="subnav#{bordered_class}#{roles}"#{style}>
|
|
24
|
+
<div#{id_attr} class="subnav#{bordered_class}#{roles}"#{style}>
|
|
24
25
|
#{title}
|
|
25
26
|
<nav>
|
|
26
27
|
<%= templates.dig("#{doc_key}", "outline") || outline %>
|
|
@@ -34,7 +34,7 @@ module Asciidoctor
|
|
|
34
34
|
def self.display_title(node)
|
|
35
35
|
prefix = display_title_prefix node
|
|
36
36
|
suffix = display_title_suffix node
|
|
37
|
-
show_title?(node) ? %(<
|
|
37
|
+
show_title?(node) ? %(<div class="block-title">#{prefix}#{node.title}#{suffix}</div>\n) : ""
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def self.display_title_suffix(node)
|
|
@@ -111,6 +111,16 @@ module Asciidoctor
|
|
|
111
111
|
classes = %( class="#{node.role}") if discrete && node.role
|
|
112
112
|
%(<#{tag_name}#{classes}>#{title}</#{tag_name}>\n)
|
|
113
113
|
end
|
|
114
|
+
|
|
115
|
+
def self.show_error(message)
|
|
116
|
+
<<~HTML
|
|
117
|
+
<p class="border border-danger p-2">#{message}</p>
|
|
118
|
+
HTML
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def self.reftext(node)
|
|
122
|
+
node.reftext || (node.title unless node.inline?) || "[#{node.id}]" if node.id
|
|
123
|
+
end
|
|
114
124
|
end
|
|
115
125
|
end
|
|
116
126
|
end
|
data/lib/asciidoctor/html.rb
CHANGED
data/lib/minitest/html_plugin.rb
CHANGED
|
@@ -9,7 +9,6 @@ module Minitest
|
|
|
9
9
|
class HTMLReporter < AbstractReporter
|
|
10
10
|
DOCS_DIR = "#{__dir__}/../../docs/asciidoc".freeze
|
|
11
11
|
TESTS_DIR = "#{__dir__}/../../test/asciidoctor/html".freeze
|
|
12
|
-
CONFIG_FILE = "#{DOCS_DIR}/config.yml".freeze
|
|
13
12
|
|
|
14
13
|
def initialize
|
|
15
14
|
@results = {}
|
|
@@ -57,7 +56,6 @@ module Minitest
|
|
|
57
56
|
end
|
|
58
57
|
adoc = %(= Test Results\n:pagestyle: multi\n\n#{time}\n\nsubnav::[border=1]\n\n#{results.join "\n"})
|
|
59
58
|
File.write("#{DOCS_DIR}/tests.adoc", adoc)
|
|
60
|
-
Asciidoctor::Html::CLI.run({ "config-file": CONFIG_FILE, watch: false })
|
|
61
59
|
end
|
|
62
60
|
end
|
|
63
61
|
|
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: 2.
|
|
4
|
+
version: 2.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ravi Rajani
|
|
@@ -29,14 +29,14 @@ dependencies:
|
|
|
29
29
|
requirements:
|
|
30
30
|
- - '='
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version:
|
|
32
|
+
version: 3.0.1
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - '='
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version:
|
|
39
|
+
version: 3.0.1
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: nokogiri
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -83,7 +83,6 @@ email:
|
|
|
83
83
|
- ravi.inajar@gmail.com
|
|
84
84
|
executables:
|
|
85
85
|
- adoctohtml
|
|
86
|
-
- build-jupyterlite
|
|
87
86
|
extensions: []
|
|
88
87
|
extra_rdoc_files: []
|
|
89
88
|
files:
|
|
@@ -106,11 +105,7 @@ files:
|
|
|
106
105
|
- assets/favicon/web-app-manifest-192x192.png
|
|
107
106
|
- assets/favicon/web-app-manifest-512x512.png
|
|
108
107
|
- exe/adoctohtml
|
|
109
|
-
- exe/build-jupyterlite
|
|
110
108
|
- jupyterlite/.gitignore
|
|
111
|
-
- jupyterlite/content/data/matplotlib.png
|
|
112
|
-
- jupyterlite/content/pyodide/matplotlib.ipynb
|
|
113
|
-
- jupyterlite/content/python.ipynb
|
|
114
109
|
- jupyterlite/overrides.json
|
|
115
110
|
- jupyterlite/repl/jupyter-lite.json
|
|
116
111
|
- jupyterlite/requirements.txt
|
|
@@ -118,6 +113,7 @@ files:
|
|
|
118
113
|
- lib/asciidoctor/html/bi_inline_macro.rb
|
|
119
114
|
- lib/asciidoctor/html/book.rb
|
|
120
115
|
- lib/asciidoctor/html/book_template.rb
|
|
116
|
+
- lib/asciidoctor/html/cache_buster.rb
|
|
121
117
|
- lib/asciidoctor/html/cli.rb
|
|
122
118
|
- lib/asciidoctor/html/converter.rb
|
|
123
119
|
- lib/asciidoctor/html/cref_inline_macro.rb
|
|
@@ -130,6 +126,7 @@ files:
|
|
|
130
126
|
- lib/asciidoctor/html/pagination.rb
|
|
131
127
|
- lib/asciidoctor/html/popovers.rb
|
|
132
128
|
- lib/asciidoctor/html/ref_tree_processor.rb
|
|
129
|
+
- lib/asciidoctor/html/reuse_block_macro.rb
|
|
133
130
|
- lib/asciidoctor/html/scroll.rb
|
|
134
131
|
- lib/asciidoctor/html/search.rb
|
|
135
132
|
- lib/asciidoctor/html/sidebar.rb
|
|
@@ -164,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
164
161
|
- !ruby/object:Gem::Version
|
|
165
162
|
version: '0'
|
|
166
163
|
requirements: []
|
|
167
|
-
rubygems_version: 3.6.
|
|
164
|
+
rubygems_version: 3.6.7
|
|
168
165
|
specification_version: 4
|
|
169
166
|
summary: An AsciiDoc-to-HTML static site generator based on Asciidoctor.
|
|
170
167
|
test_files: []
|
data/exe/build-jupyterlite
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
IFS=$'\n\t'
|
|
4
|
-
CSS_FILE="assets/css/jupyterlite.css"
|
|
5
|
-
CSS_LINK="<link rel=\"stylesheet\" href=\"../../$CSS_FILE\">"
|
|
6
|
-
USAGE="Usage: $(basename "$0") [-h] [-o outdir] srcdir"
|
|
7
|
-
|
|
8
|
-
outdir=www/jupyterlite
|
|
9
|
-
|
|
10
|
-
while getopts "o:h" opt; do
|
|
11
|
-
case $opt in
|
|
12
|
-
o)
|
|
13
|
-
outdir="$(realpath "$OPTARG")"
|
|
14
|
-
;;
|
|
15
|
-
h)
|
|
16
|
-
echo "$USAGE"
|
|
17
|
-
exit 0
|
|
18
|
-
;;
|
|
19
|
-
?)
|
|
20
|
-
echo -e "Invalid option.\n$USAGE"
|
|
21
|
-
exit 1
|
|
22
|
-
;;
|
|
23
|
-
esac
|
|
24
|
-
done
|
|
25
|
-
shift "$((OPTIND-1))"
|
|
26
|
-
if [[ "$#" -lt 1 ]]; then
|
|
27
|
-
echo -e "Missing positional argument.\n$USAGE"
|
|
28
|
-
exit 1
|
|
29
|
-
fi
|
|
30
|
-
echo "JupyterLite directory: $1"
|
|
31
|
-
echo "Output directory: $outdir"
|
|
32
|
-
cd "$1"
|
|
33
|
-
python -m pip install -r requirements.txt
|
|
34
|
-
jupyter lite build --contents content --output-dir $outdir
|
|
35
|
-
sed -i "s|</head>|$CSS_LINK\n</head>|g" "$outdir/repl/index.html"
|
|
Binary file
|