vizbuilder 1.0.2 → 1.0.3
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 +4 -4
- data/README.md +9 -9
- data/VERSION +1 -1
- data/lib/vizbuilder.rb +135 -86
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e273e34c974ba38b41ede845375fde15653789fd4dfc5dd06b2c870b9b66852a
|
4
|
+
data.tar.gz: 261ebf230a9ef189707efeab09774837072058ab79aa0e16f854bcb145be62c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a6503f0e5312e988b0636b54072ebf07de0dcd853a16aec190dd59a48d66ff8de6f0c5af814e83aa4b2560cdaef5e78d3ca50a2439391a18e9fe684db2da35e
|
7
|
+
data.tar.gz: 4e574ad770e138419ef08e0357ab1036d28c3a96f164213af3a0a29c1d7122b08fe340dc931f5541b77c7405d8216235f5e0a13d197d87f76d624c6cb7efe90c
|
data/README.md
CHANGED
@@ -89,15 +89,7 @@ In `index.html.erb`:
|
|
89
89
|
|
90
90
|
## Configuration
|
91
91
|
|
92
|
-
A new `VizBuilder` instance
|
93
|
-
|
94
|
-
```ruby
|
95
|
-
app = VizBuilder.new
|
96
|
-
app.set :some_global_config_thing, 'hello world'
|
97
|
-
app.add_page 'index.html', template: 'index.html.erb'
|
98
|
-
```
|
99
|
-
|
100
|
-
Or you can use a block:
|
92
|
+
A new `VizBuilder` instance is configured via a block passed into the constructor:
|
101
93
|
|
102
94
|
```ruby
|
103
95
|
app = VizBuilder.new do
|
@@ -106,6 +98,14 @@ app = VizBuilder.new do
|
|
106
98
|
end
|
107
99
|
```
|
108
100
|
|
101
|
+
You can add or adjust configuration directly on the `VizBuilder#config` instance, but
|
102
|
+
it may not work as expected:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
app.config.set :some_global_config_thing, 'a different thing'
|
106
|
+
app.config.add_page 'index.html', template: 'index.html.erb'
|
107
|
+
```
|
108
|
+
|
109
109
|
There are a few config settings used by Viz Builder:
|
110
110
|
|
111
111
|
#### http_prefix
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.3
|
data/lib/vizbuilder.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'psych'
|
2
4
|
require 'fileutils'
|
3
5
|
require 'erb'
|
@@ -15,28 +17,24 @@ class VizBuilder
|
|
15
17
|
attr_reader :config
|
16
18
|
delegate :sitemap, :data, :hooks, :helper_modules, to: :config
|
17
19
|
|
18
|
-
BUILD_DIR = 'build'
|
19
|
-
PREBUILT_DIR = 'prebuild'
|
20
|
-
DATA_DIR = 'data'
|
20
|
+
BUILD_DIR = 'build'
|
21
|
+
PREBUILT_DIR = 'prebuild'
|
22
|
+
DATA_DIR = 'data'
|
21
23
|
|
22
24
|
def initialize(config = {}, &blk)
|
23
25
|
# Config is an object used as the context for the given block
|
24
26
|
@config = Config.new(config: config)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
@
|
30
|
-
# Run any after load data hooks since they got added after the first load
|
31
|
-
# data was called.
|
32
|
-
run_hook!(:after_load_data)
|
33
|
-
# Add helpers to the TemplateContext class
|
34
|
-
TemplateContext.include(*helper_modules) unless helper_modules.empty?
|
27
|
+
@config_block = block_given? ? blk : nil
|
28
|
+
@config.helpers(Helpers)
|
29
|
+
@config.helpers(ConfigHelpers, type: :config)
|
30
|
+
@config.helpers(TemplateHelpers, type: :template)
|
31
|
+
@_configured = false
|
35
32
|
end
|
36
33
|
|
37
34
|
# Generate all pages in the sitemap and save to `build/`
|
38
35
|
def build!(silent: false)
|
39
|
-
|
36
|
+
configure!(mode: :build, target: :production)
|
37
|
+
ctx = TemplateContext.new(@config)
|
40
38
|
index_prebuilt!
|
41
39
|
# First we build prebuilt pages that need digests calculated by build_page
|
42
40
|
digested = sitemap.select { |_path, page| page[:digest] == true }
|
@@ -48,6 +46,7 @@ class VizBuilder
|
|
48
46
|
|
49
47
|
# Run this builder as a server
|
50
48
|
def runserver!(host: '127.0.0.1', port: '3456')
|
49
|
+
configure!(mode: :server, target: :development)
|
51
50
|
status = 0 # running: 0, reload: 1, exit: 2
|
52
51
|
# spawn a thread to watch the status flag and trigger a reload or exit
|
53
52
|
monitor = Thread.new do
|
@@ -79,6 +78,8 @@ class VizBuilder
|
|
79
78
|
|
80
79
|
# Support the call method so an instance can act as a Rack app
|
81
80
|
def call(env)
|
81
|
+
raise 'VizBuilder configuration incomplete!' unless @_configured
|
82
|
+
|
82
83
|
# Only support GET, OPTIONS, HEAD
|
83
84
|
unless env['REQUEST_METHOD'].in?(%w[GET HEAD OPTIONS])
|
84
85
|
return [405, { 'Content-Type' => 'text/plain' }, ['METHOD NOT ALLOWED']]
|
@@ -108,7 +109,7 @@ class VizBuilder
|
|
108
109
|
# Check our sitemap then our prebuilt folder for content to serve
|
109
110
|
if sitemap[path].present?
|
110
111
|
content_type = MimeMagic.by_path(path).to_s
|
111
|
-
ctx = TemplateContext.new(
|
112
|
+
ctx = TemplateContext.new(@config)
|
112
113
|
content = build_page(path, ctx)
|
113
114
|
status = 200
|
114
115
|
elsif File.exist?(build_filename)
|
@@ -126,6 +127,31 @@ class VizBuilder
|
|
126
127
|
data.merge!(load_data)
|
127
128
|
# TODO: after load hooks only run once, not every time reload_data! is called
|
128
129
|
run_hook!(:after_load_data)
|
130
|
+
# Chainable
|
131
|
+
self
|
132
|
+
end
|
133
|
+
|
134
|
+
# Complete the configuration for this app. Is used by build! and runserver!.
|
135
|
+
# You will only need this method if you're running VizBuilder as a rack app
|
136
|
+
# without using runserver!.
|
137
|
+
def configure!(kwargs = nil)
|
138
|
+
return self if @_configured
|
139
|
+
# Update config with any kwargs
|
140
|
+
@config.merge!(kwargs) if kwargs.present?
|
141
|
+
# Load data into @data
|
142
|
+
reload_data!
|
143
|
+
# Execute the given block as a method of this class. The block can then use
|
144
|
+
# the methods `add_page`, `add_data`, and `set`
|
145
|
+
@config.instance_exec(&@config_block) if @config_block.present?
|
146
|
+
# Run any after load data hooks since they got added after the first load
|
147
|
+
# data was called.
|
148
|
+
run_hook!(:after_load_data)
|
149
|
+
# Add helpers to the TemplateContext class
|
150
|
+
TemplateContext.include(*helper_modules) unless helper_modules.empty?
|
151
|
+
# Mark app configured
|
152
|
+
@_configured = true
|
153
|
+
# Chainable
|
154
|
+
self
|
129
155
|
end
|
130
156
|
|
131
157
|
# Like File.extname, but gets all extensions if multiple are present
|
@@ -152,7 +178,7 @@ class VizBuilder
|
|
152
178
|
# Convenience methods for configuring the site
|
153
179
|
class Config
|
154
180
|
attr_accessor :data, :config, :sitemap, :hooks, :helper_modules
|
155
|
-
delegate :[], :[]=, :key?, to: :config
|
181
|
+
delegate :[], :[]=, :key?, :update, :merge!, to: :config
|
156
182
|
|
157
183
|
def initialize(config: {})
|
158
184
|
# Config is a Hash of site wide configuration variables
|
@@ -204,12 +230,12 @@ class VizBuilder
|
|
204
230
|
end
|
205
231
|
|
206
232
|
# Add helper modules or define helpers in a block
|
207
|
-
def helpers(*mods, &blk)
|
233
|
+
def helpers(*mods, type: nil, &blk)
|
208
234
|
new_helpers = []
|
209
235
|
# loop over the list of arguments, making sure they're all modules, and
|
210
236
|
# then add them to the list of new helpers
|
211
237
|
mods.each do |mod|
|
212
|
-
unless
|
238
|
+
unless mod.is_a?(Module)
|
213
239
|
raise ArgumentError, 'Helpers must be defined in a module or block'
|
214
240
|
end
|
215
241
|
|
@@ -221,9 +247,9 @@ class VizBuilder
|
|
221
247
|
if new_helpers.present?
|
222
248
|
# extend the current Config instance with the helpers, making them available
|
223
249
|
# to the rest of the configuration block
|
224
|
-
extend(*new_helpers)
|
250
|
+
extend(*new_helpers) if type.nil? || type.to_sym == :config
|
225
251
|
# add our new helpers to our array of all helpers
|
226
|
-
@helper_modules += new_helpers
|
252
|
+
@helper_modules += new_helpers if type.nil? || type.to_sym == :template
|
227
253
|
end
|
228
254
|
|
229
255
|
self
|
@@ -248,11 +274,7 @@ class VizBuilder
|
|
248
274
|
attr_accessor :page
|
249
275
|
delegate :data, :sitemap, :config, to: :@config_obj
|
250
276
|
|
251
|
-
def initialize(
|
252
|
-
# Target is development or production
|
253
|
-
@target = target.to_sym
|
254
|
-
# Mode is build or server
|
255
|
-
@mode = mode.to_sym
|
277
|
+
def initialize(config)
|
256
278
|
# Config is our Builder config object
|
257
279
|
@config_obj = config
|
258
280
|
# Page is a hash representing the page. Is the same as whats in sitemap
|
@@ -287,8 +309,49 @@ class VizBuilder
|
|
287
309
|
end
|
288
310
|
end
|
289
311
|
|
290
|
-
#
|
312
|
+
# Looks for an invoked method name in locals then in config, so locals
|
313
|
+
# and config vars can be used as if they're local vars in the template
|
314
|
+
def method_missing(sym)
|
315
|
+
return @locals[sym] if @locals.key?(sym)
|
316
|
+
return config[sym] if config.key?(sym)
|
317
|
+
super
|
318
|
+
end
|
319
|
+
|
320
|
+
def respond_to_missing?(sym, *)
|
321
|
+
@locals.key?(sym) || config.key?(sym) || super
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# HELPERS
|
326
|
+
|
327
|
+
# The Helpers module holds methods that are added to both the config and
|
328
|
+
# template contexts. So you can use these in the config block and in
|
329
|
+
# templates.
|
330
|
+
module Helpers
|
331
|
+
# Are we running as a server?
|
332
|
+
def server?
|
333
|
+
config[:mode] == :server
|
334
|
+
end
|
335
|
+
|
336
|
+
# Are we building this app out?
|
337
|
+
def build?
|
338
|
+
config[:mode] == :build
|
339
|
+
end
|
340
|
+
|
341
|
+
# Is this in production?
|
342
|
+
def production?
|
343
|
+
config[:target] == :production
|
344
|
+
end
|
291
345
|
|
346
|
+
# Is this in development?
|
347
|
+
def development?
|
348
|
+
config[:target] == :development
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
# The TemplateHelpers modules hold methods that are added to the template
|
353
|
+
# context only. So you can only use these in templates.
|
354
|
+
module TemplateHelpers
|
292
355
|
# Get the full URL to the root of this site
|
293
356
|
def http_prefix
|
294
357
|
return '/' if server? && development?
|
@@ -309,9 +372,12 @@ class VizBuilder
|
|
309
372
|
def asset_path(*args)
|
310
373
|
path = args.join('/')
|
311
374
|
page = sitemap[path]
|
312
|
-
if production?
|
313
|
-
raise "Missing
|
314
|
-
|
375
|
+
if production?
|
376
|
+
raise "Missing asset #{path}" if page.blank?
|
377
|
+
if page[:digest] == true
|
378
|
+
raise "Missing digest for #{path}" if page[:digest_path].blank?
|
379
|
+
path = page[:digest_path]
|
380
|
+
end
|
315
381
|
end
|
316
382
|
asset_http_prefix + path
|
317
383
|
end
|
@@ -320,40 +386,12 @@ class VizBuilder
|
|
320
386
|
def canonical_url(*args)
|
321
387
|
http_prefix + args.join('/')
|
322
388
|
end
|
323
|
-
|
324
|
-
# Are we running as a server?
|
325
|
-
def server?
|
326
|
-
@mode == :server
|
327
|
-
end
|
328
|
-
|
329
|
-
# Are we building this app out?
|
330
|
-
def build?
|
331
|
-
@mode == :build
|
332
|
-
end
|
333
|
-
|
334
|
-
# Is this in production?
|
335
|
-
def production?
|
336
|
-
@target == :production
|
337
|
-
end
|
338
|
-
|
339
|
-
# Is this in development?
|
340
|
-
def development?
|
341
|
-
@target == :development
|
342
|
-
end
|
343
|
-
|
344
|
-
# Looks for an invoked method name in locals then in config, so locals
|
345
|
-
# and config vars can be used as if they're local vars in the template
|
346
|
-
def method_missing(sym)
|
347
|
-
return @locals[sym] if @locals.key?(sym)
|
348
|
-
return config[sym] if config.key?(sym)
|
349
|
-
super
|
350
|
-
end
|
351
|
-
|
352
|
-
def respond_to_missing?(sym, *)
|
353
|
-
@locals.key?(sym) || config.key?(sym) || super
|
354
|
-
end
|
355
389
|
end
|
356
390
|
|
391
|
+
# The ConfigHelpers modules hold methods that are added to the config block
|
392
|
+
# context only. So you can only use these with the config object instance.
|
393
|
+
module ConfigHelpers; end
|
394
|
+
|
357
395
|
private
|
358
396
|
|
359
397
|
# Generate one page from the sitemap and save to `build/`
|
@@ -362,25 +400,35 @@ class VizBuilder
|
|
362
400
|
out_fname = File.join(BUILD_DIR, path)
|
363
401
|
puts "Rendering #{out_fname}..." unless silent
|
364
402
|
|
403
|
+
# Check if we have a layout defined, use it
|
404
|
+
layout = ctx.page['layout'] || config['layout'] || nil
|
405
|
+
|
365
406
|
# Check page data for info on how to build this path
|
366
407
|
if ctx.page['template'].present?
|
367
|
-
|
368
|
-
|
369
|
-
content =
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
408
|
+
# Make sure to render the template inside the layout render so code in the
|
409
|
+
# erb layout and template are executed in a sensible order.
|
410
|
+
content = \
|
411
|
+
if layout.present?
|
412
|
+
ctx.render(layout) { ctx.render(ctx.page['template']) }
|
413
|
+
else
|
414
|
+
ctx.render(ctx.page['template'])
|
415
|
+
end
|
374
416
|
else
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
417
|
+
# Everything else static data and not executable, so we don't have to load
|
418
|
+
# the content inside the layout execution.
|
419
|
+
if ctx.page['json'].present?
|
420
|
+
content = ctx.page['json'].to_json
|
421
|
+
elsif ctx.page['file'].present?
|
422
|
+
content = File.read(ctx.page['file'])
|
423
|
+
else
|
424
|
+
raise(
|
425
|
+
ArgumentError,
|
426
|
+
"Page '#{path}' missing one of required attributes: 'template', 'json', 'file'."
|
427
|
+
)
|
428
|
+
end
|
380
429
|
|
381
|
-
|
382
|
-
|
383
|
-
content = ctx.render(layout_fname) { content } if layout_fname.present?
|
430
|
+
content = ctx.render(layout) { content } if layout.present?
|
431
|
+
end
|
384
432
|
|
385
433
|
# If page data includes a digest flag, add sha1 digest to output filename
|
386
434
|
if ctx.page['digest'] == true
|
@@ -403,16 +451,17 @@ class VizBuilder
|
|
403
451
|
def load_data
|
404
452
|
data = {}.with_indifferent_access
|
405
453
|
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
454
|
+
%w[.json .yaml].each do |ext|
|
455
|
+
Dir.glob("#{DATA_DIR}/*#{ext}") do |fname|
|
456
|
+
key = File.basename(fname, ext).to_sym
|
457
|
+
puts "Loading data[:#{key}] from #{fname}..."
|
458
|
+
data[key] = \
|
459
|
+
if ext == '.json'
|
460
|
+
JSON.parse(File.read(fname))
|
461
|
+
else
|
462
|
+
Psych.parse(fname)
|
463
|
+
end
|
464
|
+
end
|
416
465
|
end
|
417
466
|
|
418
467
|
data
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vizbuilder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Mark
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -146,7 +146,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
146
|
- !ruby/object:Gem::Version
|
147
147
|
version: '0'
|
148
148
|
requirements: []
|
149
|
-
|
149
|
+
rubyforge_project:
|
150
|
+
rubygems_version: 2.7.6.2
|
150
151
|
signing_key:
|
151
152
|
specification_version: 4
|
152
153
|
summary: Simple and fast static site generator
|