shortcode 1.2.1 → 2.0.0.pre
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/.rubocop +1 -0
- data/.rubocop.yml +72 -0
- data/.travis.yml +7 -6
- data/Appraisals +3 -7
- data/Gemfile +2 -2
- data/Gemfile.lock +136 -18
- data/bin/appraisal +17 -0
- data/bin/rspec +17 -0
- data/bin/rubocop +17 -0
- data/gemfiles/rails_4.2.gemfile +1 -1
- data/gemfiles/rails_5.0.gemfile +1 -1
- data/gemfiles/rails_5.1.gemfile +1 -1
- data/lib/shortcode.rb +17 -41
- data/lib/shortcode/configuration.rb +3 -1
- data/lib/shortcode/parser.rb +21 -17
- data/lib/shortcode/presenter.rb +18 -15
- data/lib/shortcode/processor.rb +3 -1
- data/lib/shortcode/railtie.rb +2 -0
- data/lib/shortcode/tag.rb +11 -4
- data/lib/shortcode/template_binding.rb +12 -7
- data/lib/shortcode/transformer.rb +8 -4
- data/lib/shortcode/version.rb +3 -1
- data/shortcode.gemspec +10 -7
- data/spec/.rubocop.yml +17 -0
- data/spec/performance_spec.rb +4 -5
- data/spec/rails_helpers_spec.rb +25 -31
- data/spec/shortcode/parser_spec.rb +313 -0
- data/spec/shortcode/presenter_spec.rb +118 -0
- data/spec/shortcode/tag_spec.rb +73 -0
- data/spec/shortcode_spec.rb +40 -37
- data/spec/spec_helper.rb +6 -20
- data/spec/support/fixtures.rb +4 -6
- data/spec/support/presenters/missing_attributes_presenter.rb +3 -6
- data/spec/support/presenters/missing_content_presenter.rb +3 -6
- data/spec/support/presenters/missing_for_presenter.rb +3 -6
- data/spec/support/presenters/missing_initialize_presenter.rb +3 -6
- data/spec/support/presenters/multiple_presenter.rb +4 -5
- data/spec/support/presenters/my_presenter.rb +3 -4
- data/spec/support/presenters/other_presenter.rb +3 -4
- data/spec/template_parsers_spec.rb +21 -22
- data/spec/transformer_spec.rb +26 -36
- metadata +75 -24
- data/gemfiles/rails_4.1.gemfile +0 -8
- data/spec/parser_spec.rb +0 -307
- data/spec/presenter_spec.rb +0 -126
- data/spec/tag_spec.rb +0 -86
@@ -1,4 +1,5 @@
|
|
1
1
|
class Shortcode::Configuration
|
2
|
+
|
2
3
|
# Sets the template parser to use, supports :erb, :haml, and :slim, default is :haml
|
3
4
|
attr_accessor :template_parser
|
4
5
|
|
@@ -32,7 +33,7 @@ class Shortcode::Configuration
|
|
32
33
|
# Set the quotation sign used for attribute values. Defaults to double quote (")
|
33
34
|
attr_accessor :attribute_quote_type
|
34
35
|
|
35
|
-
# Allows quotes around attributes to be omitted. Defaults to false (quotes must be present around the value)
|
36
|
+
# Allows quotes around attributes to be omitted. Defaults to false (quotes must be present around the value)
|
36
37
|
attr_accessor :use_attribute_quotes
|
37
38
|
|
38
39
|
def initialize
|
@@ -51,4 +52,5 @@ class Shortcode::Configuration
|
|
51
52
|
def register_presenter(presenter)
|
52
53
|
Shortcode::Presenter.register(self, presenter)
|
53
54
|
end
|
55
|
+
|
54
56
|
end
|
data/lib/shortcode/parser.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
class Shortcode::Parser
|
2
|
+
|
2
3
|
def initialize(configuration)
|
3
4
|
@configuration = configuration
|
4
5
|
setup_rules
|
@@ -23,51 +24,54 @@ class Shortcode::Parser
|
|
23
24
|
@klass_instance ||= klass.new
|
24
25
|
end
|
25
26
|
|
27
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/LineLength
|
26
28
|
def setup_rules
|
27
29
|
define_match_any_of
|
28
30
|
|
29
31
|
shortcode_configuration = @configuration
|
30
|
-
klass.rule(:block_tag)
|
32
|
+
klass.rule(:block_tag) { match_any_of shortcode_configuration.block_tags }
|
31
33
|
klass.rule(:self_closing_tag) { match_any_of shortcode_configuration.self_closing_tags }
|
32
34
|
|
33
35
|
klass.rule(:quotes) { str(shortcode_configuration.attribute_quote_type) }
|
34
36
|
|
35
|
-
klass.rule(:space)
|
36
|
-
klass.rule(:space?)
|
37
|
-
klass.rule(:newline)
|
38
|
-
klass.rule(:newline?)
|
39
|
-
klass.rule(:whitespace)
|
37
|
+
klass.rule(:space) { str(" ").repeat(1) }
|
38
|
+
klass.rule(:space?) { space.maybe }
|
39
|
+
klass.rule(:newline) { (str("\r\n") | str("\n")) >> space? }
|
40
|
+
klass.rule(:newline?) { newline.maybe }
|
41
|
+
klass.rule(:whitespace) { (space | newline).repeat(1) }
|
40
42
|
|
41
43
|
klass.rule(:key) { match('[a-zA-Z0-9\-_]').repeat(1) }
|
42
44
|
|
43
45
|
klass.rule(:value_with_quotes) { quotes >> (quotes.absent? >> any).repeat.as(:value) >> quotes }
|
44
|
-
klass.rule(:value_without_quotes) { quotes.absent? >> (
|
46
|
+
klass.rule(:value_without_quotes) { quotes.absent? >> ((str("]") | whitespace).absent? >> any).repeat.as(:value) }
|
45
47
|
klass.rule(:value) { shortcode_configuration.use_attribute_quotes ? value_with_quotes : (value_without_quotes | value_with_quotes) }
|
46
48
|
|
47
|
-
klass.rule(:option)
|
48
|
-
klass.rule(:options)
|
49
|
+
klass.rule(:option) { key.as(:key) >> str("=") >> value }
|
50
|
+
klass.rule(:options) { (str(" ") >> option).repeat(1) }
|
49
51
|
klass.rule(:options?) { options.repeat(0, 1) }
|
50
52
|
|
51
|
-
klass.rule(:open)
|
52
|
-
klass.rule(:close)
|
53
|
-
klass.rule(:open_close) { str(
|
53
|
+
klass.rule(:open) { str("[") >> block_tag.as(:open) >> options?.as(:options) >> str("]") >> newline? }
|
54
|
+
klass.rule(:close) { str("[/") >> block_tag.as(:close) >> str("]") >> newline? }
|
55
|
+
klass.rule(:open_close) { str("[") >> self_closing_tag.as(:open_close) >> options?.as(:options) >> str("]") >> newline? }
|
54
56
|
|
55
|
-
klass.rule(:text)
|
56
|
-
klass.rule(:block)
|
57
|
+
klass.rule(:text) { ((close | block | open_close).absent? >> any).repeat(1).as(:text) }
|
58
|
+
klass.rule(:block) { (open >> (block | text | open_close).repeat.as(:inner) >> close) }
|
57
59
|
|
58
60
|
klass.rule(:body) { (block | text | open_close).repeat.as(:body) }
|
59
61
|
klass.root(:body)
|
60
62
|
end
|
63
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/LineLength
|
61
64
|
|
62
65
|
def define_match_any_of
|
63
66
|
klass.send(:define_method, :match_any_of) do |tags|
|
64
|
-
if tags.
|
65
|
-
|
67
|
+
if tags.empty?
|
68
|
+
str("")
|
66
69
|
else
|
67
|
-
tags.map{ |tag| str(tag) }.inject do |tag_chain, tag|
|
70
|
+
tags.map { |tag| str(tag) }.inject do |tag_chain, tag|
|
68
71
|
tag_chain.send :|, tag
|
69
72
|
end
|
70
73
|
end
|
71
74
|
end
|
72
75
|
end
|
76
|
+
|
73
77
|
end
|
data/lib/shortcode/presenter.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
1
|
class Shortcode::Presenter
|
2
|
+
|
2
3
|
def self.register(configuration, presenter)
|
3
4
|
validate presenter
|
4
5
|
[*presenter.for].each { |k| configuration.presenters[k.to_sym] = presenter }
|
5
6
|
end
|
6
7
|
|
7
8
|
def self.validate(presenter)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
unless presenter.respond_to?(:for)
|
10
|
+
raise ArgumentError, "The presenter must define the class method #for"
|
11
|
+
end
|
12
|
+
unless presenter.private_instance_methods(false).include?(:initialize)
|
13
|
+
raise ArgumentError, "The presenter must define an initialize method"
|
14
|
+
end
|
15
|
+
%w[content attributes].each do |method|
|
16
|
+
unless presenter.method_defined?(method.to_sym)
|
17
|
+
raise ArgumentError, "The presenter must define the method ##{method}"
|
18
|
+
end
|
12
19
|
end
|
13
20
|
end
|
14
21
|
|
@@ -20,23 +27,19 @@ class Shortcode::Presenter
|
|
20
27
|
initialize_custom_presenter(name)
|
21
28
|
end
|
22
29
|
|
23
|
-
|
24
|
-
@content
|
25
|
-
end
|
30
|
+
attr_reader :content
|
26
31
|
|
27
|
-
|
28
|
-
@attributes
|
29
|
-
end
|
32
|
+
attr_reader :attributes
|
30
33
|
|
31
34
|
private
|
32
35
|
|
33
36
|
attr_reader :configuration
|
34
37
|
|
35
38
|
def initialize_custom_presenter(name)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
39
|
+
return unless configuration.presenters.key?(name.to_sym)
|
40
|
+
presenter = configuration.presenters[name.to_sym].new(@attributes, @content, @additional_attributes)
|
41
|
+
@attributes = presenter.attributes
|
42
|
+
@content = presenter.content
|
41
43
|
end
|
44
|
+
|
42
45
|
end
|
data/lib/shortcode/processor.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
class Shortcode::Processor
|
2
2
|
|
3
3
|
def process(string, configuration, additional_attributes=nil)
|
4
|
-
transformer(configuration).apply parser(configuration).parse(string),
|
4
|
+
transformer(configuration).apply parser(configuration).parse(string),
|
5
|
+
additional_attributes: additional_attributes
|
5
6
|
end
|
6
7
|
|
7
8
|
private
|
@@ -13,4 +14,5 @@ class Shortcode::Processor
|
|
13
14
|
def transformer(configuration)
|
14
15
|
@transformer ||= Shortcode::Transformer.new(configuration)
|
15
16
|
end
|
17
|
+
|
16
18
|
end
|
data/lib/shortcode/railtie.rb
CHANGED
data/lib/shortcode/tag.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
class Shortcode::Tag
|
2
2
|
|
3
|
-
def initialize(name, configuration, attributes=[], content=
|
3
|
+
def initialize(name, configuration, attributes=[], content="", additional_attributes=nil)
|
4
4
|
@name = name.downcase
|
5
5
|
@configuration = configuration
|
6
|
-
@binding = Shortcode::TemplateBinding.new(@name,
|
6
|
+
@binding = Shortcode::TemplateBinding.new(@name,
|
7
|
+
@configuration,
|
8
|
+
attributes,
|
9
|
+
content,
|
10
|
+
additional_attributes)
|
7
11
|
end
|
8
12
|
|
9
13
|
def markup
|
@@ -21,10 +25,11 @@ class Shortcode::Tag
|
|
21
25
|
|
22
26
|
attr_reader :configuration
|
23
27
|
|
28
|
+
# rubocop:disable Metrics/AbcSize
|
24
29
|
def render_template
|
25
30
|
case configuration.template_parser
|
26
31
|
when :erb
|
27
|
-
ERB.new(markup).result(@binding.
|
32
|
+
ERB.new(markup).result(@binding.expose_binding)
|
28
33
|
when :haml
|
29
34
|
Haml::Engine.new(markup).render(@binding)
|
30
35
|
when :slim
|
@@ -33,6 +38,7 @@ class Shortcode::Tag
|
|
33
38
|
raise Shortcode::TemplateParserNotSupported, configuration.template_parser
|
34
39
|
end
|
35
40
|
end
|
41
|
+
# rubocop:enable Metrics/AbcSize
|
36
42
|
|
37
43
|
def first_priority_template
|
38
44
|
configuration.check_config_templates_first ? markup_from_config : markup_from_file
|
@@ -60,6 +66,7 @@ class Shortcode::Tag
|
|
60
66
|
end
|
61
67
|
|
62
68
|
def template_paths
|
63
|
-
[
|
69
|
+
["#{@name}.html.#{configuration.template_parser}", "#{@name}.#{configuration.template_parser}"]
|
64
70
|
end
|
71
|
+
|
65
72
|
end
|
@@ -1,16 +1,20 @@
|
|
1
1
|
class Shortcode::TemplateBinding
|
2
2
|
|
3
|
-
def initialize(name, configuration, attributes=[], content=
|
3
|
+
def initialize(name, configuration, attributes=[], content="", additional_attributes=nil)
|
4
4
|
@configuration = configuration
|
5
5
|
include_helper_modules
|
6
|
-
presenter
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
presenter = Shortcode::Presenter.new name,
|
7
|
+
configuration,
|
8
|
+
map_attributes(attributes),
|
9
|
+
content,
|
10
|
+
additional_attributes
|
11
|
+
@name = name
|
12
|
+
@attributes = presenter.attributes
|
13
|
+
@content = presenter.content
|
10
14
|
end
|
11
15
|
|
12
16
|
# Expose private binding() method for use with erb templates
|
13
|
-
def
|
17
|
+
def expose_binding
|
14
18
|
binding
|
15
19
|
end
|
16
20
|
|
@@ -18,7 +22,7 @@ class Shortcode::TemplateBinding
|
|
18
22
|
|
19
23
|
attr_reader :configuration
|
20
24
|
|
21
|
-
def
|
25
|
+
def map_attributes(attributes)
|
22
26
|
hash = {}
|
23
27
|
attributes.each { |o| hash[o[:key].to_sym] = o[:value] }
|
24
28
|
hash
|
@@ -31,4 +35,5 @@ class Shortcode::TemplateBinding
|
|
31
35
|
self.class.send(:include, helper)
|
32
36
|
end
|
33
37
|
end
|
38
|
+
|
34
39
|
end
|
@@ -1,10 +1,11 @@
|
|
1
1
|
class Shortcode::Transformer
|
2
|
+
|
2
3
|
def initialize(configuration)
|
3
4
|
@configuration = configuration
|
4
5
|
setup_rules
|
5
6
|
end
|
6
7
|
|
7
|
-
def apply(str, options
|
8
|
+
def apply(str, options={})
|
8
9
|
klass_instance.apply(str, options)
|
9
10
|
end
|
10
11
|
|
@@ -18,8 +19,9 @@ class Shortcode::Transformer
|
|
18
19
|
@klass_instance ||= klass.new
|
19
20
|
end
|
20
21
|
|
22
|
+
# rubocop:disable Metrics/AbcSize
|
21
23
|
def setup_rules
|
22
|
-
|
24
|
+
config = @configuration
|
23
25
|
|
24
26
|
klass.rule(text: klass.send(:simple, :text)) { String(text) }
|
25
27
|
klass.rule(
|
@@ -27,12 +29,14 @@ class Shortcode::Transformer
|
|
27
29
|
options: klass.send(:subtree, :options),
|
28
30
|
inner: klass.send(:sequence, :inner),
|
29
31
|
close: klass.send(:simple, :name)
|
30
|
-
) { Shortcode::Tag.new(name.to_s,
|
32
|
+
) { Shortcode::Tag.new(name.to_s, config, options, inner.join, additional_attributes).render }
|
31
33
|
klass.rule(
|
32
34
|
open_close: klass.send(:simple, :name),
|
33
35
|
options: klass.send(:subtree, :options)
|
34
|
-
) { Shortcode::Tag.new(name.to_s,
|
36
|
+
) { Shortcode::Tag.new(name.to_s, config, options, "", additional_attributes).render }
|
35
37
|
|
36
38
|
klass.rule(body: klass.send(:sequence, :strings)) { strings.join }
|
37
39
|
end
|
40
|
+
# rubocop:enable Metrics/AbcSize
|
41
|
+
|
38
42
|
end
|
data/lib/shortcode/version.rb
CHANGED
data/shortcode.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path(
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require "shortcode/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "shortcode"
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = "https://github.com/kernow/shortcode"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
|
-
spec.files = `git ls-files`.split(
|
16
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
@@ -21,9 +21,12 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_dependency "parslet", "1.8.0"
|
22
22
|
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.15"
|
24
|
-
spec.add_development_dependency "rake", "~> 12.0"
|
25
|
-
spec.add_development_dependency "rspec", "~> 3.6"
|
26
24
|
spec.add_development_dependency "coveralls", "~> 0.8"
|
27
|
-
spec.add_development_dependency "slim", "~> 3.0"
|
28
25
|
spec.add_development_dependency "haml", "~> 5.0"
|
26
|
+
spec.add_development_dependency "rails", "5.1.4"
|
27
|
+
spec.add_development_dependency "rake", "~> 12.0"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.7"
|
29
|
+
spec.add_development_dependency "rubocop", "~> 0.51"
|
30
|
+
spec.add_development_dependency "rubocop-rspec", "~> 1.19"
|
31
|
+
spec.add_development_dependency "slim", "~> 3.0"
|
29
32
|
end
|
data/spec/.rubocop.yml
ADDED
data/spec/performance_spec.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "spec_helper"
|
2
|
+
require "parslet/rig/rspec"
|
3
|
+
require "pp"
|
4
|
+
require "benchmark"
|
5
5
|
|
6
6
|
# Uncomment to run performace specs
|
7
7
|
|
8
|
-
|
9
8
|
# describe Shortcode do
|
10
9
|
|
11
10
|
# let(:long_text) { load_fixture :long_text }
|
data/spec/rails_helpers_spec.rb
CHANGED
@@ -1,72 +1,66 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
module ShortcodeSpecViewHelper
|
4
|
+
|
4
5
|
def wrap_in_p(content)
|
5
6
|
content_tag :p, content
|
6
7
|
end
|
7
|
-
end
|
8
8
|
|
9
|
-
|
9
|
+
end
|
10
10
|
|
11
|
+
describe "rails helpers", type: :feature do
|
11
12
|
let(:template) { load_fixture :rails_helper }
|
12
13
|
|
13
14
|
let(:erb_output) { load_fixture :rails_helper_output_erb, :html }
|
14
15
|
let(:haml_output) { load_fixture :rails_helper_output_haml, :html }
|
15
16
|
let(:slim_output) { load_fixture :rails_helper_output_slim, :html }
|
16
17
|
|
17
|
-
|
18
|
+
let(:shortcode) { Shortcode.new }
|
19
|
+
let(:configuration) { shortcode.configuration }
|
18
20
|
|
21
|
+
before do
|
22
|
+
configuration.block_tags = %i[rails_helper custom_helper]
|
23
|
+
configuration.template_path = File.join File.dirname(__FILE__), "support/templates/erb"
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "erb" do
|
19
27
|
it "are accessible within erb templates" do
|
20
|
-
expect(
|
28
|
+
expect(shortcode.process(template).delete("\n")).to eq(erb_output)
|
21
29
|
end
|
22
|
-
|
23
30
|
end
|
24
31
|
|
25
32
|
describe "haml" do
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
config.template_parser = :haml
|
30
|
-
config.template_path = File.join File.dirname(__FILE__), "support/templates/haml"
|
31
|
-
end
|
33
|
+
before do
|
34
|
+
configuration.template_parser = :haml
|
35
|
+
configuration.template_path = File.join File.dirname(__FILE__), "support/templates/haml"
|
32
36
|
end
|
33
37
|
|
34
38
|
it "are accessible within haml templates" do
|
35
|
-
expect(
|
39
|
+
expect(shortcode.process(template).delete("\n")).to eq(haml_output)
|
36
40
|
end
|
37
|
-
|
38
41
|
end
|
39
42
|
|
40
43
|
describe "slim" do
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
config.template_parser = :slim
|
45
|
-
config.template_path = File.join File.dirname(__FILE__), "support/templates/slim"
|
46
|
-
end
|
44
|
+
before do
|
45
|
+
configuration.template_parser = :slim
|
46
|
+
configuration.template_path = File.join File.dirname(__FILE__), "support/templates/slim"
|
47
47
|
end
|
48
48
|
|
49
49
|
it "are accessible within slim templates" do
|
50
|
-
expect(
|
50
|
+
expect(shortcode.process(template).delete("\n")).to eq(slim_output)
|
51
51
|
end
|
52
|
-
|
53
52
|
end
|
54
53
|
|
55
54
|
describe "using a custom helper module" do
|
56
|
-
|
57
55
|
let(:template) { load_fixture :custom_helper }
|
58
|
-
let(:output) { load_fixture :custom_helper_output,
|
56
|
+
let(:output) { load_fixture :custom_helper_output, :html }
|
59
57
|
|
60
|
-
before
|
61
|
-
|
62
|
-
config.helpers = [ShortcodeSpecViewHelper]
|
63
|
-
end
|
58
|
+
before do
|
59
|
+
configuration.helpers = [ShortcodeSpecViewHelper]
|
64
60
|
end
|
65
61
|
|
66
62
|
it "is accessible within templates" do
|
67
|
-
expect(
|
63
|
+
expect(shortcode.process(template).delete("\n")).to eq(output)
|
68
64
|
end
|
69
|
-
|
70
65
|
end
|
71
|
-
|
72
66
|
end
|