hx 0.8.2 → 0.8.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.
- data/VERSION +1 -1
- data/lib/hx/cli.rb +26 -9
- data/lib/hx/output/liquidtemplate.rb +2 -2
- data/lib/hx/path.rb +24 -100
- data/lib/hx/rack/application.rb +4 -4
- data/spec/rack_spec.rb +5 -5
- data/spec/selector_spec.rb +18 -83
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.3
|
data/lib/hx/cli.rb
CHANGED
@@ -42,6 +42,7 @@ Usage: hx [--config CONFIG_FILE] [upgen]
|
|
42
42
|
hx [--config CONFIG_FILE] regen
|
43
43
|
hx [--config CONFIG_FILE] post[up] SOURCE:PATH
|
44
44
|
hx [--config CONFIG_FILE] edit[up] SOURCE:PATH
|
45
|
+
hx [--config CONFIG_FILE] list SOURCE:PATTERN
|
45
46
|
|
46
47
|
EOS
|
47
48
|
|
@@ -128,31 +129,47 @@ def self.cmd_postup(site, entry_spec)
|
|
128
129
|
cmd_upgen(site)
|
129
130
|
end
|
130
131
|
|
131
|
-
def self.
|
132
|
+
def self._parse_entry_spec(site, entry_spec)
|
132
133
|
source_name, path = entry_spec.split(':', 2)
|
134
|
+
source = site.sources[source_name]
|
135
|
+
raise ArgumentError, "No such source #{source_name}" unless source
|
136
|
+
return source, path
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.parse_entry_spec(site, entry_spec)
|
140
|
+
source, path = _parse_entry_spec(site, entry_spec)
|
133
141
|
raise "Invalid entry specification #{entry_spec}" unless path
|
134
|
-
return
|
142
|
+
return source, path
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.parse_entry_pattern(site, entry_pattern)
|
146
|
+
source, pattern = _parse_entry_spec(site, entry_pattern)
|
147
|
+
pattern = "**" unless pattern
|
148
|
+
selector = Hx::Path.parse_pattern(pattern)
|
149
|
+
return source, selector
|
135
150
|
end
|
136
151
|
|
137
152
|
def self.cmd_edit(site, entry_spec)
|
138
|
-
|
139
|
-
do_edit(site,
|
153
|
+
source, path = parse_entry_spec(site, entry_spec)
|
154
|
+
do_edit(site, source, path, nil)
|
140
155
|
end
|
141
156
|
|
142
157
|
def self.cmd_post(site, entry_spec)
|
143
|
-
|
158
|
+
source, path = parse_entry_spec(site, entry_spec)
|
144
159
|
prototype = {
|
145
160
|
'title' => Hx.make_default_title(site.options, path),
|
146
161
|
'author' => Hx.get_default_author(site.options),
|
147
162
|
'content' => ""
|
148
163
|
}
|
149
|
-
do_edit(site,
|
164
|
+
do_edit(site, source, path, prototype)
|
150
165
|
end
|
151
166
|
|
152
|
-
def self.
|
153
|
-
source = site
|
154
|
-
|
167
|
+
def self.cmd_list(site, entry_spec)
|
168
|
+
source, selector = parse_entry_pattern(site, entry_spec)
|
169
|
+
source.each_entry_path(selector) { |path| puts path }
|
170
|
+
end
|
155
171
|
|
172
|
+
def self.do_edit(site, source, path, prototype)
|
156
173
|
catch(:unchanged) do
|
157
174
|
begin
|
158
175
|
tempfile = Tempfile.new('hx-entry')
|
@@ -74,7 +74,7 @@ class LiquidTemplate
|
|
74
74
|
template_file = template_dir + "#{options[:template]}.liquid"
|
75
75
|
@template = Liquid::Template.parse(template_file.read)
|
76
76
|
@extension = options[:extension]
|
77
|
-
@
|
77
|
+
@content_type = options[:content_type]
|
78
78
|
@strip_extension_re = nil
|
79
79
|
@strip_extension_re = /\.#{Regexp.quote(@extension)}$/ if @extension
|
80
80
|
end
|
@@ -99,7 +99,7 @@ class LiquidTemplate
|
|
99
99
|
'entry' => entry
|
100
100
|
)
|
101
101
|
end
|
102
|
-
output_entry['
|
102
|
+
output_entry['content_type'] = @content_type if @content_type
|
103
103
|
if entry.has_key? 'updated'
|
104
104
|
output_entry['created'] = output_entry['updated'] = entry['updated']
|
105
105
|
end
|
data/lib/hx/path.rb
CHANGED
@@ -25,11 +25,6 @@ module Hx
|
|
25
25
|
module Path
|
26
26
|
|
27
27
|
module Selector
|
28
|
-
def prefix ; "" ; end
|
29
|
-
def suffix ; "" ; end
|
30
|
-
def regexp ; nil ; end
|
31
|
-
def remaining_suffix(prefix_consumed) ; suffix ; end
|
32
|
-
|
33
28
|
def accept?(path)
|
34
29
|
raise NotImplementedError, "#{self.class}#accept? not implemented"
|
35
30
|
end
|
@@ -49,37 +44,25 @@ end
|
|
49
44
|
|
50
45
|
class All
|
51
46
|
include Selector
|
52
|
-
|
53
|
-
REGEXP = Regexp.new("^.*$")
|
54
|
-
|
55
|
-
def regexp ; REGEXP ; end
|
56
47
|
def accept?(path) ; true ; end
|
57
48
|
end
|
58
49
|
|
59
50
|
ALL = All.new
|
60
51
|
|
61
|
-
class
|
52
|
+
class Pattern
|
62
53
|
include Selector
|
63
54
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
def remaining_suffix(prefix_consumed)
|
73
|
-
@value[prefix_consumed..-1]
|
74
|
-
end
|
75
|
-
|
76
|
-
def regexp
|
77
|
-
@regexp ||= Regexp.new("^#{Regexp.quote(@value)}$")
|
55
|
+
def initialize(tokens)
|
56
|
+
@regexp = Regexp.new("^#{tokens.map { |token|
|
57
|
+
case token
|
58
|
+
when :doublestar; '.*'
|
59
|
+
when :star; '[^/]*'
|
60
|
+
else; Regexp.quote(token)
|
61
|
+
end
|
62
|
+
}}$")
|
78
63
|
end
|
79
64
|
|
80
|
-
def accept?(path)
|
81
|
-
@value == path
|
82
|
-
end
|
65
|
+
def accept?(path) ; !!(path =~ @regexp) ; end
|
83
66
|
end
|
84
67
|
|
85
68
|
def self.parse_pattern(pattern_string)
|
@@ -91,78 +74,35 @@ def self.parse_pattern(pattern_string)
|
|
91
74
|
else; token
|
92
75
|
end
|
93
76
|
end
|
94
|
-
|
95
|
-
if tokens.size == 1 and String === prefix
|
96
|
-
Literal.new(prefix)
|
97
|
-
else
|
98
|
-
prefix = "" unless String === prefix
|
99
|
-
suffix = tokens.last
|
100
|
-
suffix = "" unless String === suffix
|
101
|
-
regexp = Regexp.new("^#{tokens.map { |token|
|
102
|
-
case token
|
103
|
-
when :doublestar; '.*'
|
104
|
-
when :star; '[^/]*'
|
105
|
-
else; Regexp.quote(token)
|
106
|
-
end
|
107
|
-
}}$")
|
108
|
-
Pattern.new(regexp, prefix, suffix)
|
109
|
-
end
|
77
|
+
Pattern.new(tokens)
|
110
78
|
end
|
111
79
|
|
112
80
|
def self.literal(literal_string)
|
113
|
-
|
114
|
-
end
|
115
|
-
|
116
|
-
class Pattern
|
117
|
-
include Selector
|
118
|
-
|
119
|
-
attr_reader :prefix
|
120
|
-
attr_reader :suffix
|
121
|
-
attr_reader :regexp
|
122
|
-
|
123
|
-
def initialize(regexp, prefix, suffix)
|
124
|
-
@regexp = regexp
|
125
|
-
@prefix = prefix
|
126
|
-
@suffix = suffix
|
127
|
-
end
|
128
|
-
|
129
|
-
def accept?(path)
|
130
|
-
!!(@regexp.match(path))
|
131
|
-
end
|
81
|
+
Pattern.new([literal_string])
|
132
82
|
end
|
133
83
|
|
134
84
|
module Connective
|
135
85
|
include Selector
|
136
86
|
|
137
|
-
attr_reader :prefix
|
138
|
-
attr_reader :suffix
|
139
|
-
|
140
87
|
def initialize(*selectors)
|
141
88
|
@selectors = selectors
|
142
|
-
prefixes = selectors.map { |s| s.prefix }
|
143
|
-
prefix_length = (prefixes.first || "").length
|
144
|
-
prefixes.each_cons(2) do |a, b|
|
145
|
-
prefix_length.downto(0) do |length|
|
146
|
-
prefix_length = length
|
147
|
-
break if a[0...length] == b[0...length]
|
148
|
-
end
|
149
|
-
end
|
150
|
-
@prefix = prefixes.first[0...prefix_length]
|
151
|
-
suffixes = selectors.map { |s| s.remaining_suffix(prefix_length) }
|
152
|
-
suffix_length = (suffixes.first || "").length
|
153
|
-
suffixes.each_cons(2) do |a, b|
|
154
|
-
suffix_length.downto(0) do |length|
|
155
|
-
suffix_length = length
|
156
|
-
break if a[-length..-1] == b[-length..-1]
|
157
|
-
end
|
158
|
-
end
|
159
|
-
@suffix = suffixes.first[-suffix_length..-1]
|
160
89
|
end
|
161
90
|
end
|
162
91
|
|
163
92
|
class Conjunction
|
164
93
|
include Connective
|
165
94
|
|
95
|
+
def self.new(*selectors)
|
96
|
+
if selectors.any? { |s| All === s }
|
97
|
+
selectors.reject! { |s| All === s }
|
98
|
+
case selectors.size
|
99
|
+
when 0; return ALL
|
100
|
+
when 1; return selectors.first
|
101
|
+
end
|
102
|
+
end
|
103
|
+
super(*selectors)
|
104
|
+
end
|
105
|
+
|
166
106
|
def accept?(path)
|
167
107
|
@selectors.all? { |s| s.accept? path }
|
168
108
|
end
|
@@ -171,24 +111,8 @@ end
|
|
171
111
|
class Disjunction
|
172
112
|
include Connective
|
173
113
|
|
174
|
-
attr_reader :regexp
|
175
|
-
|
176
|
-
def initialize(*selectors)
|
177
|
-
super
|
178
|
-
regexps = @selectors.map { |s| s.regexp }
|
179
|
-
if regexps.all?
|
180
|
-
@regexp = Regexp.union(*regexps)
|
181
|
-
else
|
182
|
-
@regexp = nil
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
114
|
def accept?(path)
|
187
|
-
|
188
|
-
!!@regexp.match(path)
|
189
|
-
else
|
190
|
-
@selectors.any? { |s| s.accept? path }
|
191
|
-
end
|
115
|
+
@selectors.any? { |s| s.accept? path }
|
192
116
|
end
|
193
117
|
end
|
194
118
|
|
data/lib/hx/rack/application.rb
CHANGED
@@ -78,13 +78,13 @@ class Application
|
|
78
78
|
end
|
79
79
|
|
80
80
|
if entry
|
81
|
-
|
82
|
-
unless
|
81
|
+
content_type = entry['content_type']
|
82
|
+
unless content_type
|
83
83
|
effective_path =~ /(\.[^.]+)$/
|
84
|
-
|
84
|
+
content_type = ::Rack::Mime.mime_type($1 || '')
|
85
85
|
end
|
86
86
|
content = entry['content'].to_s
|
87
|
-
[200, {'Content-Type' =>
|
87
|
+
[200, {'Content-Type' => content_type}, [content]]
|
88
88
|
else
|
89
89
|
message = "#{env['SCRIPT_NAME']}#{path} not found"
|
90
90
|
[404, {'Content-Type' => "text/plain"}, [message]]
|
data/spec/rack_spec.rb
CHANGED
@@ -30,22 +30,22 @@ describe Hx::Rack::Application do
|
|
30
30
|
it "should infer content type from file extension by default" do
|
31
31
|
cases = { "html" => "text/html",
|
32
32
|
"jpeg" => "image/jpeg" }
|
33
|
-
for extension,
|
33
|
+
for extension, content_type in cases
|
34
34
|
path = "blah.#{extension}"
|
35
35
|
@input.add_entry(path, "")
|
36
36
|
response = @service.get("/#{path}", :lint => true, :fatal => true)
|
37
37
|
response.status.to_i.should == 200
|
38
|
-
response['Content-Type'].should ==
|
38
|
+
response['Content-Type'].should == content_type
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
it "should allow entries to specify their mime type" do
|
43
43
|
path = "blah.html"
|
44
|
-
|
45
|
-
@input.add_entry(path, "", '
|
44
|
+
content_type = "junk/garbage"
|
45
|
+
@input.add_entry(path, "", 'content_type' => content_type)
|
46
46
|
response = @service.get("/#{path}", :lint => true, :fatal => true)
|
47
47
|
response.status.to_i.should == 200
|
48
|
-
response['Content-Type'].should ==
|
48
|
+
response['Content-Type'].should == content_type
|
49
49
|
end
|
50
50
|
|
51
51
|
it "should redirect for directories with indices" do
|
data/spec/selector_spec.rb
CHANGED
@@ -7,72 +7,27 @@ describe Hx::Path::Pattern do
|
|
7
7
|
Hx::Path::Pattern.should < Hx::Path::Selector
|
8
8
|
end
|
9
9
|
|
10
|
-
it "should
|
11
|
-
|
12
|
-
:prefix => "foo/",
|
13
|
-
:suffix => "/bar" },
|
14
|
-
{ :pattern => "foo/*/bar",
|
15
|
-
:prefix => "foo/",
|
16
|
-
:suffix => "/bar" },
|
17
|
-
{ :pattern => "[blah",
|
18
|
-
:prefix => "[blah",
|
19
|
-
:suffix => "" },
|
20
|
-
{ :pattern => "hoge*",
|
21
|
-
:prefix => "hoge",
|
22
|
-
:suffix => "" },
|
23
|
-
{ :pattern => "*hoge",
|
24
|
-
:prefix => "",
|
25
|
-
:suffix => "hoge" } ]
|
26
|
-
for test_case in cases
|
27
|
-
pattern = Hx::Path.parse_pattern(test_case[:pattern])
|
28
|
-
pattern.prefix.should == test_case[:prefix]
|
29
|
-
pattern.suffix.should == test_case[:suffix]
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should accept or reject paths" do
|
34
|
-
pattern = Hx::Path.parse_pattern("foo/bar")
|
10
|
+
it "should accept or reject literal paths" do
|
11
|
+
pattern = Hx::Path.literal("foo/bar")
|
35
12
|
pattern.should accept("foo/bar")
|
36
13
|
pattern.should_not accept("foo/baz")
|
37
14
|
end
|
38
15
|
|
39
|
-
it "should
|
40
|
-
pattern = Hx::Path.parse_pattern("foo
|
41
|
-
pattern.
|
42
|
-
pattern.
|
43
|
-
pattern.
|
16
|
+
it "should match single path components with stars" do
|
17
|
+
pattern = Hx::Path.parse_pattern("foo/*")
|
18
|
+
pattern.should_not accept("baz/eek")
|
19
|
+
pattern.should accept("foo/bar")
|
20
|
+
pattern.should_not accept("foo/bar/baz")
|
21
|
+
end
|
44
22
|
|
45
|
-
|
46
|
-
pattern.
|
47
|
-
pattern.
|
48
|
-
pattern.
|
23
|
+
it "should match multiple path components with double stars" do
|
24
|
+
pattern = Hx::Path.parse_pattern("foo/**")
|
25
|
+
pattern.should_not accept("baz/eek")
|
26
|
+
pattern.should accept("foo/bar")
|
27
|
+
pattern.should accept("foo/bar/baz")
|
49
28
|
end
|
50
29
|
end
|
51
30
|
|
52
|
-
PATHFILTER_PREFIX_CASES = [
|
53
|
-
{ :patterns => ["foo/bar", "fudge/bear"],
|
54
|
-
:prefix => "f",
|
55
|
-
:suffix => "ar" },
|
56
|
-
{ :patterns => ["foo/*/bar", "fudge/*/bear"],
|
57
|
-
:prefix => "f",
|
58
|
-
:suffix => "ar" },
|
59
|
-
{ :patterns => ["foo/bar", "fudge/*/bear"],
|
60
|
-
:prefix => "f",
|
61
|
-
:suffix => "ar" },
|
62
|
-
{ :patterns => ["bar*", "*bear"],
|
63
|
-
:prefix => "",
|
64
|
-
:suffix => "" },
|
65
|
-
{ :patterns => ["foobarbaz", "foobar*barbaz"],
|
66
|
-
:prefix => "foobar",
|
67
|
-
:suffix => "baz" },
|
68
|
-
{ :patterns => ["foobarbaz*", "foobar*barbaz"],
|
69
|
-
:prefix => "foobar",
|
70
|
-
:suffix => "" },
|
71
|
-
{ :patterns => ["*foobarbaz", "foobar*barbaz"],
|
72
|
-
:prefix => "",
|
73
|
-
:suffix => "barbaz" }
|
74
|
-
]
|
75
|
-
|
76
31
|
describe "Hx::Path::Selector disjunctions" do
|
77
32
|
it "should be possible" do
|
78
33
|
filters = ["foo/bar", "abcdefg"].map { |p| Hx::Path.parse_pattern(p) }
|
@@ -87,17 +42,6 @@ describe "Hx::Path::Selector disjunctions" do
|
|
87
42
|
filter.should accept("abcdefg")
|
88
43
|
filter.should_not accept("hoge")
|
89
44
|
end
|
90
|
-
|
91
|
-
for test_case_outer in PATHFILTER_PREFIX_CASES
|
92
|
-
Proc.new do |test_case|
|
93
|
-
it "should produce optimal prefixes and suffixes" do
|
94
|
-
filters = test_case[:patterns].map { |p| Hx::Path.parse_pattern(p) }
|
95
|
-
filter = filters.inject { |a, b| a | b }
|
96
|
-
filter.prefix.should == test_case[:prefix]
|
97
|
-
filter.suffix.should == test_case[:suffix]
|
98
|
-
end
|
99
|
-
end.call(test_case_outer)
|
100
|
-
end
|
101
45
|
end
|
102
46
|
|
103
47
|
describe "negated Hx::Path::Selectors" do
|
@@ -113,11 +57,6 @@ describe "negated Hx::Path::Selectors" do
|
|
113
57
|
@pattern.should_not accept("foobar")
|
114
58
|
@pattern.should accept("hoge")
|
115
59
|
end
|
116
|
-
|
117
|
-
it "should have empty prefix and suffix" do
|
118
|
-
@pattern.prefix.should == ""
|
119
|
-
@pattern.suffix.should == ""
|
120
|
-
end
|
121
60
|
end
|
122
61
|
|
123
62
|
describe "Hx::Path::Selector conjunctions" do
|
@@ -137,14 +76,10 @@ describe "Hx::Path::Selector conjunctions" do
|
|
137
76
|
filter.should_not accept("rebar")
|
138
77
|
end
|
139
78
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
filter.prefix.should == test_case[:prefix]
|
146
|
-
filter.suffix.should == test_case[:suffix]
|
147
|
-
end
|
148
|
-
end.call(test_case_outer)
|
79
|
+
it "should optimize use of ALL" do
|
80
|
+
filter = Hx::Path.parse_pattern("foo")
|
81
|
+
(filter & Hx::Path::ALL).should equal(filter)
|
82
|
+
(Hx::Path::ALL & filter).should equal(filter)
|
83
|
+
(Hx::Path::ALL & Hx::Path::ALL).should equal(Hx::Path::ALL)
|
149
84
|
end
|
150
85
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- MenTaLguY
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-05-29 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|