line-message-builder 0.8.0 → 0.10.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.release-please-manifest.json +1 -1
  3. data/.rubocop.yml +5 -0
  4. data/CHANGELOG.md +41 -0
  5. data/CLAUDE.md +124 -0
  6. data/CONVENTIONS.md +36 -0
  7. data/README.md +61 -43
  8. data/claudekit.json +11 -0
  9. data/docs/rubrics/rdoc.md +169 -0
  10. data/lib/line/message/builder/actions/message.rb +52 -31
  11. data/lib/line/message/builder/actions/postback.rb +63 -33
  12. data/lib/line/message/builder/actions/uri.rb +139 -0
  13. data/lib/line/message/builder/actions.rb +6 -3
  14. data/lib/line/message/builder/base.rb +92 -67
  15. data/lib/line/message/builder/container.rb +64 -69
  16. data/lib/line/message/builder/context.rb +55 -80
  17. data/lib/line/message/builder/flex/actionable.rb +53 -32
  18. data/lib/line/message/builder/flex/box.rb +366 -79
  19. data/lib/line/message/builder/flex/bubble.rb +78 -51
  20. data/lib/line/message/builder/flex/builder.rb +47 -36
  21. data/lib/line/message/builder/flex/button.rb +96 -48
  22. data/lib/line/message/builder/flex/carousel.rb +57 -29
  23. data/lib/line/message/builder/flex/icon.rb +152 -0
  24. data/lib/line/message/builder/flex/image.rb +103 -42
  25. data/lib/line/message/builder/flex/partial.rb +58 -55
  26. data/lib/line/message/builder/flex/position.rb +187 -100
  27. data/lib/line/message/builder/flex/separator.rb +84 -0
  28. data/lib/line/message/builder/flex/size.rb +67 -47
  29. data/lib/line/message/builder/flex/span.rb +184 -0
  30. data/lib/line/message/builder/flex/text.rb +210 -54
  31. data/lib/line/message/builder/flex.rb +31 -26
  32. data/lib/line/message/builder/quick_reply.rb +174 -4
  33. data/lib/line/message/builder/text.rb +70 -3
  34. data/lib/line/message/builder/version.rb +1 -1
  35. data/lib/line/message/builder.rb +16 -13
  36. data/lib/line/message/rspec/matchers/have_flex_bubble.rb +1 -1
  37. data/lib/line/message/rspec/matchers/have_flex_component.rb +26 -5
  38. data/lib/line/message/rspec/matchers/have_flex_message.rb +1 -1
  39. data/lib/line/message/rspec/matchers/have_flex_separator.rb +20 -0
  40. data/lib/line/message/rspec/matchers/have_quick_reply.rb +1 -1
  41. data/lib/line/message/rspec/matchers/have_text_message.rb +1 -1
  42. data/lib/line/message/rspec/matchers.rb +1 -0
  43. data/llm.txt +367 -45
  44. data/release-please-config.json +3 -1
  45. metadata +12 -3
data/llm.txt CHANGED
@@ -2,6 +2,49 @@
2
2
 
3
3
  This document provides a comprehensive guide on using the Line Message Builder DSL to construct various types of LINE messages.
4
4
 
5
+ ## Project Status
6
+
7
+ **Current State:** Production-ready Ruby gem with comprehensive Flex Message support. Consult the Component Support Status below before using a property — anything not listed is not implemented, and an undeclared option raises.
8
+
9
+ ### Recent Major Updates
10
+ - **Unknown options now raise**: passing an option a component does not declare raises `ValidationError` instead of being silently dropped
11
+ - **URI action**: link a component to a web page without a webhook
12
+ - **Icon component**: icon-and-text pairs inside a baseline box
13
+ - **Text styling**: `weight`, `max_lines`, `style`, `decoration`, `scaling`
14
+ - **Box appearance**: background colour, border, corner radius and linear gradients
15
+ - **Button `color` and `scaling`**; Button no longer accepts `padding` (LINE defines none)
16
+ - **Image `background_color` and `animated`**; **Span `style`**; **Separator `margin` and `color`**
17
+
18
+ ### Component Support Status
19
+
20
+ Anything not listed as supported below is not implemented. There is no raw-hash
21
+ escape hatch — an undeclared option raises.
22
+
23
+ - **Text Messages**: supported, with Quick Reply
24
+ - **Flex Containers**: Bubble, Carousel
25
+ - **Flex Components**: Box, Text, Span, Button, Image, Icon, Separator
26
+ - **Actions**: `message`, `postback`, `uri`
27
+ - **Quick Replies**: supported (`message`, `postback`, `uri`)
28
+ - **Partials**: supported
29
+ - **RSpec Matchers**: text, flex message, bubble, box, text, button, image, icon, span, separator, quick reply
30
+
31
+ **Not supported yet**: the `video` component; `Bubble#direction` and a bubble-level
32
+ action; the Datetime Picker, Camera, Camera Roll, Location, Rich Menu Switch and
33
+ Clipboard actions.
34
+
35
+ **Deliberately not supported**: the `filler` component — LINE has deprecated it.
36
+ Use the spacing properties of each component instead.
37
+
38
+ ## Installation and Setup
39
+
40
+ ```bash
41
+ # Add to Gemfile
42
+ bundle add line-message-builder
43
+
44
+ # Or install directly
45
+ gem install line-message-builder
46
+ ```
47
+
5
48
  ## Basic Usage
6
49
 
7
50
  To start building messages, use the `Line::Message::Builder.with` method. This method accepts an optional context object and a block where you define your messages.
@@ -15,9 +58,72 @@ end
15
58
 
16
59
  # The `messages` variable will now hold an array of LINE message objects.
17
60
  # You can convert them to JSON for sending to the LINE API:
18
- # json_output = messages.to_json
61
+ json_output = messages.to_json
62
+
63
+ # For LINE Bot SDK v2 compatibility:
64
+ messages = Line::Message::Builder.with(mode: :sdkv2) do
65
+ text "Hello World!"
66
+ end
67
+ ```
68
+
69
+ ### Coding Style
70
+
71
+ When using the `Line::Message::Builder` DSL, following is recommended:
72
+
73
+ ```ruby
74
+ Line::Message::Builder.with do
75
+ flex alt_text: "Hello, World!" do
76
+ bubble do
77
+ header do
78
+ text "Welcome to LINE Messaging API"
79
+ end
80
+ body do
81
+ text "This is a sample message."
82
+ end
83
+ end
84
+ end
85
+ end
86
+ ```
87
+
88
+ DO NOT use `do |container|` syntax as following:
89
+
90
+ ```ruby
91
+ Line::Message::Builder.with do |builder|
92
+ builder.flex alt_text: "Hello, World!" do
93
+ builder.bubble do
94
+ builder.header do
95
+ builder.text "Welcome to LINE Messaging API"
96
+ end
97
+ builder.body do
98
+ builder.text "This is a sample message."
99
+ end
100
+ end
101
+ end
102
+ end
19
103
  ```
20
104
 
105
+ ### Unknown Options Raise
106
+
107
+ Every component accepts only the options it declares. Passing anything else
108
+ raises `Line::Message::Builder::ValidationError`, naming the offending option and
109
+ listing the ones that component accepts:
110
+
111
+ ```ruby
112
+ text "Title", colour: "#FF0000"
113
+ # => Line::Message::Builder::ValidationError:
114
+ # Unknown option: colour for Line::Message::Builder::Flex::Text.
115
+ # Allowed options are: wrap, line_spacing, color, weight, max_lines, ...
116
+ ```
117
+
118
+ This is deliberate. A misspelled or unsupported property used to be dropped in
119
+ silence, producing a message that was missing the styling that was asked for
120
+ while every check downstream reported success. Read the error, correct the
121
+ option name against the list it prints, and rebuild.
122
+
123
+ Two consequences worth remembering:
124
+ - There is no `action:` option on any component. Declare actions inside the block.
125
+ - A `button` has no `label` option. The label belongs to its action.
126
+
21
127
  ### Context
22
128
 
23
129
  The builder can accept a context object. Methods called within the builder block will first attempt to resolve against this context object. This allows for dynamic message content based on your application's data.
@@ -79,40 +185,69 @@ You can also include emojis in text messages. A `quick_reply` can be attached (s
79
185
 
80
186
  Actions define what happens when a user interacts with a button or a tappable area in a message. They are used in Flex Message components (like buttons, or even entire boxes/images) and Quick Reply buttons.
81
187
 
82
- The primary action types defined by helper methods are:
188
+ **An action is declared inside the component's block, not passed as an `action:` keyword.** No component accepts an `action:` option; writing one raises `ValidationError`.
189
+
190
+ Three action types are supported: `message`, `postback` and `uri`.
83
191
 
84
192
  ### Message Action
85
193
  Sends a text message from the user's perspective.
86
- - `label`: (String, Required for Flex Buttons, Optional for Quick Reply if `text` is short) The text displayed on the button.
87
- - `text`: (String, Required) The text message to be sent when the button is tapped.
194
+ - First argument: (String, Required) The text message to be sent when tapped.
195
+ - `label`: (String, Optional) The text displayed on the button.
88
196
 
89
197
  ```ruby
90
- # Example in a Flex Button (action is a required parameter for button)
91
- button label: "Say Hello", action: message(label: "Say Hello", text: "Hello there!")
198
+ # In a Flex component declared inside the block
199
+ button do
200
+ message "Hello there!", label: "Say Hello"
201
+ end
92
202
 
93
- # Example in a Quick Reply
94
- # For quick reply, the first argument to `message` is the text to be sent.
203
+ # In a Quick Reply — label is required here
95
204
  quick_reply do
96
- message "Yes, please!", label: "Yes" # label is optional if text is short
205
+ message "Yes, please!", label: "Yes"
97
206
  end
98
207
  ```
99
208
 
100
209
  ### Postback Action
101
- Sends a postback event to your bot's webhook. This is useful for triggering backend logic without displaying a message in the chat.
102
- - `label`: (String, Required for Flex Buttons, Optional for Quick Reply) The text displayed on the button.
103
- - `data`: (String, Required) The data string sent in the postback event to your webhook.
104
- - `display_text`: (String, Optional) Text displayed in the chat as if the user had typed it after tapping the button.
210
+ Sends a postback event to your bot's webhook. Useful for triggering backend logic without displaying a message in the chat. A postback whose event your webhook does not handle is a dead button.
211
+ - First argument: (String, Required) The data string sent in the postback event.
212
+ - `label`: (String, Optional) The text displayed on the button.
213
+ - `display_text`: (String, Optional) Text displayed in the chat as if the user had typed it.
105
214
 
106
215
  ```ruby
107
- # Example in a Flex Button
108
- button label: "Add to Cart", action: postback(label: "Add to Cart", data: "action=add_item&item_id=101", display_text: "Added to cart!")
216
+ # In a Flex component
217
+ button do
218
+ postback "action=add_item&item_id=101", label: "Add to Cart", display_text: "Added to cart!"
219
+ end
109
220
 
110
- # Example in a Quick Reply
221
+ # In a Quick Reply
111
222
  quick_reply do
112
223
  postback "action=view_profile", label: "View Profile"
113
224
  end
114
225
  ```
115
- Other action types like URI, Datetime Picker, Camera, Camera Roll, Location can also be defined by passing a hash that conforms to the LINE API's action object structure directly to the `action` parameter of a component (e.g., `action: { type: :uri, label: "Visit Website", uri: "https://example.com" }`).
226
+
227
+ ### URI Action
228
+ Opens a URI when tapped. Needs no webhook handling, so this is the action to use for linking a card to a web page.
229
+ - First argument: (String, Required) The URI to open. Schemes `http`, `https`, `line`, `tel`. Max 1000 characters.
230
+ - `label`: (String, Optional in Flex, Required in Quick Reply) The text displayed on the button.
231
+ - `alt_uri_desktop`: (String, Optional) A different URI opened on LINE for macOS and Windows. Maps to `altUri.desktop`. Has no effect in a Quick Reply.
232
+
233
+ ```ruby
234
+ # In a Flex component
235
+ button style: :primary do
236
+ uri "https://example.com/event", label: "View event"
237
+ end
238
+
239
+ # Opening a different page on desktop
240
+ button do
241
+ uri "https://example.com/mobile", label: "Open", alt_uri_desktop: "https://example.com/desktop"
242
+ end
243
+
244
+ # In a Quick Reply
245
+ quick_reply do
246
+ uri "tel:+81312345678", label: "Call us"
247
+ end
248
+ ```
249
+
250
+ The remaining LINE action types (Datetime Picker, Camera, Camera Roll, Location, Rich Menu Switch, Clipboard) are **not yet supported**. There is no raw-hash escape hatch.
116
251
 
117
252
  ## Quick Replies
118
253
 
@@ -206,7 +341,9 @@ flex alt_text: "Recipe Card" do
206
341
  end
207
342
  end
208
343
  footer do
209
- button label: "View Recipe", action: { type: :uri, label: "View Recipe", uri: "http://example.com/recipe" }
344
+ button style: :primary do
345
+ uri "https://example.com/recipe", label: "View Recipe"
346
+ end
210
347
  end
211
348
  end
212
349
  end
@@ -232,13 +369,29 @@ A `box` arranges other components.
232
369
  - Sizing:
233
370
  - `width`, `max_width`, `height`, `max_height`: (String, Optional) Pixel or percentage strings (e.g., `'100px'`, `'50%'`).
234
371
  - `flex`: (Integer, Optional) Flex factor determining how much space this box takes relative to siblings.
235
- - `action`: (Action Object, Optional) Makes the entire box tappable. See Actions section.
372
+ - Appearance:
373
+ - `background_color`: (String, Optional) Hex colour, alpha channel allowed (e.g., `'#RRGGBBAA'`).
374
+ - `border_color`: (String, Optional) Hex colour of the border.
375
+ - `border_width`: (Symbol or String, Optional) `:none`, `:light`, `:normal`, `:medium`, `:"semi-bold"`, `:bold`, or a pixel value.
376
+ - `corner_radius`: (Symbol or String, Optional) `:none`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`, or a pixel value.
377
+ - `background_angle`, `background_start_color`, `background_end_color`: (String, Optional) A linear gradient. Setting any one of them makes all three required, otherwise a `RequiredError` is raised.
378
+ - `background_center_color`, `background_center_position`: (String, Optional) An intermediate colour stop, e.g. `'#00FF00'` at `'30%'`.
379
+ - Tappable: declare an action inside the block to make the whole box tappable.
236
380
 
237
381
  ```ruby
238
- box layout: :vertical, spacing: :md, padding_all: :lg, action: message(text: "Box tapped!") do
382
+ box layout: :vertical, spacing: :md, padding_all: :lg do
383
+ message "Box tapped!", label: "Open"
239
384
  text "Item 1"
240
385
  text "Item 2"
241
386
  end
387
+
388
+ # A rounded card with a gradient background
389
+ box layout: :vertical, corner_radius: :lg, padding_all: :lg,
390
+ background_angle: "90deg",
391
+ background_start_color: "#3F51B5",
392
+ background_end_color: "#2196F3" do
393
+ text "Gradient card", color: "#FFFFFF", weight: :bold
394
+ end
242
395
  ```
243
396
 
244
397
  #### Text Component
@@ -248,35 +401,65 @@ Displays text.
248
401
  - `wrap`: (Boolean, Optional) `true` to allow text to wrap. Default `false`.
249
402
  - `line_spacing`: (String, Optional) Spacing between lines, e.g., `'4px'`, `'1.5em'`.
250
403
  - `color`: (String, Optional) Hex color code (e.g., `'#RRGGBB'`, `'#RRGGBBAA'`).
404
+ - `weight`: (Symbol, Optional) `:regular` (default) or `:bold`.
405
+ - `style`: (Symbol, Optional) `:normal` (default) or `:italic`.
406
+ - `decoration`: (Symbol, Optional) `:none` (default), `:underline` or `:"line-through"`. A decoration set here cannot be overridden by a nested span.
407
+ - `max_lines`: (Integer, Optional) Truncate after this many lines with an ellipsis. `0` (default) shows the whole text.
408
+ - `scaling`: (Boolean, Optional) `true` to follow the reader's LINE font size setting. Nested spans scale too.
251
409
  - Layout:
252
410
  - `align`: (Symbol, Optional) Horizontal alignment of the text. Valid values: `:start`, `:center`, `:end`.
253
411
  - `gravity`: (Symbol, Optional) Vertical alignment of the text within its allocated space. Valid values: `:top`, `:center`, `:bottom`.
254
412
  - `margin`: (Symbol or String, Optional) Margin around the text component. Valid keywords: `:none`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`. Also accepts pixel values (e.g., `'10px'`).
255
413
  - Sizing:
256
- - `size`: (Symbol or String, Optional) Font size. Valid keywords: `:xxs`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`, `:3xl`, `:4xl`, `:5xl`. Also accepts pixel values (e.g., `'16px'`).
257
- - `weight`: (Symbol, Optional) Font weight. Valid values: `:regular`, `:bold`.
414
+ - `size`: (Symbol or String, Optional) Font size. Accepted keywords: `:none`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`, or a pixel value (e.g., `'16px'`). Note: LINE also defines `:xxs` and `:3xl`–`:5xl`, but this gem does not accept them yet.
258
415
  - `flex`: (Integer, Optional) Flex factor.
259
416
  - `adjust_mode`: (Symbol, Optional) How text adjusts when it overflows. Valid value: `:shrink_to_fit` (reduces font size).
260
- - `action`: (Action Object, Optional) Makes the text tappable.
417
+ - Tappable: declare an action inside the block.
418
+ - `span`: Within a Text component, you can add Span components to style parts of the text differently.
261
419
 
262
420
  ```ruby
263
- text "Special Offer!", size: :xl, weight: :bold, color: "#FF0000", align: :center, action: postback(data: "offer_details")
421
+ # Simple text component
422
+ text "Special Offer!", size: :xl, weight: :bold, color: "#FF0000", align: :center
423
+
424
+ # Truncating a long body
425
+ text article_body, wrap: true, max_lines: 3
426
+
427
+ # Making the text tappable
428
+ text "See details" do
429
+ postback "offer_details", label: "Details"
430
+ end
431
+
432
+ # Text with spans for different styling of segments
433
+ text "Welcome to our service:" do
434
+ span "Special ", color: "#FF0000"
435
+ span "Offer", weight: :bold
436
+ span "!", decoration: :underline
437
+ end
264
438
  ```
265
439
 
266
440
  #### Button Component
267
- An actionable button.
268
- - `action`: (Action Object, **Required**) Defines the action performed on tap. See Actions section.
441
+ An actionable button. **The action is declared inside the block and is required.** The button's visible text comes from the action's `label`; a button has no `label` option of its own.
269
442
  - `style`: (Symbol, Optional) Visual style of the button. Valid values: `:primary`, `:secondary`, `:link`. Default is `:link`.
443
+ - `color`: (String, Optional) Hex colour. Text colour when `style` is `:link`, background colour when `:primary` or `:secondary`.
270
444
  - `height`: (Symbol, Optional) Height of the button. Valid values: `:sm`, `:md`. Default is `:md`.
445
+ - `scaling`: (Boolean, Optional) `true` to follow the reader's LINE font size setting.
271
446
  - Layout:
272
447
  - `gravity`: (Symbol, Optional) Vertical alignment if the box containing it has extra space. Valid values: `:top`, `:center`, `:bottom`.
273
448
  - `margin`: (Symbol or String, Optional) Margin around the button. Valid keywords: `:none`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`. Also accepts pixel values (e.g., `'10px'`).
274
449
  - Sizing:
275
450
  - `flex`: (Integer, Optional) Flex factor.
276
451
  - `adjust_mode`: (Symbol, Optional) How the button adjusts its content. Valid value: `:shrink_to_fit`.
452
+ - **No padding**: LINE defines no padding properties for a button. Pad the surrounding box instead.
277
453
 
278
454
  ```ruby
279
- button label: "Confirm", style: :primary, height: :md, action: postback(data: "confirm_order", label: "Confirm")
455
+ button style: :primary, color: "#1DB446" do
456
+ postback "action=confirm_order", label: "Confirm"
457
+ end
458
+
459
+ # Linking to a web page
460
+ button style: :link do
461
+ uri "https://example.com/event", label: "View event"
462
+ end
280
463
  ```
281
464
 
282
465
  #### Image Component
@@ -285,6 +468,8 @@ Displays an image.
285
468
  - Styling:
286
469
  - `aspect_ratio`: (String, Optional) Aspect ratio as `"width:height"`, e.g., `"1:1"`, `"16:9"`, `"4:3"`.
287
470
  - `aspect_mode`: (Symbol, Optional) How the image fits the `aspect_ratio`. Valid values: `:cover` (default, crops to fill) or `:fit` (fits within, may letterbox).
471
+ - `background_color`: (String, Optional) Hex colour shown behind the image.
472
+ - `animated`: (Boolean, Optional) `true` plays an APNG. At most 10 animated images per message; frames over 300 KB are not played.
288
473
  - Layout:
289
474
  - `align`: (Symbol, Optional) Horizontal alignment of the image. Valid values: `:start`, `:center`, `:end`.
290
475
  - `gravity`: (Symbol, Optional) Vertical alignment of the image. Valid values: `:top`, `:center`, `:bottom`.
@@ -292,29 +477,95 @@ Displays an image.
292
477
  - Sizing:
293
478
  - `size`: (Symbol or String, Optional) Size of the image. Valid keywords: `:xxs`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`, `:3xl`, `:4xl`, `:5xl`, `:full`. Also accepts pixel or percentage strings (e.g. `'100px'`, `'50%'`).
294
479
  - `flex`: (Integer, Optional) Flex factor.
295
- - `action`: (Action Object, Optional) Makes the image tappable.
480
+ - Tappable: declare an action inside the block.
296
481
 
297
482
  ```ruby
298
- image "https://example.com/product_image.png", size: :full, aspect_ratio: "1:1", aspect_mode: :cover, action: message(text: "View product")
483
+ image "https://example.com/product_image.png", size: :full, aspect_ratio: "1:1", aspect_mode: :cover
484
+
485
+ # Making the image tappable
486
+ image "https://example.com/product_image.png", size: :full do
487
+ uri "https://example.com/product", label: "View product"
488
+ end
489
+ ```
490
+
491
+ #### Icon Component
492
+ An `icon` renders a small graphic that decorates the text beside it — rating stars, labelled metadata rows. **It can only be used inside a box whose `layout` is `:baseline`.** An icon takes no action and no `flex`.
493
+
494
+ - `url`: (String, Required) URL of the icon image (HTTPS).
495
+ - `size`: (Symbol or String, Optional) Icon width. Same keywords as text size. Default `:md`.
496
+ - `aspect_ratio`: (String, Optional) `"width:height"`, default `"1:1"`.
497
+ - `scaling`: (Boolean, Optional) `true` to follow the reader's LINE font size setting.
498
+ - `margin`, `position`, `offset_top`, `offset_bottom`, `offset_start`, `offset_end`: as for other components.
499
+
500
+ ```ruby
501
+ box layout: :baseline do
502
+ icon "https://example.com/star_on.png", size: :sm
503
+ icon "https://example.com/star_on.png", size: :sm
504
+ icon "https://example.com/star_off.png", size: :sm
505
+ text "3.0", size: :sm, margin: :md
506
+ end
299
507
  ```
300
508
 
301
- #### Separators and Spacers
509
+ #### Span Component
510
+ Spans are used within a Text component to apply different styling to specific portions of text. They cannot be used directly within boxes or other containers; they must be placed inside a Text component block.
302
511
 
303
- The LINE Flex Message specification includes `separator` and `spacer` component types. This DSL does not provide explicit `separator()` or `spacer()` methods. Instead:
512
+ - `text`: (String, Required) The text content of the span.
513
+ - Styling:
514
+ - `color`: (String, Optional) Hex color code (e.g., `'#RRGGBB'`, `'#RRGGBBAA'`).
515
+ - `size`: (Symbol or String, Optional) Font size. Accepted keywords: `:none`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`, or a pixel value (e.g., `'16px'`).
516
+ - `weight`: (Symbol, Optional) Font weight. Valid values: `:regular`, `:bold`.
517
+ - `style`: (Symbol, Optional) `:normal` (default) or `:italic`.
518
+ - `decoration`: (Symbol, Optional) Text decoration. Valid values: `:none`, `:underline`, `:"line-through"`. Ignored when the surrounding text sets its own `decoration`.
519
+
520
+ Spans also support helper methods to easily apply common styles:
521
+ - `bold!`: Sets the weight to `:bold`.
522
+ - `italic!`: Sets the style to `:italic`.
523
+ - `underline!`: Sets the decoration to `:underline`.
524
+ - `line_through!`: Sets the decoration to `:line-through`.
304
525
 
305
- - **Separators**: Achieve a visual line by using a `box` component styled to look like a separator. Set its `height` (for horizontal line) or `width` (for vertical line) to a small value (e.g., `"1px"`) and give it a `background_color`.
306
- ```ruby
307
- # Example of a horizontal separator
308
- box layout: :vertical, padding_all: :md do # Outer box for content
309
- text "Content above separator"
310
- box height: "1px", background_color: "#CCCCCC", margin: :md # This is the separator
311
- text "Content below separator"
526
+ ```ruby
527
+ # Basic span usage
528
+ text "This message contains:" do
529
+ span "colored", color: "#FF0000"
530
+ span " and "
531
+ span "bold", weight: :bold
532
+ span " text."
533
+ end
534
+
535
+ # Using helper methods
536
+ text "This message has:" do
537
+ span "underlined" do
538
+ underline!
539
+ end
540
+ span " and "
541
+ span "bold" do
542
+ bold!
312
543
  end
313
- ```
314
- - **Spacers**: Create space between components using:
315
- - `spacing` property on a parent `box` container.
316
- - `margin` property on individual components (e.g., `text "Hello", margin: :xl`).
317
- - An empty `box` with a defined `flex` value or `height`/`width` (e.g., `box height: "30px"`).
544
+ span " text."
545
+ end
546
+ ```
547
+
548
+ #### Separator Component
549
+ A `separator` draws a horizontal line to create visual separation between components. LINE defines exactly three properties for it; nothing else is accepted.
550
+
551
+ - `margin`: (Symbol or String, Optional) Space before the line. Keywords `:none`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`, or a pixel value.
552
+ - `color`: (String, Optional) Hex colour of the line.
553
+
554
+ ```ruby
555
+ box layout: :vertical do
556
+ text "Section 1"
557
+ separator margin: :xl, color: "#F0F0F0"
558
+ text "Section 2"
559
+ end
560
+ ```
561
+
562
+ #### Spacers
563
+ Create space between components using:
564
+ - `spacing` property on a parent `box` container.
565
+ - `margin` property on individual components (e.g., `text "Hello", margin: :xl`).
566
+ - An empty `box` with a defined `flex` value or `height`/`width` (e.g., `box height: "30px"`).
567
+
568
+ Do not reach for a `filler` component — LINE has deprecated it and this gem does not provide one.
318
569
 
319
570
  ### Flex Message Partials
320
571
 
@@ -329,7 +580,9 @@ Partials allow you to define reusable segments of Flex Message layouts. This is
329
580
  # which are made available from the `assigns` hash passed to `partial!`.
330
581
  box layout: :vertical do
331
582
  text title_text, weight: :bold # 'title_text' from assigns
332
- button label: button_label, action: message(text: "Action for #{title_text}") # 'button_label' from assigns
583
+ button do # 'button_label' from assigns
584
+ message "Action for #{title_text}", label: button_label
585
+ end
333
586
  end
334
587
  end
335
588
  end
@@ -353,4 +606,73 @@ Partials allow you to define reusable segments of Flex Message layouts. This is
353
606
  ```
354
607
  Inside the partial, variables passed via `partial!` (e.g., `title_text`, `button_label`) are accessible as methods.
355
608
 
356
- This comprehensive guide should help in effectively using the Line Message Builder DSL. For very specific or advanced features, always refer to the official LINE Messaging API documentation for Flex Messages.
609
+ ## RSpec Testing Support
610
+
611
+ The gem includes comprehensive RSpec matchers for testing LINE messages:
612
+
613
+ ```ruby
614
+ # Include in spec_helper.rb or rails_helper.rb
615
+ require "line/message/rspec"
616
+
617
+ # Configure in RSpec
618
+ RSpec.configure do |config|
619
+ config.include Line::Message::RSpec::Matchers
620
+ end
621
+
622
+ # Available matchers
623
+ describe "LINE Messages" do
624
+ let(:builder) do
625
+ Line::Message::Builder.with do
626
+ text "Hello World!"
627
+ flex alt_text: "Greeting" do
628
+ bubble do
629
+ body { text "Welcome!" }
630
+ end
631
+ end
632
+ end
633
+ end
634
+
635
+ subject { builder.build }
636
+
637
+ it { is_expected.to have_line_text_message("Hello World!") }
638
+ it { is_expected.to have_line_flex_message }
639
+ it { is_expected.to have_line_flex_bubble }
640
+ it { is_expected.to have_line_flex_text("Welcome!") }
641
+ it { is_expected.to have_line_flex_separator }
642
+ it { is_expected.to have_line_flex_span }
643
+ it { is_expected.to have_line_flex_icon("https://example.com/star.png") }
644
+
645
+ # Works with webmock for API testing
646
+ it "sends correct message" do
647
+ expect(a_request(:post, "https://api.line.me/v2/bot/message/reply")
648
+ .with(body: hash_including({
649
+ messages: have_line_text_message(/Hello World!/)
650
+ }))
651
+ ).to have_been_made.once
652
+ end
653
+ end
654
+ ```
655
+
656
+ ## Development and Testing
657
+
658
+ ```bash
659
+ # Run tests
660
+ bundle exec rspec
661
+
662
+ # Run specific test
663
+ bundle exec rspec spec/line/message/builder_spec.rb
664
+
665
+ # Run linter
666
+ bundle exec rubocop
667
+
668
+ # Run both tests and linter
669
+ bundle exec rake
670
+
671
+ # Interactive console
672
+ bin/console
673
+
674
+ # Build and install locally
675
+ bundle exec rake install
676
+ ```
677
+
678
+ This comprehensive guide should help in effectively using the Line Message Builder DSL. The gem is actively maintained and production-ready for building complex LINE messaging experiences. For very specific or advanced features, always refer to the official LINE Messaging API documentation for Flex Messages.
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "release-type": "ruby",
3
+ "bump-minor-pre-major": true,
3
4
  "packages": {
4
5
  ".":{
5
6
  "component": "line-message-builder",
6
7
  "include-component-in-tag": false,
7
- "release-type": "ruby"
8
+ "release-type": "ruby",
9
+ "bump-minor-pre-major": true
8
10
  }
9
11
  }
10
12
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: line-message-builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aotokitsuruya
@@ -14,21 +14,26 @@ email:
14
14
  - contact@aotoki.me
15
15
  executables: []
16
16
  extensions: []
17
- extra_rdoc_files: []
17
+ extra_rdoc_files:
18
+ - README.md
18
19
  files:
19
20
  - ".document"
20
21
  - ".release-please-manifest.json"
21
22
  - ".rspec"
22
23
  - ".rubocop.yml"
23
24
  - CHANGELOG.md
25
+ - CLAUDE.md
24
26
  - CONVENTIONS.md
25
27
  - LICENSE.txt
26
28
  - README.md
27
29
  - Rakefile
30
+ - claudekit.json
31
+ - docs/rubrics/rdoc.md
28
32
  - lib/line/message/builder.rb
29
33
  - lib/line/message/builder/actions.rb
30
34
  - lib/line/message/builder/actions/message.rb
31
35
  - lib/line/message/builder/actions/postback.rb
36
+ - lib/line/message/builder/actions/uri.rb
32
37
  - lib/line/message/builder/base.rb
33
38
  - lib/line/message/builder/container.rb
34
39
  - lib/line/message/builder/context.rb
@@ -39,10 +44,13 @@ files:
39
44
  - lib/line/message/builder/flex/builder.rb
40
45
  - lib/line/message/builder/flex/button.rb
41
46
  - lib/line/message/builder/flex/carousel.rb
47
+ - lib/line/message/builder/flex/icon.rb
42
48
  - lib/line/message/builder/flex/image.rb
43
49
  - lib/line/message/builder/flex/partial.rb
44
50
  - lib/line/message/builder/flex/position.rb
51
+ - lib/line/message/builder/flex/separator.rb
45
52
  - lib/line/message/builder/flex/size.rb
53
+ - lib/line/message/builder/flex/span.rb
46
54
  - lib/line/message/builder/flex/text.rb
47
55
  - lib/line/message/builder/quick_reply.rb
48
56
  - lib/line/message/builder/text.rb
@@ -55,6 +63,7 @@ files:
55
63
  - lib/line/message/rspec/matchers/have_flex_bubble.rb
56
64
  - lib/line/message/rspec/matchers/have_flex_component.rb
57
65
  - lib/line/message/rspec/matchers/have_flex_message.rb
66
+ - lib/line/message/rspec/matchers/have_flex_separator.rb
58
67
  - lib/line/message/rspec/matchers/have_quick_reply.rb
59
68
  - lib/line/message/rspec/matchers/have_text_message.rb
60
69
  - lib/line/message/rspec/matchers/utils.rb
@@ -83,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
92
  - !ruby/object:Gem::Version
84
93
  version: '0'
85
94
  requirements: []
86
- rubygems_version: 3.6.7
95
+ rubygems_version: 4.0.16
87
96
  specification_version: 4
88
97
  summary: The LINE Messaging API message builder.
89
98
  test_files: []