middleman-data_source 0.5.0 → 0.6.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 +4 -4
- data/changelog.md +4 -0
- data/lib/middleman/data_source/extension.rb +44 -19
- data/lib/middleman/data_source/version.rb +1 -1
- data/readme.md +29 -0
- data/spec/fixtures/base/config.rb +22 -1
- data/spec/lib/middleman/data_source/extension_spec.rb +12 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8149a40f5de297992c3027d32d35a35592781065
|
4
|
+
data.tar.gz: 14b91bba9a92160b4c2d696df4698eefc48266ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 218bd22fd6a2875f9015641d9f87ccaaa865a24e4022304a1ed2a89b0094276e3197b0bf651b4a1cfff6300d097918e726e764087671dc1149ee7ee230ea52ea
|
7
|
+
data.tar.gz: 6589a1e6dd03534bf4121ff797058f91776ca6b90ce34b141b1bdb3171c4203a3e51b144a5184b75147b66f133f3e68d77f7b9f9563b475719bd5832b4bd54ce
|
data/changelog.md
CHANGED
@@ -7,6 +7,10 @@ module Middleman
|
|
7
7
|
option :rack_app, nil, 'rack app to use'
|
8
8
|
option :root, nil, 'http(s) host to use'
|
9
9
|
option :files, [], 'routes to mount as remote data files'
|
10
|
+
option :sources, [], 'array of sources to mount as data'
|
11
|
+
option :decoders, {}, 'callable functions to decode data sources'
|
12
|
+
|
13
|
+
attr_reader :decoders, :sources
|
10
14
|
|
11
15
|
def rack_app
|
12
16
|
@_rack_app ||= ::Rack::Test::Session.new( ::Rack::MockSession.new( options.rack_app ) )
|
@@ -15,30 +19,32 @@ module Middleman
|
|
15
19
|
def initialize app, options_hash={}, &block
|
16
20
|
super app, options_hash, &block
|
17
21
|
|
18
|
-
app_inst
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
app_inst = app.respond_to?(:inst) ? app.inst : app
|
23
|
+
@sources = options.sources.dup
|
24
|
+
@decoders = default_decoders.merge(options.decoders)
|
25
|
+
|
26
|
+
options.files.flat_map do |remote_path, local|
|
27
|
+
@sources.push({
|
28
|
+
:alias => (local || remote_path),
|
29
|
+
:path => remote_path
|
30
|
+
})
|
25
31
|
end
|
26
32
|
|
27
|
-
|
28
|
-
raw_extension = File.extname(
|
33
|
+
@sources.each do |source|
|
34
|
+
raw_extension = File.extname(source[:path])
|
29
35
|
extension = raw_extension.split('?').first
|
30
|
-
parts =
|
36
|
+
parts = source[:alias].split(File::SEPARATOR)
|
31
37
|
basename = File.basename(parts.pop, raw_extension)
|
32
38
|
|
33
39
|
if parts.empty?
|
34
40
|
original_callback = app_inst.data.callbacks[basename]
|
35
41
|
app_inst.data.callbacks[basename] = Proc.new do
|
36
|
-
attempt_merge_then_enhance decode_data(
|
42
|
+
attempt_merge_then_enhance decode_data(source, extension), original_callback
|
37
43
|
end
|
38
44
|
else
|
39
45
|
original_callback = app_inst.data.callbacks[parts.first]
|
40
46
|
app_inst.data.callbacks[parts.first] = Proc.new do
|
41
|
-
built_data = { basename => decode_data(
|
47
|
+
built_data = { basename => decode_data(source, extension) }
|
42
48
|
parts[1..-1].reverse.each do |part|
|
43
49
|
built_data = { part => built_data }
|
44
50
|
end
|
@@ -51,6 +57,19 @@ module Middleman
|
|
51
57
|
|
52
58
|
private
|
53
59
|
|
60
|
+
def default_decoders
|
61
|
+
{
|
62
|
+
json: {
|
63
|
+
extensions: ['.json'],
|
64
|
+
decoder: ->(source) { ActiveSupport::JSON.decode(source) },
|
65
|
+
},
|
66
|
+
yaml: {
|
67
|
+
extensions: ['.yaml', '.yml'],
|
68
|
+
decoder: ->(source) { YAML.load(source) }
|
69
|
+
}
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
54
73
|
def attempt_merge_then_enhance new_data, original_callback
|
55
74
|
if original_callback
|
56
75
|
original_data = original_callback.call
|
@@ -62,21 +81,27 @@ module Middleman
|
|
62
81
|
return ::Middleman::Util.recursively_enhance new_data
|
63
82
|
end
|
64
83
|
|
65
|
-
def decode_data
|
66
|
-
if
|
67
|
-
|
68
|
-
elsif extension == '.json'
|
69
|
-
ActiveSupport::JSON.decode get_file_contents file_path
|
84
|
+
def decode_data source, extension
|
85
|
+
if source.has_key? :type
|
86
|
+
decoder = decoders[source[:type]]
|
70
87
|
else
|
71
|
-
|
88
|
+
decoder = decoders.find do |candidate|
|
89
|
+
candidate[1][:extensions].include? extension
|
90
|
+
end
|
91
|
+
decoder = decoder.last if decoder
|
72
92
|
end
|
93
|
+
|
94
|
+
raise UnsupportedDataExtension unless decoder
|
95
|
+
|
96
|
+
decoder[:decoder].call get_file_contents source[:path]
|
73
97
|
end
|
74
98
|
|
75
99
|
def get_file_contents file_path
|
76
100
|
if options.rack_app
|
77
101
|
rack_app.get( URI.escape(file_path) ).body
|
78
102
|
else
|
79
|
-
|
103
|
+
file_path = File.join( options.root, file_path ) if options.root
|
104
|
+
Borrower::Content.get file_path
|
80
105
|
end
|
81
106
|
end
|
82
107
|
|
data/readme.md
CHANGED
@@ -98,6 +98,35 @@ activate :data_source do |c|
|
|
98
98
|
end
|
99
99
|
```
|
100
100
|
|
101
|
+
### Custom data types
|
102
|
+
|
103
|
+
By default we just look at the extension of a file to determine which decoder to use. By setting a source directly you can give it any data type you need. Each source is a hash with an `alias`, `path`, and `type` key. The `alias` and `path` would be the same as if you defined the source using files as `{ path => alias }`, while type corresponds to the decoder you'd like to use.
|
104
|
+
|
105
|
+
There are default decoders for `:yaml` and `:json`, however you are free to override them or create your own types.
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
# config.rb
|
109
|
+
activate :data_source do |c|
|
110
|
+
|
111
|
+
c.files = ['by_extension.ctype']
|
112
|
+
|
113
|
+
c.sources = [
|
114
|
+
{
|
115
|
+
alias: "foo_bar",
|
116
|
+
path: "/foo/bar.ctype",
|
117
|
+
type: :my_type
|
118
|
+
}
|
119
|
+
]
|
120
|
+
|
121
|
+
c.decoders = {
|
122
|
+
my_type: {
|
123
|
+
extensions: ['.ctype'],
|
124
|
+
decoder: ->(src) { CustomType.parse(src) }
|
125
|
+
}
|
126
|
+
}
|
127
|
+
```
|
128
|
+
|
129
|
+
In the above example, I can access `app.data.by_extension` w/ the file contents decoded by `CustomType`, because it's extension `.ctype` matches the one defined by the `:my_type` decoder. Similarly, `app.data.foo_bar` is also run through `CustomType` because it's `:type` attribute is set to `:my_type`.
|
101
130
|
|
102
131
|
# Testing
|
103
132
|
|
@@ -9,13 +9,34 @@ activate :data_source do |c|
|
|
9
9
|
run lambda {|env| [404, {'Content-type' => 'text/plain'}, ['Not found']] }
|
10
10
|
end
|
11
11
|
|
12
|
+
c.sources = [
|
13
|
+
{
|
14
|
+
alias: "foo",
|
15
|
+
path: "foo.bar",
|
16
|
+
type: :yaml
|
17
|
+
},
|
18
|
+
{
|
19
|
+
alias: "my_decoder",
|
20
|
+
path: "w/e",
|
21
|
+
type: :my_decoder
|
22
|
+
}
|
23
|
+
]
|
24
|
+
|
25
|
+
c.decoders = {
|
26
|
+
my_decoder: {
|
27
|
+
extensions: ['.ctype'],
|
28
|
+
decoder: ->(data) { ["grass","is","greener"] }
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
12
32
|
c.files = [
|
13
33
|
'remote.json',
|
14
34
|
'deeply/nested.json',
|
15
35
|
'deeply/nested/routes.json',
|
16
36
|
'in_yaml.yml',
|
17
37
|
'in_json.json',
|
18
|
-
'query_param.json?token=foo'
|
38
|
+
'query_param.json?token=foo',
|
39
|
+
'run_through_my_decoder.ctype'
|
19
40
|
]
|
20
41
|
|
21
42
|
end
|
@@ -42,6 +42,18 @@ describe Middleman::DataSource::Extension do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
it_behaves_like "data import"
|
45
|
+
|
46
|
+
it "allows assignment of sources w/ given type" do
|
47
|
+
expect( @mm.data.foo ).to eq ["one","two","three"]
|
48
|
+
end
|
49
|
+
|
50
|
+
it "allows assignment of custom data decoders" do
|
51
|
+
expect( @mm.data.my_decoder ).to eq ["grass","is","greener"]
|
52
|
+
end
|
53
|
+
|
54
|
+
it "sets custom decoders based on file extensions" do
|
55
|
+
expect( @mm.data.run_through_my_decoder ).to eq ["grass","is","greener"]
|
56
|
+
end
|
45
57
|
end
|
46
58
|
|
47
59
|
context "with unsupported_extension" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: middleman-data_source
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Sloan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: middleman
|