markawesome 0.4.0 → 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 +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +33 -3
- data/lib/markawesome/transformer.rb +1 -0
- data/lib/markawesome/transformers/card_transformer.rb +5 -4
- data/lib/markawesome/transformers/layout_transformer.rb +121 -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: 2c03fbaecd8dec3c16fa5e2ddeb07b12d2eb35ad2fbc8389a49b725d77a3c2cf
|
|
4
|
+
data.tar.gz: 6b530bf8caae7b8717411b111e6e3e6f9fb6766373d0b80238cb3fa4ec7f98d6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6e2b2e8804309e702139068db433be5cbb62132eede58ff45a25d871b721bc2adab4a23d34b820ed8dda26907de2d51ab277b30a13f5d9037e3d26efd123d91f
|
|
7
|
+
data.tar.gz: 8ba50a46d31a068af6ae3d2dc28c2832d26b665e4a006fc74b34f5c59ee0a12596f4f8a7a1a98d7412f0150fe25215d3772521fe6fcaff5f1154c69ac91fc684
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,28 @@ 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
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **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
|
+
|
|
13
|
+
## [0.5.0] - 2026-02-10
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **LayoutTransformer**: New `::::` (quadruple colon) syntax for wrapping content in Web Awesome CSS layout containers
|
|
18
|
+
- Supports 6 layout types: `grid`, `stack`, `cluster`, `split`, `flank`, `frame`
|
|
19
|
+
- Common attributes: `gap:SIZE`, `align:VALUE`, `justify:VALUE` for all layouts
|
|
20
|
+
- Grid-specific: `min:CSS_VALUE` for custom minimum column size (`--min-column-size`)
|
|
21
|
+
- Split-specific: `row` and `column` direction modifiers
|
|
22
|
+
- Flank-specific: `start`/`end` position modifiers, `size:CSS_VALUE`, `content:PCT`
|
|
23
|
+
- Frame-specific: `landscape`/`portrait`/`square` aspect ratios, `radius:SIZE`
|
|
24
|
+
- Dual syntax: both `::::grid` and `::::wa-grid` work identically
|
|
25
|
+
- CSS value sanitization for user-provided values (strips quotes, angle brackets, semicolons)
|
|
26
|
+
- Inner content is not markdown-converted, allowing component `:::` syntax to be processed by subsequent transformers
|
|
27
|
+
- Runs first in the pipeline so layout containers wrap around component output
|
|
28
|
+
|
|
7
29
|
## [0.4.0] - 2026-02-09
|
|
8
30
|
|
|
9
31
|
### Added
|
data/README.md
CHANGED
|
@@ -10,22 +10,52 @@ Used as the transformation engine for the [jekyll-webawesome](https://github.com
|
|
|
10
10
|
- 🚀 **Simple Syntax** - Clean, intuitive Markdown extensions
|
|
11
11
|
- ⚙️ **Configurable** - Customize icons, variants, and component behavior
|
|
12
12
|
|
|
13
|
-
## Supported
|
|
13
|
+
## Supported Components
|
|
14
14
|
|
|
15
15
|
| Component | Primary Syntax | Alternative Syntax | HTML Output |
|
|
16
16
|
|-----------|----------------|-------------------|-------------|
|
|
17
17
|
| **Badge** | `!!!variant` | `:::wa-badge variant` | `<wa-badge variant="brand">content</wa-badge>` |
|
|
18
18
|
| **Button** | `%%%variant` | `:::wa-button variant` | `<wa-button variant="brand" href="url">text</wa-button>` or `<wa-button variant="brand">text</wa-button>` |
|
|
19
|
-
| **
|
|
19
|
+
| **Callout** | `:::info` | `:::wa-callout info` | `<wa-callout variant="brand"><wa-icon ...></wa-icon>content</wa-callout>` |
|
|
20
20
|
| **Card** | `===` | `:::wa-card` | `<wa-card>content</wa-card>` |
|
|
21
21
|
| **Carousel** | `~~~~~~` | `:::wa-carousel` | `<wa-carousel>` with carousel items |
|
|
22
22
|
| **Comparison** | `\|\|\|` or `\|\|\|25` | `:::wa-comparison` or `:::wa-comparison 25` | `<wa-comparison>` with before/after slots |
|
|
23
23
|
| **Copy Button** | `<<<` | `:::wa-copy-button` | `<wa-copy-button value="content">content</wa-copy-button>` |
|
|
24
|
-
| **Details** | `^^^appearance? icon-placement?` | `:::wa-details appearance? icon-placement?` | `<wa-details
|
|
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` | `:::wa-icon icon-name` | `<wa-icon name="icon-name"></wa-icon>` |
|
|
27
|
+
| **Image Dialog** | `` | — | Wraps images in clickable `<wa-dialog>` overlays |
|
|
26
28
|
| **Tab Group** | `++++++` | `:::wa-tabs` | `<wa-tab-group><wa-tab>content</wa-tab></wa-tab-group>` |
|
|
27
29
|
| **Tag** | `@@@brand` | `:::wa-tag brand` | `<wa-tag variant="brand">content</wa-tag>` |
|
|
28
30
|
|
|
31
|
+
## Layout Utilities
|
|
32
|
+
|
|
33
|
+
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.
|
|
34
|
+
|
|
35
|
+
| Layout | Primary Syntax | Alternative Syntax | HTML Output |
|
|
36
|
+
|--------|----------------|-------------------|-------------|
|
|
37
|
+
| **Grid** | `::::grid` | `::::wa-grid` | `<div class="wa-grid">content</div>` |
|
|
38
|
+
| **Stack** | `::::stack` | `::::wa-stack` | `<div class="wa-stack">content</div>` |
|
|
39
|
+
| **Cluster** | `::::cluster` | `::::wa-cluster` | `<div class="wa-cluster">content</div>` |
|
|
40
|
+
| **Split** | `::::split` | `::::wa-split` | `<div class="wa-split">content</div>` |
|
|
41
|
+
| **Flank** | `::::flank` | `::::wa-flank` | `<div class="wa-flank">content</div>` |
|
|
42
|
+
| **Frame** | `::::frame` | `::::wa-frame` | `<div class="wa-frame">content</div>` |
|
|
43
|
+
|
|
44
|
+
### Common layout attributes
|
|
45
|
+
|
|
46
|
+
All layouts support these key:value attributes:
|
|
47
|
+
|
|
48
|
+
- `gap:SIZE` — Sets spacing (`0`, `3xs`, `2xs`, `xs`, `s`, `m`, `l`, `xl`, `2xl`, `3xl`)
|
|
49
|
+
- `align:VALUE` — Align items (`start`, `end`, `center`, `stretch`, `baseline`)
|
|
50
|
+
- `justify:VALUE` — Justify content (`start`, `end`, `center`, `space-between`, `space-around`, `space-evenly`)
|
|
51
|
+
|
|
52
|
+
### Layout-specific attributes
|
|
53
|
+
|
|
54
|
+
- **Grid**: `min:CSS_VALUE` — Minimum column size (e.g., `min:200px`)
|
|
55
|
+
- **Split**: `row` or `column` — Direction modifier
|
|
56
|
+
- **Flank**: `start` or `end` — Position modifier; `size:CSS_VALUE`, `content:PCT`
|
|
57
|
+
- **Frame**: `landscape`, `portrait`, or `square` — Aspect ratio; `radius:SIZE` (`s`, `m`, `l`, `pill`, `circle`, `square`)
|
|
58
|
+
|
|
29
59
|
## Installation
|
|
30
60
|
|
|
31
61
|
Add this line to your application's Gemfile:
|
|
@@ -7,6 +7,7 @@ module Markawesome
|
|
|
7
7
|
# Main transformer that orchestrates all component transformers
|
|
8
8
|
class Transformer
|
|
9
9
|
def self.process(content, options = {})
|
|
10
|
+
content = LayoutTransformer.transform(content)
|
|
10
11
|
content = BadgeTransformer.transform(content)
|
|
11
12
|
content = ButtonTransformer.transform(content)
|
|
12
13
|
content = CalloutTransformer.transform(content)
|
|
@@ -10,6 +10,7 @@ module Markawesome
|
|
|
10
10
|
# Supported attributes:
|
|
11
11
|
# appearance: outlined (default), filled, filled-outlined, plain, accent
|
|
12
12
|
# orientation: vertical (default), horizontal
|
|
13
|
+
# Card header: first **bold** line (not a heading) becomes the header slot
|
|
13
14
|
class CardTransformer < BaseTransformer
|
|
14
15
|
CARD_ATTRIBUTES = {
|
|
15
16
|
appearance: %w[outlined filled filled-outlined plain accent],
|
|
@@ -57,11 +58,11 @@ module Markawesome
|
|
|
57
58
|
content = content.sub(/^!\[([^\]]*)\]\(([^)]+)\)\n?/, '')
|
|
58
59
|
end
|
|
59
60
|
|
|
60
|
-
# Extract first
|
|
61
|
-
if content.match(
|
|
61
|
+
# Extract first bold line as header
|
|
62
|
+
if content.match(/^\*\*(.+)\*\*$/)
|
|
62
63
|
parts[:header] = ::Regexp.last_match(1).strip
|
|
63
|
-
# Remove the
|
|
64
|
-
content = content.sub(
|
|
64
|
+
# Remove the bold line from content
|
|
65
|
+
content = content.sub(/^\*\*(.+)\*\*\n?/, '')
|
|
65
66
|
end
|
|
66
67
|
|
|
67
68
|
# Extract trailing buttons/links as footer
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
|
|
5
|
+
module Markawesome
|
|
6
|
+
# Transforms layout syntax into CSS layout utility containers
|
|
7
|
+
# Primary syntax: ::::type params?\ncontent\n::::
|
|
8
|
+
# Alternative syntax: ::::wa-type params?\ncontent\n::::
|
|
9
|
+
# Supported types: grid, stack, cluster, split, flank, frame
|
|
10
|
+
#
|
|
11
|
+
# Common attributes (all layouts):
|
|
12
|
+
# gap:SIZE - wa-gap-{SIZE} class (0, 3xs, 2xs, xs, s, m, l, xl, 2xl, 3xl)
|
|
13
|
+
# align:VALUE - wa-align-items-{VALUE} class (start, end, center, stretch, baseline)
|
|
14
|
+
# justify:VALUE - wa-justify-content-{VALUE} class (start, end, center, space-between, space-around, space-evenly)
|
|
15
|
+
#
|
|
16
|
+
# Grid-specific: min:CSS_VALUE - sets --min-column-size style
|
|
17
|
+
# Split-specific: row, column modifiers
|
|
18
|
+
# Flank-specific: start, end modifiers; size:CSS_VALUE, content:PCT
|
|
19
|
+
# Frame-specific: landscape, portrait, square modifiers; radius:SIZE
|
|
20
|
+
class LayoutTransformer < BaseTransformer
|
|
21
|
+
VALID_GAPS = %w[0 3xs 2xs xs s m l xl 2xl 3xl].freeze
|
|
22
|
+
VALID_ALIGNS = %w[start end center stretch baseline].freeze
|
|
23
|
+
VALID_JUSTIFIES = %w[start end center space-between space-around space-evenly].freeze
|
|
24
|
+
VALID_RADII = %w[s m l pill circle square].freeze
|
|
25
|
+
|
|
26
|
+
KEYWORD_MODIFIERS = {
|
|
27
|
+
split: %w[row column],
|
|
28
|
+
flank: %w[start end],
|
|
29
|
+
frame: %w[landscape portrait square]
|
|
30
|
+
}.freeze
|
|
31
|
+
|
|
32
|
+
COMMON_KEY_CLASS_MAP = {
|
|
33
|
+
'gap' => ->(v) { "wa-gap-#{v}" if VALID_GAPS.include?(v) },
|
|
34
|
+
'align' => ->(v) { "wa-align-items-#{v}" if VALID_ALIGNS.include?(v) },
|
|
35
|
+
'justify' => ->(v) { "wa-justify-content-#{v}" if VALID_JUSTIFIES.include?(v) }
|
|
36
|
+
}.freeze
|
|
37
|
+
|
|
38
|
+
def self.transform(content)
|
|
39
|
+
primary_regex = /^::::(grid|stack|cluster|split|flank|frame)[ \t]*([^\n]*)\n(.*?)\n::::/m
|
|
40
|
+
alternative_regex = /^::::wa-(grid|stack|cluster|split|flank|frame)[ \t]*([^\n]*)\n(.*?)\n::::/m
|
|
41
|
+
|
|
42
|
+
transform_proc = proc do |type, params_string, inner_content|
|
|
43
|
+
classes, styles = build_attributes(type, params_string)
|
|
44
|
+
build_html(classes, styles, inner_content)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
|
|
48
|
+
apply_multiple_patterns(content, patterns)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class << self
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def build_attributes(type, params_string)
|
|
55
|
+
classes = ["wa-#{type}"]
|
|
56
|
+
styles = []
|
|
57
|
+
|
|
58
|
+
return [classes, styles] if params_string.nil? || params_string.strip.empty?
|
|
59
|
+
|
|
60
|
+
tokens = params_string.strip.split(/\s+/)
|
|
61
|
+
|
|
62
|
+
tokens.each do |token|
|
|
63
|
+
process_token(type, token, classes, styles)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
[classes, styles]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def process_token(type, token, classes, styles)
|
|
70
|
+
if token.include?(':')
|
|
71
|
+
process_key_value(type, token, classes, styles)
|
|
72
|
+
else
|
|
73
|
+
process_keyword(type, token, classes)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def process_key_value(type, token, classes, styles)
|
|
78
|
+
key, value = token.split(':', 2)
|
|
79
|
+
return if value.nil? || value.empty?
|
|
80
|
+
|
|
81
|
+
if COMMON_KEY_CLASS_MAP.key?(key)
|
|
82
|
+
css_class = COMMON_KEY_CLASS_MAP[key].call(value)
|
|
83
|
+
classes << css_class if css_class
|
|
84
|
+
else
|
|
85
|
+
process_type_specific_key_value(type, key, value, classes, styles)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def process_type_specific_key_value(type, key, value, classes, styles)
|
|
90
|
+
case key
|
|
91
|
+
when 'min'
|
|
92
|
+
styles << "--min-column-size: #{sanitize_css(value)}" if type == 'grid'
|
|
93
|
+
when 'size'
|
|
94
|
+
styles << "--flank-size: #{sanitize_css(value)}" if type == 'flank'
|
|
95
|
+
when 'content'
|
|
96
|
+
styles << "--content-percentage: #{sanitize_css(value)}" if type == 'flank'
|
|
97
|
+
when 'radius'
|
|
98
|
+
classes << "wa-border-radius-#{value}" if type == 'frame' && VALID_RADII.include?(value)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def process_keyword(type, token, classes)
|
|
103
|
+
modifiers = KEYWORD_MODIFIERS[type.to_sym]
|
|
104
|
+
return unless modifiers&.include?(token)
|
|
105
|
+
|
|
106
|
+
classes[0] = "wa-#{type}:#{token}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def sanitize_css(value)
|
|
110
|
+
value.gsub(/["'<>;]/, '')
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def build_html(classes, styles, inner_content)
|
|
114
|
+
attr_parts = ["class=\"#{classes.join(' ')}\""]
|
|
115
|
+
attr_parts << "style=\"#{styles.join('; ')}\"" unless styles.empty?
|
|
116
|
+
|
|
117
|
+
"<div #{attr_parts.join(' ')}>\n#{inner_content}\n</div>"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -15,5 +15,6 @@ require_relative 'transformers/details_transformer'
|
|
|
15
15
|
require_relative 'transformers/dialog_transformer'
|
|
16
16
|
require_relative 'transformers/icon_transformer'
|
|
17
17
|
require_relative 'transformers/image_dialog_transformer'
|
|
18
|
+
require_relative 'transformers/layout_transformer'
|
|
18
19
|
require_relative 'transformers/tabs_transformer'
|
|
19
20
|
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.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Janne Waren
|
|
@@ -107,6 +107,7 @@ files:
|
|
|
107
107
|
- lib/markawesome/transformers/dialog_transformer.rb
|
|
108
108
|
- lib/markawesome/transformers/icon_transformer.rb
|
|
109
109
|
- lib/markawesome/transformers/image_dialog_transformer.rb
|
|
110
|
+
- lib/markawesome/transformers/layout_transformer.rb
|
|
110
111
|
- lib/markawesome/transformers/tabs_transformer.rb
|
|
111
112
|
- lib/markawesome/transformers/tag_transformer.rb
|
|
112
113
|
- lib/markawesome/version.rb
|