html-pipeline 0.0.10 → 0.0.11
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/CHANGELOG.md +4 -0
- data/README.md +40 -4
- data/lib/html/pipeline.rb +38 -1
- data/lib/html/pipeline/version.rb +1 -1
- data/test/helpers/mocked_instrumentation_service.rb +15 -0
- data/test/html/pipeline_test.rb +52 -0
- metadata +6 -2
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -53,9 +53,7 @@ pipeline = HTML::Pipeline.new [
|
|
53
53
|
result = pipeline.call <<-CODE
|
54
54
|
This is *great*:
|
55
55
|
|
56
|
-
|
57
|
-
some_code(:first)
|
58
|
-
```
|
56
|
+
some_code(:first)
|
59
57
|
|
60
58
|
CODE
|
61
59
|
result[:output].to_s
|
@@ -178,7 +176,7 @@ require 'uri'
|
|
178
176
|
class RootRelativeFilter < HTML::Pipeline::Filter
|
179
177
|
|
180
178
|
def call
|
181
|
-
doc.search("img").each do |img|
|
179
|
+
doc.search("img").each do |img|
|
182
180
|
next if img['src'].nil?
|
183
181
|
src = img['src'].strip
|
184
182
|
if src.start_with? '/'
|
@@ -197,6 +195,44 @@ Now this filter can be used in a pipeline:
|
|
197
195
|
Pipeline.new [ RootRelativeFilter ], { :base_url => 'http://somehost.com' }
|
198
196
|
```
|
199
197
|
|
198
|
+
## Instrumenting
|
199
|
+
|
200
|
+
To instrument each filter and a full pipeline call, set an
|
201
|
+
[ActiveSupport::Notifications](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html)
|
202
|
+
service object on a pipeline object. New pipeline objects will default to the
|
203
|
+
`HTML::Pipeline.default_instrumentation_service` object.
|
204
|
+
|
205
|
+
``` ruby
|
206
|
+
# the AS::Notifications-compatible service object
|
207
|
+
service = ActiveSupport::Notifications
|
208
|
+
|
209
|
+
# instrument a specific pipeline
|
210
|
+
pipeline = HTML::Pipeline.new [MarkdownFilter], context
|
211
|
+
pipeline.instrumentation_service = service
|
212
|
+
|
213
|
+
# or instrument all new pipelines
|
214
|
+
HTML::Pipeline.default_instrumentation_service = service
|
215
|
+
```
|
216
|
+
|
217
|
+
Filters are instrumented when they are run through the pipeline. A
|
218
|
+
`call_filter.html_pipeline` event is published once the filter finishes. The
|
219
|
+
`payload` should include the `filter` name. Each filter will trigger its own
|
220
|
+
instrumentation call.
|
221
|
+
|
222
|
+
``` ruby
|
223
|
+
service.subscribe "call_filter.html_pipeline" do |event, start, ending, transaction_id, payload|
|
224
|
+
payload[:filter] #=> "MarkdownFilter"
|
225
|
+
end
|
226
|
+
```
|
227
|
+
|
228
|
+
The full pipeline is also instrumented:
|
229
|
+
|
230
|
+
``` ruby
|
231
|
+
service.subscribe "call_pipeline.html_pipeline" do |event, start, ending, transaction_id, payload|
|
232
|
+
payload[:filters] #=> ["MarkdownFilter"]
|
233
|
+
end
|
234
|
+
```
|
235
|
+
|
200
236
|
## Development
|
201
237
|
|
202
238
|
To see what has changed in recent versions, see the [CHANGELOG](https://github.com/jch/html-pipeline/blob/master/CHANGELOG.md).
|
data/lib/html/pipeline.rb
CHANGED
@@ -61,11 +61,21 @@ module HTML
|
|
61
61
|
# Public: Returns an Array of Filter objects for this Pipeline.
|
62
62
|
attr_reader :filters
|
63
63
|
|
64
|
+
# Public: Instrumentation service for the pipeline.
|
65
|
+
# Set an ActiveSupport::Notifications compatible object to enable.
|
66
|
+
attr_accessor :instrumentation_service
|
67
|
+
|
68
|
+
class << self
|
69
|
+
# Public: Default instrumentation service for new pipeline objects.
|
70
|
+
attr_accessor :default_instrumentation_service
|
71
|
+
end
|
72
|
+
|
64
73
|
def initialize(filters, default_context = {}, result_class = nil)
|
65
74
|
raise ArgumentError, "default_context cannot be nil" if default_context.nil?
|
66
75
|
@filters = filters.flatten.freeze
|
67
76
|
@default_context = default_context.freeze
|
68
77
|
@result_class = result_class || Hash
|
78
|
+
@instrumentation_service = self.class.default_instrumentation_service
|
69
79
|
end
|
70
80
|
|
71
81
|
# Apply all filters in the pipeline to the given HTML.
|
@@ -84,10 +94,37 @@ module HTML
|
|
84
94
|
context = @default_context.merge(context)
|
85
95
|
context = context.freeze
|
86
96
|
result ||= @result_class.new
|
87
|
-
|
97
|
+
instrument "call_pipeline.html_pipeline", :filters => @filters.map(&:name) do
|
98
|
+
result[:output] =
|
99
|
+
@filters.inject(html) do |doc, filter|
|
100
|
+
perform_filter(filter, doc, context, result)
|
101
|
+
end
|
102
|
+
end
|
88
103
|
result
|
89
104
|
end
|
90
105
|
|
106
|
+
# Internal: Applies a specific filter to the supplied doc.
|
107
|
+
#
|
108
|
+
# The filter is instrumented.
|
109
|
+
#
|
110
|
+
# Returns the result of the filter.
|
111
|
+
def perform_filter(filter, doc, context, result)
|
112
|
+
instrument "call_filter.html_pipeline", :filter => filter.name do
|
113
|
+
filter.call(doc, context, result)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
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
|
+
|
91
128
|
# Like call but guarantee the value returned is a DocumentFragment.
|
92
129
|
# Pipelines may return a DocumentFragment or a String. Callers that need a
|
93
130
|
# DocumentFragment should use this method.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class MockedInstrumentationService
|
2
|
+
attr_reader :events
|
3
|
+
def initialize(event = nil, events = [])
|
4
|
+
@events = events
|
5
|
+
subscribe event
|
6
|
+
end
|
7
|
+
def instrument(event, payload = nil)
|
8
|
+
res = yield
|
9
|
+
events << [event, payload, res] if @subscribe == event
|
10
|
+
res
|
11
|
+
end
|
12
|
+
def subscribe(event)
|
13
|
+
@subscribe = event
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "helpers/mocked_instrumentation_service"
|
3
|
+
|
4
|
+
class HTML::PipelineTest < Test::Unit::TestCase
|
5
|
+
Pipeline = HTML::Pipeline
|
6
|
+
class TestFilter
|
7
|
+
def self.call(input, context, result)
|
8
|
+
input
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@context = {}
|
14
|
+
@result_class = Hash
|
15
|
+
@pipeline = Pipeline.new [TestFilter], @context, @result_class
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_filter_instrumentation
|
19
|
+
service = MockedInstrumentationService.new
|
20
|
+
service.subscribe "call_filter.html_pipeline"
|
21
|
+
@pipeline.instrumentation_service = service
|
22
|
+
filter("hello")
|
23
|
+
event, payload, res = service.events.pop
|
24
|
+
assert event, "event expected"
|
25
|
+
assert_equal "call_filter.html_pipeline", event
|
26
|
+
assert_equal TestFilter.name, payload[:filter]
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_pipeline_instrumentation
|
30
|
+
service = MockedInstrumentationService.new
|
31
|
+
service.subscribe "call_pipeline.html_pipeline"
|
32
|
+
@pipeline.instrumentation_service = service
|
33
|
+
filter("hello")
|
34
|
+
event, payload, res = service.events.pop
|
35
|
+
assert event, "event expected"
|
36
|
+
assert_equal "call_pipeline.html_pipeline", event
|
37
|
+
assert_equal @pipeline.filters.map(&:name), payload[:filters]
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_default_instrumentation_service
|
41
|
+
service = 'default'
|
42
|
+
Pipeline.default_instrumentation_service = service
|
43
|
+
pipeline = Pipeline.new [], @context, @result_class
|
44
|
+
assert_equal service, pipeline.instrumentation_service
|
45
|
+
ensure
|
46
|
+
Pipeline.default_instrumentation_service = nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def filter(input)
|
50
|
+
@pipeline.call(input)
|
51
|
+
end
|
52
|
+
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.11
|
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-03-
|
13
|
+
date: 2013-03-29 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: gemoji
|
@@ -176,6 +176,7 @@ files:
|
|
176
176
|
- lib/html/pipeline/textile_filter.rb
|
177
177
|
- lib/html/pipeline/toc_filter.rb
|
178
178
|
- lib/html/pipeline/version.rb
|
179
|
+
- test/helpers/mocked_instrumentation_service.rb
|
179
180
|
- test/html/pipeline/absolute_source_filter_test.rb
|
180
181
|
- test/html/pipeline/autolink_filter_test.rb
|
181
182
|
- test/html/pipeline/camo_filter_test.rb
|
@@ -186,6 +187,7 @@ files:
|
|
186
187
|
- test/html/pipeline/plain_text_input_filter_test.rb
|
187
188
|
- test/html/pipeline/sanitization_filter_test.rb
|
188
189
|
- test/html/pipeline/toc_filter_test.rb
|
190
|
+
- test/html/pipeline_test.rb
|
189
191
|
- test/test_helper.rb
|
190
192
|
homepage: https://github.com/jch/html-pipeline
|
191
193
|
licenses:
|
@@ -213,6 +215,7 @@ signing_key:
|
|
213
215
|
specification_version: 3
|
214
216
|
summary: Helpers for processing content through a chain of filters
|
215
217
|
test_files:
|
218
|
+
- test/helpers/mocked_instrumentation_service.rb
|
216
219
|
- test/html/pipeline/absolute_source_filter_test.rb
|
217
220
|
- test/html/pipeline/autolink_filter_test.rb
|
218
221
|
- test/html/pipeline/camo_filter_test.rb
|
@@ -223,4 +226,5 @@ test_files:
|
|
223
226
|
- test/html/pipeline/plain_text_input_filter_test.rb
|
224
227
|
- test/html/pipeline/sanitization_filter_test.rb
|
225
228
|
- test/html/pipeline/toc_filter_test.rb
|
229
|
+
- test/html/pipeline_test.rb
|
226
230
|
- test/test_helper.rb
|