line-message-builder 0.4.0 → 0.6.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 +4 -4
- data/.release-please-manifest.json +1 -1
- data/.rspec +2 -0
- data/CHANGELOG.md +32 -0
- data/README.md +10 -1
- data/lib/line/message/builder/actions/message.rb +9 -12
- data/lib/line/message/builder/actions/postback.rb +10 -17
- data/lib/line/message/builder/base.rb +3 -2
- data/lib/line/message/builder/flex/actionable.rb +24 -0
- data/lib/line/message/builder/flex/box.rb +46 -6
- data/lib/line/message/builder/flex/builder.rb +4 -0
- data/lib/line/message/builder/flex/button.rb +30 -22
- data/lib/line/message/builder/flex/carousel.rb +32 -0
- data/lib/line/message/builder/flex/image.rb +25 -9
- data/lib/line/message/builder/flex/position.rb +68 -0
- data/lib/line/message/builder/flex/size.rb +52 -0
- data/lib/line/message/builder/flex/text.rb +28 -9
- data/lib/line/message/builder/flex.rb +4 -0
- data/lib/line/message/builder/validators/enum.rb +24 -0
- data/lib/line/message/builder/validators/size.rb +52 -0
- data/lib/line/message/builder/validators.rb +13 -0
- data/lib/line/message/builder/version.rb +1 -1
- data/lib/line/message/builder.rb +2 -0
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3ed7258b9de88098b6e78ff9165c4ab4b07b5328a294106f78e3cbed16b0725
|
4
|
+
data.tar.gz: fee080b8a5c4799a9a0859cd12b42bbc32d9797ee7906b07d65a80bc882040ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5016cdac5849c4f6931b5e6810abfcbffec6ef337fecb3461c19a4af507b6bc7fbd4c8cc79ab8770183c9ecaa5403efd52686bbf4525d9c0996cf200d966acb5
|
7
|
+
data.tar.gz: 93da8212a3282dd64587679151f8b2a08d6523f60ecd32e765bb045ccae98b110ca92352402d5217d870a6405e05dd9c167b55707a47ccdef98dde2e604d469c
|
@@ -1 +1 @@
|
|
1
|
-
{".":"0.
|
1
|
+
{".":"0.6.0"}
|
data/.rspec
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,37 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.6.0](https://github.com/elct9620/line-message-builder/compare/v0.5.0...v0.6.0) (2025-04-07)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* Add Flex carousel support for Line message builder ([757b16d](https://github.com/elct9620/line-message-builder/commit/757b16d2f71ff14cff39aa1990773851bc78192b))
|
9
|
+
* Add height and max_height options to flex box with validation ([932c743](https://github.com/elct9620/line-message-builder/commit/932c7435ea11a3dec7903ffa19c48a5987231e39))
|
10
|
+
* Add shrink-to-fit adjust mode for flex buttons and texts ([b3ce3a2](https://github.com/elct9620/line-message-builder/commit/b3ce3a29614514b3049d5b6ad718b3dbcd283898))
|
11
|
+
* Add width and max_width options to flex box builder ([3d20c98](https://github.com/elct9620/line-message-builder/commit/3d20c98e670f49fad3f35c93d88364fb7f14afc0))
|
12
|
+
|
13
|
+
## [0.5.0](https://github.com/elct9620/line-message-builder/compare/v0.4.0...v0.5.0) (2025-04-07)
|
14
|
+
|
15
|
+
|
16
|
+
### Features
|
17
|
+
|
18
|
+
* Add Actionable module for flex components with message and postback actions ([9ac4b4a](https://github.com/elct9620/line-message-builder/commit/9ac4b4af591450e8f1925814b5a57e893ffa15db))
|
19
|
+
* Add enum validator for flex text alignment options ([540c58d](https://github.com/elct9620/line-message-builder/commit/540c58d94731adfe91d30e006bb0ee6714755006))
|
20
|
+
* Add justify_content and align_items options to Flex Box builder ([6c2015f](https://github.com/elct9620/line-message-builder/commit/6c2015f0a75a0f541cb52fef647e0bff1a245a28))
|
21
|
+
* Add layout validation for flex box with enum validator ([b1ecba1](https://github.com/elct9620/line-message-builder/commit/b1ecba160db03f94aaebc83b82158e75292c94eb))
|
22
|
+
* Add margin support for flex components in Line message builder ([36043b8](https://github.com/elct9620/line-message-builder/commit/36043b8d7390cb13d60174759fc5906a70aa2507))
|
23
|
+
* Add offset positioning support for flex message components ([1e28336](https://github.com/elct9620/line-message-builder/commit/1e2833656083aa72b0cfffccd5636e80ae41ccc9))
|
24
|
+
* Add padding support for flex box components with validation ([9dcd9d2](https://github.com/elct9620/line-message-builder/commit/9dcd9d20a48aed023440a2abe24e8b44eea8b425))
|
25
|
+
* Add padding support for Line Flex buttons with validation ([ca25a11](https://github.com/elct9620/line-message-builder/commit/ca25a1192c0d611ae064f935fc9335640d123b2d))
|
26
|
+
* Add SimpleCov Cobertura formatter for CI coverage reporting ([bb5bfc8](https://github.com/elct9620/line-message-builder/commit/bb5bfc8344c1b448e61a2857aa36e1f6b5ce0425))
|
27
|
+
* Add validator for spacing option in flex box builder ([06e7b98](https://github.com/elct9620/line-message-builder/commit/06e7b9805f8243c51faaf9c13c264ffb1f35091c))
|
28
|
+
* Add vertical positioning support for Flex message components ([f9ce97b](https://github.com/elct9620/line-message-builder/commit/f9ce97b666cabe47717cdd916722121372cb9bf0))
|
29
|
+
|
30
|
+
|
31
|
+
### Bug Fixes
|
32
|
+
|
33
|
+
* Correct indentation in GitHub Actions workflow file ([1c1cd2d](https://github.com/elct9620/line-message-builder/commit/1c1cd2dfe2e48bd937a04ac25f7b2b772e02e1a6))
|
34
|
+
|
3
35
|
## [0.4.0](https://github.com/elct9620/line-message-builder/compare/v0.3.0...v0.4.0) (2025-04-06)
|
4
36
|
|
5
37
|
|
data/README.md
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
# LINE Message Builder
|
2
2
|
|
3
|
+
[](https://github.com/elct9620/line-message-builder/actions/workflows/main.yml)
|
4
|
+
[](https://codecov.io/gh/elct9620/line-message-builder)
|
5
|
+
|
3
6
|
Build LINE messages using DSL (Domain Specific Language) in Ruby.
|
4
7
|
|
8
|
+
## Features
|
9
|
+
|
10
|
+
- Build LINE messages using DSL
|
11
|
+
- Validation of properties
|
12
|
+
- RSpec matchers for testing
|
13
|
+
|
5
14
|
## Installation
|
6
15
|
|
7
16
|
Install the gem and add to the application's Gemfile by executing:
|
@@ -193,7 +202,7 @@ end
|
|
193
202
|
| Component | Supported |
|
194
203
|
| --------- | --------- |
|
195
204
|
| Bubble | 🚧 |
|
196
|
-
| Carousel |
|
205
|
+
| Carousel | ✅ |
|
197
206
|
| Box | 🚧 |
|
198
207
|
| Button | 🚧 |
|
199
208
|
| Image | 🚧 |
|
@@ -6,26 +6,23 @@ module Line
|
|
6
6
|
module Actions
|
7
7
|
# The Message class is used to build message actions for quick replies.
|
8
8
|
class Message < Line::Message::Builder::Base
|
9
|
-
|
10
|
-
@text = text
|
11
|
-
@label = label
|
12
|
-
|
13
|
-
super(context: context, &)
|
14
|
-
end
|
9
|
+
attr_reader :text
|
15
10
|
|
16
|
-
|
17
|
-
@label = label
|
18
|
-
end
|
11
|
+
option :label, default: nil
|
19
12
|
|
20
|
-
def
|
13
|
+
def initialize(text, context: nil, **options, &)
|
21
14
|
@text = text
|
15
|
+
|
16
|
+
super(context: context, **options, &)
|
22
17
|
end
|
23
18
|
|
24
19
|
def to_h
|
20
|
+
raise RequiredError, "text is required" if text.nil?
|
21
|
+
|
25
22
|
{
|
26
23
|
type: "message",
|
27
|
-
label:
|
28
|
-
text:
|
24
|
+
label: label,
|
25
|
+
text: text
|
29
26
|
}.compact
|
30
27
|
end
|
31
28
|
end
|
@@ -6,32 +6,25 @@ module Line
|
|
6
6
|
module Actions
|
7
7
|
# The Postback class is used to build postback actions for quick replies.
|
8
8
|
class Postback < Line::Message::Builder::Base
|
9
|
-
|
10
|
-
@data = data
|
11
|
-
@label = label
|
12
|
-
@display_text = display_text
|
13
|
-
|
14
|
-
super(context: context, &)
|
15
|
-
end
|
9
|
+
attr_reader :data
|
16
10
|
|
17
|
-
|
18
|
-
|
19
|
-
end
|
11
|
+
option :label, default: nil
|
12
|
+
option :display_text, default: nil
|
20
13
|
|
21
|
-
def
|
14
|
+
def initialize(data, context: nil, **options, &)
|
22
15
|
@data = data
|
23
|
-
end
|
24
16
|
|
25
|
-
|
26
|
-
@display_text = display_text
|
17
|
+
super(context: context, **options, &)
|
27
18
|
end
|
28
19
|
|
29
20
|
def to_h
|
21
|
+
raise RequiredError, "data is required" if data.nil?
|
22
|
+
|
30
23
|
{
|
31
24
|
type: "postback",
|
32
|
-
label:
|
33
|
-
data:
|
34
|
-
displayText:
|
25
|
+
label: label,
|
26
|
+
data: data,
|
27
|
+
displayText: display_text
|
35
28
|
}.compact
|
36
29
|
end
|
37
30
|
end
|
@@ -18,13 +18,14 @@ module Line
|
|
18
18
|
@options ||= []
|
19
19
|
end
|
20
20
|
|
21
|
-
def option(name, default: nil)
|
21
|
+
def option(name, default: nil, validator: nil)
|
22
22
|
options << name
|
23
23
|
|
24
24
|
define_method name do |*args|
|
25
25
|
if args.empty?
|
26
26
|
instance_variable_get("@#{name}") || default
|
27
27
|
else
|
28
|
+
validator&.valid!(args.first)
|
28
29
|
instance_variable_set("@#{name}", args.first)
|
29
30
|
end
|
30
31
|
end
|
@@ -38,7 +39,7 @@ module Line
|
|
38
39
|
@quick_reply = nil
|
39
40
|
|
40
41
|
self.class.options.each do |option|
|
41
|
-
|
42
|
+
send(option, options[option]) if options.key?(option)
|
42
43
|
end
|
43
44
|
|
44
45
|
instance_eval(&block) if ::Kernel.block_given?
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Line
|
4
|
+
module Message
|
5
|
+
module Builder
|
6
|
+
module Flex
|
7
|
+
# The action DSL for flex components.
|
8
|
+
module Actionable
|
9
|
+
def self.included(base)
|
10
|
+
base.attr_reader :action
|
11
|
+
end
|
12
|
+
|
13
|
+
def message(text, **options, &)
|
14
|
+
@action = Actions::Message.new(text, context: context, **options, &)
|
15
|
+
end
|
16
|
+
|
17
|
+
def postback(data, **options, &)
|
18
|
+
@action = Actions::Postback.new(data, context: context, **options, &)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -6,11 +6,28 @@ module Line
|
|
6
6
|
module Flex
|
7
7
|
# The box is a component for the Flex message.
|
8
8
|
class Box < Line::Message::Builder::Base
|
9
|
+
include Actionable
|
10
|
+
include Position::Padding
|
11
|
+
include Position::Margin
|
12
|
+
include Position::Offset
|
13
|
+
include Size::Flex
|
14
|
+
|
9
15
|
attr_reader :contents
|
10
16
|
|
11
|
-
option :layout, default: :horizontal
|
12
|
-
|
13
|
-
|
17
|
+
option :layout, default: :horizontal, validator: Validators::Enum.new(
|
18
|
+
:horizontal, :vertical, :baseline
|
19
|
+
)
|
20
|
+
option :justify_content, default: nil, validator: Validators::Enum.new(
|
21
|
+
:flex_start, :center, :flex_end, :space_between, :space_around, :space_evenly
|
22
|
+
)
|
23
|
+
option :align_items, default: nil, validator: Validators::Enum.new(
|
24
|
+
:flex_start, :center, :flex_end
|
25
|
+
)
|
26
|
+
option :spacing, default: nil, validator: Validators::Size.new(:pixel, :keyword)
|
27
|
+
option :width, default: nil, validator: Validators::Size.new(:pixel, :percentage)
|
28
|
+
option :max_width, default: nil, validator: Validators::Size.new(:pixel, :percentage)
|
29
|
+
option :height, default: nil, validator: Validators::Size.new(:pixel, :percentage)
|
30
|
+
option :max_height, default: nil, validator: Validators::Size.new(:pixel, :percentage)
|
14
31
|
|
15
32
|
def initialize(context: nil, **options, &)
|
16
33
|
@contents = []
|
@@ -34,16 +51,39 @@ module Line
|
|
34
51
|
@contents << Flex::Image.new(url, context: context, **options, &)
|
35
52
|
end
|
36
53
|
|
37
|
-
def to_h
|
54
|
+
def to_h # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
38
55
|
raise RequiredError, "layout is required" if layout.nil?
|
39
|
-
raise RequiredError, "contents is required" if contents.empty?
|
40
56
|
|
41
57
|
{
|
42
58
|
type: "box",
|
43
59
|
layout: layout,
|
60
|
+
# Position
|
61
|
+
justifyContent: justify_content,
|
62
|
+
alignItems: align_items,
|
44
63
|
spacing: spacing,
|
64
|
+
# Position::Padding
|
65
|
+
paddingAll: padding,
|
66
|
+
paddingTop: padding_top,
|
67
|
+
paddingBottom: padding_bottom,
|
68
|
+
paddingStart: padding_start,
|
69
|
+
paddingEnd: padding_end,
|
70
|
+
# Position::Margin
|
71
|
+
margin: margin,
|
72
|
+
# Position::Offset
|
73
|
+
position: position,
|
74
|
+
offsetTop: offset_top,
|
75
|
+
offsetBottom: offset_bottom,
|
76
|
+
offsetStart: offset_start,
|
77
|
+
offsetEnd: offset_end,
|
78
|
+
# Size
|
79
|
+
width: width,
|
80
|
+
maxWidth: max_width,
|
81
|
+
height: height,
|
82
|
+
maxHeight: max_height,
|
83
|
+
# Size::Flex
|
45
84
|
flex: flex,
|
46
|
-
contents: contents.map(&:to_h)
|
85
|
+
contents: contents.map(&:to_h),
|
86
|
+
action: action&.to_h
|
47
87
|
}.compact
|
48
88
|
end
|
49
89
|
end
|
@@ -18,6 +18,10 @@ module Line
|
|
18
18
|
@contents = Line::Message::Builder::Flex::Bubble.new(context: context, **options, &)
|
19
19
|
end
|
20
20
|
|
21
|
+
def carousel(**options, &)
|
22
|
+
@contents = Line::Message::Builder::Flex::Carousel.new(context: context, **options, &)
|
23
|
+
end
|
24
|
+
|
21
25
|
def to_h
|
22
26
|
raise Error, "contents should be bubble or carousel" if @contents.nil?
|
23
27
|
|
@@ -6,37 +6,45 @@ module Line
|
|
6
6
|
module Flex
|
7
7
|
# The button is a component of the Flex message.
|
8
8
|
class Button < Line::Message::Builder::Base
|
9
|
-
|
9
|
+
include Actionable
|
10
|
+
include Position::Vertical
|
11
|
+
include Position::Padding
|
12
|
+
include Position::Margin
|
13
|
+
include Position::Offset
|
14
|
+
include Size::Flex
|
15
|
+
include Size::AdjustMode
|
10
16
|
|
11
|
-
option :flex, default: nil
|
12
|
-
option :margin, default: nil
|
13
17
|
option :style, default: :link
|
14
|
-
option :height, default: :md
|
18
|
+
option :height, default: :md, validator: Validators::Enum.new(:sm, :md)
|
15
19
|
|
16
|
-
def
|
17
|
-
@action = nil
|
18
|
-
|
19
|
-
super
|
20
|
-
end
|
21
|
-
|
22
|
-
def message(text, label:, display_text: nil, &)
|
23
|
-
@action = Actions::Message.new(text, label: label, display_text: display_text, &)
|
24
|
-
end
|
25
|
-
|
26
|
-
def postback(data, label: nil, display_text: nil, &)
|
27
|
-
@action = Actions::Postback.new(data, label: label, display_text: display_text, &)
|
28
|
-
end
|
29
|
-
|
30
|
-
def to_h
|
20
|
+
def to_h # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
31
21
|
raise RequiredError, "action is required" if action.nil?
|
32
22
|
|
33
23
|
{
|
34
24
|
type: "button",
|
35
25
|
action: action.to_h,
|
36
|
-
|
26
|
+
height: height,
|
27
|
+
# Position
|
28
|
+
grivity: gravity,
|
29
|
+
# Position::Padding
|
30
|
+
paddingAll: padding,
|
31
|
+
paddingTop: padding_top,
|
32
|
+
paddingBottom: padding_bottom,
|
33
|
+
paddingStart: padding_start,
|
34
|
+
paddingEnd: padding_end,
|
35
|
+
# Position::Margin
|
37
36
|
margin: margin,
|
38
|
-
|
39
|
-
|
37
|
+
# Position::Offset
|
38
|
+
position: position,
|
39
|
+
offsetTop: offset_top,
|
40
|
+
offsetBottom: offset_bottom,
|
41
|
+
offsetStart: offset_start,
|
42
|
+
offsetEnd: offset_end,
|
43
|
+
# Size::Flex
|
44
|
+
flex: flex,
|
45
|
+
# Size::AdjustMode
|
46
|
+
adjustMode: adjust_mode,
|
47
|
+
style: style
|
40
48
|
}.compact
|
41
49
|
end
|
42
50
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Line
|
4
|
+
module Message
|
5
|
+
module Builder
|
6
|
+
module Flex
|
7
|
+
# The carousel is multiple bubbles in a single Flex message.
|
8
|
+
class Carousel < Line::Message::Builder::Base
|
9
|
+
def initialize(context: nil, **options, &)
|
10
|
+
@contents = []
|
11
|
+
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def bubble(**options, &)
|
16
|
+
@contents << Line::Message::Builder::Flex::Bubble.new(context: context, **options, &)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
raise RequiredError, "contents should have at least 1 bubble" if @contents.empty?
|
21
|
+
raise ValidationError, "contents should have at most 12 bubbles" if @contents.size > 12
|
22
|
+
|
23
|
+
{
|
24
|
+
type: "carousel",
|
25
|
+
contents: @contents.map(&:to_h)
|
26
|
+
}.compact
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -6,14 +6,18 @@ module Line
|
|
6
6
|
module Flex
|
7
7
|
# The image is a component for the Flex message.
|
8
8
|
class Image < Line::Message::Builder::Base
|
9
|
+
include Actionable
|
10
|
+
include Position::Horizontal
|
11
|
+
include Position::Vertical
|
12
|
+
include Position::Margin
|
13
|
+
include Position::Offset
|
14
|
+
include Size::Flex
|
15
|
+
include Size::Image
|
16
|
+
|
9
17
|
attr_reader :url
|
10
18
|
|
11
|
-
option :size, default: nil
|
12
19
|
option :aspect_ratio, default: nil
|
13
20
|
option :aspect_mode, default: nil
|
14
|
-
option :flex, default: nil
|
15
|
-
option :margin, default: nil
|
16
|
-
option :align, default: nil
|
17
21
|
|
18
22
|
def initialize(url, context: nil, **options, &)
|
19
23
|
@url = url
|
@@ -21,18 +25,30 @@ module Line
|
|
21
25
|
super(context: context, **options, &)
|
22
26
|
end
|
23
27
|
|
24
|
-
def to_h # rubocop:disable Metrics/MethodLength
|
28
|
+
def to_h # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
25
29
|
raise RequiredError, "url is required" if url.nil?
|
26
30
|
|
27
31
|
{
|
28
32
|
type: "image",
|
29
33
|
url: url,
|
30
|
-
|
31
|
-
flex: flex,
|
32
|
-
margin: margin,
|
34
|
+
# Position
|
33
35
|
align: align,
|
36
|
+
gravity: gravity,
|
37
|
+
# Position::Margin
|
38
|
+
margin: margin,
|
39
|
+
# Position::Offset
|
40
|
+
position: position,
|
41
|
+
offsetTop: offset_top,
|
42
|
+
offsetBottom: offset_bottom,
|
43
|
+
offsetStart: offset_start,
|
44
|
+
offsetEnd: offset_end,
|
45
|
+
# Size::Flex
|
46
|
+
flex: flex,
|
47
|
+
# Size::Image
|
48
|
+
size: size,
|
34
49
|
aspectRatio: aspect_ratio,
|
35
|
-
aspectMode: aspect_mode
|
50
|
+
aspectMode: aspect_mode,
|
51
|
+
action: action&.to_h
|
36
52
|
}.compact
|
37
53
|
end
|
38
54
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Line
|
4
|
+
module Message
|
5
|
+
module Builder
|
6
|
+
module Flex
|
7
|
+
module Position
|
8
|
+
# The horizontal provides "align" options for flex components.
|
9
|
+
module Horizontal
|
10
|
+
def self.included(base)
|
11
|
+
base.option :align,
|
12
|
+
default: :nil,
|
13
|
+
validator: Validators::Enum.new(
|
14
|
+
:start, :center, :end
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# The vertical provides "gatvity" options for flex components.
|
20
|
+
module Vertical
|
21
|
+
def self.included(base)
|
22
|
+
base.option :gravity,
|
23
|
+
default: :nil,
|
24
|
+
validator: Validators::Enum.new(
|
25
|
+
:top, :center, :bottom
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# The padding provides "padding" options for flex components.
|
31
|
+
module Padding
|
32
|
+
def self.included(base)
|
33
|
+
%i[padding padding_top padding_bottom padding_start padding_end].each do |option|
|
34
|
+
base.option option,
|
35
|
+
default: :nil,
|
36
|
+
validator: Validators::Size.new(:pixel, :keyword, :percentage)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# The margin provides "margin" options for flex components.
|
42
|
+
module Margin
|
43
|
+
def self.included(base)
|
44
|
+
base.option :margin,
|
45
|
+
default: :nil,
|
46
|
+
validator: Validators::Size.new(:pixel, :keyword)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# The offset provides "offset" options for flex components.
|
51
|
+
module Offset
|
52
|
+
def self.included(base)
|
53
|
+
base.option :position,
|
54
|
+
default: :nil,
|
55
|
+
validator: Validators::Enum.new(:absolute, :relative)
|
56
|
+
|
57
|
+
%i[offset_top offset_bottom offset_start offset_end].each do |option|
|
58
|
+
base.option option,
|
59
|
+
default: :nil,
|
60
|
+
validator: Validators::Size.new(:pixel, :keyword)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Line
|
4
|
+
module Message
|
5
|
+
module Builder
|
6
|
+
module Flex
|
7
|
+
module Size
|
8
|
+
# The flex size provides "flex" options for flex components.
|
9
|
+
module Flex
|
10
|
+
def self.included(base)
|
11
|
+
base.option :flex,
|
12
|
+
default: :nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# The image provides "size" options for flex image component.
|
17
|
+
module Image
|
18
|
+
def self.included(base)
|
19
|
+
base.option :size,
|
20
|
+
default: :nil,
|
21
|
+
validator: Validators::Size.new(:pixel, :image, :percentage)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# The shared provides "size" options for flex components which is icon, text and span.
|
26
|
+
module Shared
|
27
|
+
def self.included(base)
|
28
|
+
base.option :size,
|
29
|
+
default: :nil,
|
30
|
+
validator: Validators::Size.new(:pixel, :keyword)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# The adjust mode provides "adjust mode" options for flex components.
|
35
|
+
module AdjustMode
|
36
|
+
def self.included(base)
|
37
|
+
base.option :adjust_mode,
|
38
|
+
default: :nil,
|
39
|
+
validator: Validators::Enum.new(
|
40
|
+
:"shrink-to-fit"
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
def shrink_to_fit!
|
45
|
+
@adjust_mode = :"shrink-to-fit"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -6,15 +6,20 @@ module Line
|
|
6
6
|
module Flex
|
7
7
|
# The text is a component of the Flex message.
|
8
8
|
class Text < Line::Message::Builder::Base
|
9
|
+
include Actionable
|
10
|
+
include Position::Horizontal
|
11
|
+
include Position::Vertical
|
12
|
+
include Position::Margin
|
13
|
+
include Position::Offset
|
14
|
+
include Size::Flex
|
15
|
+
include Size::Shared
|
16
|
+
include Size::AdjustMode
|
17
|
+
|
9
18
|
attr_reader :text
|
10
19
|
|
11
|
-
option :size, default: nil
|
12
20
|
option :wrap, default: false
|
13
21
|
option :line_spacing, default: nil
|
14
22
|
option :color, default: nil
|
15
|
-
option :align, default: nil
|
16
|
-
option :flex, default: nil
|
17
|
-
option :margin, default: nil
|
18
23
|
|
19
24
|
def initialize(text, context: nil, **options, &)
|
20
25
|
@text = text
|
@@ -26,19 +31,33 @@ module Line
|
|
26
31
|
@wrap = true
|
27
32
|
end
|
28
33
|
|
29
|
-
def to_h # rubocop:disable Metrics/MethodLength
|
34
|
+
def to_h # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
30
35
|
raise RequiredError, "text is required" if text.nil?
|
31
36
|
|
32
37
|
{
|
33
38
|
type: "text",
|
34
39
|
text: text,
|
35
40
|
wrap: wrap,
|
36
|
-
|
37
|
-
color: color,
|
38
|
-
size: size,
|
41
|
+
# Position
|
39
42
|
align: align,
|
43
|
+
gravity: gravity,
|
44
|
+
# Position::Margin
|
40
45
|
margin: margin,
|
41
|
-
|
46
|
+
# Position::Offset
|
47
|
+
position: position,
|
48
|
+
offsetTop: offset_top,
|
49
|
+
offsetBottom: offset_bottom,
|
50
|
+
offsetStart: offset_start,
|
51
|
+
offsetEnd: offset_end,
|
52
|
+
# Size::Flex
|
53
|
+
flex: flex,
|
54
|
+
# Size::Shared
|
55
|
+
size: size,
|
56
|
+
# Size::AdjustMode
|
57
|
+
adjustMode: adjust_mode,
|
58
|
+
lineSpacing: line_spacing,
|
59
|
+
color: color,
|
60
|
+
action: action&.to_h
|
42
61
|
}.compact
|
43
62
|
end
|
44
63
|
end
|
@@ -6,9 +6,13 @@ module Line
|
|
6
6
|
# The Flex module allows to build Flex messages.
|
7
7
|
module Flex
|
8
8
|
require_relative "flex/builder"
|
9
|
+
require_relative "flex/actionable"
|
10
|
+
require_relative "flex/position"
|
11
|
+
require_relative "flex/size"
|
9
12
|
|
10
13
|
# Container
|
11
14
|
require_relative "flex/bubble"
|
15
|
+
require_relative "flex/carousel"
|
12
16
|
|
13
17
|
# Components
|
14
18
|
require_relative "flex/box"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Line
|
4
|
+
module Message
|
5
|
+
module Builder
|
6
|
+
module Validators
|
7
|
+
# Validate values against a set of allowed values.
|
8
|
+
class Enum
|
9
|
+
attr_reader :allowed_values
|
10
|
+
|
11
|
+
def initialize(*allowed_values)
|
12
|
+
@allowed_values = allowed_values
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid!(value)
|
16
|
+
return if allowed_values.include?(value.to_sym)
|
17
|
+
|
18
|
+
raise ValidationError, "Invalid value: #{value}. Allowed values are: #{allowed_values.join(", ")}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Line
|
4
|
+
module Message
|
5
|
+
module Builder
|
6
|
+
module Validators
|
7
|
+
# Validate size values for LINE messages.
|
8
|
+
class Size
|
9
|
+
VARIANTS = %i[pixel keyword image percentage].freeze
|
10
|
+
KEYWORDS = %i[none xs sm md lg xl xxl].freeze
|
11
|
+
IMAGE_KEYWORDS = %i[xxs xs sm md lg xl xxl 3xl 4xl 5xl full].freeze
|
12
|
+
PIXEL_REGEX = /^\d+px$/
|
13
|
+
PERCENTAGE_REGEX = /^\f+%$/
|
14
|
+
|
15
|
+
def initialize(*variants)
|
16
|
+
@variants = variants & VARIANTS
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?(value)
|
20
|
+
@variants.any? do |variant|
|
21
|
+
send("#{variant}?", value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def pixel?(value)
|
26
|
+
value.to_s.match?(PIXEL_REGEX)
|
27
|
+
end
|
28
|
+
|
29
|
+
def keyword?(value)
|
30
|
+
KEYWORDS.include?(value.to_sym)
|
31
|
+
end
|
32
|
+
|
33
|
+
def image?(value)
|
34
|
+
IMAGE_KEYWORDS.include?(value.to_sym)
|
35
|
+
end
|
36
|
+
|
37
|
+
def percentage?(value)
|
38
|
+
value.to_s.match?(PERCENTAGE_REGEX)
|
39
|
+
end
|
40
|
+
|
41
|
+
def valid!(value)
|
42
|
+
return if valid?(value)
|
43
|
+
|
44
|
+
raise ValidationError,
|
45
|
+
"Invalid value: #{value}. " \
|
46
|
+
"Expected one of: #{VARIANTS.join(", ")}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/line/message/builder.rb
CHANGED
@@ -8,8 +8,10 @@ module Line
|
|
8
8
|
module Builder
|
9
9
|
class Error < StandardError; end
|
10
10
|
class RequiredError < Error; end
|
11
|
+
class ValidationError < Error; end
|
11
12
|
|
12
13
|
require_relative "builder/base"
|
14
|
+
require_relative "builder/validators"
|
13
15
|
require_relative "builder/actions"
|
14
16
|
require_relative "builder/quick_reply"
|
15
17
|
require_relative "builder/container"
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: line-message-builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aotokitsuruya
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date: 2025-04-
|
10
|
+
date: 2025-04-07 00:00:00.000000000 Z
|
12
11
|
dependencies: []
|
13
12
|
description: The LINE Messaging API message builder.
|
14
13
|
email:
|
@@ -32,14 +31,21 @@ files:
|
|
32
31
|
- lib/line/message/builder/base.rb
|
33
32
|
- lib/line/message/builder/container.rb
|
34
33
|
- lib/line/message/builder/flex.rb
|
34
|
+
- lib/line/message/builder/flex/actionable.rb
|
35
35
|
- lib/line/message/builder/flex/box.rb
|
36
36
|
- lib/line/message/builder/flex/bubble.rb
|
37
37
|
- lib/line/message/builder/flex/builder.rb
|
38
38
|
- lib/line/message/builder/flex/button.rb
|
39
|
+
- lib/line/message/builder/flex/carousel.rb
|
39
40
|
- lib/line/message/builder/flex/image.rb
|
41
|
+
- lib/line/message/builder/flex/position.rb
|
42
|
+
- lib/line/message/builder/flex/size.rb
|
40
43
|
- lib/line/message/builder/flex/text.rb
|
41
44
|
- lib/line/message/builder/quick_reply.rb
|
42
45
|
- lib/line/message/builder/text.rb
|
46
|
+
- lib/line/message/builder/validators.rb
|
47
|
+
- lib/line/message/builder/validators/enum.rb
|
48
|
+
- lib/line/message/builder/validators/size.rb
|
43
49
|
- lib/line/message/builder/version.rb
|
44
50
|
- lib/line/message/rspec.rb
|
45
51
|
- lib/line/message/rspec/matchers.rb
|
@@ -59,7 +65,6 @@ metadata:
|
|
59
65
|
source_code_uri: https://github.com/elct9620/line-message-builder/tree/main
|
60
66
|
changelog_uri: https://github.com/elct9620/line-message-builder/blob/main/CHANGELOG.md
|
61
67
|
rubygems_mfa_required: 'true'
|
62
|
-
post_install_message:
|
63
68
|
rdoc_options: []
|
64
69
|
require_paths:
|
65
70
|
- lib
|
@@ -74,8 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
79
|
- !ruby/object:Gem::Version
|
75
80
|
version: '0'
|
76
81
|
requirements: []
|
77
|
-
rubygems_version: 3.
|
78
|
-
signing_key:
|
82
|
+
rubygems_version: 3.6.2
|
79
83
|
specification_version: 4
|
80
84
|
summary: The LINE Messaging API message builder.
|
81
85
|
test_files: []
|