html-pipeline 0.0.11 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/README.md +24 -20
- data/lib/html/pipeline.rb +42 -14
- data/lib/html/pipeline/version.rb +1 -1
- data/test/helpers/mocked_instrumentation_service.rb +3 -1
- data/test/html/pipeline_test.rb +29 -7
- metadata +2 -2
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
GitHub HTML processing filters and utilities. This module includes a small
|
4
4
|
framework for defining DOM based content filters and applying them to user
|
5
|
-
provided content.
|
5
|
+
provided content. Read an introduction about this project in
|
6
|
+
[this blog post](https://github.com/blog/1311-html-pipeline-chainable-content-filters).
|
6
7
|
|
7
8
|
## Installation
|
8
9
|
|
@@ -197,9 +198,10 @@ Pipeline.new [ RootRelativeFilter ], { :base_url => 'http://somehost.com' }
|
|
197
198
|
|
198
199
|
## Instrumenting
|
199
200
|
|
200
|
-
|
201
|
-
[ActiveSupport::Notifications]
|
202
|
-
|
201
|
+
Filters and Pipelines can be set up to be instrumented when called. The pipeline
|
202
|
+
must be setup with an [ActiveSupport::Notifications]
|
203
|
+
(http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html)
|
204
|
+
compatible service object and a name. New pipeline objects will default to the
|
203
205
|
`HTML::Pipeline.default_instrumentation_service` object.
|
204
206
|
|
205
207
|
``` ruby
|
@@ -208,10 +210,12 @@ service = ActiveSupport::Notifications
|
|
208
210
|
|
209
211
|
# instrument a specific pipeline
|
210
212
|
pipeline = HTML::Pipeline.new [MarkdownFilter], context
|
211
|
-
pipeline.
|
213
|
+
pipeline.setup_instrumentation "MarkdownPipeline", service
|
212
214
|
|
213
|
-
# or
|
215
|
+
# or set default instrumentation service for all new pipelines
|
214
216
|
HTML::Pipeline.default_instrumentation_service = service
|
217
|
+
pipeline = HTML::Pipeline.new [MarkdownFilter], context
|
218
|
+
pipeline.setup_instrumentation "MarkdownPipeline"
|
215
219
|
```
|
216
220
|
|
217
221
|
Filters are instrumented when they are run through the pipeline. A
|
@@ -221,7 +225,11 @@ instrumentation call.
|
|
221
225
|
|
222
226
|
``` ruby
|
223
227
|
service.subscribe "call_filter.html_pipeline" do |event, start, ending, transaction_id, payload|
|
228
|
+
payload[:pipeline] #=> "MarkdownPipeline", set with `setup_instrumentation`
|
224
229
|
payload[:filter] #=> "MarkdownFilter"
|
230
|
+
payload[:context] #=> context Hash
|
231
|
+
payload[:result] #=> instance of result class
|
232
|
+
payload[:result][:output] #=> output HTML String or Nokogiri::DocumentFragment
|
225
233
|
end
|
226
234
|
```
|
227
235
|
|
@@ -229,10 +237,19 @@ The full pipeline is also instrumented:
|
|
229
237
|
|
230
238
|
``` ruby
|
231
239
|
service.subscribe "call_pipeline.html_pipeline" do |event, start, ending, transaction_id, payload|
|
240
|
+
payload[:pipeline] #=> "MarkdownPipeline", set with `setup_instrumentation`
|
232
241
|
payload[:filters] #=> ["MarkdownFilter"]
|
242
|
+
payload[:doc] #=> HTML String or Nokogiri::DocumentFragment
|
243
|
+
payload[:context] #=> context Hash
|
244
|
+
payload[:result] #=> instance of result class
|
245
|
+
payload[:result][:output] #=> output HTML String or Nokogiri::DocumentFragment
|
233
246
|
end
|
234
247
|
```
|
235
248
|
|
249
|
+
## Documentation
|
250
|
+
|
251
|
+
Full reference documentation can be [found here](http://rubydoc.info/gems/html-pipeline/frames).
|
252
|
+
|
236
253
|
## Development
|
237
254
|
|
238
255
|
To see what has changed in recent versions, see the [CHANGELOG](https://github.com/jch/html-pipeline/blob/master/CHANGELOG.md).
|
@@ -250,21 +267,8 @@ rake test
|
|
250
267
|
4. Push to the branch (`git push origin my-new-feature`)
|
251
268
|
5. Create new [Pull Request](https://help.github.com/articles/using-pull-requests)
|
252
269
|
|
253
|
-
|
254
|
-
## TODO
|
255
|
-
|
256
|
-
* test whether emoji filter works on heroku
|
257
|
-
* test whether nokogiri monkey patch is still necessary
|
258
|
-
|
259
270
|
## Contributors
|
260
271
|
|
261
|
-
|
262
|
-
* [Jake Boxer](mailto:jake@github.com)
|
263
|
-
* [Joshua Peek](mailto:josh@joshpeek.com)
|
264
|
-
* [Kyle Neath](mailto:kneath@gmail.com)
|
265
|
-
* [Rob Sanheim](mailto:rsanheim@gmail.com)
|
266
|
-
* [Simon Rozet](mailto:simon@rozet.name)
|
267
|
-
* [Vicent Martí](mailto:tanoku@gmail.com)
|
268
|
-
* [Risk :danger: Olson](mailto:technoweenie@gmail.com)
|
272
|
+
Thanks to all of [these contributors](https://github.com/jch/html-pipeline/graphs/contributors).
|
269
273
|
|
270
274
|
Project is a member of the [OSS Manifesto](http://ossmanifesto.org/).
|
data/lib/html/pipeline.rb
CHANGED
@@ -25,7 +25,6 @@ module HTML
|
|
25
25
|
# some semblance of type safety.
|
26
26
|
class Pipeline
|
27
27
|
autoload :VERSION, 'html/pipeline/version'
|
28
|
-
autoload :Pipeline, 'html/pipeline/pipeline'
|
29
28
|
autoload :Filter, 'html/pipeline/filter'
|
30
29
|
autoload :AbsoluteSourceFilter, 'html/pipeline/absolute_source_filter'
|
31
30
|
autoload :BodyContent, 'html/pipeline/body_content'
|
@@ -65,6 +64,12 @@ module HTML
|
|
65
64
|
# Set an ActiveSupport::Notifications compatible object to enable.
|
66
65
|
attr_accessor :instrumentation_service
|
67
66
|
|
67
|
+
# Public: String name for this Pipeline. Defaults to Class name.
|
68
|
+
attr_writer :instrumentation_name
|
69
|
+
def instrumentation_name
|
70
|
+
@instrumentation_name || self.class.name
|
71
|
+
end
|
72
|
+
|
68
73
|
class << self
|
69
74
|
# Public: Default instrumentation service for new pipeline objects.
|
70
75
|
attr_accessor :default_instrumentation_service
|
@@ -94,7 +99,9 @@ module HTML
|
|
94
99
|
context = @default_context.merge(context)
|
95
100
|
context = context.freeze
|
96
101
|
result ||= @result_class.new
|
97
|
-
|
102
|
+
payload = default_payload :filters => @filters.map(&:name),
|
103
|
+
:context => context, :result => result
|
104
|
+
instrument "call_pipeline.html_pipeline", payload do
|
98
105
|
result[:output] =
|
99
106
|
@filters.inject(html) do |doc, filter|
|
100
107
|
perform_filter(filter, doc, context, result)
|
@@ -109,22 +116,13 @@ module HTML
|
|
109
116
|
#
|
110
117
|
# Returns the result of the filter.
|
111
118
|
def perform_filter(filter, doc, context, result)
|
112
|
-
|
119
|
+
payload = default_payload :filter => filter.name,
|
120
|
+
:context => context, :result => result
|
121
|
+
instrument "call_filter.html_pipeline", payload do
|
113
122
|
filter.call(doc, context, result)
|
114
123
|
end
|
115
124
|
end
|
116
125
|
|
117
|
-
# Internal: if the `instrumentation_service` object is set, instruments the
|
118
|
-
# block, otherwise the block is ran without instrumentation.
|
119
|
-
#
|
120
|
-
# Returns the result of the provided block.
|
121
|
-
def instrument(event, payload = nil)
|
122
|
-
return yield unless instrumentation_service
|
123
|
-
instrumentation_service.instrument event, payload do
|
124
|
-
yield
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
126
|
# Like call but guarantee the value returned is a DocumentFragment.
|
129
127
|
# Pipelines may return a DocumentFragment or a String. Callers that need a
|
130
128
|
# DocumentFragment should use this method.
|
@@ -143,6 +141,36 @@ module HTML
|
|
143
141
|
output.to_s
|
144
142
|
end
|
145
143
|
end
|
144
|
+
|
145
|
+
# Public: setup instrumentation for this pipeline.
|
146
|
+
#
|
147
|
+
# Returns nothing.
|
148
|
+
def setup_instrumentation(name = nil, service = nil)
|
149
|
+
self.instrumentation_name = name
|
150
|
+
self.instrumentation_service =
|
151
|
+
service || self.class.default_instrumentation_service
|
152
|
+
end
|
153
|
+
|
154
|
+
# Internal: if the `instrumentation_service` object is set, instruments the
|
155
|
+
# block, otherwise the block is ran without instrumentation.
|
156
|
+
#
|
157
|
+
# Returns the result of the provided block.
|
158
|
+
def instrument(event, payload = nil)
|
159
|
+
payload ||= default_payload
|
160
|
+
return yield(payload) unless instrumentation_service
|
161
|
+
instrumentation_service.instrument event, payload do |payload|
|
162
|
+
yield payload
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Internal: Default payload for instrumentation.
|
167
|
+
#
|
168
|
+
# Accepts a Hash of additional payload data to be merged.
|
169
|
+
#
|
170
|
+
# Returns a Hash.
|
171
|
+
def default_payload(payload = {})
|
172
|
+
{:pipeline => instrumentation_name}.merge(payload)
|
173
|
+
end
|
146
174
|
end
|
147
175
|
end
|
148
176
|
|
@@ -5,11 +5,13 @@ class MockedInstrumentationService
|
|
5
5
|
subscribe event
|
6
6
|
end
|
7
7
|
def instrument(event, payload = nil)
|
8
|
-
|
8
|
+
payload ||= {}
|
9
|
+
res = yield payload
|
9
10
|
events << [event, payload, res] if @subscribe == event
|
10
11
|
res
|
11
12
|
end
|
12
13
|
def subscribe(event)
|
13
14
|
@subscribe = event
|
15
|
+
@events
|
14
16
|
end
|
15
17
|
end
|
data/test/html/pipeline_test.rb
CHANGED
@@ -5,7 +5,7 @@ class HTML::PipelineTest < Test::Unit::TestCase
|
|
5
5
|
Pipeline = HTML::Pipeline
|
6
6
|
class TestFilter
|
7
7
|
def self.call(input, context, result)
|
8
|
-
input
|
8
|
+
input.reverse
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -17,24 +17,28 @@ class HTML::PipelineTest < Test::Unit::TestCase
|
|
17
17
|
|
18
18
|
def test_filter_instrumentation
|
19
19
|
service = MockedInstrumentationService.new
|
20
|
-
service.subscribe "call_filter.html_pipeline"
|
20
|
+
events = service.subscribe "call_filter.html_pipeline"
|
21
21
|
@pipeline.instrumentation_service = service
|
22
|
-
filter("hello")
|
23
|
-
event, payload, res =
|
22
|
+
filter(body = "hello")
|
23
|
+
event, payload, res = events.pop
|
24
24
|
assert event, "event expected"
|
25
25
|
assert_equal "call_filter.html_pipeline", event
|
26
26
|
assert_equal TestFilter.name, payload[:filter]
|
27
|
+
assert_equal @pipeline.class.name, payload[:pipeline]
|
28
|
+
assert_equal body.reverse, payload[:result][:output]
|
27
29
|
end
|
28
30
|
|
29
31
|
def test_pipeline_instrumentation
|
30
32
|
service = MockedInstrumentationService.new
|
31
|
-
service.subscribe "call_pipeline.html_pipeline"
|
33
|
+
events = service.subscribe "call_pipeline.html_pipeline"
|
32
34
|
@pipeline.instrumentation_service = service
|
33
|
-
filter("hello")
|
34
|
-
event, payload, res =
|
35
|
+
filter(body = "hello")
|
36
|
+
event, payload, res = events.pop
|
35
37
|
assert event, "event expected"
|
36
38
|
assert_equal "call_pipeline.html_pipeline", event
|
37
39
|
assert_equal @pipeline.filters.map(&:name), payload[:filters]
|
40
|
+
assert_equal @pipeline.class.name, payload[:pipeline]
|
41
|
+
assert_equal body.reverse, payload[:result][:output]
|
38
42
|
end
|
39
43
|
|
40
44
|
def test_default_instrumentation_service
|
@@ -46,6 +50,24 @@ class HTML::PipelineTest < Test::Unit::TestCase
|
|
46
50
|
Pipeline.default_instrumentation_service = nil
|
47
51
|
end
|
48
52
|
|
53
|
+
def test_setup_instrumentation
|
54
|
+
assert_nil @pipeline.instrumentation_service
|
55
|
+
|
56
|
+
service = MockedInstrumentationService.new
|
57
|
+
events = service.subscribe "call_pipeline.html_pipeline"
|
58
|
+
@pipeline.setup_instrumentation name = 'foo', service
|
59
|
+
|
60
|
+
assert_equal service, @pipeline.instrumentation_service
|
61
|
+
assert_equal name, @pipeline.instrumentation_name
|
62
|
+
|
63
|
+
filter(body = 'foo')
|
64
|
+
|
65
|
+
event, payload, res = events.pop
|
66
|
+
assert event, "expected event"
|
67
|
+
assert_equal name, payload[:pipeline]
|
68
|
+
assert_equal body.reverse, payload[:result][:output]
|
69
|
+
end
|
70
|
+
|
49
71
|
def filter(input)
|
50
72
|
@pipeline.call(input)
|
51
73
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: html-pipeline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.12
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-04-01 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: gemoji
|