asciidoctor-bespoke 1.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4822d26c4ce17423d2e148a28c2d0af871853709
4
+ data.tar.gz: 031730a457905076d6c93c61466a9d4a7bca4ea2
5
+ SHA512:
6
+ metadata.gz: 0b18f5f0137dcb3485e20278346822fbb40be1ce35bfdfa7a57a496fb014f687dd553b05c8eed20c7c2285a8c7168c72cd6bc5f9d2bee62217b363b90e740a0d
7
+ data.tar.gz: 407226af5536610f26a341968f8ccf67418d8948d0a3c8f91e0e6d85827d410f5c0d651defa030282fe75bba563d194341a0bb9e28a022078dced1c11230cecd
data/LICENSE.adoc ADDED
@@ -0,0 +1,22 @@
1
+ .The MIT License
2
+ ....
3
+ Copyright (C) 2015-2016 Dan Allen and the Asciidoctor Project
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+ ....
data/README.adoc ADDED
@@ -0,0 +1,807 @@
1
+ = {project-name}
2
+ Dan Allen <https://github.com/mojavelinux>
3
+ v1.0.0.alpha.1, 2016-03-25
4
+ // Settings:
5
+ :idprefix:
6
+ :idseparator: -
7
+ ifndef::env-github[]
8
+ :icons: font
9
+ endif::[]
10
+ ifdef::env-github,env-browser[]
11
+ :toc: preamble
12
+ :toclevels: 2
13
+ endif::[]
14
+ ifdef::env-github[]
15
+ :outfilesuffix: .adoc
16
+ :!toc-title:
17
+ :caution-caption: :fire:
18
+ :important-caption: :exclamation:
19
+ :note-caption: :paperclip:
20
+ :tip-caption: :bulb:
21
+ :warning-caption: :warning:
22
+ endif::[]
23
+ // Aliases:
24
+ :latest-release: 1.0.0.alpha.1
25
+ :project-name: asciidoctor-bespoke
26
+ :conum-guard-js: //
27
+ ifndef::icons[:conum-guard-js: // //]
28
+ // URIs:
29
+ :uri-asciidoctor: http://asciidoctor.org
30
+ :uri-bespoke: http://markdalgleish.com/projects/bespoke.js/
31
+ :uri-bespoke-multimedia: https://github.com/opendevise/bespoke-multimedia
32
+ :uri-bundler: http://bundler.io
33
+ :uri-gulp: http://gulpjs.com
34
+ :uri-nodejs: https://nodejs.org
35
+ :uri-nvm: https://github.com/creationix/nvm
36
+ :uri-repo: https://github.com/asciidoctor/asciidoctor-bespoke
37
+ :uri-repo-file-prefix: {uri-repo}/blob/master/
38
+ :uri-repo-tree-prefix: {uri-repo}/tree/master/
39
+ ifdef::env-github[]
40
+ :uri-repo-file-prefix: link:
41
+ :uri-repo-tree-prefix: link:
42
+ endif::[]
43
+ :uri-ruby: https://www.ruby-lang.org
44
+ :uri-rvm: http://rvm.io
45
+ :uri-slim-docs: http://www.rubydoc.info/gems/slim/
46
+ :uri-svgo: https://github.com/svg/svgo
47
+ :uri-yo-bespoke: https://github.com/bespokejs/generator-bespoke
48
+
49
+ An {uri-asciidoctor}[Asciidoctor] converter that generates the HTML component of a {uri-bespoke}[Bespoke.js] presentation from AsciiDoc.
50
+
51
+ == Overview
52
+
53
+ The goal of {project-name} is to enable you to craft HTML-based presentations from reusable content while avoiding the tedium of writing HTML markup.
54
+ This library satisfies that goal by providing a converter that generates the HTML component of a Bespoke.js presentation from an AsciiDoc document.
55
+ In other words, it allows you to use AsciiDoc in place of HTML (or an HTML template language like Jade) in your Bespoke.js project.
56
+ (You still need to add an ample amount of CSS in order to achieve the presentation style you want).
57
+
58
+ The converter works in tandem with a typical JavaScript project structure based on npm and Gulp.
59
+ npm is used to manage dependencies, while a Gulp build is used to combine and "`browserify`" the JavaScript, compile the CSS, execute this converter (to convert AsciiDoc to HTML), launch the preview server and publish the presentation files.
60
+
61
+ The converter is implemented as a collection of Slim templates, which are packaged for your convenience as an Asciidoctor converter.
62
+ The templates come into play when you want to customize the HTML the converter generates.
63
+
64
+ This guide explains how to integrate the {project-name} converter into an existing Bespoke.js presentation project and how to write slides in AsciiDoc.
65
+
66
+ == Prerequisites
67
+
68
+ In order to use {project-name}, you must satisify the prerequisites of both Bespoke.js and Asciidoctor.
69
+
70
+ For Bespoke.js::
71
+ . {uri-nodejs}[Node.js] >= 0.12 footnote:[We strongly recommend using {uri-nvm}[nvm] to manage Node.]
72
+ . {uri-gulp}[Gulp] (command line interface only)
73
+
74
+ $ npm install -g gulp-cli
75
+
76
+ For Asciidoctor::
77
+
78
+ . {uri-ruby}[Ruby] >= 2 footnote:[We strongly recommend using {uri-rvm}[RVM] to manage Ruby.]
79
+ . {uri-bundler}[Bundler]
80
+
81
+ $ rvm use 2.3.0 --install # (optional)
82
+ $ gem install bundler
83
+
84
+ Naturally, you'll also need a Bespoke.js project, just as you would for any Bespoke.js presentation.
85
+ If you don't yet have a Bespoke.js project, you can clone the following starter project:
86
+
87
+ $ git clone https://github.com/opendevise/presentation-bespoke-starter
88
+
89
+ Alternatively, you can use the {uri-yo-bespoke}[Yeoman generator for Bespoke.js] to initialize your project.
90
+ As a word of warning, that generator has become substantially out of date.
91
+ In the future, we plan to provide an updated Yeoman generator that incorporates {project-name} into a new Bespoke.js project for you.
92
+
93
+ == Integrating AsciiDoc into a Bespoke.js Project
94
+
95
+ Once you've initialized your Bespoke.js project, the next task is to replace Jade with AsciiDoc.
96
+
97
+ TIP: If you're creating a new project using the starter project previously mentioned, and you switch to the `asciidoc` branch in that repository, you can skip the steps in this section and jump ahead to <<Creating Slides in AsciiDoc>>.
98
+ If you're curious, you can review https://github.com/opendevise/presentation-bespoke-starter/compare/asciidoc?diff=split[the diff of the changes] this section goes on to cover.
99
+
100
+ The first step is to configure Bundler to fetch and install the required gems.
101
+ Create the file [.path]_Gemfile_ at the root of the project and populate it with the following content:
102
+
103
+ .Gemfile
104
+ [source,ruby,subs=attributes+]
105
+ ----
106
+ source 'https://rubygems.org'
107
+
108
+ gem 'asciidoctor-bespoke', '{latest-release}'
109
+ # To use the latest version from git, use the following line instead:
110
+ #gem 'asciidoctor-bespoke', github: 'asciidoctor/asciidoctor-bespoke'
111
+ ----
112
+
113
+ Next, run `bundle` from the root of the project to install the gems and any dependencies:
114
+
115
+ $ bundle
116
+
117
+ [TIP]
118
+ ====
119
+ If you want to install the gems inside the project, you can pass the `--path` argument to `bundle`:
120
+
121
+ $ bundle --path=rubygems
122
+
123
+ The `bundle` command will remember this setting on subsequent invocations.
124
+ ====
125
+
126
+ The next step is to get the converter to generate the HTML from AsciiDoc when the presentation build runs.
127
+ We'll repurpose the task that currently generates HTML from Jade for this purpose.
128
+
129
+ Open [.path]_package.json_ and add the following entries to the `devDependencies` section:
130
+
131
+ .package.json (snippet)
132
+ [source,js]
133
+ "gulp-chmod": "^1.3.0",
134
+ "gulp-exec": "^2.1.2",
135
+
136
+ Save the file and run `npm i` to install the new packages into your project:
137
+
138
+ $ npm i
139
+
140
+ Open [.path]_gulpfile.js_ and add the following entries to the list of requires at the top:
141
+
142
+ .gulpfile.js (snippet)
143
+ [source,js]
144
+ chmod = require('gulp-chmod'),
145
+ exec = require('gulp-exec'),
146
+
147
+ In the same file, remove the existing `html` task and replace it with the one below:
148
+
149
+ .gulpfile.js (snippet)
150
+ [source,js,subs=attributes+]
151
+ gulp.task('html', ['clean:html'], function() {
152
+ return gulp.src('src/index.adoc')
153
+ .pipe(isDist ? through() : plumber())
154
+ .pipe(exec('bundle exec asciidoctor-bespoke -o - src/index.adoc', { pipeStdout: true }))
155
+ .pipe(exec.reporter({ stdout: false }))
156
+ .pipe(rename('index.html'))
157
+ .pipe(chmod(644))
158
+ .pipe(gulp.dest('public'))
159
+ .pipe(connect.reload());
160
+ });
161
+
162
+ //<1> Add `bundle exec` in front of the `asciidoctor-bespoke` command if you're using the development version from git.
163
+
164
+ Finally, if you want the build to watch the AsciiDoc file(s) for changes, look for the following line in the watch task:
165
+
166
+ .gulpfile.js (snippet)
167
+ [source,js]
168
+ gulp.watch('src/**/*.jade', ['html']);
169
+
170
+ and replace it with:
171
+
172
+ .gulpfile.js (snippet)
173
+ [source,js]
174
+ gulp.watch('src/**/*.adoc', ['html']);
175
+
176
+ The build is now ready.
177
+ Before we can use our new task, we need to create slide content in AsciiDoc.
178
+
179
+ == Creating Slides in AsciiDoc
180
+
181
+ Writing AsciiDoc to create slides is pretty much the same as writing AsciiDoc for any another purpose.
182
+ There are two key differences.
183
+ You'll be writing _a lot_ less content and you only need to use a single level of section headings (plus an optional document title).
184
+
185
+ === Hello, Bespoke.js!
186
+
187
+ Below is a basic presentation that is comprised of two slides, the title slide and one content slide.
188
+ To add this presentation to your project, create the file [.path]_src/index.adoc_ and populate it with the following content:
189
+
190
+ .src/index.adoc
191
+ [source,asciidoc]
192
+ ----
193
+ = My Awesome Presentation
194
+ :!sectids:
195
+
196
+ == First Topic
197
+ ----
198
+
199
+ Believe it or not, that's all it takes to make a presentation!
200
+
201
+ Here's a close approximation of the HTML the converter generates for the simple presentation shown above.
202
+
203
+ [source,html]
204
+ ----
205
+ <!DOCTYPE html>
206
+ <html lang="en">
207
+ <head>
208
+ <meta charset="utf-8">
209
+ <meta name="viewport" content="width=device-width, initial-scale=1">
210
+ <title>My Awesome Presentation</title>
211
+ <meta name="mobile-web-app-capable" content="yes">
212
+ <link rel="stylesheet" href="build/build.css">
213
+ </head>
214
+ <body>
215
+ <article class="deck">
216
+ <section class="title">
217
+ <h1>My Awesome Presentation</h1>
218
+ </section>
219
+ <section>
220
+ <h2>First Topic</h2>
221
+ </section>
222
+ </article>
223
+ <script src="build/build.js"></script>
224
+ </body>
225
+ </html>
226
+ ----
227
+
228
+ There are a few things you should notice:
229
+
230
+ * Each slide is represented as a `<section>`, which is generated for each section title.
231
+ - At runtime, Bespoke.js will add additional classes to each `<section>`, including `bespoke-slide`.
232
+ * The title slide has the class `title` and uses an `<h1>` heading.
233
+ * The section title for each content slide gets put in an `<h2>` heading.
234
+ * The presentation is wrapped in an `<article>` element with the class `deck`.
235
+ - At runtime, Bespoke.js will add additional classes to `<article>`, including `bespoke-parent`.
236
+ * CSS is used to accomplish most of the styling and layout, so you'll need to spend some time on it.
237
+ * The JavaScript and CSS to power the Bespoke.js presentation are loaded from the [.path]_build/_ folder.
238
+
239
+ Of course, this is not a very interesting presentation, so let's dig a bit deeper.
240
+
241
+ TIP: To see a complete example of a corporate-style presentation, check out the https://raw.githubusercontent.com/opendevise/bespoke-emulating-shower/master/src/index.adoc[AsciiDoc source] of the https://github.com/opendevise/bespoke-emulating-shower[Bespoke.js Emulating Shower] demo.
242
+
243
+ === The Title Slide
244
+
245
+ By default, the converter automatically creates a title slide from the document header and, if present, the preamble.
246
+ The document title (i.e., doctitle) becomes an `<h1>` heading.
247
+ The slide then incorporates additional information from the following attributes and nodes (subject to change):
248
+
249
+ * firstname (derived from the author attribute)
250
+ * lastname (derived from the author attribute)
251
+ * email (can be a URL)
252
+ * position
253
+ * organization
254
+ * twitter
255
+ * avatar (an image path relative to imagesdir)
256
+ * preamble content
257
+
258
+ NOTE: The title slide is a built-in transform mapped to the {uri-repo-file-prefix}templates/slim/slide_title.html.slim[slide_title.html.slim] template, which you can override.
259
+ You'll need to incorporate CSS (optionally using the Stylus syntax) to arrange and style the title page.
260
+
261
+ Here's an example of an AsciiDoc document that generates a title slide that is fully populated:
262
+
263
+ [source,asciidoc]
264
+ ----
265
+ = My Awesome Presentation
266
+ Author Name <http://example.com>
267
+ :organization: ACME Inc.
268
+ :position: Developer Advocate
269
+ :twitter: @asciidoctor
270
+ :avatar: author-avatar.png
271
+ :!sectids:
272
+
273
+ Additional content for title slide.
274
+
275
+ == First Topic
276
+ ----
277
+
278
+ If you don't want the title slide to be created, add the `noheader` attribute to the document header (or simply don't include a document header).
279
+
280
+ .A presentation without a title slide
281
+ [source,asciidoc]
282
+ ----
283
+ = My Awesome Presentation
284
+ :!sectids:
285
+ :noheader:
286
+
287
+ == First Topic
288
+ ----
289
+
290
+ === Content Slides
291
+
292
+ Each content slide is created from a level-1 section title.
293
+ The section title becomes an `<h2>` heading.
294
+ The remainder of the content in the section is placed below this heading.
295
+
296
+ NOTE: Any section levels below level-1 will simply be used as content in the slide.
297
+
298
+ Here's an example of a typical content slide with a heading:
299
+
300
+ .A slide with a heading and content
301
+ [source,asciidoc]
302
+ ----
303
+ == Agenda
304
+ * Lesson
305
+ * Demo
306
+ * Discussion
307
+ ----
308
+
309
+ While many of your slides may have a primary heading--perhaps as the only content on the slide--there are many slide types that don't require a heading.
310
+ You can indicate a slide without a heading by using `!` as the section title.
311
+ Here's an example:
312
+
313
+ .A slide with only content (i.e., an anonymous slide)
314
+ [source,asciidoc]
315
+ ----
316
+ == !
317
+ image::chart.svg[]
318
+ ----
319
+
320
+ If you want to assign a title to a slide, but just not show it, you can use the `conceal` option.
321
+
322
+ .A slide with a concealed heading
323
+ [source,asciidoc]
324
+ ----
325
+ [%conceal]
326
+ = An Amazing Chart
327
+ image::chart.svg[]
328
+ ----
329
+
330
+ A shorthand for the conceal option is to prefix the section title with a `!`.
331
+
332
+ .A shorthand for concealing the heading of a slide
333
+ [source,asciidoc]
334
+ ----
335
+ = !An Amazing Chart
336
+ image::chart.svg[]
337
+ ----
338
+
339
+ Notice how we're keeping the concerns of content and presentation cleanly separated.
340
+ Using very little AsciiDoc, you're able to describe a lot of different functionality.
341
+ There doesn't even have to be a direct, literal mapping between the AsciiDoc and the HTML.
342
+ Instead, you should think of the AsciiDoc as a DSL for content.
343
+
344
+ === The Speaker Slide
345
+
346
+ The converter includes an _experimental_ speaker slide, which you can place anywhere in the presentation.
347
+ To activate the speaker slide, create a section with an optional title and add the `transform=speaker` attribute.
348
+
349
+ [source,asciidoc]
350
+ ----
351
+ [transform=speaker]
352
+ == Speaker
353
+ ----
354
+
355
+ The speaker slide currently incorporates the following attributes:
356
+
357
+ * author
358
+ * position
359
+ * avatar (resolved relative to `imagesdir`)
360
+ * twitter
361
+ * email
362
+ * section content (if any)
363
+
364
+ NOTE: The speaker slide is a built-in transform mapped to the {uri-repo-file-prefix}templates/slim/slide_speaker.html.slim[slide_speaker.html.slim] template, which you can override.
365
+
366
+ Here's a rough approximation of the HTML generated for the speaker slide:
367
+
368
+ [source,html]
369
+ ----
370
+ <section class="speaker">
371
+ <header>
372
+ <h2>Speaker Name</h2>
373
+ <h3>Title</h3>
374
+ </header>
375
+ <figure class="image headshot">
376
+ <img src="images/speaker-name.jpg" alt="Speaker Name">
377
+ </figure>
378
+ <p class="contact">@speaker | speaker@example.org</p>
379
+ </section>
380
+ ----
381
+
382
+ CAUTION: The speaker slide is labeled as "`experimental`" because the HTML (content and layout) is likely to change as we learn the best way to organize the information.
383
+
384
+ === Builds
385
+
386
+ One of the most common ways to control the rate at which content is shown in a presentation is to use builds.
387
+ A [.term]_build_ is a presentation technique in which fragments of content are revealed incrementally (usually triggered by an event such as a button press or time delay).
388
+ The AsciiDoc converter supports a variety of ways to add builds to your presentation.
389
+
390
+ The build mechanism itself is handled by a Bespoke.js plugin (e.g., bespoke-bullets) with the help of some CSS.
391
+ You'll then use metadata in the AsciiDoc file to indicate which content should participate in a build.
392
+
393
+ The two ways to enlist content in a build are the build option and the build attribute.
394
+ The first should handle most situations, while the latter enables you to fine-tune the behavior.
395
+
396
+ Before diving into that metadata, we first need to do a bit of configuration.
397
+
398
+ ==== Build Configuration
399
+
400
+ Here's the JavaScript you'll need to add to your Bespoke.js configuration to activate the bespoke-bullets plugin to implement the behavior described in this section.
401
+
402
+ .src/scripts/main.js
403
+ [source,js,subs=attributes+]
404
+ ----
405
+ var bespoke = require('bespoke'),
406
+ bullets = require('bespoke-bullets'), {conum-guard-js} <1>
407
+ ...
408
+
409
+ bespoke.from('article', [
410
+ ...
411
+ bullets('.build,.build-items>*:not(.build-items)'), {conum-guard-js} <2>
412
+ ...
413
+ ]);
414
+ ----
415
+ <1> Load the bespoke-bullets plugin, assigning it to the `bullets` variable.
416
+ <2> Activate the bespoke-bullets plugin, using a CSS selector to query for buildable content.
417
+
418
+ Here's the CSS necessary to handle the visibility of build items and introduce several build effects.
419
+ You can customize the styles to your liking.
420
+
421
+ // FIXME explain how to write these styles in Stylus
422
+ [source,css]
423
+ ----
424
+ .bespoke-bullet:not(.bespoke-bullet-active) {
425
+ visibility: hidden;
426
+ pointer-events: none;
427
+ }
428
+
429
+ .fade .bespoke-bullet-active:not(.bespoke-bullet-current) {
430
+ opacity: 0.1;
431
+ }
432
+
433
+ .vanish .bespoke-bullet-active:not(.bespoke-bullet-current) {
434
+ visibility: hidden;
435
+ }
436
+ ----
437
+
438
+ ==== The build Option
439
+
440
+ Let's assume you have an unordered list on one of your slides and you want to reveal the items one-by-one.
441
+ Simply declare the build option on the list.
442
+
443
+ [source,asciidoc]
444
+ ----
445
+ [%build]
446
+ * one
447
+ * two
448
+ * three
449
+ ----
450
+
451
+ When the slide is first loaded, none of the items will be visible.
452
+ (The list container itself is the active build item).
453
+ Each time you press the button or key mapped to the "`next`" action, another item in the list will be revealed.
454
+ Past items will remain visible.
455
+
456
+ For content that doesn't have a container, such as a paragraph, you'll need to also add the build option to the section.
457
+
458
+ [source,asciidoc]
459
+ ----
460
+ [%build]
461
+ == Another Topic
462
+ [%build]
463
+ A point about this topic.
464
+ ----
465
+
466
+ The first build is automatically activated on slide entry.
467
+ Therefore, in order for the build on the paragraph to be deferred, the section title needs to be marked as the first build item.
468
+
469
+ At some point, you're likely to encounter a build permutation that can't be described using the option alone.
470
+ That's where the build attribute comes in.
471
+
472
+ ==== The build Attribute
473
+
474
+ The build attribute is used to describe more complex build scenarios.
475
+ Right now, it supports the following values (though more may be added in the futrue):
476
+
477
+ self:: The block itself should be enlisted in the build, but not its children.
478
+ items:: The block's children should be enlisted in the build, but not the block itself.
479
+ self+items (equivalent to the build option):: The block and its children should be enlisted in the build.
480
+
481
+ Using the build attribute, we can tackle the following two cases:
482
+
483
+ * Show the list all at once.
484
+ * Show the first item in the list on slide entry.
485
+
486
+ Let's first look at how to show the list all at once on the first "`next`" action.
487
+
488
+ [source,asciidoc]
489
+ ----
490
+ [%build]
491
+ == Another Topic
492
+ [build=self]
493
+ * one
494
+ * two
495
+ * three
496
+ ----
497
+
498
+ The section title is the first build step, which is automatically activated on slide entry.
499
+ The next build step is the list as a whole.
500
+
501
+ Now, instead, let's reveal the items in the list one-by-one, but show the first item on slide entry.
502
+
503
+ [source,asciidoc]
504
+ ----
505
+ == Another Topic
506
+ [build=items]
507
+ * one
508
+ * two
509
+ * three
510
+ ----
511
+
512
+ In this case, the first item in the list is the auto-activated build step.
513
+ The next build step is the second item in the list.
514
+
515
+ As you can see, the build attribute gives you more fine-grained control over the build behavior.
516
+
517
+ === Build Roles
518
+
519
+ You can use CSS to introduce additional build effects.
520
+ The effects supported out of the box are as follows:
521
+
522
+ * fade
523
+ * vanish
524
+ * replace (planned)
525
+
526
+ The CSS in the <<Build Configuration>> section implements these effects.
527
+
528
+ === Canvas Image
529
+
530
+ The converter supports adding a background image to a slide while still preserving the semantics of the document.
531
+ If the first content in a slide is a block image, and that image has the role `canvas`, the converter will pluck that image block out of the content and promote it to the background image of the slide.
532
+
533
+ [source,asciidoc]
534
+ ----
535
+ == !
536
+ [.canvas]
537
+ image::background-image.png[]
538
+ ----
539
+
540
+ This feature makes it really easy to create image-only slides that take up the full screen.
541
+
542
+ By default, the image is configured to cover the slide surface.
543
+ If you want to force the image to be contained within the dimensions of the slide (while preserving the aspect ratio), you can add the role `contain`.
544
+
545
+ [source,asciidoc]
546
+ ----
547
+ == !
548
+ [.contain.canvas]
549
+ image::background-image.png[]
550
+ ----
551
+
552
+ // QUESTION should we allow the role to be specified on the slide instead of the image block?
553
+
554
+ === Inserting SVGs
555
+
556
+ Just like for other image types, you use the block and inline image macros to add SVGs to your presentation (via AsciiDoc).
557
+ The difference comes in the fact that you can configure how the SVG is inserted into the HTML output.
558
+
559
+ The converter supports three ways of inserting an SVG into the HTML of a slide.
560
+ Each method is labeled below by the HTML element that is used:
561
+
562
+ `<img>`:: The SVG is linked as a rasterized image.
563
+ `<object>`:: The SVG is embedded as a live, interactive object (aka "`content document`").
564
+ `<svg>`:: The SVG is embedded directly into the HTML itself.
565
+
566
+ There are pros and cons of using each method (which is why the converter supports all three).
567
+ You can read more about the differences between these methods and their tradeoffs by studying the article https://www.smashingmagazine.com/2014/11/styling-and-animating-svgs-with-css/#embedding-svgs[Styling And Animating SVGs with CSS].
568
+
569
+ You declare an option on the image macro to control which method is used.
570
+ The option values are documented in the table below alongside the HTML element they emit.
571
+
572
+ .Options for controlling how the SVG is inserted into the HTML output
573
+ [cols="1,1m,2a"]
574
+ |===
575
+ |Option Name |HTML Element |AsciiDoc Example
576
+
577
+ |_none_ (default)
578
+ |<img>
579
+ |
580
+ ----
581
+ image::sample.svg[]
582
+ ----
583
+
584
+ |interactive
585
+ |<object>
586
+ |
587
+ ----
588
+ [%interactive]
589
+ image::sample.svg[]
590
+ ----
591
+
592
+ |inline
593
+ |<svg>
594
+ |
595
+ ----
596
+ [%inline]
597
+ image::sample.svg[]
598
+ ----
599
+ |===
600
+
601
+ When using inline or interactive, the `viewBox` attribute must be defined on the root `<svg>` element in order for scaling to work properly.
602
+ When using the inline option, if you specify a width or height on the image macro in AsciiDoc, the `width`, `height` and `style` attributes on the `<svg>` element will be removed.
603
+ If you're inserting an SVG using the inline method, we strongly recommend you optimize your SVG using a tool like {uri-svgo}[svgo].
604
+
605
+ TIP: The {uri-bespoke-multimedia}[bespoke-multimedia plugin] automatically adds the CSS class `active` to the root element of all "`interactive`" SVGs on the current slide, so long as the SVG is loaded from the same domain.
606
+
607
+ So which method should you choose?
608
+ It depends on how you're using the SVG.
609
+ Here are some rules of thumb to follow.
610
+
611
+ * Does the SVG have builds (aka bullets)? +
612
+ => Use *inline*.
613
+ * Do you want the SVG content to be reachable by JavaScript from the main DOM? +
614
+ => Use *inline*.
615
+ * Do you want the SVG content to inherit styles from the main DOM? +
616
+ => Use *inline*.
617
+ * Does the SVG have CSS animations? +
618
+ => Use *inline* or *interactive*.
619
+ - If using interactive, you must use the {uri-bespoke-multimedia}[bespoke-multimedia plugin] to control the animations on slide entry and exit.
620
+ * Does the SVG reference custom fonts (i.e., webfonts)? +
621
+ => Use *inline* or *interactive*.
622
+ - If using interactive, you must link to the CSS that declares the fonts in the SVG file using an XML stylesheet declaration.
623
+ * Are you simply using the SVG as a static image (and it doesn't use custom fonts)? +
624
+ => Use the *default*.
625
+
626
+ As you work with SVGs in your presentations, you'll become more comfortable making the decision about which method to employ given the circumstances.
627
+ It's only confusing the first couple of times.
628
+
629
+ === Speaker Notes
630
+
631
+ The converter recognizes designated blocks containing speaker notes and incorporates them into the presentation as hidden elements.
632
+ The speaker notes are then displayed adjacent to the current slide in a presentation console.
633
+
634
+ You add speaker notes to a slide by nesting them in a sidebar (or admonition) block and adding the role `cue` to that block.
635
+ That block must then be placed at the end of the section for that slide.
636
+
637
+ [source,asciidoc]
638
+ ----
639
+ == Topic
640
+ Slide content.
641
+
642
+ [.cue]
643
+ ****
644
+ Topic is all around us.
645
+
646
+ Topic has the following benefits:
647
+
648
+ * Easy to use
649
+ * Easy to scale
650
+ * It's free!
651
+ ****
652
+ ----
653
+
654
+ To learn more about how to setup a presentation console, see the https://github.com/opendevise/bespoke-onstage[bespoke-onstage plugin].
655
+
656
+ === Custom Transforms
657
+
658
+ While conversion from AsciiDoc is meant to save you time producing common slide types, there are cases when you find yourself going against the grain or exceeding the limits of what CSS can handle.
659
+ This situation is normal.
660
+ The truth is, certain slides require an HTML layout that is tailored to the content.
661
+ In these cases, you can use a custom transform.
662
+
663
+ You can delegate the conversion of a slide to a custom template by specifying the `transform` attribute.
664
+ The converter will then look for a template file that follows the pattern `slide_<transform>.html.slim`, where `<transform>` is the value of this attribute, inside the directory (or directories) specified by the `template_dir(s)` option.
665
+
666
+ Let's assume you want to create a custom presenter slide.
667
+ First, create a placeholder slide in the AsciiDoc and specify a custom transform.
668
+
669
+ [source,asciidoc]
670
+ ----
671
+ [transform=presenter]
672
+ == Presenter
673
+ ----
674
+
675
+ Next, create a file named [.path]_slide_presenter.html.slim_ in the directory that holds your templates.
676
+ The template is responsible for creating the `<section>` element for the slide.
677
+ (In fact, there's nothing stopping you from creating multiple slides).
678
+
679
+ .slide_presenter.html.slim
680
+ [source,slim]
681
+ ----
682
+ section.presenter id=id class=role
683
+ header
684
+ h2=document.attr :author
685
+ h3=document.attr :position
686
+ figure.image.headshot
687
+ img src=(image_uri document.attr :avatar) alt=(document.attr :author)
688
+ - unless (_content = content).empty?
689
+ =_content
690
+ ----
691
+
692
+ Finally, when you invoke the converter, you must specify the location of the template file using the `-T` option:
693
+
694
+ $ asciidoctor-bespoke -D public -T src/templates src/index.adoc
695
+
696
+ // TODO explain how to integrate into Gulp build
697
+
698
+ Since you can access the entire document model of the parsed AsciiDoc in the template, you are free to pick and choose the content you want to add to the slide and in what order.
699
+
700
+ Let's look at an example that draws from the document model selectively.
701
+ Assume you want to create one slide per item in a list.
702
+
703
+ [source,asciidoc]
704
+ ----
705
+ [transform=step_by_slide]
706
+ == !
707
+ * one
708
+ * two
709
+ * three
710
+ ----
711
+
712
+ Here's a template that implements this behavior:
713
+
714
+ .slide_step_by_slide.html.slim
715
+ [source,slim]
716
+ ----
717
+ - blocks.first.items.each do |_item|
718
+ section
719
+ p=_item.text
720
+ ----
721
+
722
+ This template applied to the previous slide content will generate the following HTML:
723
+
724
+ [source,html]
725
+ ----
726
+ <section>
727
+ <p>one</p>
728
+ </section>
729
+ <section>
730
+ <p>two</p>
731
+ </section>
732
+ <section>
733
+ <p>three</p>
734
+ </section>
735
+ ----
736
+
737
+ As you can see, there's no reason you have to stick to a 1-to-1 mapping between what is in the AsciiDoc file and the slide(s) you're generating.
738
+ The custom transform gives you the flexibility to layout the content on the slide exactly how you want.
739
+
740
+ You can go deeper and customize the template used for any node (without having to add any hints in the AsciiDoc).
741
+ This converter is based on a {uri-repo-tree-prefix}templates/slim[collection of Slim templates].
742
+ You can copy any one of these templates into your custom templates directory and make modifications to it.
743
+ Asciidoctor will use your copy instead of the matching template provided by the converter.
744
+ To learn more about how to write Slim templates, refer to the {uri-slim-docs}[Slim documentation].
745
+
746
+ ////
747
+ any global options specific to the Bespoke.js converter
748
+
749
+ === General HTML Customization (a custom template can be used for any node)
750
+
751
+ === Enclose Option
752
+
753
+ === Slice and Fit
754
+
755
+ === Fit Image
756
+
757
+ === Image Credit
758
+ ////
759
+
760
+ == Building the Presentation
761
+
762
+ === Building the Static Version
763
+
764
+ You can build a static version of the slides using the following command:
765
+
766
+ $ gulp
767
+
768
+ The files are built into the _public_ directory.
769
+ You can then view the slides by navigating to _public/index.html_ in your browser.
770
+
771
+ === Running the Preview Server
772
+
773
+ If you use the preview server, the build will monitor the project files for changes and automatically refresh the presentation in the browser when a change is detected.
774
+ You can launch the preview server using:
775
+
776
+ $ gulp serve
777
+
778
+ Once the server is running, you can view the slides by navigating to \http://localhost:8000 in your browser.
779
+
780
+ ////
781
+ == Publishing
782
+
783
+ TODO
784
+ ////
785
+
786
+ == Sample Presentations
787
+
788
+ * https://github.com/opendevise/presentation-bespoke-starter[Bespoke.js Starter Presentation]
789
+ * https://github.com/opendevise/bespoke-emulating-shower[Bespoke.js Emulating Shower]
790
+ * https://github.com/opendevise/bespoke-emulating-ioslides[Bespoke.js Emulating ioslides]
791
+ * https://github.com/opendevise/presentation-service-workers[Service Workers], a presentation by Hubert Sablonnière (ported from DZSlides)
792
+ * https://github.com/opendevise/neo4j-slide-types[Neo4j Slide Types]
793
+
794
+ == About the Project
795
+
796
+ === Authors
797
+
798
+ {project-name} was created by {email}[{author}].
799
+
800
+ Bespoke.js was created by https://github.com/markdalgleish[Mark Dalgleish] and has received contributions, mostly in the form of plugins, from many other individuals in the Bespoke.js ecosystem.
801
+
802
+ === Copyright
803
+
804
+ Copyright (C) 2015-2016 Dan Allen and the Asciidoctor Project.
805
+
806
+ Free use of this software is granted under the terms of the MIT License.
807
+ See the <<LICENSE#,LICENSE>> file for details.