jekyll-webawesome 0.5.3 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 229fd8aa9734c6c6c21684d05420d80db94b6b5a271f1dc2d8b901773bc61d3a
4
- data.tar.gz: 373f57b7afbcfe0cccc2857f20987d91c1433768f3d0257773da9d7b3018f7f6
3
+ metadata.gz: 006d303b4b8226fc4f479131a04650cdc071ca37447710f938241cb58e1bde2d
4
+ data.tar.gz: b07247507381997b47cfe8e15d1f0038f4b0845329d38de3fe16463d9ad641ca
5
5
  SHA512:
6
- metadata.gz: 4f76a3acdd6417715ed2a928a94705f99b402a843f2cfa74b30ab4b0f9b632fe90182fac3d50aa18780d98ce260e6c7de460a5b3dd565cc45ea534e89aaaaa4d
7
- data.tar.gz: d68c37818e5ae0a20f9ff236914110f163bc775374dde1c886baa210231c1a50596aaabd1ae6357c4bdbe3667385678a669a22b9ef04c72a1273135566187797
6
+ metadata.gz: e11fdc51fb7a9fa64146067e1d0e8c6e567b66e0aaf3318643c5f30a55adbf6c3cf0e814a066c327bfabe2c6bba437f41fb8f10b608e6a583b3796618ca8f0f6
7
+ data.tar.gz: a62e77aa3a531e34d6a6e850030bf6ec12cd2e416c1acb99aa83ddcd0cb2d47e5ee5073e929b0a81005caa48f015ee40a639494e635cf53615bd3d3d110322db
data/CHANGELOG.md CHANGED
@@ -8,6 +8,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
8
8
 
9
9
  - Placeholder
10
10
 
11
+ ## [0.6.0] - 2025-10-22
12
+
13
+ - Support for wa-carousel component
14
+
15
+ ## [0.5.4] - 2025-10-20
16
+
17
+ - Support for default width for the image_dialog like
18
+
19
+ ```yaml
20
+ webawesome:
21
+ image_dialog:
22
+ enabled: true
23
+ default_width: 90vh
24
+ ```
25
+
11
26
  ## [0.5.3] - 2025-10-20
12
27
 
13
28
  - Always have a header with X button on the dialogs
data/README.md CHANGED
@@ -16,6 +16,7 @@ This plugin focuses on the most commonly used Web Awesome components for Jekyll
16
16
  | **Button** | `%%%variant` | `:::wa-button variant` | `<wa-button variant="brand" href="url">text</wa-button>` or `<wa-button variant="brand">text</wa-button>` |
17
17
  | **Callouts** | `:::info` | `:::wa-callout info` | `<wa-callout variant="brand"><wa-icon name="circle-info"></wa-icon>content</wa-callout>` |
18
18
  | **Card** | `===` | `:::wa-card` | `<wa-card>content</wa-card>` |
19
+ | **Carousel** | `~~~~~~` | `:::wa-carousel` | `<wa-carousel>` with carousel items |
19
20
  | **Comparison** | `\|\|\|` or `\|\|\|25` | `:::wa-comparison` or `:::wa-comparison 25` | `<wa-comparison>` with before/after slots |
20
21
  | **Copy Button** | `<<<` | `:::wa-copy-button` | `<wa-copy-button value="content">content</wa-copy-button>` |
21
22
  | **Details** | `^^^appearance? icon-placement?` | `:::wa-details appearance? icon-placement?` | `<wa-details appearance="..." icon-placement="...">content</wa-details>` |
@@ -69,7 +70,13 @@ webawesome:
69
70
  transform_documents: true # Transform documents (like blog posts in _posts)
70
71
 
71
72
  # Enable automatic image-to-dialog transformation (default: false)
73
+ # Can be a simple boolean
72
74
  image_dialog: true # Makes all images clickable and open in dialogs
75
+
76
+ # Or a hash with options for more control
77
+ image_dialog:
78
+ enabled: true # Enable the feature
79
+ default_width: 90vh # Default width for dialogs (e.g., 90vh, 80%, 1200px)
73
80
  ```
74
81
 
75
82
  And then execute:
@@ -264,6 +271,207 @@ This card uses the accent appearance for emphasis.
264
271
 
265
272
  ![Cards component example](readme_screenshots/cards.png)
266
273
 
274
+ ### Carousel
275
+
276
+ Create carousels (image sliders/content rotators) using the `~~~~~~` syntax:
277
+
278
+ ```markdown
279
+ ~~~~~~
280
+ ~~~
281
+ ![Mountain landscape](mountain.jpg)
282
+ Beautiful mountain scenery
283
+ ~~~
284
+ ~~~
285
+ ![Ocean view](ocean.jpg)
286
+ Peaceful ocean waves
287
+ ~~~
288
+ ~~~
289
+ ![Forest path](forest.jpg)
290
+ Walking through the woods
291
+ ~~~
292
+ ~~~~~~
293
+ ```
294
+
295
+ #### Multiple Slides Per View
296
+
297
+ Show multiple slides at once by specifying the number:
298
+
299
+ ```markdown
300
+ ~~~~~~3
301
+ ~~~
302
+ Product 1 content
303
+ ~~~
304
+ ~~~
305
+ Product 2 content
306
+ ~~~
307
+ ~~~
308
+ Product 3 content
309
+ ~~~
310
+ ~~~
311
+ Product 4 content
312
+ ~~~
313
+ ~~~~~~
314
+ ```
315
+
316
+ #### Navigation and Pagination
317
+
318
+ Add navigation arrows and pagination dots with keywords:
319
+
320
+ ```markdown
321
+ ~~~~~~navigation pagination
322
+ ~~~
323
+ First slide
324
+ ~~~
325
+ ~~~
326
+ Second slide
327
+ ~~~
328
+ ~~~
329
+ Third slide
330
+ ~~~
331
+ ~~~~~~
332
+ ```
333
+
334
+ #### Slides Per Move
335
+
336
+ Control how many slides advance at a time (first number is slides-per-page, second is slides-per-move):
337
+
338
+ ```markdown
339
+ ~~~~~~3 2 navigation
340
+ ~~~
341
+ Slide 1
342
+ ~~~
343
+ ~~~
344
+ Slide 2
345
+ ~~~
346
+ ~~~
347
+ Slide 3
348
+ ~~~
349
+ ~~~
350
+ Slide 4
351
+ ~~~
352
+ ~~~
353
+ Slide 5
354
+ ~~~
355
+ ~~~~~~
356
+ ```
357
+
358
+ This shows 3 slides at a time and moves 2 slides when navigating.
359
+
360
+ #### Looping
361
+
362
+ Enable continuous looping with the `loop` keyword:
363
+
364
+ ```markdown
365
+ ~~~~~~loop navigation
366
+ ~~~
367
+ Slide 1
368
+ ~~~
369
+ ~~~
370
+ Slide 2
371
+ ~~~
372
+ ~~~
373
+ Slide 3
374
+ ~~~
375
+ ~~~~~~
376
+ ```
377
+
378
+ #### Scroll Hint
379
+
380
+ Add padding to show adjacent slides as a hint using the `scroll-hint` CSS property:
381
+
382
+ ```markdown
383
+ ~~~~~~scroll-hint:3rem navigation
384
+ ~~~
385
+ ![Photo 1](photo1.jpg)
386
+ ~~~
387
+ ~~~
388
+ ![Photo 2](photo2.jpg)
389
+ ~~~
390
+ ~~~
391
+ ![Photo 3](photo3.jpg)
392
+ ~~~
393
+ ~~~~~~
394
+ ```
395
+
396
+ #### Advanced Options
397
+
398
+ Combine multiple parameters for full control:
399
+
400
+ ```markdown
401
+ ~~~~~~3 2 loop navigation pagination scroll-hint:2rem
402
+ ~~~
403
+ ![Product 1](prod1.jpg)
404
+
405
+ # Feature One
406
+
407
+ Description here
408
+ ~~~
409
+ ~~~
410
+ ![Product 2](prod2.jpg)
411
+
412
+ # Feature Two
413
+
414
+ More details
415
+ ~~~
416
+ ~~~
417
+ ![Product 3](prod3.jpg)
418
+
419
+ # Feature Three
420
+
421
+ Additional info
422
+ ~~~
423
+ ~~~~~~
424
+ ```
425
+
426
+ #### Removing Fixed Aspect Ratio
427
+
428
+ For carousels with **text content, cards, or variable-height slides**, you may want to remove the default `16/9` aspect ratio to let content size naturally:
429
+
430
+ ```markdown
431
+ ~~~~~~aspect-ratio:auto navigation
432
+ ~~~
433
+ # First Slide
434
+
435
+ This carousel will size based on content height, not a fixed aspect ratio.
436
+
437
+ Perfect for text-heavy slides or mixed content.
438
+ ~~~
439
+ ~~~
440
+ # Second Slide
441
+
442
+ Another slide with different content height.
443
+ ~~~
444
+ ~~~~~~
445
+ ```
446
+
447
+ Use `aspect-ratio:auto` or `aspect-ratio:none` to override the default fixed height behavior.
448
+
449
+ #### Carousel Parameters
450
+
451
+ | Parameter Type | Syntax | Description |
452
+ |----------------|--------|-------------|
453
+ | **Slides Per Page** | First number (e.g., `3`) | How many slides visible at once (default: 1) |
454
+ | **Slides Per Move** | Second number (e.g., `2`) | How many slides to advance (default: 1) |
455
+ | **Loop** | `loop` | Enable continuous looping (default: off) |
456
+ | **Navigation** | `navigation` | Show previous/next buttons |
457
+ | **Pagination** | `pagination` | Show dot indicators |
458
+ | **Autoplay** | `autoplay` | Auto-advance slides |
459
+ | **Mouse Dragging** | `mouse-dragging` | Enable click-and-drag |
460
+ | **Vertical** | `vertical` | Vertical orientation |
461
+ | **Scroll Hint** | `scroll-hint:2rem` | Padding to show adjacent slides |
462
+ | **Aspect Ratio** | `aspect-ratio:3/2` | Viewport aspect ratio (default: 16/9) |
463
+ | **Slide Gap** | `slide-gap:1rem` | Space between slides |
464
+
465
+ All parameters are optional and can be combined in any order:
466
+
467
+ ```markdown
468
+ ~~~~~~vertical pagination autoplay
469
+ ~~~
470
+ Content here
471
+ ~~~
472
+ ~~~~~~
473
+ ```
474
+
267
475
  ### Tags
268
476
 
269
477
  Create tags using the `@@@` syntax:
@@ -573,6 +781,22 @@ Cards automatically parse content into these slots:
573
781
  - **Content**: Remaining content becomes main content
574
782
  - **Footer**: Trailing links become footer buttons
575
783
 
784
+ ### Carousel Options
785
+
786
+ | Parameter | Type | Description |
787
+ |-----------|------|-------------|
788
+ | Slides Per Page | Number (first numeric parameter) | How many slides visible at once (default: 1) |
789
+ | Slides Per Move | Number (second numeric parameter) | How many slides to advance (default: 1) |
790
+ | `loop` | Boolean | Enable continuous looping (default: off) |
791
+ | `navigation` | Boolean | Show previous/next buttons (default: off) |
792
+ | `pagination` | Boolean | Show dot indicators (default: off) |
793
+ | `autoplay` | Boolean | Auto-advance slides (default: off) |
794
+ | `mouse-dragging` | Boolean | Enable click-and-drag (default: off) |
795
+ | `vertical` | Keyword | Use vertical orientation (default: horizontal) |
796
+ | `scroll-hint:value` | CSS Property | Padding to show adjacent slides (e.g., `2rem`, `50px`) |
797
+ | `aspect-ratio:value` | CSS Property | Viewport aspect ratio (default: 16/9, e.g., `3/2`, `4/3`). Use `auto` or `none` for content-based height |
798
+ | `slide-gap:value` | CSS Property | Space between slides (default: `var(--wa-space-m)`) |
799
+
576
800
  ### Tag Variants
577
801
 
578
802
  | Type | Description |
@@ -622,7 +846,13 @@ Enable automatic image-to-dialog transformation in your `_config.yml`:
622
846
 
623
847
  ```yaml
624
848
  webawesome:
849
+ # Simple boolean to enable
625
850
  image_dialog: true
851
+
852
+ # Or configure with options
853
+ image_dialog:
854
+ enabled: true
855
+ default_width: 90vh # Default width for all image dialogs
626
856
  ```
627
857
 
628
858
  When enabled, all markdown images automatically become clickable and open in full-size dialogs:
@@ -631,7 +861,9 @@ When enabled, all markdown images automatically become clickable and open in ful
631
861
  ![Architecture Diagram](diagram.png)
632
862
  ```
633
863
 
634
- **Control dialog width** by adding a width parameter to the title:
864
+ **Default Width**: Set a default width for all image dialogs in the configuration. Images will use this width unless overridden in the title.
865
+
866
+ **Control dialog width** by adding a width parameter to the title (overrides default):
635
867
 
636
868
  ```markdown
637
869
  ![Diagram](diagram.png "50%") # Dialog width: 50%
@@ -651,6 +883,7 @@ Supported width units: `px`, `em`, `rem`, `vw`, `vh`, `%`, `ch`
651
883
 
652
884
  - Light-dismiss and headerless dialogs for clean UX
653
885
  - Thumbnail displays at original size, dialog shows full-size
886
+ - Configurable default width for consistent sizing
654
887
 
655
888
  ### Tab Placements
656
889
 
@@ -52,6 +52,33 @@ module Jekyll
52
52
  false
53
53
  end
54
54
 
55
+ # Get image dialog configuration with default width support
56
+ def self.image_dialog_config(site)
57
+ config = {}
58
+
59
+ # First check if it's enabled
60
+ enabled_config = nil
61
+ if Jekyll::WebAwesome.configuration
62
+ enabled_config = Jekyll::WebAwesome.configuration.image_dialog
63
+ elsif site.config.dig('webawesome', 'image_dialog') != nil
64
+ enabled_config = site.config.dig('webawesome', 'image_dialog')
65
+ end
66
+
67
+ # If disabled or not set, return empty config
68
+ return config unless enabled_config
69
+
70
+ # If it's a boolean true, set enabled
71
+ if enabled_config == true
72
+ config[:enabled] = true
73
+ # If it's a hash, merge it
74
+ elsif enabled_config.is_a?(Hash)
75
+ config = enabled_config.transform_keys(&:to_sym)
76
+ config[:enabled] = true unless config.key?(:enabled)
77
+ end
78
+
79
+ config
80
+ end
81
+
55
82
  # Check if a file is a markdown file
56
83
  def self.markdown_file?(filepath)
57
84
  filepath.to_s.match?(/\.md$/i)
@@ -13,12 +13,13 @@ module Jekyll
13
13
  content = ButtonTransformer.transform(content)
14
14
  content = CalloutTransformer.transform(content)
15
15
  content = CardTransformer.transform(content)
16
+ content = CarouselTransformer.transform(content)
16
17
  content = ComparisonTransformer.transform(content)
17
18
  content = CopyButtonTransformer.transform(content)
18
19
  content = DetailsTransformer.transform(content)
19
20
 
20
21
  # Apply image dialog transformer BEFORE dialog transformer so it can generate dialog syntax
21
- content = ImageDialogTransformer.transform(content) if site && Plugin.image_dialog_enabled?(site)
22
+ content = ImageDialogTransformer.transform(content, site) if site && Plugin.image_dialog_enabled?(site)
22
23
 
23
24
  content = DialogTransformer.transform(content)
24
25
  content = IconTransformer.transform(content)
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_transformer'
4
+
5
+ module Jekyll
6
+ module WebAwesome
7
+ # Transforms carousel syntax into wa-carousel elements
8
+ # Primary syntax: ~~~~~~params\n~~~ slide1\ncontent\n~~~\n~~~ slide2\ncontent\n~~~\n~~~~~~
9
+ # Alternative syntax: :::wa-carousel params\n~~~ slide1\ncontent\n~~~\n~~~ slide2\ncontent\n~~~\n:::
10
+ # Params can include: numbers (slides-per-page, slides-per-move), keywords (loop, navigation, pagination,
11
+ # autoplay, mouse-dragging, vertical), and CSS properties (scroll-hint:value, aspect-ratio:value, slide-gap:value)
12
+ class CarouselTransformer < BaseTransformer
13
+ def self.transform(content)
14
+ # Define both regex patterns
15
+ # Match: ~~~~~~params (optional)
16
+ # ~~~
17
+ # content (can be empty)
18
+ # ~~~
19
+ # (repeat slides)
20
+ # ~~~~~~
21
+ primary_regex = /^~{6}([^\n]*)\n((?:~~~\n(?:.*?\n)?~~~\n?)+)~{6}/m
22
+ alternative_regex = /^:::wa-carousel\s*([^\n]*)\n((?:~~~\n(?:.*?\n)?~~~\n?)+):::/m
23
+
24
+ # Define shared transformation logic
25
+ transform_proc = proc do |params, slides_block, _third_capture|
26
+ parsed_params = parse_params(params)
27
+ slides = extract_slides(slides_block)
28
+
29
+ build_carousel_html(slides, parsed_params)
30
+ end
31
+
32
+ # Apply both patterns
33
+ patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
34
+ apply_multiple_patterns(content, patterns)
35
+ end
36
+
37
+ class << self
38
+ private
39
+
40
+ def parse_params(params)
41
+ return {} if params.nil? || params.strip.empty?
42
+
43
+ result = {
44
+ attributes: {},
45
+ css_vars: {}
46
+ }
47
+
48
+ tokens = params.strip.split(/\s+/)
49
+ numeric_count = 0
50
+
51
+ tokens.each do |token|
52
+ # Check for CSS custom properties (key:value)
53
+ if token.include?(':')
54
+ key, value = token.split(':', 2)
55
+ case key
56
+ when 'scroll-hint'
57
+ result[:css_vars]['--scroll-hint'] = value
58
+ when 'aspect-ratio'
59
+ # Support 'auto', 'none', or 'unset' to remove the default aspect ratio
60
+ # This is useful for text content or variable-height slides
61
+ result[:css_vars]['--aspect-ratio'] = value
62
+ when 'slide-gap'
63
+ result[:css_vars]['--slide-gap'] = value
64
+ end
65
+ # Check for numeric values
66
+ elsif token.match?(/^\d+$/)
67
+ numeric_count += 1
68
+ if numeric_count == 1
69
+ result[:attributes]['slides-per-page'] = token
70
+ elsif numeric_count == 2
71
+ result[:attributes]['slides-per-move'] = token
72
+ end
73
+ # Check for boolean flags
74
+ elsif %w[loop navigation pagination autoplay mouse-dragging vertical].include?(token)
75
+ # For orientation, we need to handle it specially
76
+ if token == 'vertical'
77
+ result[:attributes]['orientation'] = 'vertical'
78
+ else
79
+ result[:attributes][token] = true
80
+ end
81
+ end
82
+ end
83
+
84
+ result
85
+ end
86
+
87
+ def extract_slides(slides_block)
88
+ # Extract individual slides using ~~~ markers
89
+ # Handle both content and empty slides
90
+ slide_contents = slides_block.scan(/~~~\n(.*?)~~~(?:\n|$)/m)
91
+ slide_contents.map { |match| match[0].strip }
92
+ end
93
+
94
+ def build_carousel_html(slides, parsed_params)
95
+ attributes = build_attributes(parsed_params[:attributes] || {})
96
+ style = build_style(parsed_params[:css_vars] || {})
97
+
98
+ attr_string = attributes.empty? ? '' : " #{attributes.join(' ')}"
99
+ style_string = style.empty? ? '' : " style=\"#{style}\""
100
+
101
+ slide_items = slides.map do |slide_content|
102
+ slide_html = markdown_to_html(slide_content)
103
+ "<wa-carousel-item>#{slide_html}</wa-carousel-item>"
104
+ end
105
+
106
+ "<wa-carousel#{attr_string}#{style_string}>#{slide_items.join}</wa-carousel>"
107
+ end
108
+
109
+ def build_attributes(attrs)
110
+ return [] if attrs.nil? || attrs.empty?
111
+
112
+ attrs.map do |key, value|
113
+ if value == true
114
+ key
115
+ else
116
+ "#{key}=\"#{value}\""
117
+ end
118
+ end
119
+ end
120
+
121
+ def build_style(css_vars)
122
+ return '' if css_vars.nil? || css_vars.empty?
123
+
124
+ css_vars.map { |key, value| "#{key}: #{value}" }.join('; ')
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -9,7 +9,10 @@ module Jekyll
9
9
  # Images can opt-out by adding "nodialog" to the title attribute
10
10
  # Example: ![Alt text](image.png "nodialog")
11
11
  class ImageDialogTransformer < BaseTransformer
12
- def self.transform(content)
12
+ def self.transform(content, site = nil)
13
+ # Get configuration including default width
14
+ config = site ? Plugin.image_dialog_config(site) : {}
15
+
13
16
  # First, protect code blocks, inline code, and comparison blocks from transformation
14
17
  protected_content, fenced_code_blocks = protect_fenced_code_blocks(content)
15
18
  protected_content, inline_code_blocks = protect_inline_code(protected_content)
@@ -31,7 +34,7 @@ module Jekyll
31
34
  match
32
35
  else
33
36
  # Transform to clickable image with dialog
34
- transform_to_dialog(alt_text, image_url, title)
37
+ transform_to_dialog(alt_text, image_url, title, config)
35
38
  end
36
39
  end
37
40
 
@@ -115,9 +118,12 @@ module Jekyll
115
118
 
116
119
  # Transform image into our custom dialog syntax
117
120
  # This will be processed by DialogTransformer to create the actual wa-dialog
118
- def transform_to_dialog(alt_text, image_url, title)
121
+ def transform_to_dialog(alt_text, image_url, title, config = {})
119
122
  # Parse width from title if specified (e.g., "50%", "800px", "60vw")
120
123
  width = extract_width_from_title(title)
124
+
125
+ # Use default width from config if no width specified in title
126
+ width ||= config[:default_width] if config[:default_width]
121
127
 
122
128
  # Build dialog parameters
123
129
  # Always include header with X close button for accessibility
@@ -8,6 +8,7 @@ require_relative 'transformers/badge_transformer'
8
8
  require_relative 'transformers/button_transformer'
9
9
  require_relative 'transformers/callout_transformer'
10
10
  require_relative 'transformers/card_transformer'
11
+ require_relative 'transformers/carousel_transformer'
11
12
  require_relative 'transformers/comparison_transformer'
12
13
  require_relative 'transformers/copy_button_transformer'
13
14
  require_relative 'transformers/details_transformer'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module WebAwesome
5
- VERSION = '0.5.3'
5
+ VERSION = '0.6.0'
6
6
  end
7
7
  end
@@ -31,7 +31,7 @@ module Jekyll
31
31
  @custom_components = {}
32
32
  @transform_pages = true
33
33
  @transform_documents = true
34
- @image_dialog = false # Opt-in by default for safety
34
+ @image_dialog = false # Opt-in by default for safety, or can be a hash with options
35
35
  end
36
36
 
37
37
  private
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-webawesome
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janne Waren
@@ -122,6 +122,7 @@ files:
122
122
  - lib/jekyll/webawesome/transformers/button_transformer.rb
123
123
  - lib/jekyll/webawesome/transformers/callout_transformer.rb
124
124
  - lib/jekyll/webawesome/transformers/card_transformer.rb
125
+ - lib/jekyll/webawesome/transformers/carousel_transformer.rb
125
126
  - lib/jekyll/webawesome/transformers/comparison_transformer.rb
126
127
  - lib/jekyll/webawesome/transformers/copy_button_transformer.rb
127
128
  - lib/jekyll/webawesome/transformers/details_transformer.rb