asciidoctor-revealjs 3.0.0 → 4.1.0.rc3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.adoc +1 -1
- data/README.adoc +390 -63
- data/Rakefile +30 -7
- data/asciidoctor-revealjs.gemspec +6 -4
- data/bin/asciidoctor-revealjs +7 -0
- data/examples/a11y-dark.css +99 -0
- data/examples/autoslide.adoc +22 -0
- data/examples/custom-layout.adoc +10 -0
- data/examples/customcss.adoc +1 -1
- data/examples/data-attributes.adoc +245 -0
- data/examples/docinfo-footer-revealjs.html +10 -0
- data/examples/docinfo-revealjs.html +7 -0
- data/examples/font-awesome-specific-version.adoc +11 -0
- data/examples/font-awesome.adoc +23 -4
- data/examples/font-awesome.css +3 -0
- data/examples/footnotes.adoc +46 -0
- data/examples/fragments.adoc +44 -0
- data/examples/fragments.css +18 -0
- data/examples/grid-layout-3x2.adoc +50 -0
- data/examples/grid-layout-docinfo-revealjs.html +11 -0
- data/examples/grid-layout.adoc +194 -0
- data/examples/history-hash.adoc +19 -0
- data/examples/history-regression-tests.adoc +0 -5
- data/examples/history.adoc +4 -4
- data/examples/images/asciidoctor-logo.svg +102 -0
- data/examples/images/cute-cat-1.jpg +0 -0
- data/examples/images/cute-cat-2.jpg +0 -0
- data/examples/images/cute-cat-3.jpg +0 -0
- data/examples/images/flock-of-seagulls_daniel-simion.mp3 +0 -0
- data/examples/issue-grid-layout-images.adoc +25 -0
- data/examples/level-sectnums.adoc +24 -0
- data/examples/links-preview.adoc +32 -0
- data/examples/links.adoc +39 -0
- data/examples/mathjax-cdn.adoc +21 -0
- data/examples/mathjax.adoc +20 -0
- data/examples/release-4.0.adoc +192 -0
- data/examples/release-4.0.css +23 -0
- data/examples/release-4.1.adoc +133 -0
- data/examples/release-4.1.css +50 -0
- data/examples/revealjs-custom-theme.adoc +10 -0
- data/examples/source-coderay.adoc +15 -0
- data/examples/source-emphasis.adoc +128 -0
- data/examples/source-highlightjs-html.adoc +1 -1
- data/examples/source-highlightjs-languages.adoc +27 -0
- data/examples/source-highlightjs.adoc +85 -2
- data/examples/source-pygments.adoc +12 -0
- data/examples/source-rouge-docinfo.html +8 -0
- data/examples/source-rouge.adoc +18 -0
- data/examples/steps.adoc +87 -0
- data/examples/text-alignments.adoc +44 -0
- data/examples/video.adoc +30 -8
- data/examples/with-docinfo-shared.adoc +13 -0
- data/lib/asciidoctor-revealjs/converter.rb +1053 -769
- data/lib/asciidoctor-revealjs/highlightjs.rb +333 -2
- data/lib/asciidoctor-revealjs/version.rb +1 -1
- data/templates/admonition.html.slim +1 -1
- data/templates/asciidoctor-compatibility.css +390 -0
- data/templates/audio.html.slim +1 -1
- data/templates/colist.html.slim +1 -1
- data/templates/dlist.html.slim +3 -3
- data/templates/document.html.slim +76 -59
- data/templates/example.html.slim +1 -1
- data/templates/helpers.rb +170 -5
- data/templates/image.html.slim +3 -3
- data/templates/inline_anchor.html.slim +6 -4
- data/templates/inline_button.html.slim +2 -1
- data/templates/inline_footnote.html.slim +11 -4
- data/templates/inline_image.html.slim +5 -8
- data/templates/inline_kbd.html.slim +3 -2
- data/templates/inline_menu.html.slim +4 -3
- data/templates/inline_quoted.html.slim +13 -21
- data/templates/listing.html.slim +15 -10
- data/templates/literal.html.slim +1 -1
- data/templates/olist.html.slim +2 -2
- data/templates/open.html.slim +3 -3
- data/templates/paragraph.html.slim +1 -1
- data/templates/quote.html.slim +1 -1
- data/templates/section.html.slim +51 -43
- data/templates/sidebar.html.slim +1 -1
- data/templates/stem.html.slim +1 -1
- data/templates/stretch_nested_elements.js.slim +65 -0
- data/templates/table.html.slim +3 -2
- data/templates/title_slide.html.slim +28 -0
- data/templates/ulist.html.slim +3 -3
- data/templates/verse.html.slim +1 -1
- data/templates/video.html.slim +14 -8
- metadata +81 -18
- data/CHANGELOG.adoc +0 -425
- data/HACKING.adoc +0 -386
- data/examples/revealjs-features.adoc +0 -23
- data/templates/asciidoctor_revealjs.css.slim +0 -59
data/templates/audio.html.slim
CHANGED
data/templates/colist.html.slim
CHANGED
data/templates/dlist.html.slim
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
- case @style
|
2
2
|
- when 'qanda'
|
3
|
-
|
3
|
+
= html_tag('div', { :id => @id, :class => ['qlist', @style, role] }.merge(data_attrs(@attributes)))
|
4
4
|
- if title?
|
5
5
|
.title=title
|
6
6
|
ol
|
@@ -14,7 +14,7 @@
|
|
14
14
|
- if answer.blocks?
|
15
15
|
=answer.content
|
16
16
|
- when 'horizontal'
|
17
|
-
|
17
|
+
= html_tag('div', { :id => @id, :class => ['hdlist', role] }.merge(data_attrs(@attributes)))
|
18
18
|
- if title?
|
19
19
|
.title=title
|
20
20
|
table
|
@@ -38,7 +38,7 @@
|
|
38
38
|
- if dd.blocks?
|
39
39
|
=dd.content
|
40
40
|
- else
|
41
|
-
|
41
|
+
= html_tag('div', { :id => @id, :class => ['dlist', @style, role] }.merge(data_attrs(@attributes)))
|
42
42
|
- if title?
|
43
43
|
.title=title
|
44
44
|
dl
|
@@ -2,6 +2,10 @@ doctype 5
|
|
2
2
|
html lang=(attr :lang, 'en' unless attr? :nolang)
|
3
3
|
head
|
4
4
|
meta charset="utf-8"
|
5
|
+
meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui"
|
6
|
+
|
7
|
+
title=(doctitle sanitize: true, use_fallback: true)
|
8
|
+
|
5
9
|
- if RUBY_ENGINE == 'opal' && JAVASCRIPT_PLATFORM == 'node'
|
6
10
|
- revealjsdir = (attr :revealjsdir, 'node_modules/reveal.js')
|
7
11
|
- else
|
@@ -13,27 +17,31 @@ html lang=(attr :lang, 'en' unless attr? :nolang)
|
|
13
17
|
- if attr? key
|
14
18
|
meta name=key content=(attr key)
|
15
19
|
- linkcss = (attr? 'linkcss')
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui" name="viewport"
|
20
|
-
link href="#{revealjsdir}/css/reveal.css" rel="stylesheet"
|
20
|
+
link rel="stylesheet" href="#{revealjsdir}/css/reset.css"
|
21
|
+
link rel="stylesheet" href="#{revealjsdir}/css/reveal.css"
|
22
|
+
|
21
23
|
/ Default theme required even when using custom theme
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
include asciidoctor_revealjs.css.slim
|
24
|
+
link rel='stylesheet' href=(attr :revealjs_customtheme, %(#{revealjsdir}/css/theme/#{attr 'revealjs_theme', 'black'}.css)) id='theme'
|
25
|
+
/! This CSS is generated by the Asciidoctor reveal.js converter to further integrate AsciiDoc's existing semantic with reveal.js
|
26
|
+
style type="text/css"
|
27
|
+
include asciidoctor-compatibility.css
|
27
28
|
- if attr? :icons, 'font'
|
28
29
|
/ iconfont-remote is implicitly set by Asciidoctor core. See https://github.com/asciidoctor/asciidoctor.org/issues/361
|
29
30
|
- if attr? 'iconfont-remote'
|
30
|
-
|
31
|
+
- if (iconfont_cdn = (attr 'iconfont-cdn'))
|
32
|
+
link rel='stylesheet' href=iconfont_cdn
|
33
|
+
- else
|
34
|
+
/ default icon font is Font Awesome
|
35
|
+
- font_awesome_version = (attr 'font-awesome-version', '5.15.1')
|
36
|
+
link rel='stylesheet' href=%(#{cdn_base}/font-awesome/#{font_awesome_version}/css/all.min.css)
|
37
|
+
link rel='stylesheet' href=%(#{cdn_base}/font-awesome/#{font_awesome_version}/css/v4-shims.min.css)
|
31
38
|
- else
|
32
39
|
link rel='stylesheet' href=(normalize_web_path %(#{attr 'iconfont-name', 'font-awesome'}.css), (attr 'stylesdir', ''), false)
|
33
40
|
- if attr? :stem
|
34
41
|
- eqnums_val = (attr 'eqnums', 'none')
|
35
42
|
- eqnums_val = 'AMS' if eqnums_val == ''
|
36
43
|
- eqnums_opt = %( equationNumbers: { autoNumber: "#{eqnums_val}" } )
|
44
|
+
- mathjaxdir = (attr 'mathjaxdir', "#{cdn_base}/mathjax/2.7.6")
|
37
45
|
script type='text/x-mathjax-config'
|
38
46
|
| MathJax.Hub.Config({
|
39
47
|
tex2jax: {
|
@@ -47,60 +55,38 @@ html lang=(attr :lang, 'en' unless attr? :nolang)
|
|
47
55
|
},
|
48
56
|
TeX: {#{eqnums_opt}}
|
49
57
|
});
|
50
|
-
script src='#{
|
58
|
+
script src='#{mathjaxdir}/MathJax.js?config=TeX-MML-AM_HTMLorMML'
|
51
59
|
|
52
60
|
- syntax_hl = self.syntax_highlighter
|
53
61
|
- if syntax_hl && (syntax_hl.docinfo? :head)
|
54
62
|
=syntax_hl.docinfo :head, self, cdn_base_url: cdn_base, linkcss: linkcss, self_closing_tag_slash: '/'
|
55
|
-
|
63
|
+
|
64
|
+
/! Printing and PDF exports
|
56
65
|
javascript:
|
57
66
|
var link = document.createElement( 'link' );
|
58
67
|
link.rel = 'stylesheet';
|
59
68
|
link.type = 'text/css';
|
60
69
|
link.href = window.location.search.match( /print-pdf/gi ) ? "#{revealjsdir}/css/print/pdf.css" : "#{revealjsdir}/css/print/paper.css";
|
61
70
|
document.getElementsByTagName( 'head' )[0].appendChild( link );
|
62
|
-
|
63
|
-
<script src="#{revealjsdir}/lib/js/html5shiv.js"></script>
|
64
|
-
- unless (docinfo_content = docinfo :header, '.html').empty?
|
65
|
-
=docinfo_content
|
71
|
+
|
66
72
|
- if attr? :customcss
|
67
73
|
link rel='stylesheet' href=((customcss = attr :customcss).empty? ? 'asciidoctor-revealjs.css' : customcss)
|
74
|
+
- unless (_docinfo = docinfo :head, '-revealjs.html').empty?
|
75
|
+
=_docinfo
|
68
76
|
body
|
69
77
|
.reveal
|
70
78
|
/ Any section element inside of this container is displayed as a slide
|
71
79
|
.slides
|
72
|
-
- unless
|
73
|
-
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
data-background-size=(attr 'title-slide-background-size')
|
81
|
-
data-background-image=bg_image
|
82
|
-
data-background-video=bg_video
|
83
|
-
data-background-video-loop=(attr 'title-slide-background-video-loop')
|
84
|
-
data-background-video-muted=(attr 'title-slide-background-video-muted')
|
85
|
-
data-background-opacity=(attr "background-opacity")
|
86
|
-
data-background-iframe=(attr 'title-slide-background-iframe')
|
87
|
-
data-background-color=(attr 'title-slide-background-color')
|
88
|
-
data-background-repeat=(attr 'title-slide-background-repeat')
|
89
|
-
data-background-position=(attr 'title-slide-background-position')
|
90
|
-
data-background-transition=(attr 'title-slide-background-transition'))
|
91
|
-
- if (_title_obj = doctitle partition: true, use_fallback: true).subtitle?
|
92
|
-
h1=slice_text _title_obj.title, (_slice = header.option? :slice)
|
93
|
-
h2=slice_text _title_obj.subtitle, _slice
|
94
|
-
- else
|
95
|
-
h1=@header.title
|
96
|
-
- preamble = @document.find_by context: :preamble
|
97
|
-
- unless preamble.nil? or preamble.length == 0
|
98
|
-
div.preamble=preamble.pop.content
|
99
|
-
- unless author.nil?
|
100
|
-
p.author: small=author
|
101
|
-
=content
|
102
|
-
script src="#{revealjsdir}/lib/js/head.min.js"
|
80
|
+
- unless noheader
|
81
|
+
- unless (_docinfo = docinfo :header, '-revealjs.html').empty?
|
82
|
+
= _docinfo
|
83
|
+
- if header?
|
84
|
+
include title_slide.html.slim
|
85
|
+
= content
|
86
|
+
- unless (_docinfo = docinfo :footer, '-revealjs.html').empty?
|
87
|
+
= _docinfo
|
103
88
|
script src="#{revealjsdir}/js/reveal.js"
|
89
|
+
/ Supports easy AsciiDoc syntax for background color
|
104
90
|
javascript:
|
105
91
|
Array.prototype.slice.call(document.querySelectorAll('.slides section')).forEach(function(slide) {
|
106
92
|
if (slide.getAttribute('data-background-color')) return;
|
@@ -111,9 +97,11 @@ html lang=(attr :lang, 'en' unless attr? :nolang)
|
|
111
97
|
slide.setAttribute('data-background-color', bgColor);
|
112
98
|
slide.style.backgroundColor = 'transparent';
|
113
99
|
}
|
114
|
-
})
|
100
|
+
});
|
115
101
|
|
116
|
-
//
|
102
|
+
// More info about config & dependencies:
|
103
|
+
// - https://github.com/hakimel/reveal.js#configuration
|
104
|
+
// - https://github.com/hakimel/reveal.js#dependencies
|
117
105
|
Reveal.initialize({
|
118
106
|
// Display presentation control arrows
|
119
107
|
controls: #{to_boolean(attr 'revealjs_controls', true)},
|
@@ -131,12 +119,17 @@ html lang=(attr :lang, 'en' unless attr? :nolang)
|
|
131
119
|
slideNumber: #{to_valid_slidenumber(attr 'revealjs_slidenumber', false)},
|
132
120
|
// Control which views the slide number displays on
|
133
121
|
showSlideNumber: '#{attr 'revealjs_showslidenumber', 'all'}',
|
134
|
-
//
|
122
|
+
// Add the current slide number to the URL hash so that reloading the
|
123
|
+
// page/copying the URL will return you to the same slide
|
124
|
+
hash: #{to_boolean(attr 'revealjs_hash', false)},
|
125
|
+
// Push each slide change to the browser history. Implies `hash: true`
|
135
126
|
history: #{to_boolean(attr 'revealjs_history', false)},
|
136
127
|
// Enable keyboard shortcuts for navigation
|
137
128
|
keyboard: #{to_boolean(attr 'revealjs_keyboard', true)},
|
138
129
|
// Enable the slide overview mode
|
139
130
|
overview: #{to_boolean(attr 'revealjs_overview', true)},
|
131
|
+
// Disables the default reveal.js slide layout so that you can use custom CSS layout
|
132
|
+
disableLayout: #{to_boolean(attr 'revealjs_disablelayout', false)},
|
140
133
|
// Vertical centering of slides
|
141
134
|
center: #{to_boolean(attr 'revealjs_center', true)},
|
142
135
|
// Enables touch navigation on devices with touch input
|
@@ -145,6 +138,8 @@ html lang=(attr :lang, 'en' unless attr? :nolang)
|
|
145
138
|
loop: #{to_boolean(attr 'revealjs_loop', false)},
|
146
139
|
// Change the presentation direction to be RTL
|
147
140
|
rtl: #{to_boolean(attr 'revealjs_rtl', false)},
|
141
|
+
// See https://github.com/hakimel/reveal.js/#navigation-mode
|
142
|
+
navigationMode: '#{attr 'revealjs_navigationmode', 'default'}',
|
148
143
|
// Randomizes the order of slides each time the presentation loads
|
149
144
|
shuffle: #{to_boolean(attr 'revealjs_shuffle', false)},
|
150
145
|
// Turns fragments on and off globally
|
@@ -165,6 +160,12 @@ html lang=(attr :lang, 'en' unless attr? :nolang)
|
|
165
160
|
// - true: All media will autoplay, regardless of individual setting
|
166
161
|
// - false: No media will autoplay, regardless of individual setting
|
167
162
|
autoPlayMedia: #{attr 'revealjs_autoplaymedia', 'null'},
|
163
|
+
// Global override for preloading lazy-loaded iframes
|
164
|
+
// - null: Iframes with data-src AND data-preload will be loaded when within
|
165
|
+
// the viewDistance, iframes with only data-src will be loaded when visible
|
166
|
+
// - true: All iframes with data-src will be loaded when within the viewDistance
|
167
|
+
// - false: All iframes with data-src will be loaded only when visible
|
168
|
+
preloadIframes: #{attr 'revealjs_preloadiframes', 'null'},
|
168
169
|
// Number of milliseconds between automatically proceeding to the
|
169
170
|
// next slide, disabled when set to 0, this value can be overwritten
|
170
171
|
// by using a data-autoslide attribute on your slides
|
@@ -177,8 +178,23 @@ html lang=(attr :lang, 'en' unless attr? :nolang)
|
|
177
178
|
// presenting each slide. This is used to show a pacing timer in the
|
178
179
|
// speaker view
|
179
180
|
defaultTiming: #{attr 'revealjs_defaulttiming', 120},
|
181
|
+
// Specify the total time in seconds that is available to
|
182
|
+
// present. If this is set to a nonzero value, the pacing
|
183
|
+
// timer will work out the time available for each slide,
|
184
|
+
// instead of using the defaultTiming value
|
185
|
+
totalTime: #{attr 'revealjs_totaltime', 0},
|
186
|
+
// Specify the minimum amount of time you want to allot to
|
187
|
+
// each slide, if using the totalTime calculation method. If
|
188
|
+
// the automated time allocation causes slide pacing to fall
|
189
|
+
// below this threshold, then you will see an alert in the
|
190
|
+
// speaker notes window
|
191
|
+
minimumTimePerSlide: #{attr 'revealjs_minimumtimeperslide', 0},
|
180
192
|
// Enable slide navigation via mouse wheel
|
181
193
|
mouseWheel: #{to_boolean(attr 'revealjs_mousewheel', false)},
|
194
|
+
// Hide cursor if inactive
|
195
|
+
hideInactiveCursor: #{to_boolean(attr 'revealjs_hideinactivecursor', true)},
|
196
|
+
// Time before the cursor is hidden (in ms)
|
197
|
+
hideCursorTime: #{attr 'revealjs_hidecursortime', 5000},
|
182
198
|
// Hides the address bar on mobile devices
|
183
199
|
hideAddressBar: #{to_boolean(attr 'revealjs_hideaddressbar', true)},
|
184
200
|
// Opens links in an iframe preview overlay
|
@@ -193,6 +209,10 @@ html lang=(attr :lang, 'en' unless attr? :nolang)
|
|
193
209
|
backgroundTransition: '#{attr 'revealjs_backgroundtransition', 'fade'}',
|
194
210
|
// Number of slides away from the current that are visible
|
195
211
|
viewDistance: #{attr 'revealjs_viewdistance', 3},
|
212
|
+
// Number of slides away from the current that are visible on mobile
|
213
|
+
// devices. It is advisable to set this to a lower number than
|
214
|
+
// viewDistance in order to save resources.
|
215
|
+
mobileViewDistance: #{attr 'revealjs_mobileviewdistance', 3},
|
196
216
|
// Parallax background image (e.g., "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'")
|
197
217
|
parallaxBackgroundImage: '#{attr 'revealjs_parallaxbackgroundimage', ''}',
|
198
218
|
// Parallax background size in CSS syntax (e.g., "2100px 900px")
|
@@ -226,19 +246,16 @@ html lang=(attr :lang, 'en' unless attr? :nolang)
|
|
226
246
|
|
227
247
|
// Optional libraries used to extend on reveal.js
|
228
248
|
dependencies: [
|
229
|
-
|
230
|
-
#{(document.attr? 'source-highlighter', 'highlightjs') ? "{ src: '#{revealjsdir}/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }," : nil}
|
231
|
-
#{(attr? 'revealjs_plugin_zoom', 'disabled') ? "" : "{ src: '#{revealjsdir}/plugin/zoom-js/zoom.js', async: true }," }
|
232
|
-
#{(attr? 'revealjs_plugin_notes', 'disabled') ? "" : "{ src: '#{revealjsdir}/plugin/notes/notes.js', async: true }," }
|
233
|
-
#{(attr? 'revealjs_plugin_marked', 'enabled') ? "{ src: '#{revealjsdir}/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }," : "" }
|
234
|
-
#{(attr? 'revealjs_plugin_markdown', 'enabled') ? "{ src: '#{revealjsdir}/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }," : "" }
|
235
|
-
#{(attr? 'revealjs_plugin_pdf', 'enabled') ? "{ src: '#{revealjsdir}/plugin/print-pdf/print-pdf.js', async: true }," : "" }
|
236
|
-
#{(attr? 'revealjs_plugins') ? File.read(attr('revealjs_plugins', '')) : ""}
|
249
|
+
#{revealjs_dependencies(document, self, revealjsdir)}
|
237
250
|
],
|
238
251
|
|
239
252
|
#{(attr? 'revealjs_plugins_configuration') ? File.read(attr('revealjs_plugins_configuration', '')) : ""}
|
240
253
|
|
241
254
|
});
|
255
|
+
/ Workaround the "Only direct descendants of a slide section can be stretched" limitation in reveal.js
|
256
|
+
/ https://github.com/hakimel/reveal.js/issues/2584
|
257
|
+
include stretch_nested_elements.js.slim
|
258
|
+
|
242
259
|
- if syntax_hl && (syntax_hl.docinfo? :footer)
|
243
260
|
=syntax_hl.docinfo :footer, self, cdn_base_url: cdn_base, linkcss: linkcss, self_closing_tag_slash: '/'
|
244
261
|
|
data/templates/example.html.slim
CHANGED
data/templates/helpers.rb
CHANGED
@@ -24,6 +24,23 @@ module Slim::Helpers
|
|
24
24
|
val && val != 'false' && val.to_s != '0' || false
|
25
25
|
end
|
26
26
|
|
27
|
+
# bool_data_attr
|
28
|
+
# If the AsciiDoc attribute doesn't exist, no HTML attribute is added
|
29
|
+
# If the AsciiDoc attribute exist and is a true value, HTML attribute is enabled (bool)
|
30
|
+
# If the AsciiDoc attribute exist and is a false value, HTML attribute is a false string
|
31
|
+
# Ex: a feature is enabled globally but can be disabled using a data- attribute on individual items
|
32
|
+
# :revealjs_previewlinks: True
|
33
|
+
# then link::example.com[Link text, preview=false]
|
34
|
+
# Here the template must have data-preview-link="false" not just no data-preview-link attribute
|
35
|
+
def bool_data_attr val
|
36
|
+
return false unless attr?(val)
|
37
|
+
if attr(val).downcase == 'false' || attr(val) == '0'
|
38
|
+
'false'
|
39
|
+
else
|
40
|
+
true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
27
44
|
# false needs to be verbatim everything else is a string.
|
28
45
|
# Calling side isn't responsible for quoting so we are doing it here
|
29
46
|
def to_valid_slidenumber val
|
@@ -55,25 +72,52 @@ module Slim::Helpers
|
|
55
72
|
# @yield The block of Slim/HTML code within the tag (optional).
|
56
73
|
# @return [String] a rendered HTML element.
|
57
74
|
#
|
58
|
-
|
59
75
|
def html_tag(name, attributes = {}, content = nil)
|
60
76
|
attrs = attributes.inject([]) do |attrs, (k, v)|
|
61
|
-
next attrs
|
77
|
+
next attrs unless v && (v == true || !v.nil_or_empty?)
|
62
78
|
v = v.compact.join(' ') if v.is_a? Array
|
63
79
|
attrs << (v == true ? k : %(#{k}="#{v}"))
|
64
80
|
end
|
65
81
|
attrs_str = attrs.empty? ? '' : ' ' + attrs.join(' ')
|
66
82
|
|
67
|
-
|
68
83
|
if VOID_ELEMENTS.include? name.to_s
|
69
84
|
%(<#{name}#{attrs_str}>)
|
70
85
|
else
|
71
|
-
content ||= yield if block_given?
|
86
|
+
content ||= (yield if block_given?)
|
72
87
|
%(<#{name}#{attrs_str}>#{content}</#{name}>)
|
73
88
|
end
|
74
89
|
end
|
75
90
|
|
76
91
|
|
92
|
+
#
|
93
|
+
# Extracts data- attributes from the attributes.
|
94
|
+
# @param attributes [Hash] (default: {})
|
95
|
+
# @return [Hash] a Hash that contains only data- attributes
|
96
|
+
#
|
97
|
+
def data_attrs(attributes)
|
98
|
+
# key can be an Integer (for positional attributes)
|
99
|
+
attributes.map { |key, value| (key == 'step') ? ['data-fragment-index', value] : [key, value] }
|
100
|
+
.to_h
|
101
|
+
.select { |key, _| key.to_s.start_with?('data-') }
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
#
|
106
|
+
# Wrap an inline text in a <span> element if the node contains a role, an id or data- attributes.
|
107
|
+
# @param content [#to_s] the content; +nil+ to call the block. (default: nil).
|
108
|
+
# @return [String] the content or the content wrapped in a <span> element as string
|
109
|
+
#
|
110
|
+
def inline_text_container(content = nil)
|
111
|
+
data_attrs = data_attrs(@attributes)
|
112
|
+
classes = [role, ('fragment' if (option? :step) || (attr? 'step') || (roles.include? 'step'))].compact
|
113
|
+
if !roles.empty? || !data_attrs.empty? || !@id.nil?
|
114
|
+
html_tag('span', { :id => @id, :class => classes }.merge(data_attrs), (content || (yield if block_given?)))
|
115
|
+
else
|
116
|
+
content || (yield if block_given?)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
|
77
121
|
##
|
78
122
|
# Returns corrected section level.
|
79
123
|
#
|
@@ -84,6 +128,52 @@ module Slim::Helpers
|
|
84
128
|
@_section_level ||= (sec.level == 0 && sec.special) ? 1 : sec.level
|
85
129
|
end
|
86
130
|
|
131
|
+
##
|
132
|
+
# Display footnotes per slide
|
133
|
+
#
|
134
|
+
@@slide_footnotes = {}
|
135
|
+
@@section_footnotes = {}
|
136
|
+
|
137
|
+
def slide_footnote(footnote)
|
138
|
+
footnote_parent = footnote.parent
|
139
|
+
# footnotes declared on the section title are processed during the parsing/substitution.
|
140
|
+
# as a result, we need to store them to display them on the right slide/section
|
141
|
+
if footnote_parent.instance_of?(::Asciidoctor::Section)
|
142
|
+
footnote_parent_object_id = footnote_parent.object_id
|
143
|
+
section_footnotes = (@@section_footnotes[footnote_parent_object_id] || [])
|
144
|
+
footnote_index = section_footnotes.length + 1
|
145
|
+
attributes = footnote.attributes.merge({ 'index' => footnote_index })
|
146
|
+
inline_footnote = Asciidoctor::Inline.new(footnote_parent, footnote.context, footnote.text, :attributes => attributes)
|
147
|
+
section_footnotes << Asciidoctor::Document::Footnote.new(inline_footnote.attr(:index), inline_footnote.id, inline_footnote.text)
|
148
|
+
@@section_footnotes[footnote_parent_object_id] = section_footnotes
|
149
|
+
inline_footnote
|
150
|
+
else
|
151
|
+
parent = footnote.parent
|
152
|
+
until parent == nil || parent.instance_of?(::Asciidoctor::Section)
|
153
|
+
parent = parent.parent
|
154
|
+
end
|
155
|
+
# check if there is any footnote attached on the section title
|
156
|
+
section_footnotes = parent != nil ? @@section_footnotes[parent.object_id] || [] : []
|
157
|
+
initial_index = footnote.attr(:index)
|
158
|
+
# reset the footnote numbering to 1 on each slide
|
159
|
+
# make sure that if a footnote is used more than once it will use the same index/number
|
160
|
+
slide_index = (existing_footnote = @@slide_footnotes[initial_index]) ? existing_footnote.index : @@slide_footnotes.length + section_footnotes.length + 1
|
161
|
+
attributes = footnote.attributes.merge({ 'index' => slide_index })
|
162
|
+
inline_footnote = Asciidoctor::Inline.new(footnote_parent, footnote.context, footnote.text, :attributes => attributes)
|
163
|
+
@@slide_footnotes[initial_index] = Asciidoctor::Document::Footnote.new(inline_footnote.attr(:index), inline_footnote.id, inline_footnote.text)
|
164
|
+
inline_footnote
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def clear_slide_footnotes
|
169
|
+
@@slide_footnotes = {}
|
170
|
+
end
|
171
|
+
|
172
|
+
def slide_footnotes(section)
|
173
|
+
section_object_id = section.object_id
|
174
|
+
section_footnotes = @@section_footnotes[section_object_id] || []
|
175
|
+
section_footnotes + @@slide_footnotes.values
|
176
|
+
end
|
87
177
|
|
88
178
|
##
|
89
179
|
# Returns the captioned section's title, optionally numbered.
|
@@ -101,6 +191,20 @@ module Slim::Helpers
|
|
101
191
|
end
|
102
192
|
end
|
103
193
|
|
194
|
+
def revealjs_dependencies(document, node, revealjsdir)
|
195
|
+
dependencies = []
|
196
|
+
dependencies << "{ src: '#{revealjsdir}/plugin/zoom-js/zoom.js', async: true }" unless (node.attr? 'revealjs_plugin_zoom', 'disabled')
|
197
|
+
dependencies << "{ src: '#{revealjsdir}/plugin/notes/notes.js', async: true }" unless (node.attr? 'revealjs_plugin_notes', 'disabled')
|
198
|
+
dependencies << "{ src: '#{revealjsdir}/plugin/markdown/marked.js', async: true }" if (node.attr? 'revealjs_plugin_marked', 'enabled')
|
199
|
+
dependencies << "{ src: '#{revealjsdir}/plugin/markdown/markdown.js', async: true }" if (node.attr? 'revealjs_plugin_markdown', 'enabled')
|
200
|
+
if (node.attr? 'revealjs_plugins') &&
|
201
|
+
!(revealjs_plugins_file = (node.attr 'revealjs_plugins', '').strip).empty? &&
|
202
|
+
!(revealjs_plugins_content = (File.read revealjs_plugins_file).strip).empty?
|
203
|
+
dependencies << revealjs_plugins_content
|
204
|
+
end
|
205
|
+
dependencies.join(",\n ")
|
206
|
+
end
|
207
|
+
|
104
208
|
|
105
209
|
# Between delimiters (--) is code taken from asciidoctor-bespoke 1.0.0.alpha.1
|
106
210
|
# Licensed under MIT, Copyright (C) 2015-2016 Dan Allen and the Asciidoctor Project
|
@@ -113,8 +217,69 @@ module Slim::Helpers
|
|
113
217
|
def resolve_content
|
114
218
|
@content_model == :simple ? %(<p>#{content}</p>) : content
|
115
219
|
end
|
116
|
-
#--
|
117
220
|
|
221
|
+
# Capture nested template content and register it with the specified key, to
|
222
|
+
# be executed at a later time.
|
223
|
+
#
|
224
|
+
# This method must be invoked using the control code directive (i.e., -). By
|
225
|
+
# using a control code directive, the block is set up to append the result
|
226
|
+
# directly to the output buffer. (Integrations often hide the distinction
|
227
|
+
# between a control code directive and an output directive in this context).
|
228
|
+
#
|
229
|
+
# key - The Symbol under which to save the template block.
|
230
|
+
# opts - A Hash of options to control processing (default: {}):
|
231
|
+
# * :append - A Boolean that indicates whether to append this block
|
232
|
+
# to others registered with this key (default: false).
|
233
|
+
# * :content - String content to be used if template content is not
|
234
|
+
# provided (optional).
|
235
|
+
# block - The template content (in Slim template syntax).
|
236
|
+
#
|
237
|
+
# Examples
|
238
|
+
#
|
239
|
+
# - content_for :body
|
240
|
+
# p content
|
241
|
+
# - content_for :body, append: true
|
242
|
+
# p more content
|
243
|
+
#
|
244
|
+
# Returns nothing.
|
245
|
+
def content_for key, opts = {}, &block
|
246
|
+
@content = {} unless defined? @content
|
247
|
+
(opts[:append] ? (@content[key] ||= []) : (@content[key] = [])) << (block_given? ? block : lambda { opts[:content] })
|
248
|
+
nil
|
249
|
+
end
|
250
|
+
|
251
|
+
# Checks whether deferred template content has been registered for the specified key.
|
252
|
+
#
|
253
|
+
# key - The Symbol under which to look for saved template blocks.
|
254
|
+
#
|
255
|
+
# Returns a Boolean indicating whether content has been registered for this key.
|
256
|
+
def content_for? key
|
257
|
+
(defined? @content) && (@content.key? key)
|
258
|
+
end
|
259
|
+
|
260
|
+
# Evaluates the deferred template content registered with the specified key.
|
261
|
+
#
|
262
|
+
# When the corresponding content_for method is invoked using a control code
|
263
|
+
# directive, the block is set up to append the result to the output buffer
|
264
|
+
# directly.
|
265
|
+
#
|
266
|
+
# key - The Symbol under which to look for template blocks to yield.
|
267
|
+
# opts - A Hash of options to control processing (default: {}):
|
268
|
+
# * :drain - A Boolean indicating whether to drain the key of blocks
|
269
|
+
# after calling them (default: true).
|
270
|
+
#
|
271
|
+
# Examples
|
272
|
+
#
|
273
|
+
# - yield_content :body
|
274
|
+
#
|
275
|
+
# Returns nothing (assuming the content has been captured in the context of control code).
|
276
|
+
def yield_content key, opts = {}
|
277
|
+
if (defined? @content) && (blks = (opts.fetch :drain, true) ? (@content.delete key) : @content[key])
|
278
|
+
blks.map {|b| b.call }.join
|
279
|
+
end
|
280
|
+
nil
|
281
|
+
end
|
282
|
+
#--
|
118
283
|
end
|
119
284
|
|
120
285
|
# More custom functions can be added in another namespace if required
|