This is a plugin for Jekyll that transforms custom Markdown syntax into Web Awesome components. Use a simple, intuitive Markdown-like syntax to create rich interactive components in your Jekyll website. The goal is to keep HTML out of Markdown files and create an easier experience for non-developers to update content.
The context here is a technical documentation website, and being limited to just basic Markdown features often results in a boring wall of text which the user won't read. The aim is to help create a more visually interesting page to read, by mixing in some components like callouts, tabs, cards and collapsible summary/details.
This plugin focuses on the most commonly used Web Awesome components for Jekyll content. Components are organized by support status:
| Component | Primary Syntax | Alternative Syntax | HTML Output |
|---|---|---|---|
| Badge | !!!variant |
:::wa-badge variant |
<wa-badge variant="brand">content</wa-badge> |
| Button | %%%variant |
:::wa-button variant |
<wa-button variant="brand" href="url">text</wa-button> or <wa-button variant="brand">text</wa-button> |
| Callouts | :::info |
:::wa-callout info |
<wa-callout variant="brand"><wa-icon name="circle-info"></wa-icon>content</wa-callout> |
| Card | === |
:::wa-card |
<wa-card>content</wa-card> |
| Carousel | ~~~~~~ |
:::wa-carousel |
<wa-carousel> with carousel items |
| Comparison | ||| or |||25 |
:::wa-comparison or :::wa-comparison 25 |
<wa-comparison> with before/after slots |
| Copy Button | <<< |
:::wa-copy-button |
<wa-copy-button value="content">content</wa-copy-button> |
| Details | ^^^appearance? icon-placement? |
:::wa-details appearance? icon-placement? |
<wa-details appearance="..." icon-placement="...">content</wa-details> |
| Dialog | ???params? |
:::wa-dialog params? |
<wa-dialog> with trigger button and content |
| Tab Group | ++++++ |
:::wa-tabs |
<wa-tab-group><wa-tab>content</wa-tab></wa-tab-group> |
| Tag | @@@brand |
:::wa-tag brand |
<wa-tag variant="brand">content</wa-tag> |
Not all components will make sense to include here, to be included in the "prose" content of a web page. Some components are more suitable to be used in layouts or used in the page as includes, too complicated for this purpose.
Both syntax styles work identically and can be mixed within the same document.
Add this line to your application's Gemfile:
gem 'jekyll-webawesome'
Add the plugin to your Jekyll site's _config.yml:
plugins:
- jekyll-webawesome
And add configuration options as needed in _config.yml:
webawesome:
# Enable debug output to see which files are being processed
debug: true
# Control which file types to transform (default: both true)
transform_pages: true # Transform pages (like index.md, about.md)
transform_documents: true # Transform documents (like blog posts in _posts)
# Enable automatic image-to-dialog transformation (default: false)
# Can be a simple boolean
image_dialog: true # Makes all images clickable and open in dialogs
# Or a hash with options for more control
image_dialog:
enabled: true # Enable the feature
default_width: 90vh # Default width for dialogs (e.g., 90vh, 80%, 1200px)
And then execute:
bundle install
You can also configure the plugin programmatically in a _plugins/ file or in your gem's initialization:
require 'jekyll-webawesome'
Jekyll::WebAwesome.configure do |config|
config.debug_mode = true
config.transform_pages = false # Don't transform pages
config.transform_documents = true # Only transform documents (posts)
end
See the plugin in action with a complete Jekyll site showcasing all supported components:
cd examples
bundle install
bundle exec jekyll serve
Then visit http://localhost:4000 to see all components rendered with Web Awesome styling.
Note: All components support dual syntax. You can use either the primary syntax (shown in examples below) or the alternative
:::wa-componentsyntax.
Create callouts using the ::: syntax:
:::info
This is an info callout with **bold text** and [links](https://example.com).
:::
:::success
This is a success callout.
:::
:::warning
This is a warning callout.
:::
:::danger
This is a danger callout.
:::
:::neutral
This is a neutral callout.
:::
These transform into Web Awesome callout components with appropriate icons and styling
Create before/after image comparisons using the ||| syntax:
|||


|||
You can specify the initial position of the comparison slider (0-100):
|||25


|||
This transforms into a Web Awesome comparison component that lets users interactively compare two images:
<wa-comparison position="25">
<img slot="before" src="before.jpg" alt="Grayscale version" />
<img slot="after" src="after.jpg" alt="Color version" />
</wa-comparison>
The comparison component requires exactly two images within the wrapper:
Note: If the comparison block doesn't contain exactly two images, it will be left unchanged rather than transformed.
Create cards using the === syntax:
===
This is a basic card with just content.
===
The first heading (#) automatically becomes the card header:
===
# Card Title
This is the card content that appears in the main area.
===
The first image automatically becomes the card media:
===

# Featured Content
This card includes both an image and a title.
===
Links at the end of the card content automatically become footer buttons:
===
# Get Started
Ready to begin your journey?
[Learn More](https://example.com)
===
You can combine all elements for rich content cards:
===filled

# Complete Example
This card has media, header, content, and footer with a filled appearance.
[Get Started](https://example.com)
===
You can specify different visual styles:
===filled
# Filled Card
This card uses the filled appearance.
===
===plain
# Plain Card
This card uses the plain appearance.
===
===filled-outlined
# Filled Outlined Card
This card uses the filled-outlined appearance.
===
===accent
# Accent Card
This card uses the accent appearance for emphasis.
===
Create carousels (image sliders/content rotators) using the ~~~~~~ syntax:
~~~~~~
~~~

Beautiful mountain scenery
~~~
~~~

Peaceful ocean waves
~~~
~~~

Walking through the woods
~~~
~~~~~~
Show multiple slides at once by specifying the number:
~~~~~~3
~~~
Product 1 content
~~~
~~~
Product 2 content
~~~
~~~
Product 3 content
~~~
~~~
Product 4 content
~~~
~~~~~~
Add navigation arrows and pagination dots with keywords:
~~~~~~navigation pagination
~~~
First slide
~~~
~~~
Second slide
~~~
~~~
Third slide
~~~
~~~~~~
Control how many slides advance at a time (first number is slides-per-page, second is slides-per-move):
~~~~~~3 2 navigation
~~~
Slide 1
~~~
~~~
Slide 2
~~~
~~~
Slide 3
~~~
~~~
Slide 4
~~~
~~~
Slide 5
~~~
~~~~~~
This shows 3 slides at a time and moves 2 slides when navigating.
Enable continuous looping with the loop keyword:
~~~~~~loop navigation
~~~
Slide 1
~~~
~~~
Slide 2
~~~
~~~
Slide 3
~~~
~~~~~~
Add padding to show adjacent slides as a hint using the scroll-hint CSS property:
~~~~~~scroll-hint:3rem navigation
~~~

~~~
~~~

~~~
~~~

~~~
~~~~~~
Combine multiple parameters for full control:
~~~~~~3 2 loop navigation pagination scroll-hint:2rem
~~~

# Feature One
Description here
~~~
~~~

# Feature Two
More details
~~~
~~~

# Feature Three
Additional info
~~~
~~~~~~
For carousels with text content, cards, or variable-height slides, you may want to remove the default 16/9 aspect ratio to let content size naturally:
~~~~~~aspect-ratio:auto navigation
~~~
# First Slide
This carousel will size based on content height, not a fixed aspect ratio.
Perfect for text-heavy slides or mixed content.
~~~
~~~
# Second Slide
Another slide with different content height.
~~~
~~~~~~
Use aspect-ratio:auto or aspect-ratio:none to override the default fixed height behavior.
| Parameter Type | Syntax | Description |
|---|---|---|
| Slides Per Page | First number (e.g., 3) |
How many slides visible at once (default: 1) |
| Slides Per Move | Second number (e.g., 2) |
How many slides to advance (default: 1) |
| Loop | loop |
Enable continuous looping (default: off) |
| Navigation | navigation |
Show previous/next buttons |
| Pagination | pagination |
Show dot indicators |
| Autoplay | autoplay |
Auto-advance slides |
| Mouse Dragging | mouse-dragging |
Enable click-and-drag |
| Vertical | vertical |
Vertical orientation |
| Scroll Hint | scroll-hint:2rem |
Padding to show adjacent slides |
| Aspect Ratio | aspect-ratio:3/2 |
Viewport aspect ratio (default: 16/9) |
| Slide Gap | slide-gap:1rem |
Space between slides |
All parameters are optional and can be combined in any order:
~~~~~~vertical pagination autoplay
~~~
Content here
~~~
~~~~~~
Create tags using the @@@ syntax:
@@@
Basic tag
@@@
@@@brand
Version 2.0
@@@
@@@success
Completed
@@@
@@@warning
In Progress
@@@
@@@danger
Critical Issue
@@@
@@@neutral
Documentation
@@@
These transform into Web Awesome tag components with appropriate colors and styling.
Create copy-to-clipboard buttons using the <<< syntax:
<<<
Copy this simple text
<<<
<<<
npm install jekyll-webawesome
<<<
Copy buttons support markdown formatting in the display text while preserving the original markdown in the clipboard value:
<<<
**Copy** this text with *markdown* formatting and `code`
<<<
This transforms into a Web Awesome copy button component:
<wa-copy-button value="**Copy** this text with *markdown* formatting and `code`"></wa-copy-button>
Copy buttons work well for:
Note: The
valueattribute contains the raw text (including any markdown) that gets copied to the clipboard. The copy button displays the standard Web Awesome copy icon and handles the clipboard operation automatically.
Create interactive dialogs (modals) using the ??? syntax:
???
Open Dialog
>>>
This is the dialog content with **markdown** support.
???
This creates a trigger button and a dialog that opens when clicked:
<wa-button data-dialog='open dialog-abc123'>Open Dialog</wa-button>
<wa-dialog id='dialog-abc123' label='Open Dialog'>
<p>This is the dialog content with <strong>markdown</strong> support.</p>
<wa-button slot='footer' variant='primary' data-dialog='close'>Close</wa-button>
</wa-dialog>
The first heading (#) automatically becomes the dialog's label (title):
???
Show Details
>>>
# Important Information
This is the content of the dialog.
???
The button displays "Show Details" and the dialog header shows "Important Information".
You can customize dialog behavior with optional parameters:
Light Dismiss - Dialog closes when clicking the overlay:
???light-dismiss
Open Dialog
>>>
Click outside to close this dialog.
???
Custom Width - Set a specific width using CSS units (px, em, rem, vw, vh, %):
???600px
Open Dialog
>>>
This dialog is 600 pixels wide.
???
???50vw
Open Wide Dialog
>>>
This dialog is 50% of the viewport width.
???
???40em
Open Dialog
>>>
This dialog is 40em wide.
???
Combining Options - You can combine multiple options:
???light-dismiss 700px
Open Dialog
>>>
# Custom Dialog
This dialog has light dismiss enabled and is 700px wide.
???
Note: The dialog uses Web Awesome's declarative
data-dialogAPI, so no custom JavaScript is needed. Each dialog gets a unique ID automatically generated from its content. The header with X close button is always shown for accessibility, and a "Close" button is automatically added to the footer.
Create collapsible content using the ^^^ syntax:
^^^
Click to expand this summary
>>>
This is the detailed content that can be collapsed and expanded.
You can include:
- Lists
- **Bold text**
- [Links](https://example.com)
- Code blocks
^^^
You can also specify appearance styles:
^^^filled
Filled appearance summary
>>>
Content goes here
^^^
^^^plain
Plain appearance summary
>>>
Content goes here
^^^
^^^filled-outlined
Filled and outlined appearance summary
>>>
Content goes here
^^^
You can also control icon placement (expand/collapse icon location):
^^^start
Summary with icon on the start (left)
>>>
The expand/collapse icon appears on the left side
^^^
^^^end
Summary with icon on the end (right)
>>>
The expand/collapse icon appears on the right side (default)
^^^
You can combine appearance and icon placement:
^^^filled start
Filled appearance with icon on the start
>>>
Content with both styling and icon positioning
^^^
^^^plain end
Plain appearance with icon on the end
>>>
Parameters can be in any order: start filled, filled start, etc.
^^^
Create tabbed content using the ++++++ syntax for tab groups and +++ for tabs.
++++++
+++ First Tab
Content for the first tab goes here.
+++
+++ Second Tab
Content for the second tab.
+++
+++ Third Tab
Content for the third tab.
+++
++++++
You can specify tab placement:
++++++start
+++ Tab 1
Content here
+++
+++ Tab 2
More content
+++
++++++
++++++bottom
+++ Tab 1
Content here
+++
+++ Tab 2
More content
+++
++++++
Supported placements: top (default), bottom, start, end.
| Type | Icon | Variant |
|---|---|---|
info |
circle-info | brand |
success |
circle-check | success |
warning |
triangle-exclamation | warning |
danger |
circle-exclamation | danger |
neutral |
gear | neutral |
| Type | Description |
|---|---|
outlined (default) |
Default outlined appearance |
filled |
Filled background appearance |
plain |
Minimal plain appearance |
filled-outlined |
Combination of filled and outlined |
accent |
Accent appearance for emphasis |
Cards automatically parse content into these slots:
# heading becomes header slot | Parameter | Type | Description |
|---|---|---|
| Slides Per Page | Number (first numeric parameter) | How many slides visible at once (default: 1) |
| Slides Per Move | Number (second numeric parameter) | How many slides to advance (default: 1) |
loop |
Boolean | Enable continuous looping (default: off) |
navigation |
Boolean | Show previous/next buttons (default: off) |
pagination |
Boolean | Show dot indicators (default: off) |
autoplay |
Boolean | Auto-advance slides (default: off) |
mouse-dragging |
Boolean | Enable click-and-drag (default: off) |
vertical |
Keyword | Use vertical orientation (default: horizontal) |
scroll-hint:value |
CSS Property | Padding to show adjacent slides (e.g., 2rem, 50px) |
aspect-ratio:value |
CSS Property | Viewport aspect ratio (default: 16/9, e.g., 3/2, 4/3). Use auto or none for content-based height |
slide-gap:value |
CSS Property | Space between slides (default: var(--wa-space-m)) |
| Type | Description |
|---|---|
| (none) | Default neutral appearance |
brand |
Primary brand color |
success |
Success/positive state |
warning |
Warning/caution state |
danger |
Error/critical state |
neutral |
Neutral/informational state |
| Type | CSS Class |
|---|---|
outlined (default) |
outlined |
filled |
filled |
plain |
plain |
filled-outlined |
filled outlined |
| Position | Description |
|---|---|
end (default) |
Icon appears on the right side |
start |
Icon appears on the left side |
| Option | Description |
|---|---|
light-dismiss |
Dialog closes when clicking outside/on overlay |
Width (e.g., 500px, 50vw, 40em) |
Sets custom width using CSS units (px, em, rem, vw, vh, %) |
data-dialog attributes - no custom JavaScript needed# heading becomes the dialog label, or button text is used as fallbackEnable automatic image-to-dialog transformation in your _config.yml:
webawesome:
# Simple boolean to enable
image_dialog: true
# Or configure with options
image_dialog:
enabled: true
default_width: 90vh # Default width for all image dialogs
When enabled, all markdown images automatically become clickable and open in full-size dialogs:

Default Width: Set a default width for all image dialogs in the configuration. Images will use this width unless overridden in the title.
Control dialog width by adding a width parameter to the title (overrides default):
 # Dialog width: 50%
 # Dialog width: 800px
 # Dialog width: 90% viewport
Supported width units: px, em, rem, vw, vh, %, ch
Opt-out by adding "nodialog" to the title:

Features:
top (default)bottomstartendBug reports and pull requests are welcome on GitHub at https://github.com/jannewaren/jekyll-webawesome.
The gem is available as open source under the terms of the MIT License.