mbrao 1.4.4 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +29 -0
  3. data/.travis.yml +3 -4
  4. data/CHANGELOG.md +5 -0
  5. data/Gemfile +4 -4
  6. data/doc/ActionView.html +125 -0
  7. data/doc/ActionView/Template.html +140 -0
  8. data/doc/ActionView/Template/Handlers.html +3 -3
  9. data/doc/ActionView/Template/Handlers/MbraoTemplate.html +26 -26
  10. data/doc/HTML.html +2 -2
  11. data/doc/HTML/Pipeline.html +2 -2
  12. data/doc/HTML/Pipeline/KramdownFilter.html +4 -4
  13. data/doc/Mbrao.html +3 -3
  14. data/doc/Mbrao/Author.html +29 -29
  15. data/doc/Mbrao/Content.html +1977 -3644
  16. data/doc/Mbrao/ContentInterface.html +817 -0
  17. data/doc/Mbrao/ContentInterface/ClassMethods.html +388 -0
  18. data/doc/Mbrao/Exceptions.html +1 -1
  19. data/doc/Mbrao/Exceptions/InvalidDate.html +1 -1
  20. data/doc/Mbrao/Exceptions/InvalidMetadata.html +1 -1
  21. data/doc/Mbrao/Exceptions/Parsing.html +1 -1
  22. data/doc/Mbrao/Exceptions/Rendering.html +1 -1
  23. data/doc/Mbrao/Exceptions/UnavailableLocalization.html +1 -1
  24. data/doc/Mbrao/Exceptions/Unimplemented.html +1 -1
  25. data/doc/Mbrao/Exceptions/UnknownEngine.html +1 -1
  26. data/doc/Mbrao/Parser.html +12 -12
  27. data/doc/Mbrao/ParserInterface.html +134 -0
  28. data/doc/Mbrao/ParserInterface/ClassMethods.html +1724 -0
  29. data/doc/Mbrao/ParserValidations.html +134 -0
  30. data/doc/Mbrao/ParserValidations/ClassMethods.html +348 -0
  31. data/doc/Mbrao/ParsingEngines.html +1 -1
  32. data/doc/Mbrao/ParsingEngines/Base.html +4 -4
  33. data/doc/Mbrao/ParsingEngines/PlainText.html +25 -15
  34. data/doc/Mbrao/RenderingEngines.html +1 -1
  35. data/doc/Mbrao/RenderingEngines/Base.html +2 -2
  36. data/doc/Mbrao/RenderingEngines/HtmlPipeline.html +173 -169
  37. data/doc/Mbrao/Version.html +3 -3
  38. data/doc/_index.html +51 -24
  39. data/doc/class_list.html +1 -1
  40. data/doc/file.README.html +1 -1
  41. data/doc/index.html +1 -1
  42. data/doc/method_list.html +63 -69
  43. data/doc/top-level-namespace.html +2 -2
  44. data/lib/mbrao.rb +7 -2
  45. data/lib/mbrao/author.rb +5 -5
  46. data/lib/mbrao/content.rb +110 -256
  47. data/lib/mbrao/content_interface.rb +146 -0
  48. data/lib/mbrao/exceptions.rb +1 -1
  49. data/lib/mbrao/integrations/rails.rb +48 -42
  50. data/lib/mbrao/parser.rb +24 -176
  51. data/lib/mbrao/parser_interface.rb +143 -0
  52. data/lib/mbrao/parser_validations.rb +41 -0
  53. data/lib/mbrao/parsing_engines/base.rb +4 -4
  54. data/lib/mbrao/parsing_engines/plain_text.rb +136 -121
  55. data/lib/mbrao/rendering_engines/base.rb +2 -2
  56. data/lib/mbrao/rendering_engines/html_pipeline.rb +52 -77
  57. data/lib/mbrao/rendering_engines/html_pipeline/kramdown_filter.rb +31 -0
  58. data/lib/mbrao/version.rb +2 -2
  59. data/mbrao.gemspec +3 -3
  60. data/spec/mbrao/author_spec.rb +1 -1
  61. data/spec/mbrao/content_spec.rb +1 -1
  62. data/spec/mbrao/parser_spec.rb +16 -16
  63. data/spec/mbrao/rendering_engines/html_pipeline/kramdown_filter_spec.rb +28 -0
  64. data/spec/mbrao/rendering_engines/html_pipeline_spec.rb +0 -21
  65. metadata +23 -8
@@ -0,0 +1,146 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the mbrao gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ module Mbrao
8
+ # Miscellaneous {Content Content} class methods.
9
+ module ContentInterface
10
+ extend ActiveSupport::Concern
11
+
12
+ # The allowed string format for a datetime.
13
+ ALLOWED_DATETIME_FORMATS = [
14
+ "%Y%m%dT%H%M%S%z", "%Y%m%dT%H%M%S%Z",
15
+ "%FT%T.%L%z", "%FT%T.%L%Z",
16
+ "%FT%T%z", "%FT%T%Z",
17
+ "%F %T %z", "%F %T %Z",
18
+ "%F %T.%L %z", "%F %T.%L %Z",
19
+
20
+ "%F %T.%L", "%F %T", "%F %H:%M", "%F",
21
+ "%d/%m/%Y %T.%L", "%d/%m/%Y %T", "%d/%m/%Y %H:%M", "%d/%m/%Y"
22
+ ]
23
+
24
+ # Class methods.
25
+ module ClassMethods
26
+ # Validates locales for attribute retrieval.
27
+ #
28
+ # @param locales [Array] A list of desired locales for an attribute. Can include `*` to match all. If none are specified, the default mbrao locale will be
29
+ # used.
30
+ # @param content [Content|nil] An optional content to check for availability
31
+ # @return [Array] The validated list of locales.
32
+ def validate_locales(locales, content = nil)
33
+ locales = locales.ensure_array(nil, true, true, true) { |l| l.ensure_string.strip }
34
+ locales = (locales.empty? ? [Mbrao::Parser.locale] : locales)
35
+ raise Mbrao::Exceptions::UnavailableLocalization if content && !content.enabled_for_locales?(locales)
36
+ locales
37
+ end
38
+
39
+ # Creates a content with metadata and body.
40
+ #
41
+ # @param metadata [Hash] The metadata.
42
+ # @param body [String] The body of the content.
43
+ # @return [Content] A new content.
44
+ def create(metadata, body)
45
+ rv = Mbrao::Content.new
46
+ rv.body = body.ensure_string.strip
47
+ assign_metadata(rv, metadata.symbolize_keys) if metadata.is_a?(Hash)
48
+ rv
49
+ end
50
+ end
51
+
52
+ # Checks if the content is available for at least one of the provided locales.
53
+ #
54
+ # @param locales [Array] The desired locales. Can include `*` to match all. If none are specified, the default mbrao locale will be used.
55
+ # @return [Boolean] `true` if the content is available for at least one of the desired locales, `false` otherwise.
56
+ def enabled_for_locales?(*locales)
57
+ locales = locales.flatten.ensure_array(nil, false, false, true) { |l| l.ensure_string.strip }.reject { |l| l == "*" }
58
+ @locales.blank? || locales.blank? || (@locales & locales).present?
59
+ end
60
+
61
+ # Gets the title of the content in the desired locales.
62
+ #
63
+ # @param locales [String|Array] The desired locales. Can include `*` to match all. If none are specified, the default mbrao locale will be used.
64
+ # @return [String|HashWithIndifferentAccess] Return the title of the content in the desired locales. If only one locale is required, then a `String`
65
+ # is returned, else a `HashWithIndifferentAccess` with locales as keys.
66
+ def get_title(locales = [])
67
+ filter_attribute_for_locales(@title, locales)
68
+ end
69
+
70
+ # Gets the body returning only the portion which are available for the given locales.
71
+ #
72
+ # @param locales [String|Array] The desired locales. Can include `*` to match all. If none are specified, the default mbrao locale will be used.
73
+ # @param engine [String|Symbol|Object] The engine to use to filter contents.
74
+ # @return [String|HashWithIndifferentAccess] Return the body of the content in the desired locales. If only one locale is required, then a `String`
75
+ # is returned, else a `HashWithIndifferentAccess` with locales as keys.
76
+ def get_body(locales = [], engine = :plain_text)
77
+ Mbrao::Parser.create_engine(engine).filter_content(self, locales)
78
+ end
79
+
80
+ # Gets the tags of the content in the desired locales.
81
+ #
82
+ # @param locales [String|Array] The desired locales. Can include `*` to match all. If none are specified, the default mbrao locale will be used.
83
+ # @return [Array|HashWithIndifferentAccess] Return the title of the content in the desired locales. If only one locale is required, then a `Array`
84
+ # is returned, else a `HashWithIndifferentAccess` with locales as keys.
85
+ def get_tags(locales = [])
86
+ filter_attribute_for_locales(@tags, locales)
87
+ end
88
+
89
+ # Gets the "more link" text of the content in the desired locales.
90
+ #
91
+ # @param locales [String|Array] The desired locales. Can include `*` to match all. If none are specified, the default mbrao locale will be used.
92
+ # @return [String|HashWithIndifferentAccess] Return the label of the "more link" of the content in the desired locales. If only one locale is required,
93
+ # then a `String` is returned, else a `HashWithIndifferentAccess` with locales as keys.
94
+ def get_more(locales = [])
95
+ filter_attribute_for_locales(@more, locales)
96
+ end
97
+
98
+ # Returns the content as an Hash.
99
+ #
100
+ # @param options [Hash] Options to modify behavior of the serialization.
101
+ # The only supported value are:
102
+ #
103
+ # * `:exclude`, an array of attributes to skip.
104
+ # * `:exclude_empty`, if to exclude nil values. Default is `false`.
105
+ # @return [Hash] An hash with all attributes.
106
+ def as_json(options = {})
107
+ keys = [:uid, :locales, :title, :summary, :body, :tags, :more, :author, :created_at, :updated_at, :metadata]
108
+ ::Mbrao::Parser.as_json(self, keys, options)
109
+ end
110
+
111
+ private
112
+
113
+ # Filters an attribute basing a set of locales.
114
+ #
115
+ # @param attribute [Object|HashWithIndifferentAccess] The desired attribute.
116
+ # @param locales [String|Array] The desired locales. Can include `*` to match all. If none are specified, the default mbrao locale will be used.
117
+ # @return [String|HashWithIndifferentAccess] Return the object for desired locales. If only one locale is available, then only a object is returned,
118
+ # else a `HashWithIndifferentAccess` with locales as keys.
119
+ def filter_attribute_for_locales(attribute, locales)
120
+ locales = ::Mbrao::Content.validate_locales(locales, self)
121
+
122
+ if attribute.is_a?(HashWithIndifferentAccess)
123
+ rv = attribute.reduce(HashWithIndifferentAccess.new) { |a, e| append_value_for_locale(a, e[0], locales, e[1]) }
124
+ rv.keys.length == 1 ? rv.values.first : rv
125
+ else
126
+ attribute
127
+ end
128
+ end
129
+
130
+ # Adds an value on a hash if enable for requested locales.
131
+ #
132
+ # @param hash [Hash] The hash to handle.
133
+ # @param locale [String] The list of locale (separated by commas) for which the value is available.
134
+ # @param locales [Array] The list of locale for which this value is requested. Can include `*` to match all. If none are specified, the default mbrao
135
+ # locale will be used.
136
+ # @param value [Object] The value to add.
137
+ # @return [Hash] Return the original hash.
138
+ def append_value_for_locale(hash, locale, locales, value)
139
+ locale.split(/\s*,\s*/).map(&:strip).each do |l|
140
+ hash[l] = value if locales.include?("*") || locales.include?(l)
141
+ end
142
+
143
+ hash
144
+ end
145
+ end
146
+ end
@@ -35,4 +35,4 @@ module Mbrao
35
35
  class Unimplemented < RuntimeError
36
36
  end
37
37
  end
38
- end
38
+ end
@@ -4,55 +4,61 @@
4
4
  # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
5
  #
6
6
 
7
- # Generic interface to multiple Ruby template engines.
8
- module ActionView::Template::Handlers
9
- # Class for rendering mbrao contents in Rails.
10
- class MbraoTemplate
11
- # Returns a unique (singleton) instance of the template handler.
12
- #
13
- # @param force [Boolean] If to force recreation of the instance.
14
- # @return [MbraoTemplate] The unique (singleton) instance of the template handler.
15
- def self.instance(force = false)
16
- @instance = nil if force
17
- @instance ||= ActionView::Template::Handlers::MbraoTemplate.new
18
- end
7
+ # :nodoc:
8
+ module ActionView
9
+ # :nodoc:
10
+ class Template
11
+ # :nodoc:
12
+ module Handlers
13
+ # Class for rendering mbrao contents in Rails.
14
+ class MbraoTemplate
15
+ # Returns a unique (singleton) instance of the template handler.
16
+ #
17
+ # @param force [Boolean] If to force recreation of the instance.
18
+ # @return [MbraoTemplate] The unique (singleton) instance of the template handler.
19
+ def self.instance(force = false)
20
+ @instance = nil if force
21
+ @instance ||= ActionView::Template::Handlers::MbraoTemplate.new
22
+ end
19
23
 
20
- # Register Mbrao into Rails.
21
- def self.register
22
- ActionView::Template.register_template_handler("emt", instance) if defined?(ActionView) && defined?(Rails) && Rails.version =~ /^[34]/
23
- end
24
+ # Register Mbrao into Rails.
25
+ def self.register
26
+ ActionView::Template.register_template_handler("emt", instance) if defined?(ActionView) && defined?(Rails) && Rails.version =~ /^[34]/
27
+ end
24
28
 
25
- # Renders a template into a renderer context.
26
- #
27
- # @param renderer [Object] The renderer context.
28
- # @param template [String] The template to render.
29
- # @return [String] The rendered template.
30
- def render(renderer, template)
31
- content = ::Mbrao::Parser.parse(template)
32
- controller = renderer.controller
29
+ # Renders a template into a renderer context.
30
+ #
31
+ # @param renderer [Object] The renderer context.
32
+ # @param template [String] The template to render.
33
+ # @return [String] The rendered template.
34
+ def render(renderer, template)
35
+ content = ::Mbrao::Parser.parse(template)
36
+ controller = renderer.controller
33
37
 
34
- controller.instance_variable_set(:@mbrao_content, content)
35
- controller.define_singleton_method(:mbrao_content) { @mbrao_content }
36
- controller.class.send(:helper_method, :mbrao_content)
38
+ controller.instance_variable_set(:@mbrao_content, content)
39
+ controller.define_singleton_method(:mbrao_content) { @mbrao_content }
40
+ controller.class.send(:helper_method, :mbrao_content)
37
41
 
38
- ::Mbrao::Parser.render(content, {engine: content.metadata[:engine], locale: controller.params[:locale]})
39
- end
42
+ ::Mbrao::Parser.render(content, {engine: content.metadata[:engine], locale: controller.params[:locale]})
43
+ end
40
44
 
41
- # Declares support for streaming.
42
- #
43
- # @return [TrueClass] Declares support for streaming.
44
- def supports_streaming?
45
- true
46
- end
45
+ # Declares support for streaming.
46
+ #
47
+ # @return [TrueClass] Declares support for streaming.
48
+ def supports_streaming?
49
+ true
50
+ end
47
51
 
48
- # Method called to render a template.
49
- #
50
- # @param template [ActionView::Template] The template to render.
51
- # @return [String] A Ruby snippet to execute to render the template.
52
- def call(template)
53
- "ActionView::Template::Handlers::MbraoTemplate.instance.render(self, #{template.source.to_json})"
52
+ # Method called to render a template.
53
+ #
54
+ # @param template [ActionView::Template] The template to render.
55
+ # @return [String] A Ruby snippet to execute to render the template.
56
+ def call(template)
57
+ "ActionView::Template::Handlers::MbraoTemplate.instance.render(self, #{template.source.to_json})"
58
+ end
59
+ end
54
60
  end
55
61
  end
56
62
  end
57
63
 
58
- ActionView::Template::Handlers::MbraoTemplate.register
64
+ ActionView::Template::Handlers::MbraoTemplate.register
data/lib/mbrao/parser.rb CHANGED
@@ -6,164 +6,11 @@
6
6
 
7
7
  # A content parser and renderer with embedded metadata support.
8
8
  module Mbrao
9
- # Methods to allow class level access.
10
- module PublicInterface
11
- extend ActiveSupport::Concern
12
-
13
- # Class methods.
14
- #
15
- # @attribute default_locale
16
- # @return [String] The mbrao default locale.
17
- # @attribute parsing_engine
18
- # @return [String] The default parsing engine.
19
- # @attribute rendering_engine
20
- # @return [String] The default rendering engine.
21
- module ClassMethods
22
- attr_accessor :locale
23
- attr_accessor :parsing_engine
24
- attr_accessor :rendering_engine
25
-
26
- # Gets the default locale for mbrao.
27
- #
28
- # @return [String] The default locale.
29
- def locale
30
- attribute_or_default(@locale, "en")
31
- end
32
-
33
- # Gets the default parsing engine.
34
- #
35
- # @return [String] The default parsing engine.
36
- def parsing_engine
37
- attribute_or_default(@parsing_engine, :plain_text, :to_sym)
38
- end
39
-
40
- # Gets the default rendering engine.
41
- #
42
- # @return [String] The default rendering engine.
43
- def rendering_engine
44
- attribute_or_default(@rendering_engine, :html_pipeline, :to_sym)
45
- end
46
-
47
- # Parses a source text.
48
- #
49
- # @param content [Object] The content to parse.
50
- # @param options [Hash] A list of options for parsing.
51
- # @return [Content] The parsed data.
52
- def parse(content, options = {})
53
- instance.parse(content, options)
54
- end
55
-
56
- # Renders a content.
57
- #
58
- # @param content [Content] The content to parse.
59
- # @param options [Hash] A list of options for renderer.
60
- # @param context [Hash] A context for rendering.
61
- # @return [String] The rendered content.
62
- def render(content, options = {}, context = {})
63
- instance.render(content, options, context)
64
- end
65
-
66
- # Returns an object as a JSON compatible hash
67
- #
68
- # @param target [Object] The target to serialize.
69
- # @param keys [Array] The attributes to include in the serialization
70
- # @param options [Hash] Options to modify behavior of the serialization.
71
- # The only supported value are:
72
- #
73
- # * `:exclude`, an array of attributes to skip.
74
- # * `:exclude_empty`, if to exclude nil values. Default is `false`.
75
- # @return [Hash] An hash with all attributes.
76
- def as_json(target, keys, options = {})
77
- include_empty = !options[:exclude_empty].to_boolean
78
- exclude = options[:exclude].ensure_array(nil, true, true, true, :ensure_string)
79
- keys = keys.ensure_array(nil, true, true, true, :ensure_string)
80
-
81
- (keys - exclude).reduce({}) {|rv, key|
82
- value = target.send(key)
83
- value = value.as_json if value && value.respond_to?(:as_json) && !value.is_a?(Symbol)
84
- rv[key] = value if include_empty || value.present?
85
- rv
86
- }.deep_stringify_keys
87
- end
88
-
89
- # Instantiates a new engine for rendering or parsing.
90
- #
91
- # @param cls [String|Symbol|Object] If a `String` or a `Symbol`, then it will be the class of the engine.
92
- # @param type [Symbol] The type or engine. Can be `:parsing` or `:rendering`.
93
- # @return [Object] A new engine.
94
- def create_engine(cls, type = :parsing)
95
- begin
96
- type = :parsing if type != :rendering
97
- ::Lazier.find_class(cls, "::Mbrao::#{type.to_s.classify}Engines::%CLASS%").new
98
- rescue NameError
99
- raise Mbrao::Exceptions::UnknownEngine.new
100
- end
101
- end
102
-
103
- # Returns a unique (singleton) instance of the parser.
104
- #
105
- # @param force [Boolean] If to force recreation of the instance.
106
- # @return [Parser] The unique (singleton) instance of the parser.
107
- def instance(force = false)
108
- @instance = nil if force
109
- @instance ||= Mbrao::Parser.new
110
- end
111
-
112
- private
113
- # Returns an attribute or a default value.
114
- #
115
- # @param attr [Object ]The attribute to return.
116
- # @param default_value [Object] The value to return if `attr` is blank.
117
- # @param sanitizer [Symbol] An optional method to sanitize the returned value.
118
- def attribute_or_default(attr, default_value = nil, sanitizer = :ensure_string)
119
- rv = attr.present? ? attr : default_value
120
- rv = rv.send(sanitizer) if sanitizer
121
- rv
122
- end
123
- end
124
- end
125
-
126
- # Methods to perform validations.
127
- module Validations
128
- extend ActiveSupport::Concern
129
-
130
- # Class methods.
131
- module ClassMethods
132
- # Checks if the text is a valid email.
133
- #
134
- # @param text [String] The text to check.
135
- # @return [Boolean] `true` if the string is valid email, `false` otherwise.
136
- def is_email?(text)
137
- regex = /^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i
138
- text.ensure_string.strip =~ regex
139
- end
140
-
141
- # Checks if the text is a valid URL.
142
- #
143
- # @param text [String] The text to check.
144
- # @return [Boolean] `true` if the string is valid URL, `false` otherwise.
145
- def is_url?(text)
146
- regex = /
147
- ^(
148
- ([a-z0-9\-]+:\/\/) #PROTOCOL
149
- (([\w-]+\.)?) # LOWEST TLD
150
- ([\w-]+) # 2nd LEVEL TLD
151
- (\.[a-z]+) # TOP TLD
152
- ((:\d+)?) # PORT
153
- ([\S|\?]*) # PATH, QUERYSTRING AND FRAGMENT
154
- )$
155
- /ix
156
-
157
- text.ensure_string.strip =~ regex
158
- end
159
- end
160
- end
161
-
162
9
  # A parser to handle pipelined content.
163
10
  #
164
11
  class Parser
165
- include Mbrao::PublicInterface
166
- include Mbrao::Validations
12
+ include Mbrao::ParserInterface
13
+ include Mbrao::ParserValidations
167
14
 
168
15
  # Parses a source text.
169
16
  #
@@ -187,30 +34,31 @@ module Mbrao
187
34
  end
188
35
 
189
36
  private
190
- # Sanitizes options for parsing.
191
- #
192
- # @param options [Hash] The options to sanitize.
193
- # @return [HashWithIndifferentAccess] The sanitized options.
194
- def sanitize_parsing_options(options)
195
- options = options.ensure_hash(:symbols)
196
37
 
197
- options[:engine] ||= Mbrao::Parser.parsing_engine
198
- options[:metadata] = options.fetch(:metadata, true).to_boolean
199
- options[:content] = options.fetch(:content, true).to_boolean
38
+ # Sanitizes options for parsing.
39
+ #
40
+ # @param options [Hash] The options to sanitize.
41
+ # @return [HashWithIndifferentAccess] The sanitized options.
42
+ def sanitize_parsing_options(options)
43
+ options = options.ensure_hash(:symbols)
44
+
45
+ options[:engine] ||= Mbrao::Parser.parsing_engine
46
+ options[:metadata] = options.fetch(:metadata, true).to_boolean
47
+ options[:content] = options.fetch(:content, true).to_boolean
200
48
 
201
- HashWithIndifferentAccess.new(options)
202
- end
49
+ HashWithIndifferentAccess.new(options)
50
+ end
203
51
 
204
- # Sanitizes options for rendering.
205
- #
206
- # @param options [Hash] The options to sanitize.
207
- # @return [HashWithIndifferentAccess] The sanitized options.
208
- def sanitize_rendering_options(options)
209
- options = options.ensure_hash(:symbols)
52
+ # Sanitizes options for rendering.
53
+ #
54
+ # @param options [Hash] The options to sanitize.
55
+ # @return [HashWithIndifferentAccess] The sanitized options.
56
+ def sanitize_rendering_options(options)
57
+ options = options.ensure_hash(:symbols)
210
58
 
211
- options[:engine] ||= Mbrao::Parser.rendering_engine
59
+ options[:engine] ||= Mbrao::Parser.rendering_engine
212
60
 
213
- HashWithIndifferentAccess.new(options)
214
- end
61
+ HashWithIndifferentAccess.new(options)
62
+ end
215
63
  end
216
- end
64
+ end