dove 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c6f8473843077e47f14b0dd3b99a461c11bbf4d3
4
+ data.tar.gz: 288e3a6f703f956eded4111f08f546b40a575762
5
+ SHA512:
6
+ metadata.gz: b7f0f2d445dbd7c8691ee2f9b3f57af764dd770fe302ed7877d474aa0c27c45d342174045cd019109685cb41d2287370f608ae159dfc90f06a4f06a3a615f3a8
7
+ data.tar.gz: 019eab34d953bc0a7f279eb486216283f57bfcb23a5b4942c6dfe1258ab7983438c62f2feaafaa4170666832625543f8f8ed803f9959085fe01234ac039857dc
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
@@ -0,0 +1,51 @@
1
+ # Dove
2
+
3
+ Write single page HTML documents with ease.
4
+
5
+ I sometimes want to quickly draft documents in something other than LaTeX. I've realized
6
+ that in the 21^st century HTML pages can easily serve that same purpose DOC, ODT and PDF
7
+ files serve. Dove enables you to write your text in Markdown, then generate beautiful web
8
+ documents.
9
+
10
+ Example output can be seen [here](http://archseer.github.io/dove/).
11
+
12
+ ## Note
13
+
14
+ I was really lazy and didn't want to bother converting Markdown into HTML, then inserting
15
+ it into a HTML layout and bothering with syntax highlighting, so I've searched for alternatives.
16
+ I've used Jekyll before, but for writing one-page documents I don't really need a full-blown
17
+ static website solution. I then I had found [rocco](https://github.com/rtomayko/rocco)
18
+ which is a code documentation generator, and I've used a bit of the code from it
19
+ to write Dove, a (web) document generator.
20
+
21
+ ## About
22
+
23
+ Dove takes a Markdown file, converts it using [Redcarpet](https://github.com/vmg/redcarpet), syntax highlights
24
+ any code snippets inside using [Rouge](https://github.com/jayferd/rouge), then
25
+ it takes a layout file (I use [Slim](http://slim-lang.com/)) and uses [Tilt](https://github.com/rtomayko/tilt)
26
+ to render it, and insert the document into the template. It also detects and
27
+ extracts any YAML frontmatter and inserts it into the layout as variables!
28
+
29
+ ## Usage
30
+
31
+ Dove is meant to be used using it's binary file:
32
+
33
+ ```
34
+ dove document.md
35
+ ```
36
+
37
+ Glob patterns can also be used just as easily:
38
+
39
+ ```
40
+ dove *.md README *.txt
41
+ ```
42
+
43
+ But one can also require Dove inside a script, and make a new instance of it,
44
+ passing in the filename and options, then use the `render` method.
45
+
46
+ ```ruby
47
+ dove = Dove.new('document.md', template_file: 'doc_layout.slim')
48
+ dove.render
49
+ ```
50
+
51
+ Note: The default layout requires `author` and `title` YAML frontmatter.
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env ruby
2
+ #/ Usage: dove [-o <dir>] <file>...
3
+ #/ Generate web documents from Markdown <file>s. Glob patterns can be used.
4
+ #/
5
+ #/ Options:
6
+ #/ -t, --template=<path> Specify the file to use as template
7
+ #/ -w, --watch Watch for file changes and rebuild
8
+ #/ --help Show this help message
9
+
10
+ require 'optparse'
11
+ require 'fileutils'
12
+ require 'dove'
13
+
14
+ # Write usage message to stdout and exit.
15
+ def usage(stream=$stderr, status=1)
16
+ stream.puts File.readlines(__FILE__).
17
+ grep(/^#\//).
18
+ map { |line| line.sub(/^#. ?/, '') }.
19
+ join
20
+ exit status
21
+ end
22
+
23
+ # Like `Kernel#abort` but writes a note encouraging the user to consult
24
+ # `dove --help` for more information.
25
+ def abort_with_note(message=nil)
26
+ $stderr.puts message if message
27
+ abort "See `dove --help' for usage information."
28
+ end
29
+
30
+ # Generate the file and write it to output dir.
31
+ def build(filename, options)
32
+ dove = Dove.new(filename, options)
33
+ dest = "#{File.basename(filename, '.*')}.html"
34
+ dest = File.join(options[:output_dir], dest) if options[:output_dir] != '.'
35
+ puts "dove: #{Time.now.strftime("%Y-%m-%d %H:%M:%S")} #{filename} -> #{dest}"
36
+ FileUtils.mkdir_p File.dirname(dest)
37
+ File.open(dest, 'wb') { |fd| fd.write(dove.render) }
38
+ end
39
+
40
+ # Parse command line options, aborting if anything goes wrong.
41
+ sources = []
42
+ options = {:output_dir => '.'}
43
+ ARGV.options { |o|
44
+ o.program_name = File.basename($0)
45
+ o.on("-o", "--output=DIR") { |dir| options[:output_dir] = dir }
46
+ o.on("-t", "--template=TEMPLATE") { |template| options[:template_file] = template }
47
+ o.on("-s", "--stylesheet=STYLESHEET") { |stylesheet| options[:stylesheet] = stylesheet }
48
+ o.on("-w", "--watch") { options[:watch] = true }
49
+ o.on_tail("-h", "--help") { usage($stdout, 0) }
50
+ o.parse!
51
+ } or abort_with_note
52
+
53
+ # Eat sources from ARGV.
54
+ sources.push(*Dir[ARGV.shift]) while ARGV.any?
55
+
56
+ # Make sure we have some files to work with.
57
+ if sources.empty?
58
+ abort_with_note "#{File.basename($0)}: no input <file>s given"
59
+ end
60
+
61
+ # Run each file through Dove and write output.
62
+ sources.each do |filename|
63
+ build(filename, options)
64
+ end
65
+
66
+ def watch(files, options)
67
+ require 'directory_watcher'
68
+
69
+ dw = DirectoryWatcher.new('.', glob: files, pre_load: true, interval: 1)
70
+
71
+ dw.add_observer do |*args|
72
+ args.each { |event| build(event.path, options) }
73
+ end
74
+
75
+ dw.start
76
+
77
+ trap("INT") do
78
+ puts "dove: flew away"
79
+ exit 0
80
+ end
81
+ loop { sleep 1000 }
82
+ end
83
+
84
+ # Start the watcher if the watch option was enabled.
85
+ watch(sources, options) if options[:watch]
@@ -0,0 +1,23 @@
1
+ $:.unshift File.expand_path("../lib", __FILE__)
2
+ require "dove/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.platform = Gem::Platform::RUBY
6
+ s.name = 'dove'
7
+ s.version = Dove::VERSION
8
+ s.homepage = 'https://github.com/archSeer/dove'
9
+ s.authors = ["Blaž Hrastnik"]
10
+ s.email = ['speed.the.bboy@gmail.com']
11
+ s.summary = "Write single page HTML documents with ease"
12
+ s.description = "Write single page HTML documents with ease"
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ #s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = ["dove"]
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency 'redcarpet', '~> 2.3.0'
20
+ s.add_dependency 'tilt', '~> 1.4.1'
21
+ s.add_dependency 'slim', '~> 2.0'
22
+ s.add_dependency 'rouge', '~> 0.3.7'
23
+ end
@@ -0,0 +1,47 @@
1
+ require 'redcarpet'
2
+ require 'tilt'
3
+ require 'slim'
4
+ require 'yaml'
5
+ require 'rouge'
6
+ require 'dove/rougify'
7
+
8
+ class Dove
9
+ def initialize(filename, options ={})
10
+ @file = filename
11
+
12
+ # When `block` is given, it must read the contents of the file using
13
+ # whatever means necessary and return it as a string. With no `block`,
14
+ # the file is read to retrieve data.
15
+ @data, @yaml_data = extract_yaml(if block_given? then yield else File.read(filename) end)
16
+
17
+ @options = {
18
+ :output_dir => '.',
19
+ :template_file => "#{File.dirname(__FILE__)}/dove/layout.slim",
20
+ #:stylesheet => 'styles.css'
21
+ }.merge(options)
22
+ end
23
+
24
+ # Extracts the YAML frontmatter.
25
+ def extract_yaml text
26
+ if md = text.match(/\A(---\s*\n.*?\n?)^(---\s*$\n?)/m)
27
+ [md.post_match, YAML.load(md[1])]
28
+ else
29
+ [text, {}]
30
+ end
31
+ end
32
+
33
+ # Renders the Markdown file and inserts it into the layout.
34
+ def render
35
+ extensions = {
36
+ autolink: true,
37
+ space_after_headers: true,
38
+ fenced_code_blocks: true,
39
+ lax_spacing: true,
40
+ strikethrough: true,
41
+ superscript: true,
42
+ no_intra_emphasis: true
43
+ }
44
+ markdown = Redcarpet::Markdown.new(Rougify, extensions)
45
+ Tilt.new(@options[:template_file], {pretty: true}).render(Object.new, @yaml_data) { markdown.render(@data) }
46
+ end
47
+ end
@@ -0,0 +1,12 @@
1
+ doctype html
2
+ html
3
+ head
4
+ meta charset="utf-8"
5
+ title = title
6
+ link rel='stylesheet' type='text/css' href='styles.css'
7
+ link rel='stylesheet' type='text/css' href='http://fonts.googleapis.com/css?family=Source+Sans+Pro'
8
+
9
+ body
10
+ header = title
11
+ article == yield
12
+ footer Copyright &copy; #{Time.now.year} #{author}
@@ -0,0 +1,4 @@
1
+ require 'rouge/plugins/redcarpet'
2
+ class Rougify < Redcarpet::Render::HTML
3
+ include Rouge::Plugins::Redcarpet # use Rouge with Redcarpet
4
+ end
@@ -0,0 +1,3 @@
1
+ class Dove
2
+ VERSION = '0.1.1'
3
+ end
@@ -0,0 +1,241 @@
1
+ /* http://meyerweb.com/eric/tools/css/reset/
2
+ v2.0 | 20110126
3
+ License: none (public domain)
4
+ */
5
+
6
+ html, body, div, span, applet, object, iframe,
7
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
8
+ a, abbr, acronym, address, big, cite, code,
9
+ del, dfn, em, img, ins, kbd, q, s, samp,
10
+ small, strike, strong, sub, sup, tt, var,
11
+ b, u, i, center,
12
+ dl, dt, dd, ol, ul, li,
13
+ fieldset, form, label, legend,
14
+ table, caption, tbody, tfoot, thead, tr, th, td,
15
+ article, aside, canvas, details, embed,
16
+ figure, figcaption, footer, header, hgroup,
17
+ menu, nav, output, ruby, section, summary,
18
+ time, mark, audio, video {
19
+ margin: 0;
20
+ padding: 0;
21
+ border: 0;
22
+ font-size: 100%;
23
+ font: inherit;
24
+ vertical-align: baseline;
25
+ }
26
+ /* HTML5 display-role reset for older browsers */
27
+ article, aside, details, figcaption, figure,
28
+ footer, header, hgroup, menu, nav, section {
29
+ display: block;
30
+ }
31
+ body {
32
+ line-height: 1;
33
+ }
34
+ ol, ul {
35
+ list-style: none;
36
+ }
37
+ blockquote, q {
38
+ quotes: none;
39
+ }
40
+ blockquote:before, blockquote:after,
41
+ q:before, q:after {
42
+ content: '';
43
+ content: none;
44
+ }
45
+ table {
46
+ border-collapse: collapse;
47
+ border-spacing: 0;
48
+ }
49
+
50
+ /* END reset.css */
51
+
52
+ a {
53
+ color: hsl(235, 65%, 64%);
54
+ border-bottom: 1px solid;
55
+ text-decoration: none;
56
+ }
57
+ a:hover {
58
+ color: hsl(235, 65%, 84%);
59
+ }
60
+
61
+ h1, h2, h3, h4, h5, h6 {
62
+ margin: 1em 0 15px;
63
+ font-family: inherit;
64
+ font-weight: bold;
65
+ line-height: 20px;
66
+ color: #222;
67
+ text-rendering: optimizeLegibility;
68
+ }
69
+
70
+ h1, h2, h3 {line-height: 40px}
71
+ h1 {font-size: 38.5px}
72
+ h2 {font-size: 31.5px}
73
+ h3 {font-size: 24.5px}
74
+ h4 {font-size: 17.5px}
75
+ h5 {font-size: 14px}
76
+ h6 {font-size: 11.9px}
77
+
78
+ h1 {border-bottom: 1px solid #ddd}
79
+ h2 {border-bottom: 1px solid #eee}
80
+
81
+ p, ul, ol {
82
+ margin: 0 0 1em;
83
+ line-height: 1.6;
84
+ }
85
+
86
+ em {font-style: italic}
87
+
88
+ strong {font-weight: bold; color: #444;}
89
+
90
+ code, pre {
91
+ /* colors match the Tomorrow Night rouge theme */
92
+ background-color: #1d1f21;
93
+ color: #c5c8c6;
94
+ padding: 2px 5px;
95
+ margin: 0 0 20px;
96
+ font-size: 14px;
97
+ font-family: Monaco, courier, monospace;
98
+ -webkit-font-smoothing: antialiased;
99
+ overflow: auto;
100
+ border-radius: 3px;
101
+ line-height: 1.35;
102
+ }
103
+
104
+ pre {
105
+ display: block;
106
+ padding: 10px 15px;
107
+ }
108
+
109
+ blockquote {
110
+ font-size: 14px;
111
+ line-height: 22px;
112
+ color: #777;
113
+ margin: 10px;
114
+ padding-left: 15px;
115
+ border-left: 1px solid #ccc;
116
+ }
117
+
118
+ ul, ol {margin-left: 20px;}
119
+ ul li {list-style-type: square;}
120
+ ol li {list-style-type: decimal;}
121
+
122
+
123
+ /* superscript and subscript https://gist.github.com/unruthless/413930 */
124
+ sub, sup {
125
+ /* Specified in % so that the sup/sup is the
126
+ right size relative to the surrounding text */
127
+ font-size: 75%;
128
+
129
+ /* Zero out the line-height so that it doesn't
130
+ interfere with the positioning that follows */
131
+ line-height: 0;
132
+
133
+ /* Where the magic happens: makes all browsers position
134
+ the sup/sup properly, relative to the surrounding text */
135
+ position: relative;
136
+
137
+ /* Note that if you're using Eric Meyer's reset.css, this
138
+ is already set and you can remove this rule */
139
+ vertical-align: baseline;
140
+ }
141
+
142
+ sup {
143
+ /* Move the superscripted text up */
144
+ top: -0.5em;
145
+ }
146
+
147
+ sub {
148
+ /* Move the subscripted text down, but only
149
+ half as far down as the superscript moved up */
150
+ bottom: -0.25em;
151
+ }
152
+
153
+ /* styles */
154
+
155
+ body {
156
+ font-family: Source Sans Pro;
157
+ color: #666;
158
+ max-width: 720px;
159
+ margin: 15px auto;
160
+ }
161
+
162
+ header {
163
+ color: hsl(235, 65%, 64%);
164
+ font-weight: 900;
165
+ font-size: 80px;
166
+ text-align: center;
167
+ margin: 10px 0 50px;
168
+ }
169
+
170
+ footer {
171
+ margin: 50px 0 20px;
172
+ font-size: 12px;
173
+ text-align: center;
174
+ }
175
+
176
+ /* Modified Tomorrow Again color scheme -- https://github.com/MozMorris/tomorrow-pygments*/
177
+ .highlight .hll { background-color: #373b41 }
178
+ .highlight { background: #1d1f21; color: #c5c8c6 }
179
+ .highlight .c { color: #969896 } /* Comment */
180
+ .highlight .err { color: #cc6666 } /* Error */
181
+ .highlight .k { color: #b294bb } /* Keyword */
182
+ .highlight .l { color: #de935f } /* Literal */
183
+ .highlight .n { color: #c5c8c6 } /* Name */
184
+ .highlight .o { color: #c5c8c6 } /* Operator */
185
+ .highlight .p { color: #c5c8c6 } /* Punctuation */
186
+ .highlight .cm { color: #969896 } /* Comment.Multiline */
187
+ .highlight .cp { color: #969896 } /* Comment.Preproc */
188
+ .highlight .c1 { color: #969896 } /* Comment.Single */
189
+ .highlight .cs { color: #969896 } /* Comment.Special */
190
+ .highlight .gd { color: #cc6666 } /* Generic.Deleted */
191
+ .highlight .ge { font-style: italic } /* Generic.Emph */
192
+ .highlight .gh { color: #c5c8c6; font-weight: bold } /* Generic.Heading */
193
+ .highlight .gi { color: #b5bd68 } /* Generic.Inserted */
194
+ .highlight .gp { color: #969896; font-weight: bold } /* Generic.Prompt */
195
+ .highlight .gs { font-weight: bold } /* Generic.Strong */
196
+ .highlight .gu { color: #8abeb7; font-weight: bold } /* Generic.Subheading */
197
+ .highlight .kc { color: #b294bb } /* Keyword.Constant */
198
+ .highlight .kd { color: #b294bb } /* Keyword.Declaration */
199
+ .highlight .kn { color: #8abeb7 } /* Keyword.Namespace */
200
+ .highlight .kp { color: #b294bb } /* Keyword.Pseudo */
201
+ .highlight .kr { color: #b294bb } /* Keyword.Reserved */
202
+ .highlight .kt { color: #f0c674 } /* Keyword.Type */
203
+ .highlight .ld { color: #b5bd68 } /* Literal.Date */
204
+ .highlight .m { color: #de935f } /* Literal.Number */
205
+ .highlight .s { color: #b5bd68 } /* Literal.String */
206
+ .highlight .na { color: #81a2be } /* Name.Attribute */
207
+ .highlight .nb { color: #c5c8c6 } /* Name.Builtin */
208
+ .highlight .nc { color: #f0c674 } /* Name.Class */
209
+ .highlight .no { color: #cc6666 } /* Name.Constant */
210
+ .highlight .nd { color: #8abeb7 } /* Name.Decorator */
211
+ .highlight .ni { color: #c5c8c6 } /* Name.Entity */
212
+ .highlight .ne { color: #cc6666 } /* Name.Exception */
213
+ .highlight .nf { color: #81a2be } /* Name.Function */
214
+ .highlight .nl { color: #c5c8c6 } /* Name.Label */
215
+ .highlight .nn { color: #f0c674 } /* Name.Namespace */
216
+ .highlight .nx { color: #81a2be } /* Name.Other */
217
+ .highlight .py { color: #c5c8c6 } /* Name.Property */
218
+ .highlight .nt { color: #b294bb } /* Name.Tag */
219
+ .highlight .nv { color: #cc6666 } /* Name.Variable */
220
+ .highlight .ow { color: #8abeb7 } /* Operator.Word */
221
+ .highlight .w { color: #c5c8c6 } /* Text.Whitespace */
222
+ .highlight .mf { color: #de935f } /* Literal.Number.Float */
223
+ .highlight .mh { color: #de935f } /* Literal.Number.Hex */
224
+ .highlight .mi { color: #de935f } /* Literal.Number.Integer */
225
+ .highlight .mo { color: #de935f } /* Literal.Number.Oct */
226
+ .highlight .sb { color: #b5bd68 } /* Literal.String.Backtick */
227
+ .highlight .sc { color: #c5c8c6 } /* Literal.String.Char */
228
+ .highlight .sd { color: #969896 } /* Literal.String.Doc */
229
+ .highlight .s2 { color: #b5bd68 } /* Literal.String.Double */
230
+ .highlight .se { color: #de935f } /* Literal.String.Escape */
231
+ .highlight .sh { color: #b5bd68 } /* Literal.String.Heredoc */
232
+ .highlight .si { color: #de935f } /* Literal.String.Interpol */
233
+ .highlight .sx { color: #b5bd68 } /* Literal.String.Other */
234
+ .highlight .sr { color: #b5bd68 } /* Literal.String.Regex */
235
+ .highlight .s1 { color: #b5bd68 } /* Literal.String.Single */
236
+ .highlight .ss { color: #b5bd68 } /* Literal.String.Symbol */
237
+ .highlight .bp { color: #c5c8c6 } /* Name.Builtin.Pseudo */
238
+ .highlight .vc { color: #cc6666 } /* Name.Variable.Class */
239
+ .highlight .vg { color: #cc6666 } /* Name.Variable.Global */
240
+ .highlight .vi { color: #cc6666 } /* Name.Variable.Instance */
241
+ .highlight .il { color: #de935f } /* Literal.Number.Integer.Long */
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dove
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Blaž Hrastnik
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redcarpet
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 2.3.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 2.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: tilt
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 1.4.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 1.4.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: slim
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rouge
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.3.7
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.3.7
69
+ description: Write single page HTML documents with ease
70
+ email:
71
+ - speed.the.bboy@gmail.com
72
+ executables:
73
+ - dove
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - README.md
79
+ - bin/dove
80
+ - dove.gemspec
81
+ - lib/dove.rb
82
+ - lib/dove/layout.slim
83
+ - lib/dove/rougify.rb
84
+ - lib/dove/version.rb
85
+ - styles.css
86
+ homepage: https://github.com/archSeer/dove
87
+ licenses: []
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.0.3
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: Write single page HTML documents with ease
109
+ test_files: []
110
+ has_rdoc: