line-message-builder 0.6.1 → 0.8.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/.document +3 -0
- data/.release-please-manifest.json +1 -1
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +23 -0
- data/README.md +61 -0
- data/lib/line/message/builder/actions/message.rb +67 -1
- data/lib/line/message/builder/actions/postback.rb +71 -1
- data/lib/line/message/builder/actions.rb +18 -1
- data/lib/line/message/builder/base.rb +112 -2
- data/lib/line/message/builder/container.rb +125 -5
- data/lib/line/message/builder/context.rb +142 -0
- data/lib/line/message/builder/flex/actionable.rb +46 -1
- data/lib/line/message/builder/flex/box.rb +166 -13
- data/lib/line/message/builder/flex/bubble.rb +97 -7
- data/lib/line/message/builder/flex/builder.rb +74 -8
- data/lib/line/message/builder/flex/button.rb +104 -17
- data/lib/line/message/builder/flex/carousel.rb +72 -7
- data/lib/line/message/builder/flex/image.rb +106 -20
- data/lib/line/message/builder/flex/partial.rb +124 -0
- data/lib/line/message/builder/flex/position.rb +122 -12
- data/lib/line/message/builder/flex/size.rb +65 -7
- data/lib/line/message/builder/flex/text.rb +131 -27
- data/lib/line/message/builder/flex.rb +56 -11
- data/lib/line/message/builder/quick_reply.rb +16 -4
- data/lib/line/message/builder/text.rb +12 -1
- data/lib/line/message/builder/version.rb +1 -1
- data/lib/line/message/builder.rb +34 -3
- data/lib/line/message/rspec.rb +14 -0
- data/llm.txt +356 -0
- metadata +5 -1
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Line
|
4
|
+
module Message
|
5
|
+
module Builder
|
6
|
+
module Flex
|
7
|
+
# The `HasPartial` module provides functionality for Flex Message components
|
8
|
+
# (like {Box}, {Bubble}) to render reusable "partials". Partials are defined
|
9
|
+
# by creating classes that inherit from {Partial}.
|
10
|
+
#
|
11
|
+
# Including this module into a component class gives it the {#partial!} method.
|
12
|
+
#
|
13
|
+
# @example Defining and using a partial
|
14
|
+
# # Define a reusable partial
|
15
|
+
# class MyButtonPartial < Line::Message::Builder::Flex::Partial
|
16
|
+
# def call(label:, data:)
|
17
|
+
# # `button` method is available from the context (e.g., a Box)
|
18
|
+
# button style: :primary do |btn|
|
19
|
+
# btn.postback data, label: label
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # Use the partial within a Box component
|
25
|
+
# a_box_component.instance_eval do
|
26
|
+
# # ... other box content ...
|
27
|
+
# partial! MyButtonPartial, label: "Action", data: "action=do_something"
|
28
|
+
# # ... other box content ...
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# @see Partial
|
32
|
+
module HasPartial
|
33
|
+
# Renders a given {Partial} class within the current component's context.
|
34
|
+
#
|
35
|
+
# This method temporarily makes the provided `assigns` available to the
|
36
|
+
# partial through the `context.assigns` mechanism. After the partial's
|
37
|
+
# `call` method completes, the original `context.assigns` are restored.
|
38
|
+
#
|
39
|
+
# @param partial_class [Class] The class of the partial to render. Must be a
|
40
|
+
# subclass of {Partial}.
|
41
|
+
# @param assigns [Hash] A hash of key-value pairs that will be made
|
42
|
+
# available as `assigns` within the partial's `call` method.
|
43
|
+
# @return [void]
|
44
|
+
# @raise [ArgumentError] if `partial_class` is not a subclass of {Partial}.
|
45
|
+
def partial!(partial_class, **assigns)
|
46
|
+
unless partial_class < Partial
|
47
|
+
raise ArgumentError,
|
48
|
+
"Argument must be a Line::Message::Builder::Flex::Partial class"
|
49
|
+
end
|
50
|
+
|
51
|
+
original_assigns = context.assigns
|
52
|
+
context.assigns = assigns
|
53
|
+
# `self` here is the component instance (e.g., Box, Bubble) that includes HasPartial.
|
54
|
+
# This component instance becomes the `@context` for the Partial instance.
|
55
|
+
partial_class.new(context: self).call
|
56
|
+
context.assigns = original_assigns
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# The `Partial` class is an abstract base for creating reusable snippets
|
61
|
+
# of Flex Message content. To define a partial, create a new class that
|
62
|
+
# inherits from `Partial` and implements the {#call} instance method.
|
63
|
+
#
|
64
|
+
# Within the `call` method, you can use the standard Flex Message builder
|
65
|
+
# DSL methods (e.g., `text`, `box`, `button`) as if you were directly inside
|
66
|
+
# the component where the partial is being rendered. This is possible because
|
67
|
+
# the `Partial` instance delegates unknown method calls to the component
|
68
|
+
# instance that is rendering it (passed as `context` during initialization).
|
69
|
+
#
|
70
|
+
# @abstract Subclass and implement {#call} to create a concrete partial.
|
71
|
+
# @see HasPartial For how to render partials.
|
72
|
+
class Partial
|
73
|
+
# Initializes a new Partial instance.
|
74
|
+
# This is typically called by the {HasPartial#partial!} method.
|
75
|
+
#
|
76
|
+
# @param context [Object] The component instance (e.g., {Box}, {Bubble})
|
77
|
+
# within which this partial is being rendered. This context provides
|
78
|
+
# the DSL methods (like `text`, `box`) used in the partial's `call` method.
|
79
|
+
def initialize(context:)
|
80
|
+
@context = context # The component (e.g., Box, Bubble) rendering this partial
|
81
|
+
end
|
82
|
+
|
83
|
+
# This method must be implemented by subclasses to define the content of
|
84
|
+
# the partial. Inside this method, use the Flex Message builder DSL methods
|
85
|
+
# (e.g., `text "Hello"`, `button { ... }`) which will be delegated to the
|
86
|
+
# rendering context.
|
87
|
+
#
|
88
|
+
# Any arguments passed to `partial!` as `assigns` are available via
|
89
|
+
# `context.assigns` or directly if the rendering context's `method_missing`
|
90
|
+
# handles `assigns` lookup (as {Line::Message::Builder::Context} does).
|
91
|
+
#
|
92
|
+
# @param ... [Object] Arguments passed from the `partial!` call's `assigns`
|
93
|
+
# can be explicitly defined as parameters here, or accessed via `context.assigns`.
|
94
|
+
# @raise [NotImplementedError] if a subclass does not implement this method.
|
95
|
+
def call(*)
|
96
|
+
raise NotImplementedError,
|
97
|
+
"The #{self.class.name} class must implement the #call method to define its content."
|
98
|
+
end
|
99
|
+
|
100
|
+
# @!visibility private
|
101
|
+
# Part of Ruby's dynamic method dispatch. It's overridden here to declare
|
102
|
+
# that instances of `Partial` can respond to methods to which the
|
103
|
+
# wrapped `@context` object responds.
|
104
|
+
def respond_to_missing?(method_name, include_private = false)
|
105
|
+
@context.respond_to?(method_name, include_private) || super
|
106
|
+
end
|
107
|
+
|
108
|
+
# @!visibility private
|
109
|
+
# Handles calls to methods not explicitly defined on the `Partial` class
|
110
|
+
# by delegating them to the wrapped `@context` object (the rendering component).
|
111
|
+
# This allows the `call` method of a partial to use DSL methods like `text`,
|
112
|
+
# `box`, `button`, etc., as if they were defined directly in the partial.
|
113
|
+
def method_missing(method_name, ...)
|
114
|
+
if @context.respond_to?(method_name)
|
115
|
+
@context.public_send(method_name, ...)
|
116
|
+
else
|
117
|
+
super
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -4,9 +4,34 @@ module Line
|
|
4
4
|
module Message
|
5
5
|
module Builder
|
6
6
|
module Flex
|
7
|
+
# The `Position` module serves as a namespace for several mixin modules
|
8
|
+
# that provide common positioning-related properties (options) to various
|
9
|
+
# Flex Message components (like {Box}, {Text}, {Image}, {Button}).
|
10
|
+
#
|
11
|
+
# These mixins are included in component classes to add DSL methods for
|
12
|
+
# setting properties like alignment, gravity, padding, margin, and offsets,
|
13
|
+
# which correspond to attributes in the LINE Flex Message JSON structure.
|
14
|
+
#
|
15
|
+
# @see Horizontal For `align` property.
|
16
|
+
# @see Vertical For `gravity` property.
|
17
|
+
# @see Padding For `paddingAll`, `paddingTop`, etc. properties.
|
18
|
+
# @see Margin For `margin` property.
|
19
|
+
# @see Offset For `position`, `offsetTop`, etc. properties.
|
7
20
|
module Position
|
8
|
-
#
|
21
|
+
# Provides the `align` option for horizontal alignment of a component
|
22
|
+
# within its parent {Box} (if the parent box's `layout` is vertical).
|
23
|
+
# For components like {Image} or {Text}, this controls their horizontal
|
24
|
+
# alignment within the space allocated to them.
|
25
|
+
#
|
26
|
+
# @!method align(value)
|
27
|
+
# Sets or gets the horizontal alignment.
|
28
|
+
# @param value [Symbol, String, nil] Alignment keyword:
|
29
|
+
# `:start` (aligns to the start of the horizontal space),
|
30
|
+
# `:center` (aligns to the center),
|
31
|
+
# `:end` (aligns to the end).
|
32
|
+
# @return [Symbol, String, nil] The current alignment value.
|
9
33
|
module Horizontal
|
34
|
+
# @!visibility private
|
10
35
|
def self.included(base)
|
11
36
|
base.option :align,
|
12
37
|
default: nil,
|
@@ -16,10 +41,22 @@ module Line
|
|
16
41
|
end
|
17
42
|
end
|
18
43
|
|
19
|
-
#
|
44
|
+
# Provides the `gravity` option for vertical alignment of a component
|
45
|
+
# within its parent {Box} (if the parent box's `layout` is horizontal
|
46
|
+
# or baseline). For components like {Image} or {Text}, this controls
|
47
|
+
# their vertical alignment within the space allocated to them.
|
48
|
+
#
|
49
|
+
# @!method gravity(value)
|
50
|
+
# Sets or gets the vertical alignment (gravity).
|
51
|
+
# @param value [Symbol, String, nil] Gravity keyword:
|
52
|
+
# `:top` (aligns to the top),
|
53
|
+
# `:center` (aligns to the center),
|
54
|
+
# `:bottom` (aligns to the bottom).
|
55
|
+
# @return [Symbol, String, nil] The current gravity value.
|
20
56
|
module Vertical
|
57
|
+
# @!visibility private
|
21
58
|
def self.included(base)
|
22
|
-
base.option :gravity,
|
59
|
+
base.option :gravity, # NOTE: API key is `gravity` (lowercase `g`)
|
23
60
|
default: nil,
|
24
61
|
validator: Validators::Enum.new(
|
25
62
|
:top, :center, :bottom
|
@@ -27,35 +64,108 @@ module Line
|
|
27
64
|
end
|
28
65
|
end
|
29
66
|
|
30
|
-
#
|
67
|
+
# Provides padding options for components, allowing space to be defined
|
68
|
+
# around the content of a component, inside its borders.
|
69
|
+
#
|
70
|
+
# @!method padding_all(value)
|
71
|
+
# Sets or gets the padding for all sides.
|
72
|
+
# Corresponds to LINE API `paddingAll`.
|
73
|
+
# @param value [String, Symbol, nil] Padding value (e.g., `"10px"`, `"md"`, `"5%"`).
|
74
|
+
# Keywords: `:none`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`.
|
75
|
+
# @return [String, Symbol, nil] The current padding value.
|
76
|
+
#
|
77
|
+
# @!method padding_top(value)
|
78
|
+
# Sets or gets the top padding. Corresponds to LINE API `paddingTop`.
|
79
|
+
# @param value [String, Symbol, nil] Padding value.
|
80
|
+
# @return [String, Symbol, nil] The current top padding.
|
81
|
+
#
|
82
|
+
# @!method padding_bottom(value)
|
83
|
+
# Sets or gets the bottom padding. Corresponds to LINE API `paddingBottom`.
|
84
|
+
# @param value [String, Symbol, nil] Padding value.
|
85
|
+
# @return [String, Symbol, nil] The current bottom padding.
|
86
|
+
#
|
87
|
+
# @!method padding_start(value)
|
88
|
+
# Sets or gets the start-edge padding (left in LTR, right in RTL).
|
89
|
+
# Corresponds to LINE API `paddingStart`.
|
90
|
+
# @param value [String, Symbol, nil] Padding value.
|
91
|
+
# @return [String, Symbol, nil] The current start padding.
|
92
|
+
#
|
93
|
+
# @!method padding_end(value)
|
94
|
+
# Sets or gets the end-edge padding (right in LTR, left in RTL).
|
95
|
+
# Corresponds to LINE API `paddingEnd`.
|
96
|
+
# @param value [String, Symbol, nil] Padding value.
|
97
|
+
# @return [String, Symbol, nil] The current end padding.
|
98
|
+
#
|
99
|
+
# @note In this DSL, `padding` is an alias for `padding_all`.
|
100
|
+
# The LINE API uses `paddingAll`. When using the DSL `padding(value)`,
|
101
|
+
# it sets the underlying value that will be output as `paddingAll`.
|
31
102
|
module Padding
|
103
|
+
# @!visibility private
|
32
104
|
def self.included(base)
|
33
|
-
|
34
|
-
|
105
|
+
# Individual side paddings
|
106
|
+
%i[padding padding_all padding_top padding_bottom padding_start padding_end].each do |option_name|
|
107
|
+
base.option option_name, # e.g., maps to `paddingTop` in JSON
|
35
108
|
default: nil,
|
36
109
|
validator: Validators::Size.new(:pixel, :keyword, :percentage)
|
37
110
|
end
|
38
111
|
end
|
39
112
|
end
|
40
113
|
|
41
|
-
#
|
114
|
+
# Provides the `margin` option, allowing space to be defined around a
|
115
|
+
# component, outside its borders.
|
116
|
+
#
|
117
|
+
# @!method margin(value)
|
118
|
+
# Sets or gets the margin space around the component.
|
119
|
+
# @param value [String, Symbol, nil] Margin value (e.g., `"10px"`, `"md"`).
|
120
|
+
# Keywords: `:none`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`.
|
121
|
+
# @return [String, Symbol, nil] The current margin value.
|
42
122
|
module Margin
|
123
|
+
# @!visibility private
|
43
124
|
def self.included(base)
|
44
125
|
base.option :margin,
|
45
126
|
default: nil,
|
46
|
-
validator: Validators::Size.new(:pixel, :keyword)
|
127
|
+
validator: Validators::Size.new(:pixel, :keyword) # Percentage not allowed for margin
|
47
128
|
end
|
48
129
|
end
|
49
130
|
|
50
|
-
#
|
131
|
+
# Provides options for positioning components using offsets, either
|
132
|
+
# absolutely or relatively to their normal position.
|
133
|
+
#
|
134
|
+
# @!method position(value)
|
135
|
+
# Sets or gets the positioning scheme.
|
136
|
+
# @param value [Symbol, String, nil] Positioning type:
|
137
|
+
# `:relative` (default, offsets are relative to normal position),
|
138
|
+
# `:absolute` (offsets are relative to the parent component's edges).
|
139
|
+
# @return [Symbol, String, nil] The current position type.
|
140
|
+
#
|
141
|
+
# @!method offset_top(value)
|
142
|
+
# Sets or gets the top offset. Corresponds to LINE API `offsetTop`.
|
143
|
+
# @param value [String, Symbol, nil] Offset value (e.g., `"10px"`, `"md"`).
|
144
|
+
# @return [String, Symbol, nil] The current top offset.
|
145
|
+
#
|
146
|
+
# @!method offset_bottom(value)
|
147
|
+
# Sets or gets the bottom offset. Corresponds to LINE API `offsetBottom`.
|
148
|
+
# @param value [String, Symbol, nil] Offset value.
|
149
|
+
# @return [String, Symbol, nil] The current bottom offset.
|
150
|
+
#
|
151
|
+
# @!method offset_start(value)
|
152
|
+
# Sets or gets the start-edge offset. Corresponds to LINE API `offsetStart`.
|
153
|
+
# @param value [String, Symbol, nil] Offset value.
|
154
|
+
# @return [String, Symbol, nil] The current start offset.
|
155
|
+
#
|
156
|
+
# @!method offset_end(value)
|
157
|
+
# Sets or gets the end-edge offset. Corresponds to LINE API `offsetEnd`.
|
158
|
+
# @param value [String, Symbol, nil] Offset value.
|
159
|
+
# @return [String, Symbol, nil] The current end offset.
|
51
160
|
module Offset
|
161
|
+
# @!visibility private
|
52
162
|
def self.included(base)
|
53
163
|
base.option :position,
|
54
|
-
default: nil,
|
164
|
+
default: nil, # LINE API default is :relative if offsets are used
|
55
165
|
validator: Validators::Enum.new(:absolute, :relative)
|
56
166
|
|
57
|
-
%i[offset_top offset_bottom offset_start offset_end].each do |
|
58
|
-
base.option
|
167
|
+
%i[offset_top offset_bottom offset_start offset_end].each do |option_name|
|
168
|
+
base.option option_name, # e.g., maps to `offsetTop` in JSON
|
59
169
|
default: nil,
|
60
170
|
validator: Validators::Size.new(:pixel, :keyword)
|
61
171
|
end
|
@@ -4,17 +4,50 @@ module Line
|
|
4
4
|
module Message
|
5
5
|
module Builder
|
6
6
|
module Flex
|
7
|
+
# The `Size` module acts as a namespace for several mixin modules that
|
8
|
+
# provide various size-related properties (options) to Flex Message
|
9
|
+
# components. These properties control aspects like the component's flex
|
10
|
+
# factor within a box, specific size keywords for images or text, and
|
11
|
+
# adjustment behaviors like shrink-to-fit.
|
12
|
+
#
|
13
|
+
# These mixins are included in component classes (e.g., {Box}, {Image}, {Text})
|
14
|
+
# to add DSL methods for these sizing attributes.
|
15
|
+
#
|
16
|
+
# @see Flex For `flex` property (flex grow/shrink factor).
|
17
|
+
# @see Image For image-specific `size` keywords.
|
18
|
+
# @see Shared For common `size` keywords (text, icons, spans).
|
19
|
+
# @see AdjustMode For `adjustMode` property (e.g., shrink-to-fit).
|
7
20
|
module Size
|
8
|
-
#
|
21
|
+
# Provides the `flex` option, which determines the ratio of space a
|
22
|
+
# component occupies within its parent {Box} relative to its siblings.
|
23
|
+
# A higher flex value means the component will take up more space.
|
24
|
+
# A value of 0 means the component does not flex (its size is fixed).
|
25
|
+
#
|
26
|
+
# @!method flex(value)
|
27
|
+
# Sets or gets the flex factor of the component.
|
28
|
+
# @param value [Integer, nil] The flex factor. `0` means no flex.
|
29
|
+
# Positive integers determine the ratio.
|
30
|
+
# @return [Integer, nil] The current flex factor.
|
9
31
|
module Flex
|
32
|
+
# @!visibility private
|
10
33
|
def self.included(base)
|
11
34
|
base.option :flex,
|
12
|
-
default: nil
|
35
|
+
default: nil # Default is 0 if not specified and parent is a Box
|
13
36
|
end
|
14
37
|
end
|
15
38
|
|
16
|
-
#
|
39
|
+
# Provides the `size` option specifically for {Image} components.
|
40
|
+
# This allows setting the image size using keywords recognized by the
|
41
|
+
# LINE API for images, or explicit pixel/percentage values.
|
42
|
+
#
|
43
|
+
# @!method size(value)
|
44
|
+
# Sets or gets the size of the image.
|
45
|
+
# @param value [Symbol, String, nil] Image size. Can be keywords like
|
46
|
+
# `:xxs`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`, `:full`,
|
47
|
+
# or a string like `"50px"`, `"25%"`.
|
48
|
+
# @return [Symbol, String, nil] The current image size.
|
17
49
|
module Image
|
50
|
+
# @!visibility private
|
18
51
|
def self.included(base)
|
19
52
|
base.option :size,
|
20
53
|
default: nil,
|
@@ -22,8 +55,18 @@ module Line
|
|
22
55
|
end
|
23
56
|
end
|
24
57
|
|
25
|
-
#
|
58
|
+
# Provides a common `size` option for components like {Text}, {Icon},
|
59
|
+
# and {Span}. This allows setting size using standard keywords or explicit
|
60
|
+
# pixel values.
|
61
|
+
#
|
62
|
+
# @!method size(value)
|
63
|
+
# Sets or gets the size of the component (e.g., text font size).
|
64
|
+
# @param value [Symbol, String, nil] Component size. Can be keywords like
|
65
|
+
# `:xxs`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`, `3xl`, `4xl`, `5xl`,
|
66
|
+
# or a string like `"16px"`.
|
67
|
+
# @return [Symbol, String, nil] The current component size.
|
26
68
|
module Shared
|
69
|
+
# @!visibility private
|
27
70
|
def self.included(base)
|
28
71
|
base.option :size,
|
29
72
|
default: nil,
|
@@ -31,18 +74,33 @@ module Line
|
|
31
74
|
end
|
32
75
|
end
|
33
76
|
|
34
|
-
#
|
77
|
+
# Provides the `adjust_mode` option, primarily for {Button} components,
|
78
|
+
# to control how they fit within available space. Currently, only
|
79
|
+
# `shrink-to-fit` is supported by LINE API via this property.
|
80
|
+
#
|
81
|
+
# @!method adjust_mode(value)
|
82
|
+
# Sets or gets the adjust mode.
|
83
|
+
# @param value [Symbol, String, nil] The adjust mode. Currently, only
|
84
|
+
# `:"shrink-to-fit"` is a valid value.
|
85
|
+
# @return [Symbol, String, nil] The current adjust mode.
|
35
86
|
module AdjustMode
|
87
|
+
# @!visibility private
|
36
88
|
def self.included(base)
|
37
89
|
base.option :adjust_mode,
|
38
90
|
default: nil,
|
39
91
|
validator: Validators::Enum.new(
|
40
|
-
:"shrink-to-fit"
|
92
|
+
:"shrink-to-fit" # LINE API uses "shrink-to-fit"
|
41
93
|
)
|
42
94
|
end
|
43
95
|
|
96
|
+
# A convenience DSL method to set the `adjust_mode` to `:"shrink-to-fit"`.
|
97
|
+
#
|
98
|
+
# @example
|
99
|
+
# button_component.shrink_to_fit!
|
100
|
+
#
|
101
|
+
# @return [Symbol] The value `:"shrink-to-fit"`.
|
44
102
|
def shrink_to_fit!
|
45
|
-
|
103
|
+
adjust_mode(:"shrink-to-fit")
|
46
104
|
end
|
47
105
|
end
|
48
106
|
end
|
@@ -4,43 +4,121 @@ module Line
|
|
4
4
|
module Message
|
5
5
|
module Builder
|
6
6
|
module Flex
|
7
|
-
#
|
7
|
+
# Represents a "text" component in a LINE Flex Message.
|
8
|
+
#
|
9
|
+
# Text components are used to display strings of text. They offer various
|
10
|
+
# styling options, including font `size`, `weight` (via styles in a {Box}
|
11
|
+
# or {Bubble}), `color`, `align`ment, `gravity`, text `wrap`ping,
|
12
|
+
# `line_spacing`, and more. A text component can also have an
|
13
|
+
# {Actionable#action action} to make it tappable.
|
14
|
+
#
|
15
|
+
# @example Creating a text component within a box
|
16
|
+
# Line::Message::Builder.with do |root|
|
17
|
+
# root.flex alt_text: "Text Example" do |flex|
|
18
|
+
# flex.bubble do |bubble|
|
19
|
+
# bubble.body do |body_box|
|
20
|
+
# body_box.text "Hello, Flex World!",
|
21
|
+
# size: :xl,
|
22
|
+
# color: "#FF0000",
|
23
|
+
# wrap: true do |txt_action|
|
24
|
+
# txt_action.message "More info", text: "Tell me more about text"
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# @see https://developers.line.biz/en/reference/messaging-api/#text
|
32
|
+
# @see Actionable For making the text tappable.
|
33
|
+
# @see Position::Horizontal For `align` property.
|
34
|
+
# @see Position::Vertical For `gravity` property.
|
35
|
+
# @see Position::Margin For `margin` property.
|
36
|
+
# @see Position::Offset For offset properties.
|
37
|
+
# @see Size::Flex For `flex` sizing property.
|
38
|
+
# @see Size::Shared For common `size` keywords (e.g., `:xl`, `:sm`).
|
39
|
+
# @see Size::AdjustMode For `adjust_mode` property.
|
8
40
|
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
|
41
|
+
include Actionable # Enables defining an action for the text.
|
42
|
+
include Position::Horizontal # Adds `align` option.
|
43
|
+
include Position::Vertical # Adds `gravity` option.
|
44
|
+
include Position::Margin # Adds `margin` option.
|
45
|
+
include Position::Offset # Adds offset options.
|
46
|
+
include Size::Flex # Adds `flex` option for sizing within a parent box.
|
47
|
+
include Size::Shared # Adds `size` option (e.g., :sm, :md, :xl).
|
48
|
+
include Size::AdjustMode # Adds `adjust_mode` option.
|
17
49
|
|
50
|
+
# @!attribute [r] text
|
51
|
+
# @return [String] The actual text content to be displayed.
|
52
|
+
# This is a required attribute.
|
18
53
|
attr_reader :text
|
19
54
|
|
55
|
+
# Specifies whether the text should wrap or be truncated if it exceeds
|
56
|
+
# the component's width.
|
57
|
+
# @!method wrap(value)
|
58
|
+
# @param value [Boolean] `true` to enable text wrapping, `false` (default) to disable.
|
59
|
+
# @return [Boolean] The current wrap setting.
|
20
60
|
option :wrap, default: false
|
21
|
-
|
61
|
+
|
62
|
+
# Specifies the spacing between lines of text.
|
63
|
+
# Can be a pixel value (e.g., "10px") or a keyword.
|
64
|
+
# @!method line_spacing(value)
|
65
|
+
# @param value [String, nil] The line spacing value (e.g., `"5px"`).
|
66
|
+
# @return [String, nil] The current line spacing.
|
67
|
+
option :line_spacing, default: nil # API key: lineSpacing
|
68
|
+
|
69
|
+
# Specifies the color of the text.
|
70
|
+
# @!method color(value)
|
71
|
+
# @param value [String, nil] Hexadecimal color code (e.g., `"#RRGGBB"`, `"#RRGGBBAA"`).
|
72
|
+
# @return [String, nil] The current text color.
|
22
73
|
option :color, default: nil
|
23
74
|
|
24
|
-
|
25
|
-
|
75
|
+
# Initializes a new Flex Message Text component.
|
76
|
+
#
|
77
|
+
# @param text_content [String] The text to display. This is required.
|
78
|
+
# @param context [Object, nil] An optional context for the builder.
|
79
|
+
# @param options [Hash] A hash of options to set instance variables
|
80
|
+
# (e.g., `:wrap`, `:color`, `:size`, and options from included modules).
|
81
|
+
# @param block [Proc, nil] An optional block, typically used to define an
|
82
|
+
# {Actionable#action action} for the text.
|
83
|
+
# @raise [ArgumentError] if `text_content` is nil (though the more specific
|
84
|
+
# `RequiredError` is raised in `to_h`).
|
85
|
+
def initialize(text_content, context: nil, **options, &)
|
86
|
+
@text = text_content # The text content is mandatory.
|
26
87
|
|
27
|
-
super(context: context, **options, &)
|
88
|
+
super(context: context, **options, &) # Sets options and evals block (for action).
|
28
89
|
end
|
29
90
|
|
91
|
+
# A convenience DSL method to set the `wrap` property to `true`.
|
92
|
+
#
|
93
|
+
# @example
|
94
|
+
# text_component.text "Long text..."
|
95
|
+
# text_component.wrap! # Enables text wrapping
|
96
|
+
#
|
97
|
+
# @return [true]
|
30
98
|
def wrap!
|
31
|
-
|
99
|
+
wrap(true) # Use the setter generated by `option`
|
32
100
|
end
|
33
101
|
|
34
|
-
def to_h
|
35
|
-
raise RequiredError, "text is required" if text.nil?
|
102
|
+
def to_h
|
103
|
+
raise RequiredError, "text content is required for a text component" if text.nil?
|
104
|
+
|
105
|
+
return to_sdkv2 if context.sdkv2?
|
106
|
+
|
107
|
+
to_api
|
108
|
+
end
|
36
109
|
|
110
|
+
private
|
111
|
+
|
112
|
+
def to_api # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
37
113
|
{
|
38
114
|
type: "text",
|
39
115
|
text: text,
|
40
|
-
wrap: wrap,
|
41
|
-
#
|
42
|
-
|
43
|
-
|
116
|
+
wrap: wrap, # From option
|
117
|
+
color: color, # From option
|
118
|
+
lineSpacing: line_spacing, # From option (maps to API key)
|
119
|
+
# Position::Horizontal & Position::Vertical
|
120
|
+
align: align, # From Position::Horizontal
|
121
|
+
gravity: gravity, # From Position::Vertical
|
44
122
|
# Position::Margin
|
45
123
|
margin: margin,
|
46
124
|
# Position::Offset
|
@@ -51,13 +129,39 @@ module Line
|
|
51
129
|
offsetEnd: offset_end,
|
52
130
|
# Size::Flex
|
53
131
|
flex: flex,
|
54
|
-
# Size::Shared
|
55
|
-
size: size,
|
56
|
-
# Size::AdjustMode
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
132
|
+
# Size::Shared & Size::AdjustMode
|
133
|
+
size: size, # From Size::Shared
|
134
|
+
adjustMode: adjust_mode, # From Size::AdjustMode
|
135
|
+
# Actionable
|
136
|
+
action: action&.to_h # From Actionable module
|
137
|
+
}.compact
|
138
|
+
end
|
139
|
+
|
140
|
+
def to_sdkv2 # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
141
|
+
{
|
142
|
+
type: "text",
|
143
|
+
text: text,
|
144
|
+
wrap: wrap, # From option
|
145
|
+
color: color, # From option
|
146
|
+
line_spacing: line_spacing, # From option (maps to API key)
|
147
|
+
# Position::Horizontal & Position::Vertical
|
148
|
+
align: align, # From Position::Horizontal
|
149
|
+
gravity: gravity, # From Position::Vertical
|
150
|
+
# Position::Margin
|
151
|
+
margin: margin,
|
152
|
+
# Position::Offset
|
153
|
+
position: position,
|
154
|
+
offset_top: offset_top,
|
155
|
+
offset_bottom: offset_bottom,
|
156
|
+
offset_start: offset_start,
|
157
|
+
offset_end: offset_end,
|
158
|
+
# Size::Flex
|
159
|
+
flex: flex,
|
160
|
+
# Size::Shared & Size::AdjustMode
|
161
|
+
size: size, # From Size::Shared
|
162
|
+
adjust_mode: adjust_mode, # From Size::AdjustMode
|
163
|
+
# Actionable
|
164
|
+
action: action&.to_h # From Actionable module
|
61
165
|
}.compact
|
62
166
|
end
|
63
167
|
end
|