markawesome 0.3.0 → 0.4.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 +17 -0
- data/lib/markawesome/icon_slot_parser.rb +63 -0
- data/lib/markawesome/transformers/button_transformer.rb +11 -6
- data/lib/markawesome/transformers/callout_transformer.rb +12 -2
- data/lib/markawesome/transformers/details_transformer.rb +14 -4
- data/lib/markawesome/transformers/tag_transformer.rb +14 -5
- data/lib/markawesome/version.rb +1 -1
- data/lib/markawesome.rb +1 -0
- 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: 8a3394f03fff9ca20290650589ba70022b2f8ca71b5581f5d06cb4e06ac83f3f
|
|
4
|
+
data.tar.gz: d5af8667249a450c3119641dc38a9f148bbb2b30a1f8c76eae138c3765617fd5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c29d6692c8cd45f5f2a6a544de3505ff3a9af50a0d36468385f71b38daac30465ff23d15b5d94648f48690fae43d652cf495a4c7ea8d282bc96127a7376e22a3
|
|
7
|
+
data.tar.gz: c8134fa3a4a9344efe72ffa5d4a6504763ba9ebce4a4a9c6f7d8b0907de48506ebb9a7ae843bffd0898da5379ba2ebdf9bc100978f2b86add9cec722c4e3281e
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,23 @@ 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.4.0] - 2026-02-09
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **IconSlotParser**: New reusable parser for `icon:name` and `icon:slot:name` syntax across components
|
|
12
|
+
- **ButtonTransformer**: Icon support with `icon:name` (start slot) and `icon:end:name` for start/end icon slots
|
|
13
|
+
- **CalloutTransformer**: Custom icon override with `icon:name` to replace default variant icons
|
|
14
|
+
- **DetailsTransformer**: Custom expand/collapse icons with `icon:expand:name` and `icon:collapse:name`
|
|
15
|
+
- **TagTransformer**: Inline content icons with `icon:name` for both block and inline tag syntax
|
|
16
|
+
|
|
17
|
+
### Design
|
|
18
|
+
|
|
19
|
+
- IconSlotParser composes with AttributeParser — strips icon tokens first, passes remaining params for attribute parsing
|
|
20
|
+
- Supports slot name mapping (e.g. `expand` → `expand-icon`) for Web Awesome's HTML slot conventions
|
|
21
|
+
- Rightmost-wins semantics consistent with AttributeParser
|
|
22
|
+
- Content slot mode omits `slot=` attribute for inline icon usage (tags)
|
|
23
|
+
|
|
7
24
|
## [0.3.0] - 2026-02-08
|
|
8
25
|
|
|
9
26
|
### Added
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Markawesome
|
|
4
|
+
# Parses icon:... tokens from parameter strings for Web Awesome component icon slots
|
|
5
|
+
# Supports default slot mapping, explicit slot names, and slot name remapping
|
|
6
|
+
#
|
|
7
|
+
# Examples:
|
|
8
|
+
# "icon:gear" → default slot gets "gear"
|
|
9
|
+
# "icon:end:arrow-right" → "end" slot gets "arrow-right"
|
|
10
|
+
# "success icon:gear large" → icons: { 'start' => 'gear' }, remaining: "success large"
|
|
11
|
+
class IconSlotParser
|
|
12
|
+
# Parse icon tokens from a parameter string
|
|
13
|
+
# @param params_string [String] Space-separated parameter string potentially containing icon:... tokens
|
|
14
|
+
# @param slot_config [Hash] Configuration for icon slots
|
|
15
|
+
# :default [String, nil] Default slot name for icon:name tokens (nil = no default)
|
|
16
|
+
# :slots [Array<String>] Allowed slot names
|
|
17
|
+
# :slot_map [Hash] Optional mapping from short slot names to HTML slot attributes
|
|
18
|
+
# @return [Hash] { icons: Hash, remaining: String }
|
|
19
|
+
def self.parse(params_string, slot_config)
|
|
20
|
+
return { icons: {}, remaining: '' } if params_string.nil? || params_string.strip.empty?
|
|
21
|
+
|
|
22
|
+
icons = {}
|
|
23
|
+
remaining_tokens = []
|
|
24
|
+
tokens = params_string.strip.split(/\s+/)
|
|
25
|
+
|
|
26
|
+
tokens.each do |token|
|
|
27
|
+
if token.start_with?('icon:')
|
|
28
|
+
parts = token.split(':', 3) # ["icon", slot_or_name, maybe_name]
|
|
29
|
+
|
|
30
|
+
if parts.length == 3
|
|
31
|
+
# Explicit slot: icon:slot:name
|
|
32
|
+
slot = parts[1]
|
|
33
|
+
name = parts[2]
|
|
34
|
+
icons[slot] = name if slot_config[:slots]&.include?(slot)
|
|
35
|
+
elsif parts.length == 2 && slot_config[:default]
|
|
36
|
+
# Default slot: icon:name
|
|
37
|
+
name = parts[1]
|
|
38
|
+
icons[slot_config[:default]] = name unless name.empty?
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
remaining_tokens << token
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
{ icons: icons, remaining: remaining_tokens.join(' ') }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Generate <wa-icon> HTML elements for parsed icons
|
|
49
|
+
# @param icons_hash [Hash] Slot name => icon name pairs
|
|
50
|
+
# @param slot_map [Hash, nil] Optional mapping from parsed slot names to HTML slot attributes
|
|
51
|
+
# @return [String] HTML string with <wa-icon> elements
|
|
52
|
+
def self.to_html(icons_hash, slot_map = nil)
|
|
53
|
+
icons_hash.map do |slot, name|
|
|
54
|
+
html_slot = slot_map ? (slot_map[slot] || slot) : slot
|
|
55
|
+
if html_slot == 'content'
|
|
56
|
+
"<wa-icon name=\"#{name}\"></wa-icon>"
|
|
57
|
+
else
|
|
58
|
+
"<wa-icon slot=\"#{html_slot}\" name=\"#{name}\"></wa-icon>"
|
|
59
|
+
end
|
|
60
|
+
end.join
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'base_transformer'
|
|
4
4
|
require_relative '../attribute_parser'
|
|
5
|
+
require_relative '../icon_slot_parser'
|
|
5
6
|
|
|
6
7
|
module Markawesome
|
|
7
8
|
# Transforms button syntax into wa-button elements
|
|
@@ -31,6 +32,8 @@ module Markawesome
|
|
|
31
32
|
disabled: %w[disabled]
|
|
32
33
|
}.freeze
|
|
33
34
|
|
|
35
|
+
ICON_SLOTS = { default: 'start', slots: %w[start end] }.freeze
|
|
36
|
+
|
|
34
37
|
def self.transform(content)
|
|
35
38
|
# Define both regex patterns - capture all space-separated parameters
|
|
36
39
|
primary_regex = /^%%%([^\n]*)\n(.*?)\n%%%/m
|
|
@@ -40,10 +43,11 @@ module Markawesome
|
|
|
40
43
|
transform_proc = proc do |params_string, button_content|
|
|
41
44
|
button_content = button_content.strip
|
|
42
45
|
|
|
43
|
-
# Parse
|
|
44
|
-
|
|
46
|
+
# Parse icon tokens first, then pass remaining to AttributeParser
|
|
47
|
+
icon_result = IconSlotParser.parse(params_string, ICON_SLOTS)
|
|
48
|
+
attributes = AttributeParser.parse(icon_result[:remaining], BUTTON_ATTRIBUTES)
|
|
45
49
|
|
|
46
|
-
build_button_html(button_content, attributes)
|
|
50
|
+
build_button_html(button_content, attributes, icon_result[:icons])
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
# Apply both patterns
|
|
@@ -54,7 +58,7 @@ module Markawesome
|
|
|
54
58
|
class << self
|
|
55
59
|
private
|
|
56
60
|
|
|
57
|
-
def build_button_html(content, attributes)
|
|
61
|
+
def build_button_html(content, attributes, icons = {})
|
|
58
62
|
# Build HTML attributes from parsed attributes
|
|
59
63
|
html_attrs = []
|
|
60
64
|
|
|
@@ -67,6 +71,7 @@ module Markawesome
|
|
|
67
71
|
html_attrs << 'disabled' if attributes[:disabled]
|
|
68
72
|
|
|
69
73
|
attrs_string = html_attrs.empty? ? '' : " #{html_attrs.join(' ')}"
|
|
74
|
+
icon_html = IconSlotParser.to_html(icons)
|
|
70
75
|
|
|
71
76
|
# Check if content contains a markdown link
|
|
72
77
|
link_match = content.match(/^\[([^\]]+)\]\(([^)]+)\)$/)
|
|
@@ -83,7 +88,7 @@ module Markawesome
|
|
|
83
88
|
# Fix whitespace issues like in badges
|
|
84
89
|
button_html = button_html.gsub(%r{(</\w+>)\s+}, '\1 ')
|
|
85
90
|
|
|
86
|
-
"<wa-button#{attrs_string} href=\"#{link_url}\">#{button_html}</wa-button>"
|
|
91
|
+
"<wa-button#{attrs_string} href=\"#{link_url}\">#{icon_html}#{button_html}</wa-button>"
|
|
87
92
|
else
|
|
88
93
|
# It's a regular button
|
|
89
94
|
button_html = markdown_to_html(content).strip
|
|
@@ -92,7 +97,7 @@ module Markawesome
|
|
|
92
97
|
# Fix whitespace issues like in badges
|
|
93
98
|
button_html = button_html.gsub(%r{(</\w+>)\s+}, '\1 ')
|
|
94
99
|
|
|
95
|
-
"<wa-button#{attrs_string}>#{button_html}</wa-button>"
|
|
100
|
+
"<wa-button#{attrs_string}>#{icon_html}#{button_html}</wa-button>"
|
|
96
101
|
end
|
|
97
102
|
end
|
|
98
103
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'base_transformer'
|
|
4
4
|
require_relative '../attribute_parser'
|
|
5
|
+
require_relative '../icon_slot_parser'
|
|
5
6
|
|
|
6
7
|
module Markawesome
|
|
7
8
|
# Transforms callout syntax into wa-callout elements
|
|
@@ -17,6 +18,7 @@ module Markawesome
|
|
|
17
18
|
appearance: %w[accent filled outlined plain filled-outlined]
|
|
18
19
|
}.freeze
|
|
19
20
|
VARIANT_ALIASES = { 'info' => 'brand' }.freeze
|
|
21
|
+
ICON_SLOTS = { default: 'icon', slots: %w[icon] }.freeze
|
|
20
22
|
|
|
21
23
|
def self.transform(content)
|
|
22
24
|
variant_pattern = VARIANTS.join('|')
|
|
@@ -25,13 +27,21 @@ module Markawesome
|
|
|
25
27
|
|
|
26
28
|
transform_proc = proc do |variant, extra_params, inner_content|
|
|
27
29
|
actual_variant = VARIANT_ALIASES.fetch(variant, variant)
|
|
28
|
-
|
|
30
|
+
|
|
31
|
+
# Parse icon tokens first, then pass remaining to AttributeParser
|
|
32
|
+
icon_result = IconSlotParser.parse(extra_params, ICON_SLOTS)
|
|
33
|
+
extra_attrs = AttributeParser.parse(icon_result[:remaining], CALLOUT_ATTRIBUTES)
|
|
29
34
|
|
|
30
35
|
attr_parts = ["variant=\"#{actual_variant}\""]
|
|
31
36
|
attr_parts << "appearance=\"#{extra_attrs[:appearance]}\"" if extra_attrs[:appearance]
|
|
32
37
|
attr_parts << "size=\"#{extra_attrs[:size]}\"" if extra_attrs[:size]
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
# Use custom icon if provided, otherwise use default variant icon
|
|
40
|
+
icon_html = if icon_result[:icons]['icon']
|
|
41
|
+
"<wa-icon slot=\"icon\" name=\"#{icon_result[:icons]['icon']}\" variant=\"solid\"></wa-icon>"
|
|
42
|
+
else
|
|
43
|
+
icon_for(actual_variant)
|
|
44
|
+
end
|
|
35
45
|
html_content = "#{icon_html}#{markdown_to_html(inner_content)}"
|
|
36
46
|
|
|
37
47
|
"<wa-callout #{attr_parts.join(' ')}>#{html_content}</wa-callout>"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'base_transformer'
|
|
4
4
|
require_relative '../attribute_parser'
|
|
5
|
+
require_relative '../icon_slot_parser'
|
|
5
6
|
|
|
6
7
|
module Markawesome
|
|
7
8
|
# Transforms summary/details syntax into wa-details elements
|
|
@@ -19,6 +20,12 @@ module Markawesome
|
|
|
19
20
|
open: %w[open]
|
|
20
21
|
}.freeze
|
|
21
22
|
|
|
23
|
+
ICON_SLOTS = {
|
|
24
|
+
default: nil,
|
|
25
|
+
slots: %w[expand collapse],
|
|
26
|
+
slot_map: { 'expand' => 'expand-icon', 'collapse' => 'collapse-icon' }
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
22
29
|
def self.transform(content)
|
|
23
30
|
# Define both regex patterns - capture parameter string
|
|
24
31
|
primary_regex = /^\^\^\^?(.*?)\n(.*?)\n^>>>\n(.*?)\n^\^\^\^?/m
|
|
@@ -29,11 +36,12 @@ module Markawesome
|
|
|
29
36
|
summary_content = summary_content.strip
|
|
30
37
|
details_content = details_content.strip
|
|
31
38
|
|
|
32
|
-
# Parse
|
|
33
|
-
|
|
39
|
+
# Parse icon tokens first, then pass remaining to AttributeParser and name extraction
|
|
40
|
+
icon_result = IconSlotParser.parse(params_string, ICON_SLOTS)
|
|
41
|
+
attributes = AttributeParser.parse(icon_result[:remaining], COMPONENT_ATTRIBUTES)
|
|
34
42
|
|
|
35
43
|
# Extract name parameter (format: name:value) - special handling
|
|
36
|
-
name_value = extract_name_value(
|
|
44
|
+
name_value = extract_name_value(icon_result[:remaining])
|
|
37
45
|
|
|
38
46
|
appearance_class = normalize_appearance(attributes[:appearance])
|
|
39
47
|
icon_placement = attributes[:icon_placement] || 'end'
|
|
@@ -46,9 +54,11 @@ module Markawesome
|
|
|
46
54
|
attr_parts << 'open' if attributes[:open]
|
|
47
55
|
attr_parts << "name='#{name_value}'" if name_value
|
|
48
56
|
|
|
57
|
+
icon_html = IconSlotParser.to_html(icon_result[:icons], ICON_SLOTS[:slot_map])
|
|
58
|
+
|
|
49
59
|
"<wa-details #{attr_parts.join(' ')}>" \
|
|
50
60
|
"<span slot='summary'>#{summary_html}</span>" \
|
|
51
|
-
"#{details_html}</wa-details>"
|
|
61
|
+
"#{icon_html}#{details_html}</wa-details>"
|
|
52
62
|
end
|
|
53
63
|
|
|
54
64
|
# Apply both patterns
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'base_transformer'
|
|
4
4
|
require_relative '../attribute_parser'
|
|
5
|
+
require_relative '../icon_slot_parser'
|
|
5
6
|
|
|
6
7
|
module Markawesome
|
|
7
8
|
# Transforms tag syntax into wa-tag elements
|
|
@@ -25,6 +26,8 @@ module Markawesome
|
|
|
25
26
|
'with-remove': %w[with-remove]
|
|
26
27
|
}.freeze
|
|
27
28
|
|
|
29
|
+
ICON_SLOTS = { default: 'content', slots: %w[content] }.freeze
|
|
30
|
+
|
|
28
31
|
def self.transform(content)
|
|
29
32
|
# Define regex patterns
|
|
30
33
|
# Block syntax (multiline with newlines) - supports both LF and CRLF
|
|
@@ -51,10 +54,14 @@ module Markawesome
|
|
|
51
54
|
params_tokens = []
|
|
52
55
|
content_tokens = []
|
|
53
56
|
|
|
54
|
-
# Separate attribute tokens from content tokens
|
|
57
|
+
# Separate attribute and icon tokens from content tokens
|
|
55
58
|
tokens.each do |token|
|
|
56
59
|
matched = COMPONENT_ATTRIBUTES.any? { |_attr, values| values.include?(token) }
|
|
57
|
-
matched
|
|
60
|
+
if matched || token.start_with?('icon:')
|
|
61
|
+
params_tokens << token
|
|
62
|
+
else
|
|
63
|
+
content_tokens << token
|
|
64
|
+
end
|
|
58
65
|
end
|
|
59
66
|
|
|
60
67
|
# Build params and content strings
|
|
@@ -81,8 +88,9 @@ module Markawesome
|
|
|
81
88
|
private
|
|
82
89
|
|
|
83
90
|
def build_tag_html(content, params)
|
|
84
|
-
# Parse
|
|
85
|
-
|
|
91
|
+
# Parse icon tokens first, then pass remaining to AttributeParser
|
|
92
|
+
icon_result = IconSlotParser.parse(params, ICON_SLOTS)
|
|
93
|
+
attributes = AttributeParser.parse(icon_result[:remaining], COMPONENT_ATTRIBUTES)
|
|
86
94
|
|
|
87
95
|
# Build HTML attributes
|
|
88
96
|
html_attrs = []
|
|
@@ -93,13 +101,14 @@ module Markawesome
|
|
|
93
101
|
html_attrs << 'with-remove' if attributes[:'with-remove']
|
|
94
102
|
|
|
95
103
|
attrs_string = html_attrs.empty? ? '' : " #{html_attrs.join(' ')}"
|
|
104
|
+
icon_html = IconSlotParser.to_html(icon_result[:icons])
|
|
96
105
|
|
|
97
106
|
tag_html = markdown_to_html(content).strip
|
|
98
107
|
|
|
99
108
|
# Remove paragraph tags if the content is just text
|
|
100
109
|
tag_html = tag_html.gsub(%r{^<p>(.*)</p>$}m, '\1')
|
|
101
110
|
|
|
102
|
-
"<wa-tag#{attrs_string}>#{tag_html}</wa-tag>"
|
|
111
|
+
"<wa-tag#{attrs_string}>#{icon_html}#{tag_html}</wa-tag>"
|
|
103
112
|
end
|
|
104
113
|
end
|
|
105
114
|
end
|
data/lib/markawesome/version.rb
CHANGED
data/lib/markawesome.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'markawesome/version'
|
|
4
|
+
require_relative 'markawesome/icon_slot_parser'
|
|
4
5
|
require_relative 'markawesome/transformer'
|
|
5
6
|
|
|
6
7
|
# Main module for Markawesome - framework-agnostic Markdown to Web Awesome component transformer
|
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.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Janne Waren
|
|
@@ -92,6 +92,7 @@ files:
|
|
|
92
92
|
- README.md
|
|
93
93
|
- lib/markawesome.rb
|
|
94
94
|
- lib/markawesome/attribute_parser.rb
|
|
95
|
+
- lib/markawesome/icon_slot_parser.rb
|
|
95
96
|
- lib/markawesome/transformer.rb
|
|
96
97
|
- lib/markawesome/transformers.rb
|
|
97
98
|
- lib/markawesome/transformers/badge_transformer.rb
|