markawesome 0.7.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 +4 -4
- data/CHANGELOG.md +16 -4
- data/README.md +2 -40
- data/lib/markawesome/transformer.rb +1 -0
- data/lib/markawesome/transformers/icon_transformer.rb +17 -41
- data/lib/markawesome/transformers/popover_transformer.rb +111 -0
- data/lib/markawesome/transformers.rb +1 -0
- data/lib/markawesome/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0ed0214570dcd6897e7433e6a2891a5f1d7fdc69650a7c0d11a0265924c5376b
|
|
4
|
+
data.tar.gz: c44001d3a303f7c59eb0d29f8335a08ad52e82f6b1bdc613a2977a65b6279247
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c374b8048b195255d1779d09efbd3de1a4e5fbbd0264b72940e75b73f9fd2a3517e0710a2414c4f0f411028064ea3f3b17066285a1c17d6558e57e533a9e1a85
|
|
7
|
+
data.tar.gz: f362ad4bdcde37cf129dd5f9a83ef006d8eb11dd6f06a1bd2a6b410e22ee83b32c518909a0e3b083b8cded3c7b56d4b7f37e85cdb448f30517f68824d628eeae
|
data/CHANGELOG.md
CHANGED
|
@@ -4,19 +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.
|
|
7
|
+
## [0.8.0] - 2026-03-12
|
|
8
8
|
|
|
9
9
|
### Added
|
|
10
10
|
|
|
11
|
-
- **
|
|
12
|
-
-
|
|
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)
|
|
13
21
|
|
|
14
|
-
## [0.
|
|
22
|
+
## [0.7.0]
|
|
15
23
|
|
|
16
24
|
### Changed
|
|
17
25
|
|
|
18
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.
|
|
19
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
|
+
|
|
20
32
|
## [0.5.0] - 2026-02-10
|
|
21
33
|
|
|
22
34
|
### Added
|
data/README.md
CHANGED
|
@@ -23,50 +23,12 @@ Used as the transformation engine for the [jekyll-webawesome](https://github.com
|
|
|
23
23
|
| **Copy Button** | `<<<` | `:::wa-copy-button` | `<wa-copy-button value="content">content</wa-copy-button>` |
|
|
24
24
|
| **Details** | `^^^appearance? icon-placement?` | `:::wa-details appearance? icon-placement?` | `<wa-details>content</wa-details>` |
|
|
25
25
|
| **Dialog** | `???params?` | `:::wa-dialog params?` | `<wa-dialog>` with trigger button and content |
|
|
26
|
-
| **Icon** | `$$$icon-name`
|
|
26
|
+
| **Icon** | `$$$icon-name` | `:::wa-icon icon-name` | `<wa-icon name="icon-name"></wa-icon>` |
|
|
27
27
|
| **Image Dialog** | `` | — | Wraps images in clickable `<wa-dialog>` overlays |
|
|
28
|
+
| **Popover** | `&&¶ms?` | `:::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
|
|
|
31
|
-
## Icon
|
|
32
|
-
|
|
33
|
-
### Named icons
|
|
34
|
-
|
|
35
|
-
Use a Web Awesome icon name:
|
|
36
|
-
|
|
37
|
-
```markdown
|
|
38
|
-
Click $$$settings to configure.
|
|
39
|
-
A large $$$home:lg icon.
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Custom SVG icons
|
|
43
|
-
|
|
44
|
-
Point to a local SVG file by starting the path with `/` or `./`:
|
|
45
|
-
|
|
46
|
-
```markdown
|
|
47
|
-
$$$/assets/icons/shoe.svg
|
|
48
|
-
$$$/assets/icons/shoe.svg:2x
|
|
49
|
-
$$$./icons/logo.svg:xl
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
This outputs `<wa-icon src="/assets/icons/shoe.svg"></wa-icon>` instead of using the `name` attribute.
|
|
53
|
-
|
|
54
|
-
### Sizes
|
|
55
|
-
|
|
56
|
-
Append a size token after `:` (primary syntax) or as a space-separated parameter (alternative syntax):
|
|
57
|
-
|
|
58
|
-
| Token | CSS `font-size` |
|
|
59
|
-
|-------|----------------|
|
|
60
|
-
| `xs` | 0.75em |
|
|
61
|
-
| `sm` | 0.875em |
|
|
62
|
-
| `lg` | 1.25em |
|
|
63
|
-
| `xl` | 1.5em |
|
|
64
|
-
| `2x` | 2em |
|
|
65
|
-
| `3x` | 3em |
|
|
66
|
-
| `4x` | 4em |
|
|
67
|
-
|
|
68
|
-
Without a size token, the icon inherits the surrounding font size.
|
|
69
|
-
|
|
70
32
|
## Layout Utilities
|
|
71
33
|
|
|
72
34
|
Layout utilities use `::::` (quadruple colon) syntax to wrap content in CSS layout containers. Inner content is not markdown-converted, so component `:::` syntax inside layouts works normally.
|
|
@@ -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)
|
|
@@ -4,46 +4,30 @@ require_relative 'base_transformer'
|
|
|
4
4
|
|
|
5
5
|
module Markawesome
|
|
6
6
|
# Transforms icon syntax into wa-icon elements
|
|
7
|
-
# Primary syntax: $$$icon-name
|
|
8
|
-
#
|
|
9
|
-
# Alternative syntax: :::wa-icon icon-name [size] or :::wa-icon /path/to/icon.svg [size]
|
|
7
|
+
# Primary syntax: $$$icon-name
|
|
8
|
+
# Alternative syntax: :::wa-icon icon-name
|
|
10
9
|
#
|
|
11
10
|
# Examples:
|
|
12
11
|
# $$$settings -> <wa-icon name="settings"></wa-icon>
|
|
13
|
-
# $$$
|
|
14
|
-
#
|
|
15
|
-
# $$$/assets/icons/shoe.svg:2x -> <wa-icon src="/assets/icons/shoe.svg" style="font-size: 2em;"></wa-icon>
|
|
16
|
-
#
|
|
17
|
-
# Available sizes: xs (0.75em), sm (0.875em), lg (1.25em), xl (1.5em), 2x (2em), 3x (3em), 4x (4em)
|
|
12
|
+
# $$$home -> <wa-icon name="home"></wa-icon>
|
|
13
|
+
# $$$user-circle -> <wa-icon name="user-circle"></wa-icon>
|
|
18
14
|
class IconTransformer < BaseTransformer
|
|
19
|
-
SIZES = {
|
|
20
|
-
'xs' => '0.75em',
|
|
21
|
-
'sm' => '0.875em',
|
|
22
|
-
'lg' => '1.25em',
|
|
23
|
-
'xl' => '1.5em',
|
|
24
|
-
'2x' => '2em',
|
|
25
|
-
'3x' => '3em',
|
|
26
|
-
'4x' => '4em'
|
|
27
|
-
}.freeze
|
|
28
|
-
|
|
29
15
|
def self.transform(content)
|
|
30
16
|
# Protect code blocks first
|
|
31
17
|
protected_content, code_blocks = protect_code_blocks(content)
|
|
32
18
|
|
|
33
19
|
# Apply primary syntax transformation
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
build_icon_html(
|
|
20
|
+
# Only block patterns that look like incomplete icon names:
|
|
21
|
+
# $$$icon name (where 'icon name' could be intended as one identifier)
|
|
22
|
+
result = protected_content.gsub(/\$\$\$([a-zA-Z0-9\-_]+)(?![a-zA-Z0-9\-_]|\s+name\b)/) do
|
|
23
|
+
icon_name = ::Regexp.last_match(1)
|
|
24
|
+
build_icon_html(icon_name)
|
|
39
25
|
end
|
|
40
26
|
|
|
41
27
|
# Apply alternative syntax transformation
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
size = ::Regexp.last_match(2)
|
|
46
|
-
build_icon_html(icon_ref, size)
|
|
28
|
+
result = result.gsub(/:::wa-icon\s+([a-zA-Z0-9\-_]+)\s*\n:::/m) do
|
|
29
|
+
icon_name = ::Regexp.last_match(1)
|
|
30
|
+
build_icon_html(icon_name)
|
|
47
31
|
end
|
|
48
32
|
|
|
49
33
|
# Restore code blocks
|
|
@@ -53,20 +37,12 @@ module Markawesome
|
|
|
53
37
|
class << self
|
|
54
38
|
private
|
|
55
39
|
|
|
56
|
-
def build_icon_html(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
# Paths (starting with / or ./) use src attribute, otherwise use name
|
|
60
|
-
attr = if clean_ref.include?('/')
|
|
61
|
-
"src=\"#{clean_ref}\""
|
|
62
|
-
else
|
|
63
|
-
"name=\"#{clean_ref}\""
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Build style attribute for size
|
|
67
|
-
style = SIZES[size] ? " style=\"font-size: #{SIZES[size]};\"" : ''
|
|
40
|
+
def build_icon_html(icon_name)
|
|
41
|
+
# Clean and validate icon name
|
|
42
|
+
clean_name = icon_name.strip
|
|
68
43
|
|
|
69
|
-
|
|
44
|
+
# Return the wa-icon element
|
|
45
|
+
"<wa-icon name=\"#{clean_name}\"></wa-icon>"
|
|
70
46
|
end
|
|
71
47
|
|
|
72
48
|
def protect_code_blocks(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: &&¶ms\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('&', '&')
|
|
104
|
+
.gsub('<', '<')
|
|
105
|
+
.gsub('>', '>')
|
|
106
|
+
.gsub('"', '"')
|
|
107
|
+
.gsub("'", ''')
|
|
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'
|
data/lib/markawesome/version.rb
CHANGED
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.
|
|
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
|