liquidoc 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.
- checksums.yaml +7 -0
- data/bin/liquidoc +3 -0
- data/lib/liquidoc/version.rb +3 -0
- data/lib/liquidoc.rb +405 -0
- metadata +80 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: e6d540613bd9ce63cedb817ae5faec345f8f1ef6
|
|
4
|
+
data.tar.gz: b8d3ebaae9154e2c06632288226f0d0d790cba60
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 520b0885644503d9ef90e0283423c5eedfa3a53b2c3b6d920dcc60776e8173d770b64a80994e463cdb7a1c5411f1fc11e4d0b7ba43ec9687b349a82940067955
|
|
7
|
+
data.tar.gz: 760c4c9a0c6315f0c3488db65f839441a91e09e8e596c0c73ec9756443b2de21e21561154fe7db0511e81fdb598edf527567098f5cd6d62e184442d9241c256c
|
data/bin/liquidoc
ADDED
data/lib/liquidoc.rb
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
require "liquidoc"
|
|
2
|
+
require 'yaml'
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'optparse'
|
|
5
|
+
require 'liquid'
|
|
6
|
+
require 'asciidoctor'
|
|
7
|
+
require 'logger'
|
|
8
|
+
require 'csv'
|
|
9
|
+
require 'crack/xml'
|
|
10
|
+
|
|
11
|
+
# Default settings
|
|
12
|
+
@base_dir_def = Dir.pwd + '/'
|
|
13
|
+
@base_dir = @base_dir_def
|
|
14
|
+
@configs_dir = @base_dir + '_configs'
|
|
15
|
+
@templates_dir = @base_dir + '_templates/'
|
|
16
|
+
@data_dir = @base_dir + '_data/'
|
|
17
|
+
@output_dir = @base_dir + '_output/'
|
|
18
|
+
@config_file_def = @base_dir + '_configs/cfg-sample.yml'
|
|
19
|
+
@config_file = @config_file_def
|
|
20
|
+
@attributes_file_def = '_data/asciidoctor.yml'
|
|
21
|
+
@attributes_file = @attributes_file_def
|
|
22
|
+
@pdf_theme_file = 'theme/pdf-theme.yml'
|
|
23
|
+
@fonts_dir = 'theme/fonts/'
|
|
24
|
+
@output_filename = 'index'
|
|
25
|
+
@attributes = {}
|
|
26
|
+
|
|
27
|
+
@logger = Logger.new(STDOUT)
|
|
28
|
+
@logger.level = Logger::INFO
|
|
29
|
+
@logger.formatter = proc do |severity, datetime, progname, msg|
|
|
30
|
+
"#{severity}: #{msg}\n"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# ===
|
|
34
|
+
# General methods
|
|
35
|
+
# ===
|
|
36
|
+
|
|
37
|
+
# Pull in a semi-structured data file, converting contents to a Ruby hash
|
|
38
|
+
def get_data data_file
|
|
39
|
+
case File.extname(data_file)
|
|
40
|
+
when ".yml"
|
|
41
|
+
begin
|
|
42
|
+
return YAML.load_file(data_file)
|
|
43
|
+
rescue Exception => ex
|
|
44
|
+
@logger.error "There was a problem with the data file. #{ex.message}"
|
|
45
|
+
end
|
|
46
|
+
when ".json"
|
|
47
|
+
begin
|
|
48
|
+
return JSON.parse(File.read(data_file))
|
|
49
|
+
rescue Exception => ex
|
|
50
|
+
@logger.error "There was a problem with the data file. #{ex.message}"
|
|
51
|
+
end
|
|
52
|
+
when ".xml"
|
|
53
|
+
begin
|
|
54
|
+
data = Crack::XML.parse(File.read(data_file))
|
|
55
|
+
return data['root']
|
|
56
|
+
rescue Exception => ex
|
|
57
|
+
@logger.error "There was a problem with the data file. #{ex.message}"
|
|
58
|
+
end
|
|
59
|
+
when ".csv"
|
|
60
|
+
output = []
|
|
61
|
+
i = 0
|
|
62
|
+
begin
|
|
63
|
+
CSV.foreach(data_file, headers: true, skip_blanks: true) do |row|
|
|
64
|
+
output[i] = row.to_hash
|
|
65
|
+
i = i+1
|
|
66
|
+
end
|
|
67
|
+
output = {"data" => output}
|
|
68
|
+
return output
|
|
69
|
+
rescue
|
|
70
|
+
@logger.error "The CSV format is invalid."
|
|
71
|
+
end
|
|
72
|
+
else
|
|
73
|
+
@logger.error "The data file is an invalid type. Allowed: .yml, .json, .xml, and .csv."
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Establish source, template, index, etc details for build jobs from a config file
|
|
78
|
+
# TODO This needs to be turned into a Class?
|
|
79
|
+
def config_build config_file
|
|
80
|
+
@logger.debug "Using config file #{config_file}."
|
|
81
|
+
validate_file_input(config_file, "config")
|
|
82
|
+
begin
|
|
83
|
+
config = YAML.load_file(config_file)
|
|
84
|
+
rescue
|
|
85
|
+
unless File.exists?(config_file)
|
|
86
|
+
@logger.error "Config file not found."
|
|
87
|
+
else
|
|
88
|
+
@logger.error "Problem loading config file. Exiting."
|
|
89
|
+
end
|
|
90
|
+
raise "Could not load #{config_file}"
|
|
91
|
+
end
|
|
92
|
+
validate_config_structure(config)
|
|
93
|
+
if config['compile']
|
|
94
|
+
for src in config['compile']
|
|
95
|
+
data = @base_dir + src['data']
|
|
96
|
+
for cfgn in src['builds']
|
|
97
|
+
template = @base_dir + cfgn['template']
|
|
98
|
+
unless cfgn['output'] == "STDOUT" or @output_type == "STDOUT"
|
|
99
|
+
output = @base_dir + cfgn['output']
|
|
100
|
+
else
|
|
101
|
+
output = "STDOUT"
|
|
102
|
+
end
|
|
103
|
+
liquify(data, template, output)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
if config['publish']
|
|
108
|
+
begin
|
|
109
|
+
for pub in config['publish']
|
|
110
|
+
for bld in pub['builds']
|
|
111
|
+
if bld['publish']
|
|
112
|
+
publish(pub, bld)
|
|
113
|
+
else
|
|
114
|
+
@logger.warn "Publish build for '#{index}' backend '#{backend}' disabled."
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
rescue Exception => ex
|
|
119
|
+
@logger.error "Error during publish action. #{ex}"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Verify files exist
|
|
125
|
+
def validate_file_input file, type
|
|
126
|
+
@logger.debug "Validating input file for #{type} file #{file}"
|
|
127
|
+
error = false
|
|
128
|
+
unless file.is_a?(String) and !file.nil?
|
|
129
|
+
error = "The #{type} file (#{file}) is not valid."
|
|
130
|
+
else
|
|
131
|
+
unless File.exists?(file)
|
|
132
|
+
error = "The #{type} file (#{file}) was not found."
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
unless error
|
|
136
|
+
@logger.debug "Input file validated for #{type} file #{file}."
|
|
137
|
+
else
|
|
138
|
+
@logger.error
|
|
139
|
+
raise "Could not validate file input: #{error}"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def validate_config_structure config
|
|
144
|
+
unless config.is_a? Hash
|
|
145
|
+
message = "The configuration file is not properly structured; it is not a Hash"
|
|
146
|
+
@logger.error message
|
|
147
|
+
raise message
|
|
148
|
+
else
|
|
149
|
+
unless config['publish'] or config['compile']
|
|
150
|
+
raise "Config file must have at least one top-level section named 'publish:' or 'compile:'."
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
# TODO More validation needed
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# ===
|
|
157
|
+
# Liquify BUILD methods
|
|
158
|
+
# ===
|
|
159
|
+
|
|
160
|
+
# Parse given data using given template, saving to given filename
|
|
161
|
+
def liquify data_file, template_file, output_file
|
|
162
|
+
@logger.debug "Executing... liquify parsing operation on data file: #{data_file}, template #{template_file}, to #{output_file}."
|
|
163
|
+
validate_file_input(data_file, "data")
|
|
164
|
+
validate_file_input(template_file, "template")
|
|
165
|
+
data = get_data(data_file) # gathers the data
|
|
166
|
+
begin
|
|
167
|
+
template = File.read(template_file) # reads the template file
|
|
168
|
+
template = Liquid::Template.parse(template) # compiles template
|
|
169
|
+
rendered = template.render(data) # renders the output
|
|
170
|
+
rescue Exception => ex
|
|
171
|
+
message = "Problem rendering Liquid template. #{template_file}\n" \
|
|
172
|
+
"#{ex.class} thrown. #{ex.message}"
|
|
173
|
+
@logger.error message
|
|
174
|
+
raise message
|
|
175
|
+
end
|
|
176
|
+
unless @output_type == "STDOUT"
|
|
177
|
+
begin
|
|
178
|
+
Dir.mkdir(@output_dir) unless File.exists?(@output_dir)
|
|
179
|
+
File.open(output_file, 'w') { |file| file.write(rendered) } # saves file
|
|
180
|
+
rescue Exception => ex
|
|
181
|
+
@logger.error "Failed to save output.\n#{ex.class} #{ex.message}"
|
|
182
|
+
end
|
|
183
|
+
if File.exists?(output_file)
|
|
184
|
+
@logger.info "File built: #{File.basename(output_file)}"
|
|
185
|
+
else
|
|
186
|
+
@logger.error "Hrmp! File not built."
|
|
187
|
+
end
|
|
188
|
+
else # if stdout
|
|
189
|
+
puts "========\nOUTPUT: Rendered with template #{template_file}:\n\n#{rendered}\n"
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Copy images and other assets into output dir for HTML operations
|
|
194
|
+
def copy_assets src, dest
|
|
195
|
+
if @recursive
|
|
196
|
+
dest = "#{dest}/#{src}"
|
|
197
|
+
recursively = "Recursively c"
|
|
198
|
+
else
|
|
199
|
+
recursively = "C"
|
|
200
|
+
end
|
|
201
|
+
@logger.debug "#{recursively}opying image assets to #{dest}"
|
|
202
|
+
begin
|
|
203
|
+
FileUtils.mkdir_p(dest) unless File.exists?(dest)
|
|
204
|
+
FileUtils.cp_r(src, dest)
|
|
205
|
+
rescue Exception => ex
|
|
206
|
+
@logger.warn "Problem while copying assets. #{ex.message}"
|
|
207
|
+
return
|
|
208
|
+
end
|
|
209
|
+
@logger.debug "\s\s#{recursively}opied: #{src} --> #{dest}/#{src}"
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# ===
|
|
213
|
+
# PUBLISH methods
|
|
214
|
+
# ===
|
|
215
|
+
|
|
216
|
+
# Gather attributes from a fixed attributes file
|
|
217
|
+
# Use _data/attributes.yml or designate as -a path/to/filename.yml
|
|
218
|
+
def get_attributes attributes_file
|
|
219
|
+
if attributes_file == nil
|
|
220
|
+
attributes_file = @attributes_file_def
|
|
221
|
+
end
|
|
222
|
+
validate_file_input(attributes_file, "attributes")
|
|
223
|
+
begin
|
|
224
|
+
attributes = YAML.load_file(attributes_file)
|
|
225
|
+
return attributes
|
|
226
|
+
rescue
|
|
227
|
+
@logger.warn "Attributes file invalid."
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Set attributes for direct Asciidoctor operations
|
|
232
|
+
def set_attributes attributes
|
|
233
|
+
unless attributes.is_a?(Enumerable)
|
|
234
|
+
attributes = { }
|
|
235
|
+
end
|
|
236
|
+
attributes["basedir"] = @base_path
|
|
237
|
+
attributes.merge!get_attributes(@attributes_file)
|
|
238
|
+
attributes = '-a ' + attributes.map{|k,v| "#{k}='#{v}'"}.join(' -a ')
|
|
239
|
+
return attributes
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# To be replaced with a gem call
|
|
243
|
+
def publish pub, bld
|
|
244
|
+
@logger.warn "Publish actions not yet implemented."
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# ===
|
|
248
|
+
# Misc Classes, Modules, filters, etc
|
|
249
|
+
# ===
|
|
250
|
+
|
|
251
|
+
class String
|
|
252
|
+
# Adapted from Nikhil Gupta
|
|
253
|
+
# http://nikhgupta.com/code/wrapping-long-lines-in-ruby-for-display-in-source-files/
|
|
254
|
+
def wrap options = {}
|
|
255
|
+
width = options.fetch(:width, 76)
|
|
256
|
+
commentchar = options.fetch(:commentchar, '')
|
|
257
|
+
self.strip.split("\n").collect do |line|
|
|
258
|
+
line.length > width ? line.gsub(/(.{1,#{width}})(\s+|$)/, "\\1\n#{commentchar}") : line
|
|
259
|
+
end.map(&:strip).join("\n#{commentchar}")
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def indent options = {}
|
|
263
|
+
spaces = " " * options.fetch(:spaces, 4)
|
|
264
|
+
self.gsub(/^/, spaces).gsub(/^\s*$/, '')
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def indent_with_wrap options = {}
|
|
268
|
+
spaces = options.fetch(:spaces, 4)
|
|
269
|
+
width = options.fetch(:width, 80)
|
|
270
|
+
width = width > spaces ? width - spaces : 1
|
|
271
|
+
self.wrap(width: width).indent(spaces: spaces)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Liquid modules for text manipulation
|
|
277
|
+
module CustomFilters
|
|
278
|
+
def plainwrap input
|
|
279
|
+
input.wrap
|
|
280
|
+
end
|
|
281
|
+
def commentwrap input
|
|
282
|
+
input.wrap commentchar: "# "
|
|
283
|
+
end
|
|
284
|
+
def unwrap input # Not fully functional; inserts explicit '\n'
|
|
285
|
+
if input
|
|
286
|
+
token = "[g59hj1k]"
|
|
287
|
+
input.gsub(/\n\n/, token).gsub(/\n/, ' ').gsub(token, "\n\n")
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# From Slate Studio's fork of Locomotive CMS engine
|
|
292
|
+
# https://github.com/slate-studio/engine/blob/master/lib/locomotive/core_ext.rb
|
|
293
|
+
def slugify(options = {})
|
|
294
|
+
options = { :sep => '_', :without_extension => false, :downcase => false, :underscore => false }.merge(options)
|
|
295
|
+
# replace accented chars with ther ascii equivalents
|
|
296
|
+
s = ActiveSupport::Inflector.transliterate(self).to_s
|
|
297
|
+
# No more than one slash in a row
|
|
298
|
+
s.gsub!(/(\/[\/]+)/, '/')
|
|
299
|
+
# Remove leading or trailing space
|
|
300
|
+
s.strip!
|
|
301
|
+
# Remove leading or trailing slash
|
|
302
|
+
s.gsub!(/(^[\/]+)|([\/]+$)/, '')
|
|
303
|
+
# Remove extensions
|
|
304
|
+
s.gsub!(/(\.[a-zA-Z]{2,})/, '') if options[:without_extension]
|
|
305
|
+
# Downcase
|
|
306
|
+
s.downcase! if options[:downcase]
|
|
307
|
+
# Turn unwanted chars into the seperator
|
|
308
|
+
s.gsub!(/[^a-zA-Z0-9\-_\+\/]+/i, options[:sep])
|
|
309
|
+
# Underscore
|
|
310
|
+
s.gsub!(/[\-]/i, '_') if options[:underscore]
|
|
311
|
+
s
|
|
312
|
+
end
|
|
313
|
+
def slugify!(options = {})
|
|
314
|
+
replace(self.slugify(options))
|
|
315
|
+
end
|
|
316
|
+
def parameterize!(sep = '_')
|
|
317
|
+
replace(self.parameterize(sep))
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
Liquid::Template.register_filter(CustomFilters)
|
|
323
|
+
|
|
324
|
+
# Define command-line option/argument parameters
|
|
325
|
+
# From the root directory of your project:
|
|
326
|
+
# $ ./parse.rb --help
|
|
327
|
+
command_parser = OptionParser.new do|opts|
|
|
328
|
+
opts.banner = "Usage: liquidoc [options]"
|
|
329
|
+
|
|
330
|
+
opts.on("-a PATH", "--attributes-file=PATH", "For passing in a standard YAML AsciiDoc attributes file. Default: #{@attributes_file_def}") do |n|
|
|
331
|
+
@assets_path = n
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
opts.on("--attr=STRING", "For passing an AsciiDoc attribute parameter to Asciidoctor. Ex: --attr basedir=some/path --attr imagesdir=some/path/images") do |n|
|
|
335
|
+
@passed_attrs = @passed_attrs.merge!n
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
# Global Options
|
|
339
|
+
opts.on("-b PATH", "--base=PATH", "The base directory, relative to this script. Defaults to `.`, or pwd." ) do |n|
|
|
340
|
+
@data_file = @base_dir + n
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
opts.on("-c", "--config=PATH", "Configuration file, enables preset source, template, and output.") do |n|
|
|
344
|
+
@config_file = @base_dir + n
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
opts.on("-d PATH", "--data=PATH", "Semi-structured data source (input) path. Ex. path/to/data.yml. Required unless --config is called." ) do |n|
|
|
348
|
+
@data_file = @base_dir + n
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
opts.on("-f PATH", "--from=PATH", "Directory to copy assets from." ) do |n|
|
|
352
|
+
@attributes_file = n
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
opts.on("-i PATH", "--index=PATH", "An AsciiDoc index file for mapping an Asciidoctor build." ) do |n|
|
|
356
|
+
@index_file = n
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
opts.on("-o PATH", "--output=PATH", "Output file path for generated content. Ex. path/to/file.adoc. Required unless --config is called.") do |n|
|
|
360
|
+
@output_file = @base_dir + n
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
opts.on("-t PATH", "--template=PATH", "Path to liquid template. Required unless --configuration is called." ) do |n|
|
|
364
|
+
@template_file = @base_dir + n
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
opts.on("--verbose", "Run verbose") do |n|
|
|
368
|
+
@logger.level = Logger::DEBUG
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
opts.on("--stdout", "Puts the output in STDOUT instead of writing to a file.") do
|
|
372
|
+
@output_type = "STDOUT"
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
opts.on("-h", "--help", "Returns help.") do
|
|
376
|
+
puts opts
|
|
377
|
+
exit
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# Parse options.
|
|
383
|
+
command_parser.parse!
|
|
384
|
+
|
|
385
|
+
# Upfront debug output
|
|
386
|
+
@logger.debug "Base dir: #{@base_dir}"
|
|
387
|
+
@logger.debug "Config file: #{@config_file}"
|
|
388
|
+
@logger.debug "Index file: #{@index_file}"
|
|
389
|
+
|
|
390
|
+
# Parse data into docs!
|
|
391
|
+
# liquify() takes the names of a Liquid template, a data file, and an output doc.
|
|
392
|
+
# Input and output file extensions are non-determinant; your template
|
|
393
|
+
# file establishes the structure.
|
|
394
|
+
|
|
395
|
+
unless @config_file
|
|
396
|
+
if @data_file
|
|
397
|
+
liquify(@data_file, @template_file, @output_file)
|
|
398
|
+
end
|
|
399
|
+
if @index_file
|
|
400
|
+
@logger.warn "Publishing via command line arguments not yet implemented. Use a config file."
|
|
401
|
+
end
|
|
402
|
+
else
|
|
403
|
+
@logger.debug "Executing... config_build"
|
|
404
|
+
config_build(@config_file)
|
|
405
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: liquidoc
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Brian Dominick
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2017-09-07 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.15'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.15'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '10.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '10.0'
|
|
41
|
+
description: LiquiDoc conveniently harnesses the power of Liquid templates, flat-file
|
|
42
|
+
data formats such as YAML, JSON, XML, and CSV, as well as AsciiDoc markup and powerful
|
|
43
|
+
Asciidoctor output capabilities -- all in a single command-line tool.
|
|
44
|
+
email:
|
|
45
|
+
- badominick@gmail.com
|
|
46
|
+
executables:
|
|
47
|
+
- liquidoc
|
|
48
|
+
extensions: []
|
|
49
|
+
extra_rdoc_files: []
|
|
50
|
+
files:
|
|
51
|
+
- bin/liquidoc
|
|
52
|
+
- lib/liquidoc.rb
|
|
53
|
+
- lib/liquidoc/version.rb
|
|
54
|
+
homepage: https://github.com/scalingdata/liquidoc
|
|
55
|
+
licenses:
|
|
56
|
+
- MIT
|
|
57
|
+
metadata:
|
|
58
|
+
allowed_push_host: https://rubygems.org
|
|
59
|
+
post_install_message:
|
|
60
|
+
rdoc_options: []
|
|
61
|
+
require_paths:
|
|
62
|
+
- lib
|
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '0'
|
|
73
|
+
requirements: []
|
|
74
|
+
rubyforge_project:
|
|
75
|
+
rubygems_version: 2.4.8
|
|
76
|
+
signing_key:
|
|
77
|
+
specification_version: 4
|
|
78
|
+
summary: A highly configurable command-line tool for parsing data and content in common
|
|
79
|
+
flat-file formats.
|
|
80
|
+
test_files: []
|