jekyll-webawesome 0.6.0 → 0.7.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 +41 -0
- data/README.md +0 -15
- data/jekyll-webawesome.gemspec +1 -1
- data/lib/jekyll/webawesome/code_block_transformer.rb +46 -43
- data/lib/jekyll/webawesome/plugin.rb +49 -13
- data/lib/jekyll/webawesome/version.rb +1 -1
- data/lib/jekyll/webawesome.rb +13 -1
- metadata +4 -20
- data/lib/jekyll/webawesome/transformer.rb +0 -31
- data/lib/jekyll/webawesome/transformers/badge_transformer.rb +0 -48
- data/lib/jekyll/webawesome/transformers/base_transformer.rb +0 -65
- data/lib/jekyll/webawesome/transformers/button_transformer.rb +0 -68
- data/lib/jekyll/webawesome/transformers/callout_transformer.rb +0 -72
- data/lib/jekyll/webawesome/transformers/card_transformer.rb +0 -121
- data/lib/jekyll/webawesome/transformers/carousel_transformer.rb +0 -129
- data/lib/jekyll/webawesome/transformers/comparison_transformer.rb +0 -74
- data/lib/jekyll/webawesome/transformers/copy_button_transformer.rb +0 -49
- data/lib/jekyll/webawesome/transformers/details_transformer.rb +0 -85
- data/lib/jekyll/webawesome/transformers/dialog_transformer.rb +0 -175
- data/lib/jekyll/webawesome/transformers/icon_transformer.rb +0 -82
- data/lib/jekyll/webawesome/transformers/image_dialog_transformer.rb +0 -174
- data/lib/jekyll/webawesome/transformers/tabs_transformer.rb +0 -53
- data/lib/jekyll/webawesome/transformers/tag_transformer.rb +0 -44
- data/lib/jekyll/webawesome/transformers.rb +0 -19
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'base_transformer'
|
|
4
|
-
|
|
5
|
-
module Jekyll
|
|
6
|
-
module WebAwesome
|
|
7
|
-
# Transforms icon syntax into wa-icon elements
|
|
8
|
-
# Primary syntax: $$$icon-name
|
|
9
|
-
# Alternative syntax: :::wa-icon icon-name
|
|
10
|
-
#
|
|
11
|
-
# Examples:
|
|
12
|
-
# $$$settings -> <wa-icon name="settings"></wa-icon>
|
|
13
|
-
# $$$home -> <wa-icon name="home"></wa-icon>
|
|
14
|
-
# $$$user-circle -> <wa-icon name="user-circle"></wa-icon>
|
|
15
|
-
class IconTransformer < BaseTransformer
|
|
16
|
-
def self.transform(content)
|
|
17
|
-
# Protect code blocks first
|
|
18
|
-
protected_content, code_blocks = protect_code_blocks(content)
|
|
19
|
-
|
|
20
|
-
# Apply primary syntax transformation
|
|
21
|
-
# Only block patterns that look like incomplete icon names:
|
|
22
|
-
# $$$icon name (where 'icon name' could be intended as one identifier)
|
|
23
|
-
result = protected_content.gsub(/\$\$\$([a-zA-Z0-9\-_]+)(?![a-zA-Z0-9\-_]|\s+name\b)/) do
|
|
24
|
-
icon_name = ::Regexp.last_match(1)
|
|
25
|
-
build_icon_html(icon_name)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Apply alternative syntax transformation
|
|
29
|
-
result = result.gsub(/:::wa-icon\s+([a-zA-Z0-9\-_]+)\s*\n:::/m) do
|
|
30
|
-
icon_name = ::Regexp.last_match(1)
|
|
31
|
-
build_icon_html(icon_name)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Restore code blocks
|
|
35
|
-
restore_code_blocks(result, code_blocks)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
class << self
|
|
39
|
-
private
|
|
40
|
-
|
|
41
|
-
def build_icon_html(icon_name)
|
|
42
|
-
# Clean and validate icon name
|
|
43
|
-
clean_name = icon_name.strip
|
|
44
|
-
|
|
45
|
-
# Return the wa-icon element
|
|
46
|
-
"<wa-icon name=\"#{clean_name}\"></wa-icon>"
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def protect_code_blocks(content)
|
|
50
|
-
code_blocks = {}
|
|
51
|
-
counter = 0
|
|
52
|
-
|
|
53
|
-
# Protect fenced code blocks
|
|
54
|
-
protected = content.gsub(/```.*?```/m) do |match|
|
|
55
|
-
placeholder = "<!--ICON_PROTECTED_CODE_BLOCK_#{counter}-->"
|
|
56
|
-
code_blocks[placeholder] = match
|
|
57
|
-
counter += 1
|
|
58
|
-
placeholder
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Protect inline code
|
|
62
|
-
protected = protected.gsub(/`[^`]+`/) do |match|
|
|
63
|
-
placeholder = "<!--ICON_PROTECTED_INLINE_CODE_#{counter}-->"
|
|
64
|
-
code_blocks[placeholder] = match
|
|
65
|
-
counter += 1
|
|
66
|
-
placeholder
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
[protected, code_blocks]
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def restore_code_blocks(content, code_blocks)
|
|
73
|
-
result = content
|
|
74
|
-
code_blocks.each do |placeholder, original|
|
|
75
|
-
result = result.gsub(placeholder, original)
|
|
76
|
-
end
|
|
77
|
-
result
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'digest'
|
|
4
|
-
require_relative 'base_transformer'
|
|
5
|
-
|
|
6
|
-
module Jekyll
|
|
7
|
-
module WebAwesome
|
|
8
|
-
# Transforms standalone images into clickable images that open in dialogs
|
|
9
|
-
# Images can opt-out by adding "nodialog" to the title attribute
|
|
10
|
-
# Example: 
|
|
11
|
-
class ImageDialogTransformer < BaseTransformer
|
|
12
|
-
def self.transform(content, site = nil)
|
|
13
|
-
# Get configuration including default width
|
|
14
|
-
config = site ? Plugin.image_dialog_config(site) : {}
|
|
15
|
-
|
|
16
|
-
# First, protect code blocks, inline code, and comparison blocks from transformation
|
|
17
|
-
protected_content, fenced_code_blocks = protect_fenced_code_blocks(content)
|
|
18
|
-
protected_content, inline_code_blocks = protect_inline_code(protected_content)
|
|
19
|
-
protected_content, comparison_blocks = protect_comparisons(protected_content)
|
|
20
|
-
|
|
21
|
-
# Match markdown images:  or 
|
|
22
|
-
# Capture alt text, URL, and optional title
|
|
23
|
-
# URL can contain spaces and special characters
|
|
24
|
-
image_regex = /!\[([^\]]*)\]\(([^)]+?)(?:\s+"([^"]*)")?\)/
|
|
25
|
-
|
|
26
|
-
result = protected_content.gsub(image_regex) do |match|
|
|
27
|
-
alt_text = Regexp.last_match(1)
|
|
28
|
-
image_url = Regexp.last_match(2).strip
|
|
29
|
-
title = Regexp.last_match(3)
|
|
30
|
-
|
|
31
|
-
# Skip transformation if title contains "nodialog"
|
|
32
|
-
if title&.include?('nodialog')
|
|
33
|
-
# Return original image without dialog
|
|
34
|
-
match
|
|
35
|
-
else
|
|
36
|
-
# Transform to clickable image with dialog
|
|
37
|
-
transform_to_dialog(alt_text, image_url, title, config)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# Restore protected blocks in reverse order
|
|
42
|
-
result = restore_comparisons(result, comparison_blocks)
|
|
43
|
-
result = restore_inline_code(result, inline_code_blocks)
|
|
44
|
-
restore_fenced_code_blocks(result, fenced_code_blocks)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
class << self
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
# Protect fenced code blocks from transformation
|
|
51
|
-
def protect_fenced_code_blocks(content)
|
|
52
|
-
code_blocks = []
|
|
53
|
-
# Match both ``` and ~~~ style code blocks with optional language
|
|
54
|
-
protected = content.gsub(/^```.*?^```$|^~~~.*?^~~~$/m) do |match|
|
|
55
|
-
placeholder = "<!--IMAGE_DIALOG_FENCED_CODE_#{code_blocks.length}-->"
|
|
56
|
-
code_blocks << match
|
|
57
|
-
placeholder
|
|
58
|
-
end
|
|
59
|
-
[protected, code_blocks]
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# Restore protected fenced code blocks
|
|
63
|
-
def restore_fenced_code_blocks(content, code_blocks)
|
|
64
|
-
code_blocks.each_with_index do |code, index|
|
|
65
|
-
content = content.gsub("<!--IMAGE_DIALOG_FENCED_CODE_#{index}-->", code)
|
|
66
|
-
end
|
|
67
|
-
content
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# Protect inline code from transformation
|
|
71
|
-
def protect_inline_code(content)
|
|
72
|
-
code_blocks = []
|
|
73
|
-
protected = content.gsub(/`[^`]+`/) do |match|
|
|
74
|
-
placeholder = "<!--IMAGE_DIALOG_INLINE_CODE_#{code_blocks.length}-->"
|
|
75
|
-
code_blocks << match
|
|
76
|
-
placeholder
|
|
77
|
-
end
|
|
78
|
-
[protected, code_blocks]
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# Restore protected inline code
|
|
82
|
-
def restore_inline_code(content, code_blocks)
|
|
83
|
-
code_blocks.each_with_index do |code, index|
|
|
84
|
-
content = content.gsub("<!--IMAGE_DIALOG_INLINE_CODE_#{index}-->", code)
|
|
85
|
-
end
|
|
86
|
-
content
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
# Protect comparison blocks from image transformation
|
|
90
|
-
# Must protect both markdown syntax (|||...|||) and already-transformed HTML
|
|
91
|
-
def protect_comparisons(content)
|
|
92
|
-
comparison_blocks = []
|
|
93
|
-
|
|
94
|
-
# First protect markdown comparison syntax: |||...|||
|
|
95
|
-
protected = content.gsub(/\|\|\|(\d+)?\n.*?\n\|\|\|/m) do |match|
|
|
96
|
-
placeholder = "<!--IMAGE_DIALOG_COMPARISON_#{comparison_blocks.length}-->"
|
|
97
|
-
comparison_blocks << match
|
|
98
|
-
placeholder
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# Also protect already-transformed HTML comparison blocks: <wa-comparison ...>...</wa-comparison>
|
|
102
|
-
protected = protected.gsub(/<wa-comparison[^>]*>.*?<\/wa-comparison>/m) do |match|
|
|
103
|
-
placeholder = "<!--IMAGE_DIALOG_COMPARISON_#{comparison_blocks.length}-->"
|
|
104
|
-
comparison_blocks << match
|
|
105
|
-
placeholder
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
[protected, comparison_blocks]
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
# Restore protected comparison blocks
|
|
112
|
-
def restore_comparisons(content, comparison_blocks)
|
|
113
|
-
comparison_blocks.each_with_index do |block, index|
|
|
114
|
-
content = content.gsub("<!--IMAGE_DIALOG_COMPARISON_#{index}-->", block)
|
|
115
|
-
end
|
|
116
|
-
content
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# Transform image into our custom dialog syntax
|
|
120
|
-
# This will be processed by DialogTransformer to create the actual wa-dialog
|
|
121
|
-
def transform_to_dialog(alt_text, image_url, title, config = {})
|
|
122
|
-
# Parse width from title if specified (e.g., "50%", "800px", "60vw")
|
|
123
|
-
width = extract_width_from_title(title)
|
|
124
|
-
|
|
125
|
-
# Use default width from config if no width specified in title
|
|
126
|
-
width ||= config[:default_width] if config[:default_width]
|
|
127
|
-
|
|
128
|
-
# Build dialog parameters
|
|
129
|
-
# Always include header with X close button for accessibility
|
|
130
|
-
params = ['light-dismiss']
|
|
131
|
-
params << width if width
|
|
132
|
-
params_string = params.join(' ')
|
|
133
|
-
|
|
134
|
-
# Build the button content - a styled image that acts as the trigger
|
|
135
|
-
# Add title attribute if provided and doesn't contain "nodialog" or width
|
|
136
|
-
title_attr = title && !title.include?('nodialog') && !contains_width?(title) ? " title=\"#{title}\"" : ''
|
|
137
|
-
button_content = "<img src=\"#{image_url}\" alt=\"#{alt_text}\" style=\"cursor: zoom-in; display: block; width: 100%; height: auto;\"#{title_attr} />"
|
|
138
|
-
|
|
139
|
-
# Build the dialog content with alt text as heading for the label
|
|
140
|
-
# Use alt text for the label, or "Image" as fallback if alt is empty
|
|
141
|
-
label_text = alt_text.empty? ? 'Image' : alt_text
|
|
142
|
-
dialog_content = "# #{label_text}\n\n<img src=\"#{image_url}\" alt=\"#{alt_text}\" style=\"max-width: 100%; height: auto; display: block; margin: 0 auto;\" />"
|
|
143
|
-
|
|
144
|
-
# Use our custom dialog syntax that will be processed by DialogTransformer
|
|
145
|
-
# Format: ???params\nbutton_content\n>>>\ndialog_content\n???
|
|
146
|
-
result = []
|
|
147
|
-
result << "???#{params_string}"
|
|
148
|
-
result << button_content
|
|
149
|
-
result << '>>>'
|
|
150
|
-
result << dialog_content
|
|
151
|
-
result << '???'
|
|
152
|
-
|
|
153
|
-
result.join("\n")
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
# Extract width parameter from title attribute
|
|
157
|
-
def extract_width_from_title(title)
|
|
158
|
-
return nil unless title
|
|
159
|
-
|
|
160
|
-
# Match CSS width units: px, em, rem, vw, vh, %, ch
|
|
161
|
-
match = title.match(/(\d+(?:\.\d+)?(?:px|em|rem|vw|vh|%|ch))/)
|
|
162
|
-
match ? match[1] : nil
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
# Check if title contains a width value
|
|
166
|
-
def contains_width?(title)
|
|
167
|
-
return false unless title
|
|
168
|
-
|
|
169
|
-
title.match?(/\d+(?:\.\d+)?(?:px|em|rem|vw|vh|%|ch)/)
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
end
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'base_transformer'
|
|
4
|
-
|
|
5
|
-
module Jekyll
|
|
6
|
-
module WebAwesome
|
|
7
|
-
# Transforms tabs syntax into wa-tab-group elements
|
|
8
|
-
# Primary syntax: ++++++placement?\n+++tab1\ncontent\n+++\n+++tab2\ncontent\n+++\n++++++
|
|
9
|
-
# Alternative syntax: :::wa-tabs placement?\n+++tab1\ncontent\n+++\n+++tab2\ncontent\n+++\n:::
|
|
10
|
-
# Placements: top (default), bottom, start, end
|
|
11
|
-
class TabsTransformer < BaseTransformer
|
|
12
|
-
def self.transform(content)
|
|
13
|
-
# Define both regex patterns
|
|
14
|
-
primary_regex = /^\+{6}(top|bottom|start|end)?\n((\+\+\+ [^\n]+\n.*?\n\+\+\+\n?)+)\+{6}/m
|
|
15
|
-
alternative_regex = /^:::wa-tabs\s*(top|bottom|start|end)?\n((\+\+\+ [^\n]+\n.*?\n\+\+\+\n?)+):::/m
|
|
16
|
-
|
|
17
|
-
# Define shared transformation logic
|
|
18
|
-
transform_proc = proc do |placement, tabs_block, _third_capture|
|
|
19
|
-
placement ||= 'top'
|
|
20
|
-
|
|
21
|
-
tabs, tab_panels = extract_tabs_and_panels(tabs_block)
|
|
22
|
-
|
|
23
|
-
"<wa-tab-group placement=\"#{placement}\">#{tabs.join}#{tab_panels.join}</wa-tab-group>"
|
|
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 extract_tabs_and_panels(tabs_block)
|
|
35
|
-
# Extract individual tabs
|
|
36
|
-
tab_contents = tabs_block.scan(/^\+\+\+ ([^\n]+)\n(.*?)\n\+\+\+/m)
|
|
37
|
-
tabs = []
|
|
38
|
-
tab_panels = []
|
|
39
|
-
|
|
40
|
-
tab_contents.each_with_index do |(title, panel_content), index|
|
|
41
|
-
tab_id = "tab-#{index + 1}"
|
|
42
|
-
tabs << "<wa-tab panel=\"#{tab_id}\">#{title.strip}</wa-tab>"
|
|
43
|
-
|
|
44
|
-
panel_html = markdown_to_html(panel_content.strip)
|
|
45
|
-
tab_panels << "<wa-tab-panel name=\"#{tab_id}\">#{panel_html}</wa-tab-panel>"
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
[tabs, tab_panels]
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'base_transformer'
|
|
4
|
-
|
|
5
|
-
module Jekyll
|
|
6
|
-
module WebAwesome
|
|
7
|
-
# Transforms tag syntax into wa-tag elements
|
|
8
|
-
# Primary syntax: @@@variant?\ncontent\n@@@
|
|
9
|
-
# Alternative syntax: :::wa-tag variant?\ncontent\n:::
|
|
10
|
-
# Variants: brand, success, neutral, warning, danger
|
|
11
|
-
class TagTransformer < BaseTransformer
|
|
12
|
-
def self.transform(content)
|
|
13
|
-
# Define both regex patterns
|
|
14
|
-
primary_regex = /^@@@(brand|success|neutral|warning|danger)?\n(.*?)\n@@@/m
|
|
15
|
-
alternative_regex = /^:::wa-tag\s*(brand|success|neutral|warning|danger)?\n(.*?)\n:::/m
|
|
16
|
-
|
|
17
|
-
# Define shared transformation logic
|
|
18
|
-
transform_proc = proc do |variant, tag_content|
|
|
19
|
-
tag_content = tag_content.strip
|
|
20
|
-
|
|
21
|
-
build_tag_html(tag_content, variant)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Apply both patterns
|
|
25
|
-
patterns = dual_syntax_patterns(primary_regex, alternative_regex, transform_proc)
|
|
26
|
-
apply_multiple_patterns(content, patterns)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
class << self
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
def build_tag_html(content, variant)
|
|
33
|
-
variant_attr = variant ? " variant=\"#{variant}\"" : ''
|
|
34
|
-
tag_html = markdown_to_html(content).strip
|
|
35
|
-
|
|
36
|
-
# Remove paragraph tags if the content is just text
|
|
37
|
-
tag_html = tag_html.gsub(%r{^<p>(.*)</p>$}m, '\1')
|
|
38
|
-
|
|
39
|
-
"<wa-tag#{variant_attr}>#{tag_html}</wa-tag>"
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
@@ -1,19 +0,0 @@
|
|
|
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/carousel_transformer'
|
|
12
|
-
require_relative 'transformers/comparison_transformer'
|
|
13
|
-
require_relative 'transformers/copy_button_transformer'
|
|
14
|
-
require_relative 'transformers/details_transformer'
|
|
15
|
-
require_relative 'transformers/dialog_transformer'
|
|
16
|
-
require_relative 'transformers/icon_transformer'
|
|
17
|
-
require_relative 'transformers/image_dialog_transformer'
|
|
18
|
-
require_relative 'transformers/tabs_transformer'
|
|
19
|
-
require_relative 'transformers/tag_transformer'
|