slideck 0.1.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.
data/README.md ADDED
@@ -0,0 +1,475 @@
1
+ # Slideck
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/slideck.svg)][gem]
4
+ [![Actions CI](https://github.com/piotrmurach/slideck/workflows/CI/badge.svg?branch=master)][gh_actions_ci]
5
+ [![Build status](https://ci.appveyor.com/api/projects/status/kvlo53t54qimbfqy?svg=true)][appveyor]
6
+ [![Maintainability](https://api.codeclimate.com/v1/badges/c96e8367481519c38a06/maintainability)][codeclimate]
7
+ [![Coverage Status](https://coveralls.io/repos/github/piotrmurach/slideck/badge.svg)][coverage]
8
+
9
+ [gem]: https://badge.fury.io/rb/slideck
10
+ [gh_actions_ci]: https://github.com/piotrmurach/slideck/actions?query=workflow%3ACI
11
+ [appveyor]: https://ci.appveyor.com/project/piotrmurach/slideck
12
+ [codeclimate]:https://codeclimate.com/github/piotrmurach/slideck/maintainability
13
+ [coverage]: https://coveralls.io/github/piotrmurach/slideck
14
+
15
+ > Terminal tool for presenting Markdown-powered slide decks.
16
+
17
+ ## Features
18
+
19
+ * Write slides in the **Markdown** with extended syntax.
20
+ * Show code snippets in [fenced code blocks](https://www.markdownguide.org/extended-syntax/#fenced-code-blocks).
21
+ * Syntax highlight code for [over 200 languages](https://github.com/rouge-ruby/rouge/blob/master/docs/Languages.md).
22
+ * Create Markdown [tables](https://www.markdownguide.org/extended-syntax/#tables) with advanced formatting.
23
+ * [Align](#21-align) slide content with familiar CSS syntax.
24
+ * Add [margin](#23-margin) around content for all or a single slide.
25
+ * Track progress through the slides with a [pager](#24-pager).
26
+ * Display a [footer](#22-footer) at the bottom of every slide.
27
+ * Apply custom [symbols](#25-symbols) and style [theme](#26-theme) to content.
28
+ * Auto reload presentation when a file with slides changes.
29
+
30
+ ## Installation
31
+
32
+ **Slideck** will work with any version of Ruby greater than or equal to `2.0`.
33
+ Read [Installing Ruby](https://www.ruby-lang.org/en/documentation/installation/)
34
+ guide to choose the best installation method.
35
+
36
+ Once Ruby is set up, install the `slideck` with:
37
+
38
+ ```shell
39
+ $ gem install slideck
40
+ ```
41
+
42
+ ## Contents
43
+
44
+ * [1. Usage](#1-usage)
45
+ * [2. Configuration](#2-configuration)
46
+ * [2.1 align](#21-align)
47
+ * [2.2 footer](#22-footer)
48
+ * [2.3 margin](#23-margin)
49
+ * [2.4 pager](#24-pager)
50
+ * [2.5 symbols](#25-symbols)
51
+ * [2.6 theme](#26-theme)
52
+
53
+ ## 1. Usage
54
+
55
+ Open a text file and start writing slides in Markdown. Begin the document
56
+ by adding configuration for all slides in `YAML` format. Then to denote
57
+ a slide, separate its content with three dashes. Use the same configuration
58
+ settings to override the global settings for a slide. To do so, specify
59
+ settings with `YAML` flow mappings after the slide separator.
60
+
61
+ Here's a sample of a few slides with global and slide-specific configuration
62
+ settings:
63
+
64
+ ````markdown
65
+ align: center
66
+ margin: 2 5
67
+ footer:
68
+ align: center bottom
69
+ text: Footer content
70
+
71
+ --- margin: 0
72
+
73
+ # Welcome to Slideck
74
+
75
+ ## Built with TTY Toolkit
76
+
77
+ --- align: center top
78
+
79
+ # Code Block
80
+
81
+ ```ruby
82
+ puts "Welcome to Slideck"
83
+ ```
84
+
85
+ --- theme: {list: magenta}
86
+
87
+ # Unordered List
88
+
89
+ - Item 1
90
+ - Item 2
91
+ - Item 3
92
+
93
+ --- symbols: ascii
94
+
95
+ # Table
96
+
97
+ | A | B | C |
98
+ |---|---|---|
99
+ | a | b | c |
100
+ | a | b | c |
101
+ | a | b | c |
102
+
103
+ --- {pager: false, footer: false}
104
+
105
+ # The End
106
+ ````
107
+
108
+ To start presenting, for example, `slides.md` file in a terminal:
109
+
110
+ ```shell
111
+ $ slideck slides.md
112
+ ```
113
+
114
+ Use the `-h` or `--help` flag to see help about available presentation
115
+ controls and options:
116
+
117
+ ```shell
118
+ $ slideck --help
119
+ ```
120
+
121
+ Use the `-w` or `--watch` flag to automatically reload the presentation
122
+ with any update to the `slides.md` file:
123
+
124
+ ```shell
125
+ $ slideck slides.md --watch
126
+ ```
127
+
128
+ ## 2. Configuration
129
+
130
+ Configuration options can be global or slide-specific.
131
+
132
+ Add global configuration options in `YAML` format at the beginning
133
+ of a document.
134
+
135
+ For example, to configure [alignment](#21-align) and [margin](#23-margin)
136
+ for all slides:
137
+
138
+ ```markdown
139
+ align: center
140
+ margin: 2 5
141
+
142
+ ---
143
+
144
+ First Slide
145
+
146
+ ---
147
+
148
+ Second Slide
149
+
150
+ ---
151
+ ```
152
+
153
+ Use `YAML` flow mappings syntax to change the global configuration for a given
154
+ slide. This format is a series of key/value pairs separated by commas and
155
+ surrounded by curly braces. The semicolon with space follows a key and splits
156
+ it from value. Braces are optional for a single key/value pair.
157
+ A slide-specific configuration follows three dashes and needs to be on
158
+ the same line.
159
+
160
+ For example, to override [alignment](#21-align) and [margin](#23-margin)
161
+ for a given slide:
162
+
163
+ ```markdown
164
+ align: center
165
+ margin: 2 5
166
+
167
+ --- margin: 0
168
+
169
+ First Slide
170
+
171
+ --- {align: center top, margin: 1 3}
172
+
173
+ Second Slide
174
+
175
+ ---
176
+ ```
177
+
178
+ ### 2.1 Align
179
+
180
+ **Slideck** draws the slide's content from the left top of the terminal screen
181
+ by default. It positions the pager at the bottom right corner. When given, the
182
+ footer ends up at the bottom left corner. Use the `:align` configuration to
183
+ change the default positioning of content, [footer](#22-footer) and
184
+ [pager](#24-pager).
185
+
186
+ The `align` configuration takes either one or two values. The first value
187
+ specifies the horizontal alignment out of `left`, `center` and `right`.
188
+ The second value describes vertical alignment out of the `top`, `center`
189
+ and `bottom`. Skipping the second value will default the vertical alignment
190
+ to the `center`. Use a space, comma or both to separate two values.
191
+
192
+ For example, to position content at the top center of the screen
193
+ on every slide:
194
+
195
+ ```yaml
196
+ align: center top
197
+ ```
198
+
199
+ Or use shorthand to place content at the center left on every slide:
200
+
201
+ ```yaml
202
+ align: left
203
+ ```
204
+
205
+ Use the same configuration to change the alignment for a single slide. It
206
+ needs to follow after the slide separator and be on the same line.
207
+
208
+ For example, to place a given slide at the bottom left:
209
+
210
+ ```yaml
211
+ --- align: left bottom
212
+ ```
213
+
214
+ ### 2.2 Footer
215
+
216
+ **Slideck** doesn't show the footer by default. Use the `:footer` configuration
217
+ to add content to the bottom left of the screen for every slide.
218
+
219
+ For example, to display a footer on every slide:
220
+
221
+ ```yaml
222
+ footer: Footer content
223
+ ```
224
+
225
+ The footer supports `Markdown` syntax:
226
+
227
+ ```yaml
228
+ footer: **bold** content
229
+ ```
230
+
231
+ The footer can also span more than one line:
232
+
233
+ ```yaml
234
+ footer: "first line\nsecond line\nthird line"
235
+ ```
236
+
237
+ Use the `:align` key to change the footer alignment and the `:text` key
238
+ to specify its content.
239
+
240
+ For example, to specify a global footer at the bottom center of every slide:
241
+
242
+ ```yaml
243
+ footer:
244
+ align: center bottom
245
+ text: Footer content
246
+ ```
247
+
248
+ Use the same configuration to change the footer for a single slide. It needs
249
+ to follow after the slide separator and be on the same line.
250
+
251
+ For example, to place a footer at the bottom center of the screen:
252
+
253
+ ```yaml
254
+ --- footer: {align: center bottom, text: Footer content}
255
+ ```
256
+
257
+ Or, use a `false` value to hide a footer for a single slide:
258
+
259
+ ```yaml
260
+ --- footer: false
261
+ ```
262
+
263
+ ### 2.3 Margin
264
+
265
+ The `margin` specifies a distance from all four sides of the terminal screen.
266
+ It follows CSS rules and can have one, two, three or four integer values. Use
267
+ a space or comma to separate each integer value.
268
+
269
+ The following are all possible ways to specify a margin:
270
+
271
+ ```yaml
272
+ margin: 1 # the same margin of 1 for all sides
273
+ margin: 1 2 # 1 to the top and bottom, and 2 to the left and right
274
+ margin: 1 2 3 # 1 to the top, 2 to the left and right, and 3 to the bottom
275
+ margin: 1 2 3 4 # 1 to the top, 2 to the right, 3 to the bottom, 4 to the left
276
+ ```
277
+
278
+ Or, specify a margin with explicit side names:
279
+
280
+ ```yaml
281
+ margin:
282
+ top: 1
283
+ right: 2
284
+ bottom: 3
285
+ left: 4
286
+ ```
287
+
288
+ Like shorthand notation, specify names only for the configured sides.
289
+
290
+ For example, to add only the top margin and leave all the other sides with
291
+ their default values:
292
+
293
+ ```yaml
294
+ margin:
295
+ top: 1
296
+ ```
297
+
298
+ Use the same configuration to change the margin for a single slide. It needs
299
+ to follow after the slide separator and be on the same line.
300
+
301
+ For example, to zero out the margin for a given slide:
302
+
303
+ ```yaml
304
+ --- margin: 0
305
+ ```
306
+
307
+ ### 2.4 Pager
308
+
309
+ **Slideck** displays the `pager` in the bottom right corner of the terminal
310
+ screen. The display format is `%<page>d / %<total>d`, where the first
311
+ placeholder represents the current slide and the second is the total
312
+ number of slides.
313
+
314
+ For example, to change the pager display:
315
+
316
+ ```yaml
317
+ pager: "Page %<page>d of %<total>d"
318
+ ```
319
+
320
+ The pager supports `Markdown` syntax:
321
+
322
+ ```yaml
323
+ pager: "**Bold** %<total> pages"
324
+ ```
325
+
326
+ The pager can also span more than one line:
327
+
328
+ ```yaml
329
+ pager: "Page\n%<page>d\nof\n%<total>d"
330
+ ```
331
+
332
+ Use the `:align` key to change the pager alignment and the `:text` key
333
+ to specify its content.
334
+
335
+ For example, to place the pager at the bottom center of every slide:
336
+
337
+ ```yaml
338
+ pager:
339
+ align: center bottom
340
+ text: "Page %<page>d of %<total>d"
341
+ ```
342
+
343
+ Or, use a `false` value to hide a pager on all slides:
344
+
345
+ ```yaml
346
+ pager: false
347
+ ```
348
+
349
+ Use the same configuration to change the pager for a single slide. It needs
350
+ to follow after the slide separator and be on the same line.
351
+
352
+ For example, to place a pager at the bottom center of a given slide:
353
+
354
+ ```yaml
355
+ --- pager: {align: center bottom, text: "Page %<page>d of %<total>d"}
356
+ ```
357
+
358
+ Or, use a `false` value to hide a pager for a single slide:
359
+
360
+ ```yaml
361
+ --- pager: false
362
+ ```
363
+
364
+ ### 2.5 Symbols
365
+
366
+ **Slideck** decorates `Markdown` elements with `unicode` symbols by default.
367
+ Use the `:symbols` configuration to change the display of decorative
368
+ characters. It takes either a single value or key/value pairs. The single
369
+ value specifies a character set out of `ascii` or `unicode`. The key/value
370
+ pairs accept the `:base` and `:override` keys. Like a single value,
371
+ the `:base` key takes either `ascii` or `unicode`.
372
+
373
+ For example, to change the default symbols for all slides to `ascii`:
374
+
375
+ ```yaml
376
+ symbols: ascii
377
+ ```
378
+
379
+ Or, use the `:base` key to specify the `ascii` character set:
380
+
381
+ ```yaml
382
+ symbols:
383
+ base: ascii
384
+ ```
385
+
386
+ The `:override` key accepts key/value pairs, where the key is a symbol name
387
+ and the value is a decorative character. Please see the
388
+ [tty-markdown](https://github.com/piotrmurach/tty-markdown#24-symbols)
389
+ for a complete list of symbols.
390
+
391
+ For example, to change the `:bullet` symbol for every slide:
392
+
393
+ ```yaml
394
+ symbols:
395
+ override:
396
+ bullet: x
397
+ ```
398
+
399
+ Use the same configuration to change the symbols for a single slide. It needs
400
+ to follow after the slide separator and be on the same line.
401
+
402
+ For example, to change a character set to `ascii` for a single slide:
403
+
404
+ ```yaml
405
+ --- symbols: ascii
406
+ ```
407
+
408
+ Or, to change the `:bullet` symbol for a single slide:
409
+
410
+ ```yaml
411
+ --- symbols: {override: {bullet: x}}
412
+ ```
413
+
414
+ ### 2.6 Theme
415
+
416
+ **Slideck** displays `Markdown` elements with a default style theme. Use
417
+ the `:theme` configuration to change individual element styles. It takes
418
+ key/value pairs where the key is the element name, and the value is a single
419
+ style or list of styles. Please see the
420
+ [tty-markdown](https://github.com/piotrmurach/tty-markdown#22-theme)
421
+ for a complete list of element names and their styles.
422
+
423
+ For example, to change `em`, `link` and `list` element styles for every slide:
424
+
425
+ ```yaml
426
+ theme:
427
+ em: blue
428
+ link: cyan
429
+ list: magenta
430
+ ```
431
+
432
+ Use the same configuration to change the theme for a single slide. It needs
433
+ to follow after the slide separator and be on the same line.
434
+
435
+ For example, to change `em`, `link` and `list` element styles for
436
+ a single slide:
437
+
438
+ ```yaml
439
+ --- theme: {em: blue, link: cyan, list: magenta}
440
+ ```
441
+
442
+ ## Development
443
+
444
+ After checking out the repo, run `bin/setup` to install dependencies.
445
+ Then, run `rake spec` to run the tests. You can also run `bin/console`
446
+ for an interactive prompt that will allow you to experiment.
447
+
448
+ To install this gem onto your local machine, run `bundle exec rake install`.
449
+ To release a new version, update the version number in `version.rb`, and then
450
+ run `bundle exec rake release`, which will create a git tag for the version,
451
+ push git commits and the created tag, and push the `.gem` file to
452
+ [rubygems.org](https://rubygems.org).
453
+
454
+ ## Contributing
455
+
456
+ Bug reports and pull requests are welcome on GitHub at
457
+ https://github.com/piotrmurach/slideck. This project is intended to be a safe,
458
+ welcoming space for collaboration, and contributors are expected to adhere to
459
+ the [code of conduct](https://github.com/piotrmurach/slideck/blob/master/CODE_OF_CONDUCT.md).
460
+
461
+ ## License
462
+
463
+ The gem is available as open source under the terms of the
464
+ [GNU Affero General Public License v3.0](https://opensource.org/licenses/AGPL-3.0).
465
+
466
+ ## Code of Conduct
467
+
468
+ Everyone interacting in the Slideck project's codebases, issue trackers, chat
469
+ rooms and mailing lists is expected to follow the
470
+ [code of conduct](https://github.com/piotrmurach/slideck/blob/master/CODE_OF_CONDUCT.md).
471
+
472
+ ## Copyright
473
+
474
+ Copyright (c) 2022 Piotr Murach. See [LICENSE.txt](LICENSE.txt) for further
475
+ details.
data/exe/slideck ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/slideck"
4
+
5
+ Slideck.run
@@ -0,0 +1,201 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Slideck
4
+ # Responsible for accessing alignment configuration
5
+ #
6
+ # @api private
7
+ class Alignment
8
+ # The allowed horizontal alignment values
9
+ #
10
+ # @return [Array<String>]
11
+ #
12
+ # @api private
13
+ HORIZONTAL_VALUES = %w[left center right].freeze
14
+ private_constant :HORIZONTAL_VALUES
15
+
16
+ # The allowed vertical alignment values
17
+ #
18
+ # @return [Array<String>]
19
+ #
20
+ # @api private
21
+ VERTICAL_VALUES = %w[top center bottom].freeze
22
+ private_constant :VERTICAL_VALUES
23
+
24
+ # Create an Alignment instance from a string
25
+ #
26
+ # @example
27
+ # Slideck::Alignment.from("right top")
28
+ #
29
+ # @example
30
+ # Slideck::Alignment.from("right,top")
31
+ #
32
+ # @param [String] value
33
+ # the value to extract alignments from
34
+ # @param [String] default
35
+ # the default vertical alignment
36
+ #
37
+ # @return [Slideck::Alignment]
38
+ #
39
+ # @api public
40
+ def self.from(value, default: "center")
41
+ horizontal, vertical = *value.split(/[ ,]+/)
42
+ vertical = default if vertical.nil?
43
+
44
+ new(horizontal, vertical)
45
+ end
46
+
47
+ # Create an Alignment instance with an array-like initialiser
48
+ #
49
+ # @example
50
+ # Slideck::Alignment["right", "top"]
51
+ #
52
+ # @param [String] horizontal
53
+ # the horizontal value
54
+ # @param [String] vertical
55
+ # the vertical value
56
+ #
57
+ # @return [Slideck::Alignment]
58
+ #
59
+ # @api public
60
+ def self.[](horizontal, vertical)
61
+ new(horizontal, vertical)
62
+ end
63
+
64
+ # The horizontal alignment
65
+ #
66
+ # @example
67
+ # alignemnt.horizontal
68
+ #
69
+ # @return [String]
70
+ #
71
+ # @api public
72
+ attr_reader :horizontal
73
+
74
+ # The vertical alignment
75
+ #
76
+ # @example
77
+ # alignment.vertical
78
+ #
79
+ # @return [String]
80
+ #
81
+ # @api public
82
+ attr_reader :vertical
83
+
84
+ # Create an Alignment
85
+ #
86
+ # @example
87
+ # Slideck::Alignment.new("left", "top")
88
+ #
89
+ # @param [String] horizontal
90
+ # the horizontal value
91
+ # @param [String] vertical
92
+ # the vertical value
93
+ #
94
+ # @raise [Slideck::InvalidArgumentError]
95
+ #
96
+ # @api private
97
+ def initialize(horizontal, vertical)
98
+ @horizontal = validate_horizontal(horizontal)
99
+ @vertical = validate_vertical(vertical)
100
+
101
+ freeze
102
+ end
103
+ private_class_method :new
104
+
105
+ # Determine equivalence with another object
106
+ #
107
+ # @example
108
+ # alignment == other
109
+ #
110
+ # @param [Object] other
111
+ # the other object to determine equivalence with
112
+ #
113
+ # @return [Boolean]
114
+ # true if this object is equivalent to the other, false otherwise
115
+ #
116
+ # @api public
117
+ def ==(other)
118
+ other.is_a?(self.class) &&
119
+ horizontal == other.horizontal && vertical == other.vertical
120
+ end
121
+
122
+ # Determine equality with another object
123
+ #
124
+ # @example
125
+ # alignment.eql?(other)
126
+ #
127
+ # @param [Object] other
128
+ # the other object to determine equality with
129
+ #
130
+ # @return [Boolean]
131
+ # true if this object is equal to the other, false otherwise
132
+ #
133
+ # @api public
134
+ def eql?(other)
135
+ instance_of?(other.class) &&
136
+ horizontal.eql?(other.horizontal) && vertical.eql?(other.vertical)
137
+ end
138
+
139
+ # Generate hash value of this alignment
140
+ #
141
+ # @example
142
+ # alignment.hash
143
+ #
144
+ # @return [Integer]
145
+ #
146
+ # @api public
147
+ def hash
148
+ [self.class, horizontal, vertical].hash
149
+ end
150
+
151
+ # Convert this alignment into an array
152
+ #
153
+ # @example
154
+ # alignment.to_a
155
+ #
156
+ # @return [Array<String, String>]
157
+ #
158
+ # @api public
159
+ def to_a
160
+ [horizontal, vertical]
161
+ end
162
+
163
+ private
164
+
165
+ # Check whether a value is allowed as horizontal alignment
166
+ #
167
+ # @param [String] value
168
+ # the horizontal alignment value to check
169
+ #
170
+ # @raise [Slideck::InvalidArgumentError]
171
+ #
172
+ # @return [String]
173
+ #
174
+ # @api private
175
+ def validate_horizontal(value)
176
+ return value if HORIZONTAL_VALUES.include?(value)
177
+
178
+ raise InvalidArgumentError,
179
+ "unknown '#{value}' horizontal alignment. " \
180
+ "Valid value is: left, center and right."
181
+ end
182
+
183
+ # Check whether a vlaue is allowed as vertical alignment
184
+ #
185
+ # @param [String] value
186
+ # the vertical alignment value to check
187
+ #
188
+ # @raise [Slideck::InvalidArgumentError]
189
+ #
190
+ # @return [String]
191
+ #
192
+ # @api private
193
+ def validate_vertical(value)
194
+ return value if VERTICAL_VALUES.include?(value)
195
+
196
+ raise InvalidArgumentError,
197
+ "unknown '#{value}' vertical alignment. " \
198
+ "Valid value is: top, center and bottom."
199
+ end
200
+ end # Alignment
201
+ end # Slideck