markawesome 0.1.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 +7 -0
- data/CHANGELOG.md +25 -0
- data/LICENSE.txt +9 -0
- data/README.md +75 -0
- data/lib/markawesome/transformer.rb +22 -0
- data/lib/markawesome/transformers/badge_transformer.rb +46 -0
- data/lib/markawesome/transformers/base_transformer.rb +62 -0
- data/lib/markawesome/transformers/button_transformer.rb +66 -0
- data/lib/markawesome/transformers/callout_transformer.rb +83 -0
- data/lib/markawesome/transformers/card_transformer.rb +119 -0
- data/lib/markawesome/transformers/comparison_transformer.rb +72 -0
- data/lib/markawesome/transformers/copy_button_transformer.rb +47 -0
- data/lib/markawesome/transformers/details_transformer.rb +83 -0
- data/lib/markawesome/transformers/icon_transformer.rb +80 -0
- data/lib/markawesome/transformers/tabs_transformer.rb +51 -0
- data/lib/markawesome/transformers/tag_transformer.rb +42 -0
- data/lib/markawesome/transformers.rb +16 -0
- data/lib/markawesome/version.rb +5 -0
- data/lib/markawesome.rb +41 -0
- data/markawesome.gemspec +40 -0
- metadata +132 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 0bfe7629915ad2e621b40c4bc478c90f00313fe5f19ff46739cf1d9ddbff4583
|
|
4
|
+
data.tar.gz: b898ba0b05ba42755ddee581d9cc10cfa8a405df6b29e0d7bfad9f6e86523ec3
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 24fc7fb6409b036053e0bfd475e1ea287c0cf34e28870ef11e2767ae78bb990c5a7038b5a84ecd776d976aeacc53afc531a6cab3a19a2f962f4845a8e27ea2e1
|
|
7
|
+
data.tar.gz: 5efa1542577c5bbbaf6417cc4c0b145a6c66725eca661b3b48241e791000eff6a4f66c7d1aac29971f45cf20a152b7ece83597f9a8ae426f0ab3c4fea94d8465
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
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
|
+
|
|
7
|
+
## [0.1.0] - 2025-10-27
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Initial release
|
|
12
|
+
- Core transformer functionality extracted from jekyll-webawesome
|
|
13
|
+
- Support for Web Awesome components:
|
|
14
|
+
- Badges
|
|
15
|
+
- Buttons
|
|
16
|
+
- Callouts
|
|
17
|
+
- Cards
|
|
18
|
+
- Comparisons
|
|
19
|
+
- Copy Buttons
|
|
20
|
+
- Details
|
|
21
|
+
- Icons
|
|
22
|
+
- Tabs
|
|
23
|
+
- Tags
|
|
24
|
+
- Configuration system for customizing component behavior
|
|
25
|
+
- Framework-agnostic Markdown to Web Awesome transformation
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Janne Warén
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Markawesome
|
|
2
|
+
|
|
3
|
+
Markawesome is a Ruby library that transforms custom Markdown syntax into Web Awesome components. It provides a framework-agnostic way to convert Markdown to Web Awesome HTML.
|
|
4
|
+
|
|
5
|
+
Used as the transformation engine behind the [jekyll-webawesome](https://github.com/jannewaren/jekyll-webawesome) plugin for [Jekyll](https://jekyllrb.com/).
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add this line to your application's Gemfile:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
gem 'markawesome'
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
And then execute:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bundle install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or install it yourself as:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
gem install markawesome
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
require 'markawesome'
|
|
31
|
+
|
|
32
|
+
content = <<~MARKDOWN
|
|
33
|
+
:::info
|
|
34
|
+
This is an info callout!
|
|
35
|
+
:::
|
|
36
|
+
MARKDOWN
|
|
37
|
+
|
|
38
|
+
transformed = Markawesome::Transformer.process(content)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Supported Components
|
|
42
|
+
|
|
43
|
+
| Component | Primary Syntax | Alternative Syntax | HTML Output |
|
|
44
|
+
|-----------|----------------|-------------------|-------------|
|
|
45
|
+
| **Badge** | `!!!variant` | `:::wa-badge variant` | `<wa-badge variant="brand">content</wa-badge>` |
|
|
46
|
+
| **Button** | `%%%variant` | `:::wa-button variant` | `<wa-button variant="brand" href="url">text</wa-button>` or `<wa-button variant="brand">text</wa-button>` |
|
|
47
|
+
| **Callouts** | `:::info` | `:::wa-callout info` | `<wa-callout variant="brand"><wa-icon name="circle-info"></wa-icon>content</wa-callout>` |
|
|
48
|
+
| **Card** | `===` | `:::wa-card` | `<wa-card>content</wa-card>` |
|
|
49
|
+
| **Comparison** | `\|\|\|` or `\|\|\|25` | `:::wa-comparison` or `:::wa-comparison 25` | `<wa-comparison>` with before/after slots |
|
|
50
|
+
| **Copy Button** | `<<<` | `:::wa-copy-button` | `<wa-copy-button value="content">content</wa-copy-button>` |
|
|
51
|
+
| **Details** | `^^^appearance? icon-placement?` | `:::wa-details appearance? icon-placement?` | `<wa-details appearance="..." icon-placement="...">content</wa-details>` |
|
|
52
|
+
| **Tab Group** | `++++++` | `:::wa-tabs` | `<wa-tab-group><wa-tab>content</wa-tab></wa-tab-group>` |
|
|
53
|
+
| **Tag** | `@@@brand` | `:::wa-tag brand` | `<wa-tag variant="brand">content</wa-tag>` |
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
Markawesome.configure do |config|
|
|
59
|
+
config.callout_icons = {
|
|
60
|
+
info: 'circle-info',
|
|
61
|
+
success: 'circle-check',
|
|
62
|
+
neutral: 'gear',
|
|
63
|
+
warning: 'triangle-exclamation',
|
|
64
|
+
danger: 'circle-exclamation'
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Contributing
|
|
70
|
+
|
|
71
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/jannewaren/markawesome.
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'kramdown'
|
|
4
|
+
require_relative 'transformers'
|
|
5
|
+
|
|
6
|
+
module Markawesome
|
|
7
|
+
# Main transformer that orchestrates all component transformers
|
|
8
|
+
class Transformer
|
|
9
|
+
def self.process(content)
|
|
10
|
+
content = BadgeTransformer.transform(content)
|
|
11
|
+
content = ButtonTransformer.transform(content)
|
|
12
|
+
content = CalloutTransformer.transform(content)
|
|
13
|
+
content = CardTransformer.transform(content)
|
|
14
|
+
content = ComparisonTransformer.transform(content)
|
|
15
|
+
content = CopyButtonTransformer.transform(content)
|
|
16
|
+
content = DetailsTransformer.transform(content)
|
|
17
|
+
content = IconTransformer.transform(content)
|
|
18
|
+
content = TagTransformer.transform(content)
|
|
19
|
+
TabsTransformer.transform(content)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
|
|
5
|
+
module Markawesome
|
|
6
|
+
# Transforms badge syntax into wa-badge elements
|
|
7
|
+
# Primary syntax: !!!variant?\ncontent\n!!!
|
|
8
|
+
# Alternative syntax: :::wa-badge variant?\ncontent\n:::
|
|
9
|
+
# Variants: brand, success, neutral, warning, danger
|
|
10
|
+
class BadgeTransformer < BaseTransformer
|
|
11
|
+
def self.transform(content)
|
|
12
|
+
# Define both regex patterns
|
|
13
|
+
primary_regex = /^!!!(brand|success|neutral|warning|danger)?\n(.*?)\n!!!/m
|
|
14
|
+
alternative_regex = /^:::wa-badge\s*(brand|success|neutral|warning|danger)?\n(.*?)\n:::/m
|
|
15
|
+
|
|
16
|
+
# Define shared transformation logic
|
|
17
|
+
transform_proc = proc do |variant, badge_content|
|
|
18
|
+
badge_content = badge_content.strip
|
|
19
|
+
|
|
20
|
+
build_badge_html(badge_content, variant)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Apply both patterns
|
|
24
|
+
patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
|
|
25
|
+
apply_multiple_patterns(content, patterns)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class << self
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def build_badge_html(content, variant)
|
|
32
|
+
variant_attr = variant ? " variant=\"#{variant}\"" : ''
|
|
33
|
+
badge_html = markdown_to_html(content).strip
|
|
34
|
+
|
|
35
|
+
# Remove paragraph tags if the content is just text
|
|
36
|
+
badge_html = badge_html.gsub(%r{^<p>(.*)</p>$}m, '\1')
|
|
37
|
+
|
|
38
|
+
# Fix whitespace issues in Web Awesome badges by ensuring proper spacing
|
|
39
|
+
# Replace spaces after closing tags with non-breaking spaces to prevent CSS collapse
|
|
40
|
+
badge_html = badge_html.gsub(%r{(</\w+>)\s+}, '\1 ')
|
|
41
|
+
|
|
42
|
+
"<wa-badge#{variant_attr}>#{badge_html}</wa-badge>"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'English'
|
|
4
|
+
require 'kramdown'
|
|
5
|
+
|
|
6
|
+
module Markawesome
|
|
7
|
+
# Base class for all Web Awesome component transformers
|
|
8
|
+
# Each transformer should implement the transform method
|
|
9
|
+
class BaseTransformer
|
|
10
|
+
def self.transform(content)
|
|
11
|
+
raise NotImplementedError, 'Subclasses must implement the transform method'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
protected
|
|
16
|
+
|
|
17
|
+
# Helper method to convert markdown content to HTML
|
|
18
|
+
def markdown_to_html(content)
|
|
19
|
+
Kramdown::Document.new(content).to_html
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Helper method to apply multiple regex patterns with the same transformation logic
|
|
23
|
+
# @param content [String] The content to transform
|
|
24
|
+
# @param patterns [Array<Hash>] Array of pattern hashes with :regex and :block
|
|
25
|
+
# @return [String] The transformed content
|
|
26
|
+
def apply_multiple_patterns(content, patterns)
|
|
27
|
+
patterns.each do |pattern|
|
|
28
|
+
content = content.gsub(pattern[:regex]) do |match|
|
|
29
|
+
pattern[:block].call(match, $LAST_MATCH_INFO)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
content
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Helper method to create both primary and alternative syntax patterns
|
|
36
|
+
# @param primary_regex [Regexp] The primary syntax regex
|
|
37
|
+
# @param alternative_regex [Regexp] The alternative syntax regex
|
|
38
|
+
# @param transform_proc [Proc] The proc that takes captured groups and returns HTML
|
|
39
|
+
# @return [Array<Hash>] Array of pattern hashes
|
|
40
|
+
def dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
|
|
41
|
+
[
|
|
42
|
+
{
|
|
43
|
+
regex: primary_regex,
|
|
44
|
+
block: proc do |_match, matchdata|
|
|
45
|
+
# Get all captured groups from the matchdata
|
|
46
|
+
captures = matchdata.captures
|
|
47
|
+
transform_proc.call(*captures)
|
|
48
|
+
end
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
regex: alternative_regex,
|
|
52
|
+
block: proc do |_match, matchdata|
|
|
53
|
+
# Get all captured groups from the matchdata
|
|
54
|
+
captures = matchdata.captures
|
|
55
|
+
transform_proc.call(*captures)
|
|
56
|
+
end
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
|
|
5
|
+
module Markawesome
|
|
6
|
+
# Transforms button syntax into wa-button elements
|
|
7
|
+
# Primary syntax: %%%variant?\ncontent\n%%%
|
|
8
|
+
# Alternative syntax: :::wa-button variant?\ncontent\n:::
|
|
9
|
+
# Variants: brand, success, neutral, warning, danger
|
|
10
|
+
#
|
|
11
|
+
# Link buttons: %%%brand\n[Text](url)\n%%%
|
|
12
|
+
# Regular buttons: %%%brand\nText\n%%%
|
|
13
|
+
class ButtonTransformer < BaseTransformer
|
|
14
|
+
def self.transform(content)
|
|
15
|
+
# Define both regex patterns
|
|
16
|
+
primary_regex = /^%%%(brand|success|neutral|warning|danger)?\n(.*?)\n%%%/m
|
|
17
|
+
alternative_regex = /^:::wa-button\s*(brand|success|neutral|warning|danger)?\n(.*?)\n:::/m
|
|
18
|
+
|
|
19
|
+
# Define shared transformation logic
|
|
20
|
+
transform_proc = proc do |variant, button_content|
|
|
21
|
+
button_content = button_content.strip
|
|
22
|
+
|
|
23
|
+
build_button_html(button_content, variant)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Apply both patterns
|
|
27
|
+
patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
|
|
28
|
+
apply_multiple_patterns(content, patterns)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class << self
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def build_button_html(content, variant)
|
|
35
|
+
variant_attr = variant ? " variant=\"#{variant}\"" : ''
|
|
36
|
+
|
|
37
|
+
# Check if content contains a markdown link
|
|
38
|
+
link_match = content.match(/^\[([^\]]+)\]\(([^)]+)\)$/)
|
|
39
|
+
|
|
40
|
+
if link_match
|
|
41
|
+
# It's a link button
|
|
42
|
+
link_text = link_match[1]
|
|
43
|
+
link_url = link_match[2]
|
|
44
|
+
|
|
45
|
+
# Process any markdown in the link text (bold, italic, etc.)
|
|
46
|
+
button_html = markdown_to_html(link_text).strip
|
|
47
|
+
button_html = button_html.gsub(%r{^<p>(.*)</p>$}m, '\1')
|
|
48
|
+
|
|
49
|
+
# Fix whitespace issues like in badges
|
|
50
|
+
button_html = button_html.gsub(%r{(</\w+>)\s+}, '\1 ')
|
|
51
|
+
|
|
52
|
+
"<wa-button#{variant_attr} href=\"#{link_url}\">#{button_html}</wa-button>"
|
|
53
|
+
else
|
|
54
|
+
# It's a regular button
|
|
55
|
+
button_html = markdown_to_html(content).strip
|
|
56
|
+
button_html = button_html.gsub(%r{^<p>(.*)</p>$}m, '\1')
|
|
57
|
+
|
|
58
|
+
# Fix whitespace issues like in badges
|
|
59
|
+
button_html = button_html.gsub(%r{(</\w+>)\s+}, '\1 ')
|
|
60
|
+
|
|
61
|
+
"<wa-button#{variant_attr}>#{button_html}</wa-button>"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
|
|
5
|
+
module Markawesome
|
|
6
|
+
# Transforms callout syntax into wa-callout elements
|
|
7
|
+
# Primary syntax: :::variant\ncontent\n:::
|
|
8
|
+
# Alternative syntax: :::wa-callout variant\ncontent\n:::
|
|
9
|
+
# Variants: info, success, neutral, warning, danger
|
|
10
|
+
class CalloutTransformer < BaseTransformer
|
|
11
|
+
def self.transform(content)
|
|
12
|
+
# Define both regex patterns
|
|
13
|
+
primary_regex = /^:::(info|success|neutral|warning|danger)\n(.*?)\n:::/m
|
|
14
|
+
alternative_regex = /^:::wa-callout\s+(info|success|neutral|warning|danger)\n(.*?)\n:::/m
|
|
15
|
+
|
|
16
|
+
# Define shared transformation logic
|
|
17
|
+
transform_proc = proc do |variant, inner_content|
|
|
18
|
+
attrs = callout_attributes(variant)
|
|
19
|
+
|
|
20
|
+
element_tag = "wa-callout#{attrs[:additional_params]}"
|
|
21
|
+
html_content = "#{attrs[:inner_prepend]}#{markdown_to_html(inner_content)}"
|
|
22
|
+
|
|
23
|
+
"<#{element_tag}>#{html_content}</wa-callout>"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Apply both patterns
|
|
27
|
+
patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
|
|
28
|
+
apply_multiple_patterns(content, patterns)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class << self
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def callout_attributes(variant)
|
|
35
|
+
config = Markawesome.configuration
|
|
36
|
+
icons = config&.callout_icons || default_callout_icons
|
|
37
|
+
|
|
38
|
+
case variant
|
|
39
|
+
when 'info'
|
|
40
|
+
{
|
|
41
|
+
additional_params: ' variant="brand"',
|
|
42
|
+
inner_prepend: "<wa-icon slot=\"icon\" name=\"#{icons[:info]}\" variant=\"solid\"></wa-icon>"
|
|
43
|
+
}
|
|
44
|
+
when 'success'
|
|
45
|
+
{
|
|
46
|
+
additional_params: ' variant="success"',
|
|
47
|
+
inner_prepend: "<wa-icon slot=\"icon\" name=\"#{icons[:success]}\" variant=\"solid\"></wa-icon>"
|
|
48
|
+
}
|
|
49
|
+
when 'neutral'
|
|
50
|
+
{
|
|
51
|
+
additional_params: ' variant="neutral"',
|
|
52
|
+
inner_prepend: "<wa-icon slot=\"icon\" name=\"#{icons[:neutral]}\" variant=\"solid\"></wa-icon>"
|
|
53
|
+
}
|
|
54
|
+
when 'warning'
|
|
55
|
+
{
|
|
56
|
+
additional_params: ' variant="warning"',
|
|
57
|
+
inner_prepend: "<wa-icon slot=\"icon\" name=\"#{icons[:warning]}\" variant=\"solid\"></wa-icon>"
|
|
58
|
+
}
|
|
59
|
+
when 'danger'
|
|
60
|
+
{
|
|
61
|
+
additional_params: ' variant="danger"',
|
|
62
|
+
inner_prepend: "<wa-icon slot=\"icon\" name=\"#{icons[:danger]}\" variant=\"solid\"></wa-icon>"
|
|
63
|
+
}
|
|
64
|
+
else
|
|
65
|
+
{
|
|
66
|
+
additional_params: '',
|
|
67
|
+
inner_prepend: ''
|
|
68
|
+
}
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def default_callout_icons
|
|
73
|
+
{
|
|
74
|
+
info: 'circle-info',
|
|
75
|
+
success: 'circle-check',
|
|
76
|
+
neutral: 'gear',
|
|
77
|
+
warning: 'triangle-exclamation',
|
|
78
|
+
danger: 'circle-exclamation'
|
|
79
|
+
}
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
|
|
5
|
+
module Markawesome
|
|
6
|
+
# Transforms card syntax into wa-card elements
|
|
7
|
+
# Primary syntax: ===appearance?\ncontent\n===
|
|
8
|
+
# Alternative syntax: :::wa-card appearance?\ncontent\n:::
|
|
9
|
+
# Appearances: outlined (default), filled, filled-outlined, plain, accent
|
|
10
|
+
class CardTransformer < BaseTransformer
|
|
11
|
+
def self.transform(content)
|
|
12
|
+
# Define both regex patterns
|
|
13
|
+
primary_regex = /^===(outlined|filled|filled-outlined|plain|accent)?\n(.*?)\n===/m
|
|
14
|
+
alternative_regex = /^:::wa-card\s*(outlined|filled|filled-outlined|plain|accent)?\n(.*?)\n:::/m
|
|
15
|
+
|
|
16
|
+
# Define shared transformation logic
|
|
17
|
+
transform_proc = proc do |appearance_param, card_content|
|
|
18
|
+
card_content = card_content.strip
|
|
19
|
+
|
|
20
|
+
appearance = normalize_appearance(appearance_param)
|
|
21
|
+
card_parts = parse_card_content(card_content)
|
|
22
|
+
|
|
23
|
+
build_card_html(card_parts, appearance)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Apply both patterns
|
|
27
|
+
patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
|
|
28
|
+
apply_multiple_patterns(content, patterns)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class << self
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def normalize_appearance(appearance_param)
|
|
35
|
+
case appearance_param
|
|
36
|
+
when 'filled', 'filled-outlined', 'plain', 'accent'
|
|
37
|
+
appearance_param
|
|
38
|
+
else
|
|
39
|
+
'outlined' # default
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def parse_card_content(content)
|
|
44
|
+
parts = {
|
|
45
|
+
media: nil,
|
|
46
|
+
header: nil,
|
|
47
|
+
content: content,
|
|
48
|
+
footer: nil
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Extract first image as media
|
|
52
|
+
if content.match(/^!\[([^\]]*)\]\(([^)]+)\)/)
|
|
53
|
+
parts[:media] = {
|
|
54
|
+
alt: ::Regexp.last_match(1),
|
|
55
|
+
src: ::Regexp.last_match(2)
|
|
56
|
+
}
|
|
57
|
+
# Remove the image from content
|
|
58
|
+
content = content.sub(/^!\[([^\]]*)\]\(([^)]+)\)\n?/, '')
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Extract first heading as header
|
|
62
|
+
if content.match(/^# (.+)$/)
|
|
63
|
+
parts[:header] = ::Regexp.last_match(1).strip
|
|
64
|
+
# Remove the heading from content
|
|
65
|
+
content = content.sub(/^# .+\n?/, '')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Extract trailing buttons/links as footer
|
|
69
|
+
# Look for links or buttons at the end of the content
|
|
70
|
+
if content.match(/\n\[([^\]]+)\]\(([^)]+)\)\s*$/)
|
|
71
|
+
parts[:footer] = {
|
|
72
|
+
text: ::Regexp.last_match(1),
|
|
73
|
+
href: ::Regexp.last_match(2)
|
|
74
|
+
}
|
|
75
|
+
# Remove the footer link from content
|
|
76
|
+
content = content.sub(/\n\[([^\]]+)\]\(([^)]+)\)\s*$/, '')
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Update the main content after extractions
|
|
80
|
+
parts[:content] = content.strip
|
|
81
|
+
parts
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def build_card_html(parts, appearance)
|
|
85
|
+
attributes = []
|
|
86
|
+
attributes << "appearance=\"#{appearance}\"" if appearance != 'outlined'
|
|
87
|
+
|
|
88
|
+
# Add SSR attributes if slots are present
|
|
89
|
+
attributes << 'with-media' if parts[:media]
|
|
90
|
+
attributes << 'with-header' if parts[:header]
|
|
91
|
+
attributes << 'with-footer' if parts[:footer]
|
|
92
|
+
|
|
93
|
+
attr_string = attributes.empty? ? '' : " #{attributes.join(' ')}"
|
|
94
|
+
|
|
95
|
+
html_parts = []
|
|
96
|
+
|
|
97
|
+
# Media slot
|
|
98
|
+
html_parts << "<img slot=\"media\" src=\"#{parts[:media][:src]}\" alt=\"#{parts[:media][:alt]}\">" if parts[:media]
|
|
99
|
+
|
|
100
|
+
# Header slot
|
|
101
|
+
if parts[:header]
|
|
102
|
+
header_html = markdown_to_html(parts[:header])
|
|
103
|
+
html_parts << "<div slot=\"header\">#{header_html}</div>"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Main content
|
|
107
|
+
if parts[:content] && !parts[:content].empty?
|
|
108
|
+
content_html = markdown_to_html(parts[:content])
|
|
109
|
+
html_parts << content_html
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Footer slot
|
|
113
|
+
html_parts << "<div slot=\"footer\"><wa-button href=\"#{parts[:footer][:href]}\">#{parts[:footer][:text]}</wa-button></div>" if parts[:footer]
|
|
114
|
+
|
|
115
|
+
"<wa-card#{attr_string}>#{html_parts.join}</wa-card>"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
|
|
5
|
+
module Markawesome
|
|
6
|
+
# Transforms comparison syntax into wa-comparison elements
|
|
7
|
+
# Primary syntax: |||\n\n\n|||
|
|
8
|
+
# Primary syntax with position: |||50\n\n\n|||
|
|
9
|
+
# Alternative syntax: :::wa-comparison\n\n\n:::
|
|
10
|
+
# Alternative syntax with position: :::wa-comparison 50\n\n\n:::
|
|
11
|
+
# Expects exactly two image elements inside the wrapper
|
|
12
|
+
class ComparisonTransformer < BaseTransformer
|
|
13
|
+
def self.transform(content)
|
|
14
|
+
# Process primary syntax
|
|
15
|
+
content = content.gsub(/^\|\|\|(\d+)?\n(.*?)\n\|\|\|/m) do |match|
|
|
16
|
+
position = Regexp.last_match(1)
|
|
17
|
+
inner_content = Regexp.last_match(2).strip
|
|
18
|
+
images = extract_images(inner_content)
|
|
19
|
+
|
|
20
|
+
if images.length == 2
|
|
21
|
+
build_comparison_html(inner_content, position)
|
|
22
|
+
else
|
|
23
|
+
match # Return original match if not exactly 2 images
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Process alternative syntax
|
|
28
|
+
content.gsub(/^:::wa-comparison\s*(\d+)?\n(.*?)\n:::/m) do |match|
|
|
29
|
+
position = Regexp.last_match(1)
|
|
30
|
+
inner_content = Regexp.last_match(2).strip
|
|
31
|
+
images = extract_images(inner_content)
|
|
32
|
+
|
|
33
|
+
if images.length == 2
|
|
34
|
+
build_comparison_html(inner_content, position)
|
|
35
|
+
else
|
|
36
|
+
match # Return original match if not exactly 2 images
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class << self
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def build_comparison_html(content, position = nil)
|
|
45
|
+
images = extract_images(content)
|
|
46
|
+
|
|
47
|
+
before_image = build_image_html(images[0], 'before')
|
|
48
|
+
after_image = build_image_html(images[1], 'after')
|
|
49
|
+
|
|
50
|
+
position_attr = position ? " position=\"#{position}\"" : ''
|
|
51
|
+
|
|
52
|
+
"<wa-comparison#{position_attr}>#{before_image}#{after_image}</wa-comparison>"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def extract_images(content)
|
|
56
|
+
# Extract markdown image syntax: 
|
|
57
|
+
image_regex = /!\[([^\]]*)\]\(([^)]+)\)/
|
|
58
|
+
content.scan(image_regex)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def build_image_html(image_match, slot)
|
|
62
|
+
alt_text = image_match[0]
|
|
63
|
+
src = image_match[1]
|
|
64
|
+
|
|
65
|
+
# Escape HTML characters in alt text
|
|
66
|
+
escaped_alt = alt_text.gsub('&', '&').gsub('"', '"').gsub('<', '<').gsub('>', '>')
|
|
67
|
+
|
|
68
|
+
"<img slot=\"#{slot}\" src=\"#{src}\" alt=\"#{escaped_alt}\" />"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
|
|
5
|
+
module Markawesome
|
|
6
|
+
# Transforms copy button syntax into wa-copy-button elements
|
|
7
|
+
# Primary syntax: <<<\ncontent\n<<<
|
|
8
|
+
# Alternative syntax: :::wa-copy-button\ncontent\n:::
|
|
9
|
+
#
|
|
10
|
+
# Usage:
|
|
11
|
+
# <<<
|
|
12
|
+
# This text will be copied to clipboard
|
|
13
|
+
# <<<
|
|
14
|
+
#
|
|
15
|
+
# :::wa-copy-button
|
|
16
|
+
# Copy this text
|
|
17
|
+
# :::
|
|
18
|
+
class CopyButtonTransformer < BaseTransformer
|
|
19
|
+
def self.transform(content)
|
|
20
|
+
# Define both regex patterns
|
|
21
|
+
primary_regex = /^<<<\n(.*?)\n<<</m
|
|
22
|
+
alternative_regex = /^:::wa-copy-button\n(.*?)\n:::/m
|
|
23
|
+
|
|
24
|
+
# Define shared transformation logic
|
|
25
|
+
transform_proc = proc do |copy_content|
|
|
26
|
+
copy_content = copy_content.strip
|
|
27
|
+
|
|
28
|
+
build_copy_button_html(copy_content)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Apply both patterns
|
|
32
|
+
patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
|
|
33
|
+
apply_multiple_patterns(content, patterns)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class << self
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def build_copy_button_html(content)
|
|
40
|
+
# Escape the content for the value attribute
|
|
41
|
+
escaped_content = content.gsub('"', '"').gsub("'", ''')
|
|
42
|
+
|
|
43
|
+
"<wa-copy-button value=\"#{escaped_content}\"></wa-copy-button>"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
|
|
5
|
+
module Markawesome
|
|
6
|
+
# Transforms summary/details syntax into wa-details elements
|
|
7
|
+
# Primary syntax: ^^^appearance? icon-placement?\nsummary\n>>>\ndetails\n^^^
|
|
8
|
+
# Alternative syntax: :::wa-details appearance? icon-placement?\nsummary\n>>>\ndetails\n:::
|
|
9
|
+
# Appearances: outlined (default), filled, filled-outlined, plain
|
|
10
|
+
# Icon placement: start, end (default)
|
|
11
|
+
class DetailsTransformer < BaseTransformer
|
|
12
|
+
def self.transform(content)
|
|
13
|
+
# Define both regex patterns - capture parameter string
|
|
14
|
+
primary_regex = /^\^\^\^?(.*?)\n(.*?)\n^>>>\n(.*?)\n^\^\^\^?/m
|
|
15
|
+
alternative_regex = /^:::wa-details\s*(.*?)\n(.*?)\n^>>>\n(.*?)\n:::/m
|
|
16
|
+
|
|
17
|
+
# Define shared transformation logic
|
|
18
|
+
transform_proc = proc do |params_string, summary_content, details_content|
|
|
19
|
+
summary_content = summary_content.strip
|
|
20
|
+
details_content = details_content.strip
|
|
21
|
+
|
|
22
|
+
# Parse parameters from the params string
|
|
23
|
+
appearance_param, icon_placement_param = parse_parameters(params_string)
|
|
24
|
+
|
|
25
|
+
appearance_class = normalize_appearance(appearance_param)
|
|
26
|
+
icon_placement = normalize_icon_placement(icon_placement_param)
|
|
27
|
+
summary_html = markdown_to_html(summary_content)
|
|
28
|
+
details_html = markdown_to_html(details_content)
|
|
29
|
+
|
|
30
|
+
"<wa-details appearance='#{appearance_class}' icon-placement='#{icon_placement}'>" \
|
|
31
|
+
"<span slot='summary'>#{summary_html}</span>" \
|
|
32
|
+
"#{details_html}</wa-details>"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Apply both patterns
|
|
36
|
+
patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
|
|
37
|
+
apply_multiple_patterns(content, patterns)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class << self
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def parse_parameters(params_string)
|
|
44
|
+
return [nil, nil] if params_string.nil? || params_string.strip.empty?
|
|
45
|
+
|
|
46
|
+
# Split by whitespace and extract known parameters
|
|
47
|
+
tokens = params_string.strip.split(/\s+/)
|
|
48
|
+
|
|
49
|
+
appearance_options = %w[outlined filled filled-outlined plain]
|
|
50
|
+
placement_options = %w[start end]
|
|
51
|
+
|
|
52
|
+
appearance_param = tokens.find { |token| appearance_options.include?(token) }
|
|
53
|
+
icon_placement_param = tokens.find { |token| placement_options.include?(token) }
|
|
54
|
+
|
|
55
|
+
[appearance_param, icon_placement_param]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def normalize_appearance(appearance_param)
|
|
59
|
+
case appearance_param
|
|
60
|
+
when 'filled'
|
|
61
|
+
'filled'
|
|
62
|
+
when 'filled-outlined'
|
|
63
|
+
'filled outlined'
|
|
64
|
+
when 'plain'
|
|
65
|
+
'plain'
|
|
66
|
+
else
|
|
67
|
+
'outlined'
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def normalize_icon_placement(icon_placement_param)
|
|
72
|
+
case icon_placement_param
|
|
73
|
+
when 'start'
|
|
74
|
+
'start'
|
|
75
|
+
when 'end'
|
|
76
|
+
'end'
|
|
77
|
+
else
|
|
78
|
+
'end'
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
|
|
5
|
+
module Markawesome
|
|
6
|
+
# Transforms icon syntax into wa-icon elements
|
|
7
|
+
# Primary syntax: $$$icon-name
|
|
8
|
+
# Alternative syntax: :::wa-icon icon-name
|
|
9
|
+
#
|
|
10
|
+
# Examples:
|
|
11
|
+
# $$$settings -> <wa-icon name="settings"></wa-icon>
|
|
12
|
+
# $$$home -> <wa-icon name="home"></wa-icon>
|
|
13
|
+
# $$$user-circle -> <wa-icon name="user-circle"></wa-icon>
|
|
14
|
+
class IconTransformer < BaseTransformer
|
|
15
|
+
def self.transform(content)
|
|
16
|
+
# Protect code blocks first
|
|
17
|
+
protected_content, code_blocks = protect_code_blocks(content)
|
|
18
|
+
|
|
19
|
+
# Apply primary syntax transformation
|
|
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)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Apply alternative syntax transformation
|
|
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)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Restore code blocks
|
|
34
|
+
restore_code_blocks(result, code_blocks)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class << self
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def build_icon_html(icon_name)
|
|
41
|
+
# Clean and validate icon name
|
|
42
|
+
clean_name = icon_name.strip
|
|
43
|
+
|
|
44
|
+
# Return the wa-icon element
|
|
45
|
+
"<wa-icon name=\"#{clean_name}\"></wa-icon>"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def protect_code_blocks(content)
|
|
49
|
+
code_blocks = {}
|
|
50
|
+
counter = 0
|
|
51
|
+
|
|
52
|
+
# Protect fenced code blocks
|
|
53
|
+
protected = content.gsub(/```.*?```/m) do |match|
|
|
54
|
+
placeholder = "<!--ICON_PROTECTED_CODE_BLOCK_#{counter}-->"
|
|
55
|
+
code_blocks[placeholder] = match
|
|
56
|
+
counter += 1
|
|
57
|
+
placeholder
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Protect inline code
|
|
61
|
+
protected = protected.gsub(/`[^`]+`/) do |match|
|
|
62
|
+
placeholder = "<!--ICON_PROTECTED_INLINE_CODE_#{counter}-->"
|
|
63
|
+
code_blocks[placeholder] = match
|
|
64
|
+
counter += 1
|
|
65
|
+
placeholder
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
[protected, code_blocks]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def restore_code_blocks(content, code_blocks)
|
|
72
|
+
result = content
|
|
73
|
+
code_blocks.each do |placeholder, original|
|
|
74
|
+
result = result.gsub(placeholder, original)
|
|
75
|
+
end
|
|
76
|
+
result
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
|
|
5
|
+
module Markawesome
|
|
6
|
+
# Transforms tabs syntax into wa-tab-group elements
|
|
7
|
+
# Primary syntax: ++++++placement?\n+++tab1\ncontent\n+++\n+++tab2\ncontent\n+++\n++++++
|
|
8
|
+
# Alternative syntax: :::wa-tabs placement?\n+++tab1\ncontent\n+++\n+++tab2\ncontent\n+++\n:::
|
|
9
|
+
# Placements: top (default), bottom, start, end
|
|
10
|
+
class TabsTransformer < BaseTransformer
|
|
11
|
+
def self.transform(content)
|
|
12
|
+
# Define both regex patterns
|
|
13
|
+
primary_regex = /^\+{6}(top|bottom|start|end)?\n((\+\+\+ [^\n]+\n.*?\n\+\+\+\n?)+)\+{6}/m
|
|
14
|
+
alternative_regex = /^:::wa-tabs\s*(top|bottom|start|end)?\n((\+\+\+ [^\n]+\n.*?\n\+\+\+\n?)+):::/m
|
|
15
|
+
|
|
16
|
+
# Define shared transformation logic
|
|
17
|
+
transform_proc = proc do |placement, tabs_block, _third_capture|
|
|
18
|
+
placement ||= 'top'
|
|
19
|
+
|
|
20
|
+
tabs, tab_panels = extract_tabs_and_panels(tabs_block)
|
|
21
|
+
|
|
22
|
+
"<wa-tab-group placement=\"#{placement}\">#{tabs.join}#{tab_panels.join}</wa-tab-group>"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Apply both patterns
|
|
26
|
+
patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
|
|
27
|
+
apply_multiple_patterns(content, patterns)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class << self
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def extract_tabs_and_panels(tabs_block)
|
|
34
|
+
# Extract individual tabs
|
|
35
|
+
tab_contents = tabs_block.scan(/^\+\+\+ ([^\n]+)\n(.*?)\n\+\+\+/m)
|
|
36
|
+
tabs = []
|
|
37
|
+
tab_panels = []
|
|
38
|
+
|
|
39
|
+
tab_contents.each_with_index do |(title, panel_content), index|
|
|
40
|
+
tab_id = "tab-#{index + 1}"
|
|
41
|
+
tabs << "<wa-tab panel=\"#{tab_id}\">#{title.strip}</wa-tab>"
|
|
42
|
+
|
|
43
|
+
panel_html = markdown_to_html(panel_content.strip)
|
|
44
|
+
tab_panels << "<wa-tab-panel name=\"#{tab_id}\">#{panel_html}</wa-tab-panel>"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
[tabs, tab_panels]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_transformer'
|
|
4
|
+
|
|
5
|
+
module Markawesome
|
|
6
|
+
# Transforms tag syntax into wa-tag elements
|
|
7
|
+
# Primary syntax: @@@variant?\ncontent\n@@@
|
|
8
|
+
# Alternative syntax: :::wa-tag variant?\ncontent\n:::
|
|
9
|
+
# Variants: brand, success, neutral, warning, danger
|
|
10
|
+
class TagTransformer < BaseTransformer
|
|
11
|
+
def self.transform(content)
|
|
12
|
+
# Define both regex patterns
|
|
13
|
+
primary_regex = /^@@@(brand|success|neutral|warning|danger)?\n(.*?)\n@@@/m
|
|
14
|
+
alternative_regex = /^:::wa-tag\s*(brand|success|neutral|warning|danger)?\n(.*?)\n:::/m
|
|
15
|
+
|
|
16
|
+
# Define shared transformation logic
|
|
17
|
+
transform_proc = proc do |variant, tag_content|
|
|
18
|
+
tag_content = tag_content.strip
|
|
19
|
+
|
|
20
|
+
build_tag_html(tag_content, variant)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Apply both patterns
|
|
24
|
+
patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
|
|
25
|
+
apply_multiple_patterns(content, patterns)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class << self
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def build_tag_html(content, variant)
|
|
32
|
+
variant_attr = variant ? " variant=\"#{variant}\"" : ''
|
|
33
|
+
tag_html = markdown_to_html(content).strip
|
|
34
|
+
|
|
35
|
+
# Remove paragraph tags if the content is just text
|
|
36
|
+
tag_html = tag_html.gsub(%r{^<p>(.*)</p>$}m, '\1')
|
|
37
|
+
|
|
38
|
+
"<wa-tag#{variant_attr}>#{tag_html}</wa-tag>"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Index file for all Web Awesome transformers
|
|
4
|
+
# This file makes it easy to require all transformers at once
|
|
5
|
+
|
|
6
|
+
require_relative 'transformers/base_transformer'
|
|
7
|
+
require_relative 'transformers/badge_transformer'
|
|
8
|
+
require_relative 'transformers/button_transformer'
|
|
9
|
+
require_relative 'transformers/callout_transformer'
|
|
10
|
+
require_relative 'transformers/card_transformer'
|
|
11
|
+
require_relative 'transformers/comparison_transformer'
|
|
12
|
+
require_relative 'transformers/copy_button_transformer'
|
|
13
|
+
require_relative 'transformers/details_transformer'
|
|
14
|
+
require_relative 'transformers/icon_transformer'
|
|
15
|
+
require_relative 'transformers/tabs_transformer'
|
|
16
|
+
require_relative 'transformers/tag_transformer'
|
data/lib/markawesome.rb
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'markawesome/version'
|
|
4
|
+
require_relative 'markawesome/transformer'
|
|
5
|
+
|
|
6
|
+
module Markawesome
|
|
7
|
+
class Error < StandardError; end
|
|
8
|
+
|
|
9
|
+
# Configuration options
|
|
10
|
+
class << self
|
|
11
|
+
attr_accessor :configuration
|
|
12
|
+
|
|
13
|
+
def configure
|
|
14
|
+
self.configuration ||= Configuration.new
|
|
15
|
+
yield(configuration) if block_given?
|
|
16
|
+
configuration
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Configuration class for customizing transformation behavior
|
|
21
|
+
class Configuration
|
|
22
|
+
attr_accessor :callout_icons, :custom_components
|
|
23
|
+
|
|
24
|
+
def initialize
|
|
25
|
+
@callout_icons = default_callout_icons
|
|
26
|
+
@custom_components = {}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def default_callout_icons
|
|
32
|
+
{
|
|
33
|
+
info: 'circle-info',
|
|
34
|
+
success: 'circle-check',
|
|
35
|
+
neutral: 'gear',
|
|
36
|
+
warning: 'triangle-exclamation',
|
|
37
|
+
danger: 'circle-exclamation'
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
data/markawesome.gemspec
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/markawesome/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'markawesome'
|
|
7
|
+
spec.version = Markawesome::VERSION
|
|
8
|
+
spec.authors = ['Janne Waren']
|
|
9
|
+
spec.email = ['janne.waren@iki.fi']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Markdown to Web Awesome transformer'
|
|
12
|
+
spec.description = 'A library that transforms custom Markdown syntax into Web Awesome components.'
|
|
13
|
+
spec.homepage = 'https://github.com/jannewaren/markawesome'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 3.2'
|
|
16
|
+
|
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
|
+
spec.metadata['source_code_uri'] = "#{spec.homepage}/tree/main"
|
|
19
|
+
spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
20
|
+
|
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
|
22
|
+
spec.files = Dir.chdir(__dir__) do
|
|
23
|
+
Dir.glob('lib/**/*.rb') + %w[
|
|
24
|
+
README.md
|
|
25
|
+
CHANGELOG.md
|
|
26
|
+
LICENSE.txt
|
|
27
|
+
markawesome.gemspec
|
|
28
|
+
]
|
|
29
|
+
end
|
|
30
|
+
spec.bindir = 'exe'
|
|
31
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
32
|
+
spec.require_paths = ['lib']
|
|
33
|
+
|
|
34
|
+
spec.add_dependency 'kramdown', '~> 2.0'
|
|
35
|
+
|
|
36
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
37
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
38
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
39
|
+
spec.add_development_dependency 'rubocop', '~> 1.0'
|
|
40
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: markawesome
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Janne Waren
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: kramdown
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: bundler
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '2.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '2.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rake
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '13.0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '13.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rspec
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '3.0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rubocop
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '1.0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '1.0'
|
|
82
|
+
description: A library that transforms custom Markdown syntax into Web Awesome components.
|
|
83
|
+
email:
|
|
84
|
+
- janne.waren@iki.fi
|
|
85
|
+
executables: []
|
|
86
|
+
extensions: []
|
|
87
|
+
extra_rdoc_files: []
|
|
88
|
+
files:
|
|
89
|
+
- CHANGELOG.md
|
|
90
|
+
- LICENSE.txt
|
|
91
|
+
- README.md
|
|
92
|
+
- lib/markawesome.rb
|
|
93
|
+
- lib/markawesome/transformer.rb
|
|
94
|
+
- lib/markawesome/transformers.rb
|
|
95
|
+
- lib/markawesome/transformers/badge_transformer.rb
|
|
96
|
+
- lib/markawesome/transformers/base_transformer.rb
|
|
97
|
+
- lib/markawesome/transformers/button_transformer.rb
|
|
98
|
+
- lib/markawesome/transformers/callout_transformer.rb
|
|
99
|
+
- lib/markawesome/transformers/card_transformer.rb
|
|
100
|
+
- lib/markawesome/transformers/comparison_transformer.rb
|
|
101
|
+
- lib/markawesome/transformers/copy_button_transformer.rb
|
|
102
|
+
- lib/markawesome/transformers/details_transformer.rb
|
|
103
|
+
- lib/markawesome/transformers/icon_transformer.rb
|
|
104
|
+
- lib/markawesome/transformers/tabs_transformer.rb
|
|
105
|
+
- lib/markawesome/transformers/tag_transformer.rb
|
|
106
|
+
- lib/markawesome/version.rb
|
|
107
|
+
- markawesome.gemspec
|
|
108
|
+
homepage: https://github.com/jannewaren/markawesome
|
|
109
|
+
licenses:
|
|
110
|
+
- MIT
|
|
111
|
+
metadata:
|
|
112
|
+
homepage_uri: https://github.com/jannewaren/markawesome
|
|
113
|
+
source_code_uri: https://github.com/jannewaren/markawesome/tree/main
|
|
114
|
+
changelog_uri: https://github.com/jannewaren/markawesome/blob/main/CHANGELOG.md
|
|
115
|
+
rdoc_options: []
|
|
116
|
+
require_paths:
|
|
117
|
+
- lib
|
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
|
+
requirements:
|
|
120
|
+
- - ">="
|
|
121
|
+
- !ruby/object:Gem::Version
|
|
122
|
+
version: '3.2'
|
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
|
+
requirements:
|
|
125
|
+
- - ">="
|
|
126
|
+
- !ruby/object:Gem::Version
|
|
127
|
+
version: '0'
|
|
128
|
+
requirements: []
|
|
129
|
+
rubygems_version: 3.6.9
|
|
130
|
+
specification_version: 4
|
|
131
|
+
summary: Markdown to Web Awesome transformer
|
|
132
|
+
test_files: []
|