comfortable_mexican_sofa 2.0.13 → 2.0.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b4189f8584e5fbfcc3083d72b892dee0d17407e1893674eed30927e6e5c6d336
4
- data.tar.gz: '02964679fbddf7a9f1c46dc35482d11a6a3736409a32daa4a137d0600a921d3d'
3
+ metadata.gz: 7cc4680084f0e38ab3a3e902264eb28487be58a3cfb10abb3722ead0a917e7c4
4
+ data.tar.gz: 7fe8523b33056e692bb8f3ee552517adbd994dfcf3e830466ff078e72e646439
5
5
  SHA512:
6
- metadata.gz: 47387e45ccebcad1bc3429c6b64633dfd9cc8f0810f7c28745dc578f391404e57a16fb8bd1ecd221acdd6701710aded9ee318eb2b110f7d7374e63063fc472b0
7
- data.tar.gz: d16d2d2aaeb92e761c6b3559816f33e1339dd239f8691d6b8194bc5cf60d67ec0dbe34aae18ee2cc2a4f1bf24b15edc4105812bcd4427d04b048a850bc339819
6
+ metadata.gz: e01f50e27b67203265c0d4683ae78d50644a5f64a8a4ea9898f3e94b163c5990c04b83b4d25133ecc8c531ceadadd87a32d249724211562622d5341ede61bd5b
7
+ data.tar.gz: 26695cba7cf37dcc11ce3955d8dca504231bcaf33b62e736c7eff19304ffe0f0ad920fa12d62f3bda92f0bea087bc25e309ca7ce6c2ddc60a43cdedd7dc008f9
data/.travis.yml CHANGED
@@ -1,8 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.3.6
4
- - 2.4.3
5
- - 2.5.0
3
+ - 2.3.7
4
+ - 2.4.4
5
+ - 2.5.1
6
6
  - ruby-head
7
7
  gemfile:
8
8
  - test/gemfiles/5.2.gemfile
@@ -23,7 +23,7 @@ class Comfy::Admin::Cms::FilesController < Comfy::Admin::Cms::BaseController
23
23
  case params[:type]
24
24
  when "image"
25
25
  file_scope.with_images.collect do |file|
26
- { thumb: url_for(file.attachment.variant(Comfy::Cms::File::VARIANT_SIZE[:redactor])),
26
+ { thumb: url_for(file.attachment.variant(combine_options: Comfy::Cms::File::VARIANT_SIZE[:redactor])),
27
27
  image: url_for(file.attachment),
28
28
  title: file.label }
29
29
  end
@@ -1,7 +1,7 @@
1
1
  %li{data: {id: file.id}}
2
2
  :ruby
3
3
  file_tag = cms_file_link_tag(file)
4
- thumb_url = url_for(file.attachment.variant(Comfy::Cms::File::VARIANT_SIZE[:thumb])) if file.attachment.image?
4
+ thumb_url = url_for(file.attachment.variant(combine_options: Comfy::Cms::File::VARIANT_SIZE[:thumb])) if file.attachment.image?
5
5
  .row
6
6
  .col-md-5.item
7
7
  .item-controls.d-none.d-lg-block
@@ -1,8 +1,10 @@
1
1
  .fragment-attachments
2
2
  - attachments.each do |attachment|
3
3
  :ruby
4
- thumb_url = url_for(attachment.variant(Comfy::Cms::File::VARIANT_SIZE[:thumb])) if attachment.image?
5
- filename = attachment.filename.to_s
4
+ thumb_url = if attachment.image?
5
+ url_for(attachment.variant(combine_options: Comfy::Cms::File::VARIANT_SIZE[:thumb]))
6
+ end
7
+ filename = attachment.filename.to_s
6
8
  truncated_filename = truncate(filename, length: 40, omission: "...#{filename.last(10)}")
7
9
 
8
10
  link_data = {
@@ -2,78 +2,116 @@
2
2
 
3
3
  require "strscan"
4
4
 
5
- module ComfortableMexicanSofa::Content::ParamsParser
5
+ class ComfortableMexicanSofa::Content::ParamsParser
6
6
 
7
7
  class Error < StandardError; end
8
8
 
9
- STRING_LITERAL = %r{'[^']*'|"[^"]*"}
10
- IDENTIFIER = %r{[a-z0-9][\w\-/.]*}i
11
- COLON = %r{:}
12
- COMMA = %r{,}
9
+ STRING_LITERAL = %r{'[^']*'|"[^"]*"}
10
+ IDENTIFIER = %r{[a-z0-9][\w\-/.]*}i
11
+ HASH_KEY = %r{#{IDENTIFIER}:}
12
+ COMMA = %r{,}
13
+ HASH_OPEN = %r{\{}
14
+ HASH_CLOSE = %r{\}}
15
+ ARRAY_OPEN = %r{\[}
16
+ ARRAY_CLOSE = %r{\]}
13
17
 
14
- # @param [String] text
18
+ # @param <String> string
19
+ def initialize(string = "")
20
+ @string = string
21
+ end
22
+
23
+ # Takes CMS content tag parameters and converts them into array of strings,
24
+ # hashes and arrays.
25
+ #
15
26
  # @return [Array<String, {String => String}>]
16
27
  # @raise [Error] if the given `text` is malformed.
17
28
  #
18
29
  # @example
19
- # parse("happy greeting name:Joe show:true")
20
- # #=> ['happy', 'greeting', {'name' => 'Joe', 'show' => 'true'}]
21
- def self.parse(text)
22
- parse_token_groups(split_on_commas(tokenize(text.to_s)))
30
+ # new("a, b, c").parse
31
+ # #=> ["a", "b", "c"]
32
+ #
33
+ # new("a, b: c, d: e").parse
34
+ # #=> ["a", {"b" => "c", "d" => "e"}]
35
+ #
36
+ # new("a, b: {c: [d, e]}").parse
37
+ # #=> ["a", {"b" => {"c" => ["d", "e"]}}]
38
+ #
39
+ def params
40
+ @tokens = tokenize(@string)
41
+ parse_params
23
42
  end
24
43
 
25
- # @param [Enumerable<Array<(Symbol, String)>>] token_groups
26
- # @return [Array<String, {String => String}>]
27
- def self.parse_token_groups(token_groups)
28
- token_groups.each_with_object([]) do |tokens, params|
29
- case tokens.count
30
- when 1
31
- params << parse_string_param(tokens[0])
32
- when 3
33
- param = parse_key_value_param(tokens)
34
- if params.last.is_a?(Hash)
35
- params.last.update(param)
36
- else
37
- params << param
38
- end
39
- else
40
- raise Error, "Unexpected tokens found: #{tokens}"
41
- end
44
+ private
45
+
46
+ # Contructs root-level list of arguments sent via content tag
47
+ def parse_params
48
+ params = []
49
+ while (token = @tokens.shift)
50
+ params << parse_value(token)
42
51
  end
52
+ params
43
53
  end
44
54
 
45
- # @param [(:string, String)] token
46
- # @return [String]
47
- # @raise [Error] if `token[0] != :string`.
48
- def self.parse_string_param(token)
49
- type, value = token
50
- raise Error, "Unexpected token: #{token}" unless type == :string
51
- value
55
+ # Gets token value. Will trigger parsing of hash and array structures
56
+ def parse_value(token)
57
+ case token&.first
58
+ when :string
59
+ token[1]
60
+ when :hash_key
61
+ @tokens.unshift(token)
62
+ parse_hash
63
+ when :hash_open
64
+ parse_hash
65
+ when :array_open
66
+ parse_array
67
+ else
68
+ raise Error, "Invalid params: #{@string}"
69
+ end
52
70
  end
53
71
 
54
- # @param [((:string, String), (:colon, String), (:string, String))] tokens
55
- # @return [{String => String}]
56
- # @raise [Error] if `tokens[0][0] != :string`, or `tokens[1][0] != :colon`,
57
- # or `tokens[2][0] != :string`.
58
- def self.parse_key_value_param(tokens)
59
- (key_type, key_value), (col_type, _col_value), (val_type, val_value) = tokens
60
- unless key_type == :string && col_type == :colon && val_type == :string
61
- raise Error, "Unexpected tokens: #{tokens}"
72
+ # Hash constructor method. Will handle nested hashes as well
73
+ def parse_hash
74
+ opens = 1
75
+ hash = {}
76
+
77
+ while (token = @tokens.shift)
78
+ case token&.first
79
+ when :hash_key
80
+ hash[token[1]] = parse_value(@tokens.shift)
81
+ when :hash_close
82
+ opens -= 1
83
+ when :hash_open
84
+ opens += 1
85
+ else
86
+ raise Error, "Invalid params: #{@string}"
87
+ end
88
+
89
+ return hash if opens.zero?
62
90
  end
63
- { key_value => val_value }
91
+
92
+ # We're can't really detect unclosed hashes as we can construct them without
93
+ # opening brakets. For example, `a: b, c: d` is same as `{a: b, c: d}` and
94
+ # `{a: b, c: d` is also ends up to be a valid hash. It will error out if
95
+ # unclosed hash is followed by some other unexpected token. Like: `{a: b, c`
96
+ hash
64
97
  end
65
98
 
66
- # Splits tokens on commas. The result contains no `:comma` tokens.
67
- #
68
- # @param [Enumerable<(Symbol, String)>] tokens
69
- # @return [Enumerable<Array<(Symbol, String)>>] Token groups.
70
- def self.split_on_commas(tokens)
71
- slices = tokens.slice_after do |token|
72
- token[0] == :comma
73
- end
74
- slices.map do |expression|
75
- expression.reject { |t| t[0] == :comma }
99
+ # Array construction method. Will handle nested arrays
100
+ def parse_array
101
+ opens = 1
102
+ array = []
103
+ while (token = @tokens.shift)
104
+ case token&.first
105
+ when :array_close
106
+ opens -= 1
107
+ else
108
+ array << parse_value(token)
109
+ end
110
+
111
+ return array if opens.zero?
76
112
  end
113
+
114
+ raise Error, "Unclosed array param: #{@string}"
77
115
  end
78
116
 
79
117
  # Tokenizing input string into a list of touples
@@ -81,22 +119,30 @@ module ComfortableMexicanSofa::Content::ParamsParser
81
119
  #
82
120
  # @param [String] args_string
83
121
  # @return [Array<String>] tokens
84
- def self.tokenize(args_string)
122
+ def tokenize(args_string)
85
123
  args_string = args_string.tr("“”‘’", %q(""''))
86
124
  ss = StringScanner.new(args_string)
87
125
  tokens = []
88
126
  loop do
89
127
  ss.skip(%r{\s*})
90
128
  break if ss.eos?
129
+
130
+ # commas are just separators like spaces
131
+ next if ss.scan(COMMA)
132
+
91
133
  tokens <<
92
134
  if (t = ss.scan(STRING_LITERAL)) then [:string, t[1...-1]]
135
+ elsif (t = ss.scan(HASH_KEY)) then [:hash_key, t[0...-1]]
93
136
  elsif (t = ss.scan(IDENTIFIER)) then [:string, t]
94
- elsif (t = ss.scan(COLON)) then [:colon, t]
95
- elsif (t = ss.scan(COMMA)) then [:comma, t]
137
+ elsif (t = ss.scan(HASH_OPEN)) then [:hash_open, t]
138
+ elsif (t = ss.scan(HASH_CLOSE)) then [:hash_close, t]
139
+ elsif (t = ss.scan(ARRAY_OPEN)) then [:array_open, t]
140
+ elsif (t = ss.scan(ARRAY_CLOSE)) then [:array_close, t]
96
141
  else
97
142
  raise Error, "Unexpected char: #{ss.getch}"
98
143
  end
99
144
  end
145
+
100
146
  tokens
101
147
  end
102
148
 
@@ -122,7 +122,7 @@ class ComfortableMexicanSofa::Content::Renderer
122
122
  # @type [ComfortableMexicanSofa::Content::Tag]
123
123
  tag = klass.new(
124
124
  context: @context,
125
- params: ComfortableMexicanSofa::Content::ParamsParser.parse(token[:tag_params]),
125
+ params: ComfortableMexicanSofa::Content::ParamsParser.new(token[:tag_params]).params,
126
126
  source: token[:source]
127
127
  )
128
128
  nodes.last << tag
@@ -3,11 +3,7 @@
3
3
  # Tag for text content that is going to be rendered using text input with date widget
4
4
  # {{ cms:date identifier }}
5
5
  #
6
- class ComfortableMexicanSofa::Content::Tag::Date < ComfortableMexicanSofa::Content::Tag::Fragment
7
-
8
- def content
9
- fragment.datetime
10
- end
6
+ class ComfortableMexicanSofa::Content::Tag::Date < ComfortableMexicanSofa::Content::Tag::Datetime
11
7
 
12
8
  def form_field(object_name, view, index)
13
9
  name = "#{object_name}[fragments_attributes][#{index}][datetime]"
@@ -1,14 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Tag for text content that is going to be rendered using text input with datetime widget
4
- # {{ cms:datetime identifier }}
4
+ # {{ cms:datetime identifier, strftime: "at %I:%M%p" }}
5
+ #
6
+ # `strftime` - Format datetime string during rendering
5
7
  #
6
8
  class ComfortableMexicanSofa::Content::Tag::Datetime < ComfortableMexicanSofa::Content::Tag::Fragment
7
9
 
10
+ attr_reader :strftime
11
+
12
+ def initialize(context:, params: [], source: nil)
13
+ super
14
+ @strftime = options["strftime"]
15
+ end
16
+
8
17
  def content
9
18
  fragment.datetime
10
19
  end
11
20
 
21
+ def render
22
+ if strftime.present?
23
+ content.strftime(strftime)
24
+ else
25
+ content.to_s
26
+ end
27
+ end
28
+
12
29
  def form_field(object_name, view, index)
13
30
  name = "#{object_name}[fragments_attributes][#{index}][datetime]"
14
31
  options = { id: form_field_id, class: "form-control", data: { "cms-datetime" => true } }
@@ -13,7 +13,7 @@ module ComfortableMexicanSofa::Content::Tag::Mixins
13
13
  return "" unless file
14
14
 
15
15
  if variant_attrs.present? && attachment.image?
16
- file = file.variant(variant_attrs)
16
+ file = file.variant(combine_options: variant_attrs)
17
17
  end
18
18
 
19
19
  url = rails_blob_path(file)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ComfortableMexicanSofa
4
4
 
5
- VERSION = "2.0.13"
5
+ VERSION = "2.0.14"
6
6
 
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: comfortable_mexican_sofa
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.13
4
+ version: 2.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleg Khabarov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-13 00:00:00.000000000 Z
11
+ date: 2018-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_link_to