markawesome 0.6.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c03fbaecd8dec3c16fa5e2ddeb07b12d2eb35ad2fbc8389a49b725d77a3c2cf
4
- data.tar.gz: 6b530bf8caae7b8717411b111e6e3e6f9fb6766373d0b80238cb3fa4ec7f98d6
3
+ metadata.gz: 0ed0214570dcd6897e7433e6a2891a5f1d7fdc69650a7c0d11a0265924c5376b
4
+ data.tar.gz: c44001d3a303f7c59eb0d29f8335a08ad52e82f6b1bdc613a2977a65b6279247
5
5
  SHA512:
6
- metadata.gz: 6e2b2e8804309e702139068db433be5cbb62132eede58ff45a25d871b721bc2adab4a23d34b820ed8dda26907de2d51ab277b30a13f5d9037e3d26efd123d91f
7
- data.tar.gz: 8ba50a46d31a068af6ae3d2dc28c2832d26b665e4a006fc74b34f5c59ee0a12596f4f8a7a1a98d7412f0150fe25215d3772521fe6fcaff5f1154c69ac91fc684
6
+ metadata.gz: c374b8048b195255d1779d09efbd3de1a4e5fbbd0264b72940e75b73f9fd2a3517e0710a2414c4f0f411028064ea3f3b17066285a1c17d6558e57e533a9e1a85
7
+ data.tar.gz: f362ad4bdcde37cf129dd5f9a83ef006d8eb11dd6f06a1bd2a6b410e22ee83b32c518909a0e3b083b8cded3c7b56d4b7f37e85cdb448f30517f68824d628eeae
data/CHANGELOG.md CHANGED
@@ -4,12 +4,31 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## [0.6.0] - 2026-02-14
7
+ ## [0.8.0] - 2026-03-12
8
+
9
+ ### Added
10
+
11
+ - **PopoverTransformer**: New `&&&` syntax for `wa-popover` floating content component
12
+ - Trigger text and popover content separated by `>>>` (same pattern as dialog/details)
13
+ - Placement options: `top` (default), `bottom`, `left`, `right`
14
+ - `without-arrow` flag to hide the popover arrow
15
+ - `distance:N` parameter for custom trigger-to-popover distance in pixels
16
+ - `link` flag to render trigger as a link-styled element instead of a button
17
+ - Unique anchor IDs generated via MD5 hash for trigger/popover pairing
18
+ - Alternative `:::wa-popover` syntax supported
19
+ - Markdown content support in popover body via Kramdown
20
+ - HTML escaping for trigger text (XSS prevention)
21
+
22
+ ## [0.7.0]
8
23
 
9
24
  ### Changed
10
25
 
11
26
  - **BREAKING: Card header syntax** — Card headers now use `**bold text**` instead of `# heading`. The first bold-only line inside a card block becomes the header slot. This avoids markdownlint warnings about multiple top-level headings (MD025) and incorrect heading levels (MD001), and better reflects that card titles are not semantic document headings.
12
27
 
28
+ ## [0.6.0] - 2026-02-14
29
+
30
+ _(Version bump included LayoutTransformer and icon slot syntax — see 0.5.0 and 0.4.0 entries below.)_
31
+
13
32
  ## [0.5.0] - 2026-02-10
14
33
 
15
34
  ### Added
data/README.md CHANGED
@@ -25,6 +25,7 @@ Used as the transformation engine for the [jekyll-webawesome](https://github.com
25
25
  | **Dialog** | `???params?` | `:::wa-dialog params?` | `<wa-dialog>` with trigger button and content |
26
26
  | **Icon** | `$$$icon-name` | `:::wa-icon icon-name` | `<wa-icon name="icon-name"></wa-icon>` |
27
27
  | **Image Dialog** | `![alt](url)` | — | Wraps images in clickable `<wa-dialog>` overlays |
28
+ | **Popover** | `&&&params?` | `:::wa-popover params?` | `<wa-popover>` with trigger button and content |
28
29
  | **Tab Group** | `++++++` | `:::wa-tabs` | `<wa-tab-group><wa-tab>content</wa-tab></wa-tab-group>` |
29
30
  | **Tag** | `@@@brand` | `:::wa-tag brand` | `<wa-tag variant="brand">content</wa-tag>` |
30
31
 
@@ -24,6 +24,7 @@ module Markawesome
24
24
  end
25
25
 
26
26
  content = DialogTransformer.transform(content)
27
+ content = PopoverTransformer.transform(content)
27
28
  content = IconTransformer.transform(content)
28
29
  content = TagTransformer.transform(content)
29
30
  TabsTransformer.transform(content)
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+ require_relative 'base_transformer'
5
+ require_relative '../attribute_parser'
6
+
7
+ module Markawesome
8
+ # Transforms popover syntax into wa-popover elements with trigger buttons
9
+ # Primary syntax: &&&params\ntrigger text\n>>>\ncontent\n&&&
10
+ # Alternative syntax: :::wa-popover params\ntrigger text\n>>>\ncontent\n:::
11
+ #
12
+ # Params: space-separated tokens (order doesn't matter)
13
+ # Placement: top (default), bottom, left, right
14
+ # Flags: without-arrow
15
+ # Distance: distance:N (e.g., distance:10)
16
+ class PopoverTransformer < BaseTransformer
17
+ POPOVER_ATTRIBUTES = {
18
+ placement: %w[top bottom left right],
19
+ without_arrow: %w[without-arrow],
20
+ trigger_style: %w[link]
21
+ }.freeze
22
+
23
+ def self.transform(content)
24
+ primary_regex = /^&&&([^\n]*)$\n(.*?)\n^>>>$\n(.*?)\n^&&&$/m
25
+ alternative_regex = /^:::wa-popover([^\n]*)$\n(.*?)\n^>>>$\n(.*?)\n^:::$/m
26
+
27
+ transform_proc = proc do |params_string, trigger_text, popover_content|
28
+ trigger_text = trigger_text.strip
29
+ popover_content = popover_content.strip
30
+
31
+ placement, without_arrow, distance, link_style = parse_parameters(params_string)
32
+
33
+ popover_id = generate_popover_id(trigger_text, popover_content)
34
+
35
+ content_html = markdown_to_html(popover_content)
36
+
37
+ build_popover_html(popover_id, trigger_text, content_html,
38
+ { placement: placement, without_arrow: without_arrow,
39
+ distance: distance, link_style: link_style })
40
+ end
41
+
42
+ patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
43
+ apply_multiple_patterns(content, patterns)
44
+ end
45
+
46
+ class << self
47
+ private
48
+
49
+ def parse_parameters(params_string)
50
+ return ['top', false, nil, false] if params_string.nil? || params_string.strip.empty?
51
+
52
+ attributes = AttributeParser.parse(params_string, POPOVER_ATTRIBUTES)
53
+ placement = attributes[:placement] || 'top'
54
+ without_arrow = attributes[:without_arrow] == 'without-arrow'
55
+ link_style = attributes[:trigger_style] == 'link'
56
+
57
+ # Look for distance:N parameter
58
+ tokens = params_string.strip.split(/\s+/)
59
+ distance_token = tokens.find { |token| token.match?(/^distance:\d+$/) }
60
+ distance = distance_token&.sub('distance:', '')
61
+
62
+ [placement, without_arrow, distance, link_style]
63
+ end
64
+
65
+ def generate_popover_id(trigger_text, content)
66
+ hash_input = "#{trigger_text}#{content}"
67
+ hash = Digest::MD5.hexdigest(hash_input)
68
+ "popover-#{hash[0..7]}"
69
+ end
70
+
71
+ def build_popover_html(popover_id, trigger_text, content_html, options)
72
+ # Escape trigger text for security
73
+ trigger_content = escape_html(trigger_text)
74
+
75
+ # Build popover attributes
76
+ popover_attrs = ["for='#{popover_id}'"]
77
+ popover_attrs << "placement='#{options[:placement]}'"
78
+ popover_attrs << 'without-arrow' if options[:without_arrow]
79
+ popover_attrs << "distance='#{options[:distance]}'" if options[:distance]
80
+
81
+ trigger = build_trigger(popover_id, trigger_content, options[:link_style])
82
+
83
+ html = []
84
+ html << trigger
85
+ html << "<wa-popover #{popover_attrs.join(' ')}>"
86
+ html << content_html
87
+ html << '</wa-popover>'
88
+ html.join("\n")
89
+ end
90
+
91
+ def build_trigger(popover_id, trigger_content, link_style)
92
+ if link_style
93
+ link_style_attr = 'background: none; border: none; padding: 0; ' \
94
+ 'color: inherit; text-decoration: underline; ' \
95
+ 'cursor: pointer; font: inherit;'
96
+ "<button id='#{popover_id}' style='#{link_style_attr}'>#{trigger_content}</button>"
97
+ else
98
+ "<wa-button id='#{popover_id}' variant='text'>#{trigger_content}</wa-button>"
99
+ end
100
+ end
101
+
102
+ def escape_html(text)
103
+ text.gsub('&', '&amp;')
104
+ .gsub('<', '&lt;')
105
+ .gsub('>', '&gt;')
106
+ .gsub('"', '&quot;')
107
+ .gsub("'", '&#39;')
108
+ end
109
+ end
110
+ end
111
+ end
@@ -16,5 +16,6 @@ require_relative 'transformers/dialog_transformer'
16
16
  require_relative 'transformers/icon_transformer'
17
17
  require_relative 'transformers/image_dialog_transformer'
18
18
  require_relative 'transformers/layout_transformer'
19
+ require_relative 'transformers/popover_transformer'
19
20
  require_relative 'transformers/tabs_transformer'
20
21
  require_relative 'transformers/tag_transformer'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Markawesome
4
- VERSION = '0.6.0'
4
+ VERSION = '0.8.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: markawesome
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janne Waren
@@ -108,6 +108,7 @@ files:
108
108
  - lib/markawesome/transformers/icon_transformer.rb
109
109
  - lib/markawesome/transformers/image_dialog_transformer.rb
110
110
  - lib/markawesome/transformers/layout_transformer.rb
111
+ - lib/markawesome/transformers/popover_transformer.rb
111
112
  - lib/markawesome/transformers/tabs_transformer.rb
112
113
  - lib/markawesome/transformers/tag_transformer.rb
113
114
  - lib/markawesome/version.rb