semantic_date_time_tags 0.1.13 → 0.2.0
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 +5 -5
- data/.github/workflows/ruby.yml +30 -0
- data/.rubocop.yml +6 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +162 -131
- data/Guardfile +4 -2
- data/README.md +1 -1
- data/Rakefile +7 -5
- data/lib/semantic_date_time_tags.rb +3 -1
- data/lib/semantic_date_time_tags/engine.rb +4 -2
- data/lib/semantic_date_time_tags/format_parser.rb +31 -25
- data/lib/semantic_date_time_tags/railtie.rb +5 -3
- data/lib/semantic_date_time_tags/tag.rb +48 -57
- data/lib/semantic_date_time_tags/tag/date.rb +12 -10
- data/lib/semantic_date_time_tags/tag/date_range.rb +22 -25
- data/lib/semantic_date_time_tags/tag/date_time.rb +19 -14
- data/lib/semantic_date_time_tags/tag/time.rb +9 -10
- data/lib/semantic_date_time_tags/version.rb +3 -1
- data/lib/semantic_date_time_tags/view_helpers.rb +8 -8
- data/semantic_date_time_tags.gemspec +9 -7
- data/test/semantic_date_time_tags/format_parser_test.rb +43 -43
- data/test/semantic_date_time_tags/semantic_date_range_test.rb +71 -0
- data/test/semantic_date_time_tags/semantic_date_tag_test.rb +61 -0
- data/test/semantic_date_time_tags/semantic_date_time_tag_test.rb +49 -0
- data/test/semantic_date_time_tags/semantic_time_tag_test.rb +90 -0
- data/test/test_helper.rb +10 -13
- metadata +27 -20
- data/.coveralls.yml +0 -1
- data/.travis.yml +0 -13
- data/test/semantic_date_time_tags/view_helpers_test.rb +0 -212
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "i18n"
|
2
4
|
require "semantic_date_time_tags/railtie" if defined?(Rails)
|
3
5
|
require "semantic_date_time_tags/engine"
|
4
6
|
require "semantic_date_time_tags/version"
|
5
7
|
|
6
|
-
I18n.load_path += Dir.glob(File.join(
|
8
|
+
I18n.load_path += Dir.glob(File.join(File.dirname(__FILE__), "config", "locales", "*.yml"))
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "action_view"
|
3
5
|
|
4
6
|
module SemanticDateTimeTags
|
5
7
|
class FormatParser < Struct.new(:format, :str)
|
@@ -8,44 +10,48 @@ module SemanticDateTimeTags
|
|
8
10
|
def to_html
|
9
11
|
processed_str = str
|
10
12
|
(
|
11
|
-
formatting_components.flatten.inject(
|
13
|
+
formatting_components.flatten.inject("") do |res, comp|
|
12
14
|
regexp = Regexp.new(get_regexp_for_component(comp))
|
13
15
|
if match = processed_str.match(regexp)
|
14
16
|
res += get_tag_for_match(match[0], comp)
|
15
17
|
processed_str = processed_str[match[0].length..-1]
|
16
18
|
end
|
17
19
|
res
|
18
|
-
end + processed_str
|
20
|
+
end + get_tag_for_str(processed_str)
|
19
21
|
).html_safe
|
20
22
|
end
|
21
23
|
|
22
|
-
private
|
24
|
+
private
|
25
|
+
def formatting_components
|
26
|
+
format.scan(/(%-?[[:word:]]|.+?(?=%))/)
|
27
|
+
end
|
23
28
|
|
24
|
-
|
25
|
-
|
26
|
-
|
29
|
+
def get_tag_for_match(match, comp)
|
30
|
+
content_tag :span, match, class: get_classes_for_component(comp)
|
31
|
+
end
|
27
32
|
|
28
|
-
|
29
|
-
|
30
|
-
|
33
|
+
def get_tag_for_str(str)
|
34
|
+
return "" unless str.present?
|
35
|
+
content_tag :span, str, class: "str"
|
36
|
+
end
|
31
37
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
38
|
+
def get_regexp_for_component(comp)
|
39
|
+
case comp
|
40
|
+
when /%-?[[:word:]]/ then "([[:word:]]+)"
|
41
|
+
else "(#{comp})"
|
42
|
+
end
|
36
43
|
end
|
37
|
-
end
|
38
44
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
def get_classes_for_component(comp)
|
46
|
+
case comp
|
47
|
+
when /%-?[YCy]/ then ["year", comp[/[[:word:]]/]]
|
48
|
+
when /%-?[mBbh]/ then ["month", comp[/[[:word:]]/]]
|
49
|
+
when /%-?[aAdej]/ then ["day", comp[/[[:word:]]/]]
|
50
|
+
when /%-?[HKIl]/ then ["hours", comp[/[[:word:]]/]]
|
51
|
+
when /%-?[M]/ then ["minutes", comp[/[[:word:]]/]]
|
52
|
+
when /%-?[pP]/ then ["ampm", comp[/[[:word:]]/]]
|
53
|
+
when /\W+/ then ["sep"]
|
54
|
+
end
|
48
55
|
end
|
49
|
-
end
|
50
56
|
end
|
51
57
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "semantic_date_time_tags/view_helpers"
|
4
|
+
require "rails/railtie"
|
3
5
|
|
4
6
|
module SemanticDateTimeTags
|
5
7
|
class Railtie < Rails::Railtie
|
@@ -7,4 +9,4 @@ module SemanticDateTimeTags
|
|
7
9
|
ActionView::Base.send :include, ViewHelpers
|
8
10
|
end
|
9
11
|
end
|
10
|
-
end
|
12
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_view"
|
4
|
+
require "i18n"
|
3
5
|
|
4
6
|
module SemanticDateTimeTags
|
5
7
|
class Tag
|
@@ -10,24 +12,18 @@ module SemanticDateTimeTags
|
|
10
12
|
attr_accessor :options
|
11
13
|
attr_accessor :output_buffer
|
12
14
|
|
13
|
-
# =====================================================================
|
14
|
-
|
15
15
|
def initialize(obj, options = {})
|
16
16
|
@obj = obj
|
17
|
-
@options = options.
|
17
|
+
@options = options.except(*%i(scope))
|
18
18
|
end
|
19
19
|
|
20
|
-
# ---------------------------------------------------------------------
|
21
|
-
|
22
20
|
def to_html
|
23
21
|
raise NotImplementedError
|
24
22
|
end
|
25
23
|
|
26
|
-
# ---------------------------------------------------------------------
|
27
|
-
|
28
24
|
def dom_classes
|
29
25
|
[
|
30
|
-
|
26
|
+
"semantic",
|
31
27
|
locale_class,
|
32
28
|
am_pm_class,
|
33
29
|
type_class,
|
@@ -47,39 +43,39 @@ module SemanticDateTimeTags
|
|
47
43
|
|
48
44
|
def current_date_class
|
49
45
|
return unless [::Date, ::DateTime].any? { |c| obj.instance_of? c }
|
50
|
-
|
46
|
+
"current_date" if obj.today?
|
51
47
|
end
|
52
48
|
|
53
49
|
def current_year_class
|
54
50
|
return unless [::Date, ::DateTime].any? { |c| obj.instance_of? c }
|
55
|
-
|
51
|
+
"current_year" if obj.year == ::Date.today.year
|
56
52
|
end
|
57
53
|
|
58
54
|
def whole_hour_class
|
59
55
|
return unless [::Time, ::DateTime].any? { |c| obj.instance_of? c }
|
60
|
-
|
56
|
+
"whole_hour" unless obj.min > 0
|
61
57
|
end
|
62
58
|
|
63
59
|
def whole_minute_class
|
64
60
|
return unless [::Time, ::DateTime].any? { |c| obj.instance_of? c }
|
65
|
-
|
61
|
+
"whole_minute" unless obj.sec > 0
|
66
62
|
end
|
67
63
|
|
68
64
|
def noon_class
|
69
65
|
return unless [::Time, ::DateTime].any? { |c| obj.instance_of? c }
|
70
|
-
|
66
|
+
"noon" if obj == obj.noon
|
71
67
|
end
|
72
68
|
|
73
69
|
def midnight_class
|
74
70
|
return unless [::Time, ::DateTime].any? { |c| obj.instance_of? c }
|
75
|
-
|
71
|
+
"midnight" if obj == obj.midnight
|
76
72
|
end
|
77
73
|
|
78
74
|
def am_pm_class
|
79
75
|
return unless [::Time, ::DateTime].any? { |c| obj.instance_of? c }
|
80
76
|
case
|
81
|
-
when (0..11).cover?(obj.hour) then
|
82
|
-
else
|
77
|
+
when (0..11).cover?(obj.hour) then "am"
|
78
|
+
else "pm"
|
83
79
|
end
|
84
80
|
end
|
85
81
|
|
@@ -87,54 +83,49 @@ module SemanticDateTimeTags
|
|
87
83
|
I18n.locale.to_s
|
88
84
|
end
|
89
85
|
|
90
|
-
# ---------------------------------------------------------------------
|
91
|
-
|
92
86
|
def dom_data
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
private # =============================================================
|
97
|
-
|
98
|
-
def scope
|
99
|
-
raise NotImplementedError
|
100
|
-
end
|
101
|
-
|
102
|
-
def format_string
|
103
|
-
I18n.t(scope)[format]
|
87
|
+
options.fetch(:data, {})
|
88
|
+
.merge(in_words: in_words, format: format.to_s)
|
104
89
|
end
|
105
90
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
# ---------------------------------------------------------------------
|
91
|
+
private
|
92
|
+
def scope
|
93
|
+
raise NotImplementedError
|
94
|
+
end
|
111
95
|
|
112
|
-
|
113
|
-
|
114
|
-
|
96
|
+
def format_string
|
97
|
+
case format
|
98
|
+
when Symbol then I18n.t(scope)[format]
|
99
|
+
else format
|
100
|
+
end
|
101
|
+
end
|
115
102
|
|
116
|
-
|
103
|
+
def format
|
104
|
+
options.fetch :format, :full
|
105
|
+
end
|
117
106
|
|
118
|
-
|
119
|
-
|
120
|
-
|
107
|
+
def localized_obj
|
108
|
+
I18n.l obj, format: format
|
109
|
+
end
|
121
110
|
|
122
|
-
|
111
|
+
def tag_name
|
112
|
+
options.fetch :tag_name, :time
|
113
|
+
end
|
123
114
|
|
124
|
-
|
125
|
-
|
126
|
-
|
115
|
+
def in_words
|
116
|
+
[noon_in_words, midnight_in_words].reject(&:blank?).join(" ")
|
117
|
+
end
|
127
118
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
119
|
+
def noon_in_words
|
120
|
+
return unless [::Time, ::DateTime].any? { |c| obj.instance_of? c }
|
121
|
+
return unless obj == obj.noon
|
122
|
+
I18n.t :noon, scope: %i(time in_words)
|
123
|
+
end
|
133
124
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
125
|
+
def midnight_in_words
|
126
|
+
return unless [::Time, ::DateTime].any? { |c| obj.instance_of? c }
|
127
|
+
return unless obj == obj.midnight
|
128
|
+
I18n.t :midnight, scope: %i(time in_words)
|
129
|
+
end
|
139
130
|
end
|
140
131
|
end
|
@@ -1,15 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../format_parser"
|
2
4
|
|
3
5
|
module SemanticDateTimeTags
|
4
6
|
class Tag
|
5
7
|
class Date < Tag
|
6
8
|
def initialize(obj, options = {})
|
7
|
-
raise
|
9
|
+
raise "object must be Date or DateTime" unless [::Date, ::DateTime].any? { |c| obj.instance_of? c }
|
10
|
+
|
11
|
+
options = options.except(*%i(separator))
|
12
|
+
|
8
13
|
super(obj, options)
|
9
14
|
end
|
10
15
|
|
11
|
-
# ---------------------------------------------------------------------
|
12
|
-
|
13
16
|
def to_html
|
14
17
|
if tag_name == :time
|
15
18
|
datetime = obj.acts_like?(:time) ? obj.xmlschema : obj.iso8601
|
@@ -21,14 +24,13 @@ module SemanticDateTimeTags
|
|
21
24
|
|
22
25
|
value = SemanticDateTimeTags::FormatParser.new(format_string, localized_obj).to_html.html_safe
|
23
26
|
|
24
|
-
content_tag(tag_name, options) { value }.html_safe
|
27
|
+
content_tag(tag_name, options.except(*%i(format))) { value }.html_safe
|
25
28
|
end
|
26
29
|
|
27
|
-
private
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
30
|
+
private
|
31
|
+
def scope
|
32
|
+
"date.formats"
|
33
|
+
end
|
32
34
|
end
|
33
35
|
end
|
34
36
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SemanticDateTimeTags
|
2
4
|
class Tag
|
3
5
|
class DateRange < Tag
|
@@ -9,10 +11,9 @@ module SemanticDateTimeTags
|
|
9
11
|
@date_from = date_from
|
10
12
|
@date_to = date_to
|
11
13
|
@options = options
|
14
|
+
@separator = options.delete(:separator) || " – "
|
12
15
|
end
|
13
16
|
|
14
|
-
# ---------------------------------------------------------------------
|
15
|
-
|
16
17
|
def spans_years?
|
17
18
|
return false if date_to.nil?
|
18
19
|
date_from.year != date_to.year
|
@@ -45,43 +46,39 @@ module SemanticDateTimeTags
|
|
45
46
|
(date_from.to_datetime.hour >= 12 && date_to.to_datetime.hour >= 12)
|
46
47
|
end
|
47
48
|
|
48
|
-
# ---------------------------------------------------------------------
|
49
|
-
|
50
49
|
def dom_classes
|
51
50
|
res = []
|
52
|
-
res <<
|
53
|
-
res <<
|
54
|
-
res <<
|
55
|
-
res <<
|
56
|
-
res <<
|
57
|
-
res <<
|
58
|
-
res <<
|
59
|
-
res <<
|
51
|
+
res << "date_range"
|
52
|
+
res << "same_year" unless spans_years?
|
53
|
+
res << "current_year" if both_in_current_year?
|
54
|
+
res << "same_month" unless spans_months?
|
55
|
+
res << "more_than_a_week" unless within_a_week?
|
56
|
+
res << "same_day" if same_day?
|
57
|
+
res << "same_time" if same_time?
|
58
|
+
res << "same_meridian" if same_meridian?
|
60
59
|
res
|
61
60
|
end
|
62
61
|
|
63
|
-
|
62
|
+
def dom_data
|
63
|
+
options.fetch(:data, {})
|
64
|
+
end
|
64
65
|
|
65
66
|
def to_html
|
67
|
+
from_options = options.merge(class: "from").except(:data, :time_data).merge(data: options.fetch(:time_data, {}))
|
66
68
|
from = case date_from
|
67
|
-
when ::DateTime then SemanticDateTimeTags::Tag::DateTime.new(date_from,
|
68
|
-
when ::Date then SemanticDateTimeTags::Tag::Date.new(date_from.to_date,
|
69
|
+
when ::DateTime then SemanticDateTimeTags::Tag::DateTime.new(date_from, from_options).to_html
|
70
|
+
when ::Date then SemanticDateTimeTags::Tag::Date.new(date_from.to_date, from_options).to_html
|
69
71
|
end
|
70
72
|
|
71
|
-
sep = content_tag(:span, separator, class:
|
73
|
+
sep = content_tag(:span, @separator, class: "date_range_separator")
|
72
74
|
|
75
|
+
to_options = options.merge(class: "to").except(:data, :time_data).merge(data: options.fetch(:time_data, {}))
|
73
76
|
to = case date_to
|
74
|
-
when ::DateTime then SemanticDateTimeTags::Tag::DateTime.new(date_to,
|
75
|
-
when ::Date then SemanticDateTimeTags::Tag::Date.new(date_to.to_date,
|
77
|
+
when ::DateTime then SemanticDateTimeTags::Tag::DateTime.new(date_to, to_options).to_html
|
78
|
+
when ::Date then SemanticDateTimeTags::Tag::Date.new(date_to.to_date, to_options).to_html
|
76
79
|
end
|
77
80
|
|
78
|
-
content_tag(:span, class: dom_classes) { [from, sep, to].join.html_safe }.html_safe
|
79
|
-
end
|
80
|
-
|
81
|
-
private # =============================================================
|
82
|
-
|
83
|
-
def separator
|
84
|
-
options.fetch(:separator, ' – ')
|
81
|
+
content_tag(:span, class: dom_classes, data: dom_data) { [from, sep, to].join.html_safe }.html_safe
|
85
82
|
end
|
86
83
|
end
|
87
84
|
end
|
@@ -1,15 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../format_parser"
|
2
4
|
|
3
5
|
module SemanticDateTimeTags
|
4
6
|
class Tag
|
5
7
|
class DateTime < Tag
|
6
8
|
def initialize(obj, options = {})
|
7
|
-
raise
|
9
|
+
raise "object must be DateTime" unless obj.instance_of?(::DateTime)
|
10
|
+
|
11
|
+
options = options.except(*%i(separator))
|
12
|
+
|
8
13
|
super(obj, options)
|
9
14
|
end
|
10
15
|
|
11
|
-
# ---------------------------------------------------------------------
|
12
|
-
|
13
16
|
def to_html
|
14
17
|
if tag_name == :time
|
15
18
|
datetime = obj.acts_like?(:time) ? obj.xmlschema : obj.iso8601
|
@@ -21,19 +24,21 @@ module SemanticDateTimeTags
|
|
21
24
|
|
22
25
|
value = SemanticDateTimeTags::FormatParser.new(format_string, localized_obj).to_html.html_safe
|
23
26
|
|
24
|
-
time_tag(obj, options) { value }.html_safe
|
27
|
+
time_tag(obj, options.except(*%i(format))) { value }.html_safe
|
25
28
|
end
|
26
29
|
|
27
|
-
private
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
30
|
+
private
|
31
|
+
def scope
|
32
|
+
"date_time.formats"
|
33
|
+
end
|
32
34
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
def localized_obj
|
36
|
+
format_string = case format
|
37
|
+
when Symbol then I18n.t(format, scope: scope, locale: I18n.locale)
|
38
|
+
else format
|
39
|
+
end
|
40
|
+
I18n.l(obj, format: format_string)
|
41
|
+
end
|
37
42
|
end
|
38
43
|
end
|
39
44
|
end
|