content-pipeline 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +12 -0
- data/License +11 -0
- data/Rakefile +3 -0
- data/Readme.md +6 -0
- data/lib/content/pipeline.rb +53 -0
- data/lib/content/pipeline/core_extensions/hash_ext.rb +21 -0
- data/lib/content/pipeline/core_extensions/object_ext.rb +43 -0
- data/lib/content/pipeline/filters.rb +60 -0
- data/lib/content/pipeline/filters/code_highlight.rb +71 -0
- data/lib/content/pipeline/filters/markdown.rb +89 -0
- data/lib/content/pipeline/version.rb +5 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 63e843633684063415b4e1b255c2cb31951eef56
|
4
|
+
data.tar.gz: 77a10f7cb27a40367be4713dbaad5f7c7a676aa3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cfd257ad678d8a45a1e4f939c7b586f050958614a8e8d5161bd65840eb6ce99fa0c901771a8d16efbbe5f12b93c59444c1837377b62c54bcfd32a53cb66603aa
|
7
|
+
data.tar.gz: ab38717b3c52a5174c07ea42ab6c40bb391643b21cc8d278427ebe8b3b4b0cd6c416d2d5ac3e7d48c63bd93b0167b168db2256a1a4e6db347ce6e28079b93812
|
data/Gemfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
group :development do
|
5
|
+
gem 'kramdown', '~> 1.1.0'
|
6
|
+
gem 'pry', '~> 0.9.12'
|
7
|
+
|
8
|
+
unless RbConfig::CONFIG['ruby_install_name'] == 'jruby'
|
9
|
+
gem 'pygments.rb', '~> 0.5.1'
|
10
|
+
gem 'github-markdown', '~> 0.5.3'
|
11
|
+
end
|
12
|
+
end
|
data/License
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
Copyright 2013 Jordon Bedwell
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
4
|
+
use this file except in compliance with the License. You may obtain a copy of
|
5
|
+
the License at: http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
|
7
|
+
Unless required by applicable law or agreed to in writing, software
|
8
|
+
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
9
|
+
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
10
|
+
License for the specific language governing permissions and limitations under
|
11
|
+
the License.
|
data/Rakefile
ADDED
data/Readme.md
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
# Content Pipeline.
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/envygeeks/content-pipeline.png?branch=master)](https://travis-ci.org/envygeeks/content-pipeline) [![Coverage Status](https://coveralls.io/repos/envygeeks/content-pipeline/badge.png)](https://coveralls.io/r/envygeeks/content-pipeline) [![Code Climate](https://codeclimate.com/github/envygeeks/content-pipeline.png)](https://codeclimate.com/github/envygeeks/content-pipeline) [![Dependency Status](https://gemnasium.com/envygeeks/content-pipeline.png)](https://gemnasium.com/envygeeks/content-pipeline)
|
4
|
+
|
5
|
+
|
6
|
+
Content pipeline is like `html-pipeline` except it's less restrictive.
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require_relative 'pipeline/core_extensions/object_ext'
|
2
|
+
require_relative 'pipeline/core_extensions/hash_ext'
|
3
|
+
$:.unshift(File.expand_path('../../', __FILE__))
|
4
|
+
|
5
|
+
module Content
|
6
|
+
|
7
|
+
# --------------------------------------------------------------------------
|
8
|
+
# Content pipeline is a class that runs content through a pipeline of user
|
9
|
+
# set and/or defined filters returning the final result. It can be mixed
|
10
|
+
# and matched anyway and filters can even be skipped and removed.
|
11
|
+
# --------------------------------------------------------------------------
|
12
|
+
|
13
|
+
class Pipeline
|
14
|
+
require_relative 'pipeline/filters'
|
15
|
+
attr_reader :filters, :opts
|
16
|
+
|
17
|
+
# ------------------------------------------------------------------------
|
18
|
+
# Allows the user to initialize with a custom set of filters or to auto
|
19
|
+
# load our filters and use them, the base filters we provider are
|
20
|
+
# redcarpet and pygments.
|
21
|
+
#
|
22
|
+
# @opt filters [Array] a list of filters to use.
|
23
|
+
# ------------------------------------------------------------------------
|
24
|
+
|
25
|
+
def initialize(filters = Filters::DEFAULT_FILTERS, opts = nil)
|
26
|
+
@opts, @filters = (opts || {}).freeze, [ filters ].flatten.freeze
|
27
|
+
end
|
28
|
+
|
29
|
+
# ------------------------------------------------------------------------
|
30
|
+
# Runs through each of the extensions chosen by the user and then calls
|
31
|
+
# them, returning the final result as the final HTML string.
|
32
|
+
# ------------------------------------------------------------------------
|
33
|
+
|
34
|
+
def filter(content, opts = nil)
|
35
|
+
opts = @opts.deep_merge(opts || {})
|
36
|
+
@filters.each do |filter|
|
37
|
+
content = filter.new(content, opts[to_opt(filter)]).run
|
38
|
+
end
|
39
|
+
|
40
|
+
content
|
41
|
+
end
|
42
|
+
|
43
|
+
# ------------------------------------------------------------------------
|
44
|
+
# Convert a class and it's name into an opt by splitting up it's name
|
45
|
+
# and downcasing the last part returning it as a symbol for opts.
|
46
|
+
# ------------------------------------------------------------------------
|
47
|
+
|
48
|
+
private
|
49
|
+
def to_opt(cls)
|
50
|
+
cls.name.split(/::/).last.downcase.to_sym
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module CoreExtensions
|
2
|
+
|
3
|
+
# --------------------------------------------------------------------------
|
4
|
+
# Hash Extensions.
|
5
|
+
# --------------------------------------------------------------------------
|
6
|
+
|
7
|
+
module HashExt
|
8
|
+
|
9
|
+
# ------------------------------------------------------------------------
|
10
|
+
# Merge a hash, merging hashes in hashes with hashes in hashes if hashes.
|
11
|
+
# ------------------------------------------------------------------------
|
12
|
+
|
13
|
+
def deep_merge(new_hash)
|
14
|
+
merge(new_hash) do |k, o, n|
|
15
|
+
Hash === o && Hash === n ? o.deep_merge(n) : n
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Hash.send(:include, CoreExtensions::HashExt)
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module CoreExtensions
|
4
|
+
|
5
|
+
# --------------------------------------------------------------------------
|
6
|
+
# Object Extensions.
|
7
|
+
# --------------------------------------------------------------------------
|
8
|
+
|
9
|
+
module ObjectExt
|
10
|
+
|
11
|
+
def jruby?
|
12
|
+
RbConfig::CONFIG['ruby_install_name'] == 'jruby'
|
13
|
+
end
|
14
|
+
|
15
|
+
# ------------------------------------------------------------------------
|
16
|
+
# Convert an element to a Nokogiri document fragment.
|
17
|
+
# ------------------------------------------------------------------------
|
18
|
+
|
19
|
+
def to_nokogiri_fragment
|
20
|
+
return self if Nokogiri::HTML::DocumentFragment === self
|
21
|
+
Nokogiri::HTML.fragment(respond_to?(:to_html) ? to_html : to_s)
|
22
|
+
end
|
23
|
+
|
24
|
+
# ------------------------------------------------------------------------
|
25
|
+
# Require a file with a fallback and if all else fails send an error.
|
26
|
+
# ------------------------------------------------------------------------
|
27
|
+
|
28
|
+
def require_or_fail(a, b, msg)
|
29
|
+
require a
|
30
|
+
rescue LoadError
|
31
|
+
begin
|
32
|
+
require b
|
33
|
+
rescue LoadError => error
|
34
|
+
# Try to keep the call chain proper.
|
35
|
+
raise LoadError, msg, error.backtrace[3...-1]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# ----------------------------------------------------------------------------
|
42
|
+
|
43
|
+
Object.send(:include, CoreExtensions::ObjectExt)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class Content::Pipeline
|
2
|
+
|
3
|
+
# --------------------------------------------------------------------------
|
4
|
+
# Pipeline is an "abstract" class meant to be inherited from in a defined
|
5
|
+
# filter. It provides a set of base methods, namely initialize which
|
6
|
+
# spawns the str not to mention add_filter which allows the filter author
|
7
|
+
# to define a set of methods that need to be run on this filter.
|
8
|
+
# --------------------------------------------------------------------------
|
9
|
+
|
10
|
+
class Filter
|
11
|
+
|
12
|
+
# ------------------------------------------------------------------------
|
13
|
+
# Initialize.
|
14
|
+
# ------------------------------------------------------------------------
|
15
|
+
|
16
|
+
def initialize(str, opts = nil)
|
17
|
+
@opts, @str = (opts || {}), str
|
18
|
+
end
|
19
|
+
|
20
|
+
# ------------------------------------------------------------------------
|
21
|
+
# Run the set of filters the user wants ran on the filter.
|
22
|
+
# ------------------------------------------------------------------------
|
23
|
+
|
24
|
+
def run
|
25
|
+
self.class.filters.each do |f|
|
26
|
+
send(f)
|
27
|
+
end
|
28
|
+
|
29
|
+
@str.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
class << self
|
33
|
+
attr_reader :filters
|
34
|
+
|
35
|
+
# ----------------------------------------------------------------------
|
36
|
+
# Allows the author of a filter to set a method to be run on this,
|
37
|
+
# filter, without us having to enforce a specific type of name.
|
38
|
+
# ----------------------------------------------------------------------
|
39
|
+
|
40
|
+
def add_filter(*filters)
|
41
|
+
@filters ||= []
|
42
|
+
@filters.push(*filters.flatten)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# --------------------------------------------------------------------------
|
48
|
+
|
49
|
+
module Filters
|
50
|
+
require_relative 'filters/code_highlight'
|
51
|
+
require_relative 'filters/markdown'
|
52
|
+
|
53
|
+
# ------------------------------------------------------------------------
|
54
|
+
# A set of default filters that we use if the user does not supply their
|
55
|
+
# own filters for us to use.
|
56
|
+
# ------------------------------------------------------------------------
|
57
|
+
|
58
|
+
DEFAULT_FILTERS = [ Markdown, CodeHighlight ].freeze
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'pygments' unless jruby?
|
2
|
+
|
3
|
+
# ----------------------------------------------------------------------------
|
4
|
+
# A filter that discovers pre tags and then syntax highlights them, also
|
5
|
+
# allowing for fallback to just wrapping them so they stay consistent.
|
6
|
+
# ----------------------------------------------------------------------------
|
7
|
+
|
8
|
+
class Content::Pipeline::Filters::CodeHighlight < Content::Pipeline::Filter
|
9
|
+
add_filter :highlight
|
10
|
+
|
11
|
+
Matcher = /<pre>(.+)<\/pre>/m
|
12
|
+
Templates = {
|
13
|
+
:numb => %Q{<span class="line-number">%s</span>\n},
|
14
|
+
:line => '<span class="line">%s</span>',
|
15
|
+
:wrap => <<-HTML
|
16
|
+
<figure class="code">
|
17
|
+
<div class="highlight">
|
18
|
+
<table>
|
19
|
+
<tbody>
|
20
|
+
<tr>
|
21
|
+
<td class="gutter">
|
22
|
+
<pre>%s</pre>
|
23
|
+
</td>
|
24
|
+
<td class="code">
|
25
|
+
<pre><code class="%s">%s</code></pre>
|
26
|
+
</td>
|
27
|
+
</tr>
|
28
|
+
</tbody>
|
29
|
+
</table>
|
30
|
+
</div>
|
31
|
+
</figure>
|
32
|
+
HTML
|
33
|
+
}
|
34
|
+
|
35
|
+
# --------------------------------------------------------------------------
|
36
|
+
# Searches for elements we want to transform and transforms them.
|
37
|
+
# --------------------------------------------------------------------------
|
38
|
+
|
39
|
+
private
|
40
|
+
def highlight
|
41
|
+
@str = @str.to_nokogiri_fragment
|
42
|
+
@str.search('pre').each do |node|
|
43
|
+
node.replace Templates[:wrap] %
|
44
|
+
wrap(pygments(node.inner_text, node[:lang]), node[:lang] || 'text')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# --------------------------------------------------------------------------
|
49
|
+
# Goes through each line and wraps it as well as creates line numbers.
|
50
|
+
# --------------------------------------------------------------------------
|
51
|
+
|
52
|
+
private
|
53
|
+
def wrap(str, lang)
|
54
|
+
lines, numbs = '', ''; str.each_line.with_index(1) do |line, numb|
|
55
|
+
lines+= Templates[:line] % line
|
56
|
+
numbs+= Templates[:numb] % numb
|
57
|
+
end
|
58
|
+
|
59
|
+
[numbs, lang, lines]
|
60
|
+
end
|
61
|
+
|
62
|
+
# --------------------------------------------------------------------------
|
63
|
+
# Wraps around Pygments catching a timeout error so that it can cont.
|
64
|
+
# --------------------------------------------------------------------------
|
65
|
+
|
66
|
+
private
|
67
|
+
def pygments(str, lang)
|
68
|
+
return str if jruby? || !Pygments::Lexer[lang]
|
69
|
+
Pygments::Lexer[lang].highlight(str) =~ Matcher ? $1 : str
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# ----------------------------------------------------------------------------
|
2
|
+
# A filter that supports Github-Markdown and also has a few filters to strip
|
3
|
+
# the most basic unsafe content, if the user chooses this to be done.
|
4
|
+
# ----------------------------------------------------------------------------
|
5
|
+
|
6
|
+
class Content::Pipeline::Filters::Markdown < Content::Pipeline::Filter
|
7
|
+
add_filter :markdown, :strip_html
|
8
|
+
|
9
|
+
# --------------------------------------------------------------------------
|
10
|
+
# Parse Markdown content.
|
11
|
+
# --------------------------------------------------------------------------
|
12
|
+
|
13
|
+
private
|
14
|
+
def markdown
|
15
|
+
type = @opts.fetch(:type, ((jruby?) ? (:kramdown) : (:gfm)))
|
16
|
+
|
17
|
+
@str = case
|
18
|
+
when type =~ /\Amarkdown|gfm\Z/
|
19
|
+
require 'github/markdown'
|
20
|
+
GitHub::Markdown.to_html(@str, @opts.fetch(:type, :gfm))
|
21
|
+
else
|
22
|
+
require 'kramdown'
|
23
|
+
fix_kramdown_wraps(Kramdown::Document.
|
24
|
+
new(convert_backtick(@str), :enable_coderay => false).to_html)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# --------------------------------------------------------------------------
|
29
|
+
# Discovers private methods that start with strip_ and runs them if the
|
30
|
+
# filter is in safe mode. Which will strip certain tags from the data.
|
31
|
+
#
|
32
|
+
# Doing it this way allows us to allow people to extend this class and add
|
33
|
+
# what they wish to it, while us preventing them from monkey patching key
|
34
|
+
# methods and having to keep those up-to-date.
|
35
|
+
# --------------------------------------------------------------------------
|
36
|
+
|
37
|
+
private
|
38
|
+
def strip_html
|
39
|
+
@str = @str.to_nokogiri_fragment
|
40
|
+
if @opts[:safe]
|
41
|
+
private_methods(false).keep_if { |m| m =~ /\Astrip_/ }.each do |m|
|
42
|
+
unless m == :strip_html
|
43
|
+
send(m)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# --------------------------------------------------------------------------
|
50
|
+
# Strip anchor tags.
|
51
|
+
# --------------------------------------------------------------------------
|
52
|
+
|
53
|
+
private
|
54
|
+
def strip_links
|
55
|
+
@str.search('a').each do |node|
|
56
|
+
node.replace(node[:href])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# --------------------------------------------------------------------------
|
61
|
+
# Strip image tags.
|
62
|
+
# --------------------------------------------------------------------------
|
63
|
+
|
64
|
+
private
|
65
|
+
def strip_image
|
66
|
+
@str.search('img').each do |node|
|
67
|
+
# Tries to cover single line images wrapped in a paragraph.
|
68
|
+
node.parent.children.count == 1 ? node.parent.remove : node.remove
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# --------------------------------------------------------------------------
|
73
|
+
# Converts Github style backticks over to Portable ~~~.
|
74
|
+
# --------------------------------------------------------------------------
|
75
|
+
|
76
|
+
private
|
77
|
+
def convert_backtick(str)
|
78
|
+
str.gsub(/^`{3}(\s?[a-zA-Z0-9]+)?$/, '~~~\\1')
|
79
|
+
end
|
80
|
+
|
81
|
+
# --------------------------------------------------------------------------
|
82
|
+
# Converts <pre><code class="language-ruby"> to <pre lang="lang">.
|
83
|
+
# --------------------------------------------------------------------------
|
84
|
+
|
85
|
+
private
|
86
|
+
def fix_kramdown_wraps(str)
|
87
|
+
str.gsub(/<pre><code class="language-([A-Za-z0-9]+)">/, '<pre lang="\\1"><code>')
|
88
|
+
end
|
89
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: content-pipeline
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jordon Bedwell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.6.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.6.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: coveralls
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.6.7
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.6.7
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 10.1.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 10.1.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.14.0.rc1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.14.0.rc1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: luna-rspec-formatters
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.0.1
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.0.1
|
83
|
+
description: A less restrictive version of html-pipeline for content.
|
84
|
+
email: envygeeks@gmail.com
|
85
|
+
executables: []
|
86
|
+
extensions: []
|
87
|
+
extra_rdoc_files: []
|
88
|
+
files:
|
89
|
+
- Readme.md
|
90
|
+
- License
|
91
|
+
- Rakefile
|
92
|
+
- Gemfile
|
93
|
+
- lib/content/pipeline/filters/markdown.rb
|
94
|
+
- lib/content/pipeline/filters/code_highlight.rb
|
95
|
+
- lib/content/pipeline/core_extensions/object_ext.rb
|
96
|
+
- lib/content/pipeline/core_extensions/hash_ext.rb
|
97
|
+
- lib/content/pipeline/version.rb
|
98
|
+
- lib/content/pipeline/filters.rb
|
99
|
+
- lib/content/pipeline.rb
|
100
|
+
homepage: https://github.com/envygeeks/content-pipeline
|
101
|
+
licenses:
|
102
|
+
- Apache 2.0
|
103
|
+
metadata: {}
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
requirements: []
|
119
|
+
rubyforge_project:
|
120
|
+
rubygems_version: 2.0.3
|
121
|
+
signing_key:
|
122
|
+
specification_version: 4
|
123
|
+
summary: Adds a pipeline for your content.
|
124
|
+
test_files: []
|