markawesome 0.12.0 → 0.14.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 +20 -0
- data/lib/markawesome/icon_attributes.rb +20 -0
- data/lib/markawesome/plain_markdown_renderer.rb +5 -3
- data/lib/markawesome/transformer.rb +4 -0
- data/lib/markawesome/transformers/accordion_transformer.rb +138 -0
- data/lib/markawesome/transformers/callout_transformer.rb +16 -10
- data/lib/markawesome/transformers/icon_transformer.rb +43 -11
- data/lib/markawesome/transformers.rb +1 -0
- data/lib/markawesome/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: afd9d40552aa4f47c46ce12a72e4340075e9049a0d374dabbd894d6b4e9c0771
|
|
4
|
+
data.tar.gz: bf63ff67375e59593d352c35b9e6852fd4f436a4005eba52bdf695b54d734f11
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eeb2dffdb406f0eeb414cedfe834a616540956dddf5854c972b9743088e62b9d92054a4a1db2be1dc68817b5b81bec1ef7f0b30a0055a5508c6641710b8dc5f1
|
|
7
|
+
data.tar.gz: c76afeb5d61c70cab00f10e8a3a0d9b2f825bf04b5c4e5f46915506092fb826c9f1e4cb49061da3c29437404c2c0d2188eaf38d634704a56f6398a3410438770
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,26 @@ 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.14.0] - 2026-06-24
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- New `AccordionTransformer` producing Web Awesome `<wa-accordion>` / `<wa-accordion-item>` — a multi-section collapsible container for FAQs, docs sections, and "show more" content (the grouped, mutually-exclusive-capable sibling of `details`). The `/` delimiter is the container/item marker: container fence `//////` (6×), item fence `///` (3×) with an explicit `///` close, mirroring tabs (`++++++`/`+++`). An alternative `:::wa-accordion … :::` form is also accepted.
|
|
12
|
+
- **Container line** (bare tokens, order-independent, rightmost-wins): `appearance` (`outlined` default, `filled`, `filled-outlined`, `plain`), `mode` (`multiple`, `single`, `single-collapsible`), `icon-placement` (`start`, `end`), and a value-form `heading:N` → `heading-level="N"` where `N` is `1`–`6` or `none` (out-of-range values fall back to omitting the attribute). `appearance` is always emitted (defaulting to `outlined`); `mode`, `icon-placement`, and `heading-level` are emitted only when specified.
|
|
13
|
+
- **Item header** (`/// [expanded] [disabled] [icon:name] Label`): leading `expanded`/`disabled` flags become the matching boolean attributes; `icon:name` becomes a `<wa-icon slot="icon" name="…">` first child; the remaining text becomes the HTML-escaped `label`. Item bodies are full markdown and may contain other components.
|
|
14
|
+
- **Plain-markdown degradation** (`render_as_markdown`, used for `.md` endpoints / llms.txt): each item degrades to a `### Label` heading followed by its body, mirroring tabs.
|
|
15
|
+
- `wa-accordion` is **experimental** in Web Awesome (added in 3.7), but `expanded`, `disabled`, and the `mode`/`appearance`/`icon-placement`/`heading-level` attributes are all declarative and static-site-safe — no JavaScript required. The interactive `expandAll()`/`collapseAll()` controls and rich/HTML `label` slot are out of scope for v1; item labels are plain text. The `--wa-accordion-divider-color` custom property removed in WA 3.9.0 is intentionally not exposed.
|
|
16
|
+
|
|
17
|
+
## [0.13.0] - 2026-06-20
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- The standalone `:::wa-icon` block now accepts `family` (`classic`, `sharp`, `duotone`, `sharp-duotone`, `brands`), `variant` (`thin`, `light`, `regular`, `solid`), and `animation` (`beat`, `fade`, `beat-fade`, `bounce`, `flip`, `shake`, `spin`, `spin-pulse`, `spin-reverse`) as bare enumerated tokens after the icon name (order-independent, rightmost-wins, unknown tokens dropped — same parsing as button `variant`/`size`). The block body becomes the icon's accessible `label` (stripped, whitespace-collapsed, HTML-escaped); an empty body emits no `label`, leaving the icon presentational per Web Awesome's default. Emit order is deterministic: `name family variant animation label`.
|
|
22
|
+
- `CalloutTransformer` callouts can now override their icon's `family`/`variant`/`animation` using the same bare tokens on the callout line (e.g. `:::warning shake`). The historical `variant="solid"` default is preserved when no icon-variant token is given, so existing callouts render byte-identically. Works alongside the existing `icon:name` override.
|
|
23
|
+
- New shared `Markawesome::IconAttributes` module — single source of truth for the `<wa-icon>` family/variant/animation vocabulary (verified against Web Awesome 3.x), consumed by both `IconTransformer` and `CalloutTransformer`.
|
|
24
|
+
|
|
25
|
+
The inline `$$$name` form stays **name-only** (mid-prose, semantically decorative). Embedded `icon:slot:name` icons in button/tag/details are unchanged. Note: `family`/`variant` produce a *visible* weight/family change only with a Font Awesome Pro kit; the attributes are always emitted to the DOM regardless of kit tier (validated against the examples site's WA 3.8.0 kit, where `animation` and `label` are fully functional and the weight/family attributes reach the element without a visible glyph swap on the free tier).
|
|
26
|
+
|
|
7
27
|
## [0.12.0] - 2026-06-19
|
|
8
28
|
|
|
9
29
|
### Added
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Markawesome
|
|
4
|
+
# Shared <wa-icon> attribute vocabulary (family/variant/animation) and emission helper.
|
|
5
|
+
# Values verified against Web Awesome 3.x. Adding a value later is a one-line change.
|
|
6
|
+
module IconAttributes
|
|
7
|
+
SCHEMA = {
|
|
8
|
+
family: %w[classic sharp duotone sharp-duotone brands],
|
|
9
|
+
variant: %w[thin light regular solid],
|
|
10
|
+
animation: %w[beat fade beat-fade bounce flip shake spin spin-pulse spin-reverse]
|
|
11
|
+
}.freeze
|
|
12
|
+
|
|
13
|
+
# Returns ordered ['family="…"', 'variant="…"', 'animation="…"'] for present keys.
|
|
14
|
+
def self.pairs(attributes)
|
|
15
|
+
%i[family variant animation].filter_map do |key|
|
|
16
|
+
"#{key}=\"#{attributes[key]}\"" if attributes[key]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -24,8 +24,8 @@ module Markawesome
|
|
|
24
24
|
# plugin during boot to override the default rendering for a single
|
|
25
25
|
# component without forking the gem.
|
|
26
26
|
#
|
|
27
|
-
# @param component [Symbol] one of :callout, :badge, :button,
|
|
28
|
-
# :carousel, :comparison, :copy_button, :details, :dialog, :icon,
|
|
27
|
+
# @param component [Symbol] one of :accordion, :callout, :badge, :button,
|
|
28
|
+
# :card, :carousel, :comparison, :copy_button, :details, :dialog, :icon,
|
|
29
29
|
# :image_dialog, :layout, :popover, :tabs, :tag.
|
|
30
30
|
# @yield [content, options] Proc that receives the full source content
|
|
31
31
|
# and the renderer options; returns the content with that component
|
|
@@ -58,6 +58,7 @@ module Markawesome
|
|
|
58
58
|
icon
|
|
59
59
|
tag
|
|
60
60
|
tabs
|
|
61
|
+
accordion
|
|
61
62
|
].freeze
|
|
62
63
|
|
|
63
64
|
TRANSFORMER_MAP = {
|
|
@@ -75,7 +76,8 @@ module Markawesome
|
|
|
75
76
|
dialog: DialogTransformer,
|
|
76
77
|
icon: IconTransformer,
|
|
77
78
|
tag: TagTransformer,
|
|
78
|
-
tabs: TabsTransformer
|
|
79
|
+
tabs: TabsTransformer,
|
|
80
|
+
accordion: AccordionTransformer
|
|
79
81
|
}.freeze
|
|
80
82
|
|
|
81
83
|
def self.process(content, options = {})
|
|
@@ -32,6 +32,10 @@ module Markawesome
|
|
|
32
32
|
content = TagTransformer.transform(content)
|
|
33
33
|
content = TabsTransformer.transform(content)
|
|
34
34
|
|
|
35
|
+
# Accordion runs last so item bodies may contain other already-transformed
|
|
36
|
+
# components (same reason tabs runs near the end).
|
|
37
|
+
content = AccordionTransformer.transform(content)
|
|
38
|
+
|
|
35
39
|
CodeBlockProtector.restore(content, tokens)
|
|
36
40
|
end
|
|
37
41
|
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
require_relative '../attribute_parser'
|
|
5
|
+
require_relative '../icon_slot_parser'
|
|
6
|
+
|
|
7
|
+
module Markawesome
|
|
8
|
+
# Transforms accordion syntax into wa-accordion / wa-accordion-item elements
|
|
9
|
+
# Primary syntax:
|
|
10
|
+
# //////appearance? mode? icon-placement? heading:N?
|
|
11
|
+
# /// [expanded] [disabled] [icon:name] Label text
|
|
12
|
+
# item body markdown
|
|
13
|
+
# ///
|
|
14
|
+
# //////
|
|
15
|
+
# Alternative syntax: :::wa-accordion ...same items... :::
|
|
16
|
+
#
|
|
17
|
+
# Container attributes (bare, order-independent, rightmost-wins):
|
|
18
|
+
# - appearance: outlined (default), filled, filled-outlined, plain
|
|
19
|
+
# - mode: multiple (default), single, single-collapsible
|
|
20
|
+
# - icon-placement: start, end (default emitted only when given)
|
|
21
|
+
# - heading:N -> heading-level="N" where N is 1-6 or "none"
|
|
22
|
+
# Item tokens (leading flags, then the rest of the line is the label):
|
|
23
|
+
# - expanded -> expanded; disabled -> disabled
|
|
24
|
+
# - icon:name -> <wa-icon slot="icon" name="name"></wa-icon> as first child
|
|
25
|
+
#
|
|
26
|
+
# wa-accordion is experimental in Web Awesome (added 3.7). expanded/disabled
|
|
27
|
+
# and the mode/appearance/icon-placement attributes are all static-safe.
|
|
28
|
+
class AccordionTransformer < BaseTransformer
|
|
29
|
+
CONTAINER_ATTRIBUTES = {
|
|
30
|
+
appearance: %w[outlined filled filled-outlined plain],
|
|
31
|
+
mode: %w[multiple single single-collapsible],
|
|
32
|
+
icon_placement: %w[start end]
|
|
33
|
+
}.freeze
|
|
34
|
+
|
|
35
|
+
ICON_SLOTS = {
|
|
36
|
+
default: 'icon',
|
|
37
|
+
slots: %w[icon],
|
|
38
|
+
slot_map: { 'icon' => 'icon' }
|
|
39
|
+
}.freeze
|
|
40
|
+
|
|
41
|
+
ITEM_FLAGS = %w[expanded disabled].freeze
|
|
42
|
+
|
|
43
|
+
PRIMARY_REGEX = %r{^/{6}([^\n]*)\n((?:/{3} [^\n]+\n.*?\n/{3}\n?)+)/{6}}m
|
|
44
|
+
ALTERNATIVE_REGEX = %r{^:::wa-accordion\s*([^\n]*)\n((?:/{3} [^\n]+\n.*?\n/{3}\n?)+):::}m
|
|
45
|
+
ITEM_REGEX = %r{^/{3} ([^\n]+)\n(.*?)\n/{3}}m
|
|
46
|
+
|
|
47
|
+
def self.transform(content)
|
|
48
|
+
transform_proc = proc do |params_string, items_block, _third|
|
|
49
|
+
attributes = AttributeParser.parse(params_string.to_s.strip, CONTAINER_ATTRIBUTES)
|
|
50
|
+
heading_level = extract_heading_level(params_string)
|
|
51
|
+
|
|
52
|
+
attr_parts = ["appearance=\"#{normalize_appearance(attributes[:appearance])}\""]
|
|
53
|
+
attr_parts << "mode=\"#{attributes[:mode]}\"" if attributes[:mode]
|
|
54
|
+
attr_parts << "icon-placement=\"#{attributes[:icon_placement]}\"" if attributes[:icon_placement]
|
|
55
|
+
attr_parts << "heading-level=\"#{heading_level}\"" if heading_level
|
|
56
|
+
|
|
57
|
+
"<wa-accordion #{attr_parts.join(' ')}>#{build_items(items_block)}</wa-accordion>"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
patterns = dual_syntax_patterns(PRIMARY_REGEX, ALTERNATIVE_REGEX, transform_proc)
|
|
61
|
+
apply_multiple_patterns(content, patterns)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.render_as_markdown(content, _options = {})
|
|
65
|
+
transform_proc = proc do |_params_string, items_block, _third|
|
|
66
|
+
items_block.scan(ITEM_REGEX).map do |header, body|
|
|
67
|
+
_flags, label = parse_item_flags_and_label(IconSlotParser.parse(header, ICON_SLOTS)[:remaining])
|
|
68
|
+
"### #{label}\n\n#{body.strip}"
|
|
69
|
+
end.join("\n\n")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
patterns = dual_syntax_patterns(PRIMARY_REGEX, ALTERNATIVE_REGEX, transform_proc)
|
|
73
|
+
apply_multiple_patterns(content, patterns)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class << self
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def build_items(items_block)
|
|
80
|
+
items_block.scan(ITEM_REGEX).map do |header, body|
|
|
81
|
+
icon_result = IconSlotParser.parse(header, ICON_SLOTS)
|
|
82
|
+
flags, label = parse_item_flags_and_label(icon_result[:remaining])
|
|
83
|
+
|
|
84
|
+
item_attrs = ["label=\"#{escape_html(label)}\""]
|
|
85
|
+
item_attrs << 'expanded' if flags.include?('expanded')
|
|
86
|
+
item_attrs << 'disabled' if flags.include?('disabled')
|
|
87
|
+
|
|
88
|
+
icon_html = IconSlotParser.to_html(icon_result[:icons], ICON_SLOTS[:slot_map])
|
|
89
|
+
body_html = markdown_to_html(body.strip)
|
|
90
|
+
|
|
91
|
+
"<wa-accordion-item #{item_attrs.join(' ')}>#{icon_html}#{body_html}</wa-accordion-item>"
|
|
92
|
+
end.join
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Consume leading expanded/disabled tokens; the remainder is the label.
|
|
96
|
+
def parse_item_flags_and_label(remaining)
|
|
97
|
+
tokens = remaining.to_s.strip.split(/\s+/)
|
|
98
|
+
flags = []
|
|
99
|
+
flags << tokens.shift while tokens.any? && ITEM_FLAGS.include?(tokens.first)
|
|
100
|
+
[flags, tokens.join(' ')]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def extract_heading_level(params_string)
|
|
104
|
+
return nil if params_string.nil? || params_string.strip.empty?
|
|
105
|
+
|
|
106
|
+
token = params_string.strip.split(/\s+/).find { |t| t.start_with?('heading:') }
|
|
107
|
+
return nil unless token
|
|
108
|
+
|
|
109
|
+
value = token.sub(/^heading:/, '')
|
|
110
|
+
return value if value == 'none' || value.match?(/\A[1-6]\z/)
|
|
111
|
+
|
|
112
|
+
nil
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def normalize_appearance(appearance_param)
|
|
116
|
+
case appearance_param
|
|
117
|
+
when 'filled'
|
|
118
|
+
'filled'
|
|
119
|
+
when 'filled-outlined'
|
|
120
|
+
'filled-outlined'
|
|
121
|
+
when 'plain'
|
|
122
|
+
'plain'
|
|
123
|
+
else
|
|
124
|
+
'outlined'
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def escape_html(text)
|
|
129
|
+
text.to_s
|
|
130
|
+
.gsub('&', '&')
|
|
131
|
+
.gsub('<', '<')
|
|
132
|
+
.gsub('>', '>')
|
|
133
|
+
.gsub('"', '"')
|
|
134
|
+
.gsub("'", ''')
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative 'base_transformer'
|
|
4
4
|
require_relative '../attribute_parser'
|
|
5
5
|
require_relative '../icon_slot_parser'
|
|
6
|
+
require_relative '../icon_attributes'
|
|
6
7
|
|
|
7
8
|
module Markawesome
|
|
8
9
|
# Transforms callout syntax into wa-callout elements
|
|
@@ -28,20 +29,20 @@ module Markawesome
|
|
|
28
29
|
transform_proc = proc do |variant, extra_params, inner_content|
|
|
29
30
|
actual_variant = VARIANT_ALIASES.fetch(variant, variant)
|
|
30
31
|
|
|
31
|
-
# Parse icon tokens first, then pass remaining to AttributeParser
|
|
32
|
+
# Parse icon tokens first, then pass remaining to AttributeParser.
|
|
33
|
+
# CALLOUT_ATTRIBUTES and IconAttributes::SCHEMA namespaces are disjoint, so the
|
|
34
|
+
# same remaining-token string can be parsed against both independently.
|
|
32
35
|
icon_result = IconSlotParser.parse(extra_params, ICON_SLOTS)
|
|
33
36
|
extra_attrs = AttributeParser.parse(icon_result[:remaining], CALLOUT_ATTRIBUTES)
|
|
37
|
+
icon_attrs = AttributeParser.parse(icon_result[:remaining], IconAttributes::SCHEMA)
|
|
38
|
+
icon_attrs[:variant] ||= 'solid' # preserve historical default
|
|
34
39
|
|
|
35
40
|
attr_parts = ["variant=\"#{actual_variant}\""]
|
|
36
41
|
attr_parts << "appearance=\"#{extra_attrs[:appearance]}\"" if extra_attrs[:appearance]
|
|
37
42
|
attr_parts << "size=\"#{extra_attrs[:size]}\"" if extra_attrs[:size]
|
|
38
43
|
|
|
39
|
-
|
|
40
|
-
icon_html =
|
|
41
|
-
"<wa-icon slot=\"icon\" name=\"#{icon_result[:icons]['icon']}\" variant=\"solid\"></wa-icon>"
|
|
42
|
-
else
|
|
43
|
-
icon_for(actual_variant)
|
|
44
|
-
end
|
|
44
|
+
icon_name = icon_result[:icons]['icon'] || icon_name_for(actual_variant)
|
|
45
|
+
icon_html = callout_icon_html(icon_name, icon_attrs)
|
|
45
46
|
html_content = "#{icon_html}#{markdown_to_html(inner_content)}"
|
|
46
47
|
|
|
47
48
|
"<wa-callout #{attr_parts.join(' ')}>#{html_content}</wa-callout>"
|
|
@@ -79,11 +80,16 @@ module Markawesome
|
|
|
79
80
|
class << self
|
|
80
81
|
private
|
|
81
82
|
|
|
82
|
-
def
|
|
83
|
+
def icon_name_for(variant)
|
|
83
84
|
config = Markawesome.configuration
|
|
84
85
|
icons = config&.callout_icons || default_icons
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
icons[variant.to_sym]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def callout_icon_html(name, attributes)
|
|
90
|
+
parts = ['slot="icon"', "name=\"#{name}\""]
|
|
91
|
+
parts.concat(IconAttributes.pairs(attributes))
|
|
92
|
+
"<wa-icon #{parts.join(' ')}></wa-icon>"
|
|
87
93
|
end
|
|
88
94
|
|
|
89
95
|
def default_icons
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'base_transformer'
|
|
4
|
+
require_relative '../attribute_parser'
|
|
5
|
+
require_relative '../icon_attributes'
|
|
4
6
|
|
|
5
7
|
module Markawesome
|
|
6
8
|
# Transforms icon syntax into wa-icon elements
|
|
7
|
-
# Primary syntax: $$$icon-name
|
|
8
|
-
# Alternative syntax: :::wa-icon icon-name
|
|
9
|
+
# Primary syntax: $$$icon-name (name only, decorative)
|
|
10
|
+
# Alternative syntax: :::wa-icon icon-name [family] [variant] [animation]\n[label]\n:::
|
|
9
11
|
#
|
|
10
12
|
# Examples:
|
|
11
13
|
# $$$settings -> <wa-icon name="settings"></wa-icon>
|
|
12
14
|
# $$$home -> <wa-icon name="home"></wa-icon>
|
|
13
15
|
# $$$user-circle -> <wa-icon name="user-circle"></wa-icon>
|
|
16
|
+
# :::wa-icon star spin\n::: -> <wa-icon name="star" animation="spin"></wa-icon>
|
|
17
|
+
# :::wa-icon heart solid\nFavorite\n::: ->
|
|
18
|
+
# <wa-icon name="heart" variant="solid" label="Favorite"></wa-icon>
|
|
14
19
|
class IconTransformer < BaseTransformer
|
|
20
|
+
# First-line params + optional multi-line body. The closer is anchored to a line
|
|
21
|
+
# start; the opener is intentionally not anchored so it still matches mid-prose.
|
|
22
|
+
ALTERNATIVE_REGEX = /:::wa-icon[ \t]+([^\n]*?)[ \t]*\n(.*?)^:::/m
|
|
15
23
|
def self.transform(content)
|
|
16
24
|
# Protect code blocks first
|
|
17
25
|
protected_content, code_blocks = protect_code_blocks(content)
|
|
@@ -25,9 +33,16 @@ module Markawesome
|
|
|
25
33
|
end
|
|
26
34
|
|
|
27
35
|
# Apply alternative syntax transformation
|
|
28
|
-
result = result.gsub(
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
result = result.gsub(ALTERNATIVE_REGEX) do
|
|
37
|
+
first_line = ::Regexp.last_match(1)
|
|
38
|
+
raw_body = ::Regexp.last_match(2)
|
|
39
|
+
|
|
40
|
+
tokens = first_line.strip.split(/\s+/)
|
|
41
|
+
icon_name = tokens.shift # first token is always the name
|
|
42
|
+
attributes = AttributeParser.parse(tokens.join(' '), IconAttributes::SCHEMA)
|
|
43
|
+
label = normalize_label(raw_body)
|
|
44
|
+
|
|
45
|
+
build_icon_html(icon_name, attributes, label)
|
|
31
46
|
end
|
|
32
47
|
|
|
33
48
|
# Restore code blocks
|
|
@@ -39,7 +54,12 @@ module Markawesome
|
|
|
39
54
|
|
|
40
55
|
# Drop primary-syntax icons entirely.
|
|
41
56
|
result = protected_content.gsub(/\$\$\$([a-zA-Z0-9\-_]+)(?![a-zA-Z0-9\-_]|\s+name\b)/, '')
|
|
42
|
-
|
|
57
|
+
|
|
58
|
+
# A labeled block degrades to its label text (collapsed, not HTML-escaped — it
|
|
59
|
+
# re-enters a markdown stream); an unlabeled block degrades to ''.
|
|
60
|
+
result = result.gsub(ALTERNATIVE_REGEX) do
|
|
61
|
+
::Regexp.last_match(2).to_s.strip.gsub(/\s+/, ' ')
|
|
62
|
+
end
|
|
43
63
|
|
|
44
64
|
restore_code_blocks(result, code_blocks)
|
|
45
65
|
end
|
|
@@ -47,12 +67,24 @@ module Markawesome
|
|
|
47
67
|
class << self
|
|
48
68
|
private
|
|
49
69
|
|
|
50
|
-
def build_icon_html(icon_name)
|
|
51
|
-
|
|
52
|
-
|
|
70
|
+
def build_icon_html(icon_name, attributes = {}, label = nil)
|
|
71
|
+
parts = ["name=\"#{icon_name.strip}\""]
|
|
72
|
+
parts.concat(IconAttributes.pairs(attributes))
|
|
73
|
+
parts << "label=\"#{label}\"" if label && !label.empty?
|
|
74
|
+
"<wa-icon #{parts.join(' ')}></wa-icon>"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Label is an attribute VALUE, not markup: strip, collapse whitespace, HTML-escape.
|
|
78
|
+
# Deliberately NOT run through markdown_to_html (unlike button/callout bodies).
|
|
79
|
+
def normalize_label(raw_body)
|
|
80
|
+
text = raw_body.to_s.strip.gsub(/\s+/, ' ')
|
|
81
|
+
text.empty? ? nil : escape_html(text)
|
|
82
|
+
end
|
|
53
83
|
|
|
54
|
-
|
|
55
|
-
|
|
84
|
+
# Same escape set as Dialog/Popover transformers.
|
|
85
|
+
def escape_html(text)
|
|
86
|
+
text.gsub('&', '&').gsub('<', '<').gsub('>', '>')
|
|
87
|
+
.gsub('"', '"').gsub("'", ''')
|
|
56
88
|
end
|
|
57
89
|
|
|
58
90
|
def protect_code_blocks(content)
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
# This file makes it easy to require all transformers at once
|
|
5
5
|
|
|
6
6
|
require_relative 'transformers/base_transformer'
|
|
7
|
+
require_relative 'transformers/accordion_transformer'
|
|
7
8
|
require_relative 'transformers/badge_transformer'
|
|
8
9
|
require_relative 'transformers/button_transformer'
|
|
9
10
|
require_relative 'transformers/callout_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.14.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Janne Waren
|
|
@@ -79,10 +79,12 @@ files:
|
|
|
79
79
|
- lib/markawesome.rb
|
|
80
80
|
- lib/markawesome/attribute_parser.rb
|
|
81
81
|
- lib/markawesome/code_block_protector.rb
|
|
82
|
+
- lib/markawesome/icon_attributes.rb
|
|
82
83
|
- lib/markawesome/icon_slot_parser.rb
|
|
83
84
|
- lib/markawesome/plain_markdown_renderer.rb
|
|
84
85
|
- lib/markawesome/transformer.rb
|
|
85
86
|
- lib/markawesome/transformers.rb
|
|
87
|
+
- lib/markawesome/transformers/accordion_transformer.rb
|
|
86
88
|
- lib/markawesome/transformers/badge_transformer.rb
|
|
87
89
|
- lib/markawesome/transformers/base_transformer.rb
|
|
88
90
|
- lib/markawesome/transformers/button_transformer.rb
|