jekyll-timeline 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6ba528cce1ef2c9f28ba15637bb84e820e0daa26cef50676d47ed500d732cf01
4
+ data.tar.gz: 314be5deed55191ada292275d17b0a0ef3e3af3416d3c1613c517c493235134d
5
+ SHA512:
6
+ metadata.gz: c427bda6e18cfbd29b8c30f9553ac6f249030f6fc2ad83993d7c4762a3deda4763c4ab120c2eecaad009fc6c8d22f13e6fe6c12451aab0bbd11c90de86b386d8
7
+ data.tar.gz: 2c8593e301ba653a05f14530ea3d6b6ea1a5359fb7de9caa2bf989210b3aaf587624b4925b598888e505e2b8b11b6f57b6848f000eabcc8437762dc9b190b704
data/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
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/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-08-22
9
+
10
+ ### Added
11
+ - Initial release
12
+ - `{% timeline %}` / `{% endtimeline %}` outer block tag
13
+ - `{% event %}` / `{% endevent %}` inner block tag with `date`, `title`, `icon`, `color` attributes
14
+ - `order="asc"` (default) and `order="desc"` sort support
15
+ - Icon support: Font Awesome classes, emoji, plain text, or empty dot fallback
16
+ - `timeline.default_icon_prefix` config option (default: `fa-solid`)
17
+ - Pure HTML+CSS output — no JavaScript, no external dependencies
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,3 @@
1
+ # Contributing
2
+
3
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jchance/jekyll-timeline.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jason Chance
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # jekyll-timeline
2
+
3
+ A Jekyll plugin providing `{% timeline %}` and `{% timeline_event %}` block tags that render a vertical timeline component. Pure HTML+CSS output — no JavaScript, no external dependencies.
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/jekyll-timeline.svg)](https://rubygems.org/gems/jekyll-timeline)
6
+
7
+ ## Installation
8
+
9
+ Add to your `Gemfile`:
10
+
11
+ ```ruby
12
+ gem "jekyll-timeline"
13
+ ```
14
+
15
+ Add to `_config.yml`:
16
+
17
+ ```yaml
18
+ plugins:
19
+ - jekyll-timeline
20
+ ```
21
+
22
+ Run `bundle install`.
23
+
24
+ Copy `_timeline.scss` from the gem into your site's SCSS directory and import it:
25
+
26
+ ```scss
27
+ @import "timeline";
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ Wrap events in a `{% timeline %}` block. Each `{% timeline_event %}` block is one entry.
33
+
34
+ ```liquid
35
+ {% timeline %}
36
+
37
+ {% timeline_event date="January 2024" title="Project launched" icon="fa-rocket" %}
38
+ We shipped the first public release after six months of development.
39
+ {% endtimeline_event %}
40
+
41
+ {% timeline_event date="March 2024" title="1,000 users" icon="fa-users" color="#2ecc71" %}
42
+ Crossed 1,000 active users. Added team management features.
43
+ {% endtimeline_event %}
44
+
45
+ {% timeline_event date="June 2024" title="v2.0 released" icon="fa-bolt" %}
46
+ Complete rewrite with improved performance and a new API.
47
+ {% endtimeline_event %}
48
+
49
+ {% endtimeline %}
50
+ ```
51
+
52
+ ### Reverse order
53
+
54
+ ```liquid
55
+ {% timeline order="desc" %}
56
+ ...
57
+ {% endtimeline %}
58
+ ```
59
+
60
+ ## Event attributes
61
+
62
+ | Attribute | Required | Description |
63
+ |-----------|----------|-------------|
64
+ | `date` | No | Display date string (any format — it's not parsed) |
65
+ | `title` | No | Event headline |
66
+ | `icon` | No | Icon class(es), emoji, or plain text. Omit for dot fallback. |
67
+ | `color` | No | CSS color value for this event's icon background |
68
+
69
+ ### Icon formats
70
+
71
+ **Font Awesome classes** — pass one or two CSS classes:
72
+
73
+ ```liquid
74
+ {% timeline_event icon="fa-rocket" %} <!-- uses default_icon_prefix -->
75
+ {% timeline_event icon="fa-solid fa-rocket" %} <!-- explicit style -->
76
+ {% timeline_event icon="fa-brands fa-github" %}
77
+ {% timeline_event icon="fa-duotone fa-star" %} <!-- FA Pro -->
78
+ ```
79
+
80
+ **Emoji:**
81
+
82
+ ```liquid
83
+ {% timeline_event icon="🚀" %}
84
+ ```
85
+
86
+ **No icon** — omit the attribute entirely for a neutral dot:
87
+
88
+ ```liquid
89
+ {% timeline_event date="2024" title="Something happened" %}
90
+ ```
91
+
92
+ ## Configuration
93
+
94
+ All options are optional:
95
+
96
+ ```yaml
97
+ timeline:
98
+ default_icon_prefix: "fa-solid" # prepended when icon has no spaces (default: fa-solid)
99
+ ```
100
+
101
+ ## Styling
102
+
103
+ Copy `_timeline.scss` into your site and customize via CSS custom properties:
104
+
105
+ ```css
106
+ :root {
107
+ --timeline-line-color: #dee2e6; /* vertical line color */
108
+ --timeline-icon-bg: #6c757d; /* default icon circle background */
109
+ --timeline-icon-color: #fff; /* icon/emoji color */
110
+ --timeline-date-color: #6c757d; /* date label color */
111
+ --timeline-title-color: inherit; /* event title color */
112
+ --timeline-body-color: inherit; /* body text color */
113
+ }
114
+ ```
115
+
116
+ Per-event color override via the `color=` attribute sets `--timeline-event-color` inline on that event, overriding `--timeline-icon-bg` for that circle only.
117
+
118
+ ## GitHub Pages compatibility
119
+
120
+ Compatible with GitHub Pages when built via a custom GitHub Actions workflow. Not compatible with the default GitHub Pages safe-mode build.
121
+
122
+ ## License
123
+
124
+ MIT
@@ -0,0 +1,100 @@
1
+ require "jekyll"
2
+
3
+ module Jekyll
4
+ TIMELINE_ATTR_RE = /(\w+)\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+))/
5
+
6
+ def self.parse_attrs(markup)
7
+ attrs = {}
8
+ markup.scan(TIMELINE_ATTR_RE) do |key, dq, sq, bare|
9
+ attrs[key] = dq || sq || bare || ""
10
+ end
11
+ attrs
12
+ end
13
+
14
+ # Inner block tag — registered so Liquid knows about it.
15
+ # When rendered standalone (excerpt, search.json), outputs nothing silently.
16
+ # When rendered inside {% timeline %}, its output is collected by the outer tag.
17
+ class TimelineEventTag < Liquid::Block
18
+ def initialize(tag_name, markup, tokens)
19
+ super
20
+ @attributes = Jekyll.parse_attrs(markup)
21
+ end
22
+
23
+ def render(context)
24
+ site = context.registers[:site]
25
+ config = site.config["timeline"] || {}
26
+ default_prefix = config["default_icon_prefix"] || "fa-solid"
27
+
28
+ content = super.strip
29
+
30
+ rendered_content = begin
31
+ converter = site.find_converter_instance(Jekyll::Converters::Markdown)
32
+ converter.convert(content)
33
+ rescue StandardError
34
+ content
35
+ end
36
+
37
+ date = @attributes["date"] || ""
38
+ title = @attributes["title"] || ""
39
+ icon = @attributes["icon"]
40
+ color = @attributes["color"]
41
+
42
+ color_style = color ? %( style="--timeline-event-color: #{color};") : ""
43
+
44
+ icon_html = if icon.nil? || icon.strip.empty?
45
+ '<span class="timeline__icon timeline__icon--empty"></span>'
46
+ elsif !icon.match?(/[a-zA-Z]/) || (icon.length <= 4 && !icon.include?("-"))
47
+ %(<span class="timeline__icon timeline__icon--text">#{icon}</span>)
48
+ else
49
+ classes = icon.include?(" ") ? icon : "#{default_prefix} #{icon}"
50
+ %(<span class="timeline__icon"><i class="#{classes}" aria-hidden="true"></i></span>)
51
+ end
52
+
53
+ html = <<~HTML
54
+ <div class="timeline__event"#{color_style}>
55
+ #{icon_html}
56
+ <div class="timeline__content">
57
+ <div class="timeline__date">#{date}</div>
58
+ <div class="timeline__title">#{title}</div>
59
+ <div class="timeline__body">#{rendered_content.strip}</div>
60
+ </div>
61
+ </div>
62
+ HTML
63
+
64
+ # If inside a timeline, accumulate; otherwise silently drop
65
+ if context.registers[:timeline_events]
66
+ context.registers[:timeline_events] << html.strip
67
+ end
68
+ ""
69
+ end
70
+ end
71
+
72
+ # Outer block tag
73
+ class TimelineTag < Liquid::Block
74
+ def initialize(tag_name, markup, tokens)
75
+ super
76
+ @attributes = Jekyll.parse_attrs(markup)
77
+ end
78
+
79
+ def render(context)
80
+ context.registers[:timeline_events] = []
81
+ super
82
+
83
+ events = context.registers[:timeline_events] || []
84
+ order = @attributes["order"] || "asc"
85
+ events = events.reverse if order == "desc"
86
+
87
+ # Clean up so nested timelines don't bleed
88
+ context.registers[:timeline_events] = nil
89
+
90
+ <<~HTML
91
+ <div class="timeline">
92
+ #{events.join("\n ")}
93
+ </div>
94
+ HTML
95
+ end
96
+ end
97
+ end
98
+
99
+ Liquid::Template.register_tag("timeline_event", Jekyll::TimelineEventTag)
100
+ Liquid::Template.register_tag("timeline", Jekyll::TimelineTag)
@@ -0,0 +1,4 @@
1
+ require "jekyll"
2
+ require "liquid"
3
+
4
+ require_relative "jekyll/timeline_tag"
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-timeline
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jason Chance
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2026-08-22 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: jekyll
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '4.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '4.0'
26
+ description: A Jekyll plugin providing {% timeline %} and {% event %} block tags that
27
+ render a vertical timeline component. Pure HTML+CSS output — no JavaScript, no external
28
+ dependencies. Supports icon libraries (Font Awesome, emoji, or plain text) and per-event
29
+ color customization.
30
+ email:
31
+ - jchance@gmail.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - CHANGELOG.md
37
+ - CONTRIBUTING.md
38
+ - LICENSE.txt
39
+ - README.md
40
+ - lib/jekyll-timeline.rb
41
+ - lib/jekyll/timeline_tag.rb
42
+ homepage: https://jasonchance.com/projects/jekyll-timeline/
43
+ licenses:
44
+ - MIT
45
+ metadata:
46
+ homepage_uri: https://jasonchance.com/projects/jekyll-timeline/
47
+ source_code_uri: https://github.com/jchance/jekyll-timeline
48
+ changelog_uri: https://github.com/jchance/jekyll-timeline/blob/main/CHANGELOG.md
49
+ bug_tracker_uri: https://github.com/jchance/jekyll-timeline/issues
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '3.0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubygems_version: 3.6.2
65
+ specification_version: 4
66
+ summary: Jekyll Liquid tags for rendering a pure HTML/CSS vertical timeline
67
+ test_files: []