Skip to content

Commit

Permalink
Add breadcrumbs to articles (#628)
Browse files Browse the repository at this point in the history
  • Loading branch information
aduth authored Dec 9, 2024
1 parent b2598eb commit fbb6281
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 8 deletions.
5 changes: 4 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ source "https://rubygems.org"

ruby '~> 3.2.2'

gem "actionpack", "~> 8.0.0"
gem "activesupport", "~> 8.0.0"
gem "actionview", "~> 8.0.0"
gem "jekyll", "~> 4"
gem "kramdown", ">= 2.3.0"
gem "view_component", "~> 3.20.0"

group :jekyll_plugins do
gem "jekyll-redirect-from"
Expand All @@ -12,7 +16,6 @@ group :jekyll_plugins do
end

group :test do
gem 'activesupport', '~> 7.0.7'
gem 'html-proofer', '~> 4.4.3'
gem 'nokogiri', '~> 1.16.5'
gem 'rspec', '~> 3.9.0'
Expand Down
73 changes: 66 additions & 7 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,19 +1,51 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (7.0.7.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
actionpack (8.0.0)
actionview (= 8.0.0)
activesupport (= 8.0.0)
nokogiri (>= 1.8.5)
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
actionview (8.0.0)
activesupport (= 8.0.0)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
activesupport (8.0.0)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
tzinfo (~> 2.0)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.8)
builder (3.3.0)
colorator (1.1.0)
concurrent-ruby (1.2.2)
concurrent-ruby (1.3.4)
connection_pool (2.4.1)
crass (1.0.6)
diff-lcs (1.5.0)
drb (2.2.1)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
erubi (1.13.0)
ethon (0.16.0)
ffi (>= 1.15.0)
eventmachine (1.2.7)
Expand All @@ -30,7 +62,7 @@ GEM
yell (~> 2.0)
zeitwerk (~> 2.5)
http_parser.rb (0.8.0)
i18n (1.14.1)
i18n (1.14.6)
concurrent-ruby (~> 1.0)
jekyll (4.3.2)
addressable (~> 2.4)
Expand Down Expand Up @@ -67,9 +99,14 @@ GEM
listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.6.2)
loofah (2.23.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mercenary (0.4.0)
method_source (1.1.0)
mini_portile2 (2.8.6)
minitest (5.19.0)
minitest (5.25.4)
nokogiri (1.16.5)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
Expand All @@ -79,6 +116,18 @@ GEM
posix-spawn (0.3.15)
public_suffix (5.0.1)
racc (1.7.3)
rack (3.1.8)
rack-session (2.0.0)
rack (>= 3.0.0)
rack-test (2.1.0)
rack (>= 1.3)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
rainbow (3.1.1)
rake (13.0.6)
rb-fsevent (0.11.2)
Expand All @@ -103,13 +152,20 @@ GEM
sass-embedded (1.63.2)
google-protobuf (~> 3.23)
rake (>= 10.0.0)
securerandom (0.4.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.4.2)
uri (1.0.2)
useragent (0.16.11)
view_component (3.20.0)
activesupport (>= 5.2.0, < 8.1)
concurrent-ruby (~> 1.0)
method_source (~> 1.0)
webrick (1.8.2)
yell (2.2.2)
zeitwerk (2.6.7)
Expand All @@ -118,7 +174,9 @@ PLATFORMS
ruby

DEPENDENCIES
activesupport (~> 7.0.7)
actionpack (~> 8.0.0)
actionview (~> 8.0.0)
activesupport (~> 8.0.0)
html-proofer (~> 4.4.3)
jekyll (~> 4)
jekyll-environment-variables
Expand All @@ -127,6 +185,7 @@ DEPENDENCIES
kramdown (>= 2.3.0)
nokogiri (~> 1.16.5)
rspec (~> 3.9.0)
view_component (~> 3.20.0)

RUBY VERSION
ruby 3.2.2p53
Expand Down
5 changes: 5 additions & 0 deletions _components/breadcrumb_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<nav class="usa-breadcrumb" aria-label="Breadcrumbs,,">
<ol class="usa-breadcrumb__list">
<%= content %>
</ol>
</nav>
1 change: 1 addition & 0 deletions _components/breadcrumb_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
class BreadcrumbComponent < ViewComponent::Base; end
3 changes: 3 additions & 0 deletions _components/breadcrumb_item_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<li class="usa-breadcrumb__list-item<%= current? ? ' usa-current' : '' %>">
<a href="<%= href %>" class="usa-breadcrumb__link"><span><%= content %></span></a>
</li>
9 changes: 9 additions & 0 deletions _components/breadcrumb_item_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class BreadcrumbItemComponent < ViewComponent::Base
attr_reader :href, :current
alias_method :current?, :current

def initialize(href:, current: false)
@href = href
@current = current
end
end
10 changes: 10 additions & 0 deletions _layouts/article.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@

<div class="tablet:grid-col-8">
<div class="usa-prose" role="main">
{% if page.category %}
{% assign home_url = "/" | prepend: site.baseurl %}
{% assign category_url = page.category | slugify | prepend: "/categories/" | prepend: site.baseurl | append: ".html" %}
{% component breadcrumb %}
{% component breadcrumb_item href=home_url %}Home{% endcomponent %}
{% component breadcrumb_item href=category_url %}{{ page.category }}{% endcomponent %}
{% component breadcrumb_item href=page.url current %}{{ page.title }}{% endcomponent %}
{% endcomponent %}
{% endif %}

<h1>
{{ page.title }}
{% if page.deprecated %}
Expand Down
6 changes: 6 additions & 0 deletions _layouts/category.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@

<div class="tablet:grid-col-8">
<div class="usa-prose" role="main">
{% assign home_url = "/" | prepend: site.baseurl %}
{% component breadcrumb %}
{% component breadcrumb_item href=home_url %}Home{% endcomponent %}
{% component breadcrumb_item href=page.url current %}{{ page.title }}{% endcomponent %}
{% endcomponent %}

<h1>
{% if page.icon %}
{% include uswds-icon.html icon=page.icon %}
Expand Down
82 changes: 82 additions & 0 deletions _plugins/view_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
require 'action_controller'
require 'action_view'
require 'active_support'
require 'view_component'

unless defined?(Rails)
module Rails
class Application
def routes
@routes ||= Struct.new(:url_helpers).new(Module.new)
end
end

def self.version
ActionView.version.to_s
end

module VERSION
MAJOR, MINOR = Rails.version.split('.').map(&:to_i)
end

def self.env
@env ||= Struct.new(:development?, :test?, :production?).new(false, false, true)
end

def self.application
@application ||= Application.new
end
end
end

Dir['_components/**/*.rb'].each { |f| require File.join('.', f) }

class ComponentTag < Liquid::Block
PARAM_SYNTAX = /(\w+)(?:=(?:"([^"]+?)"|(\S+)))?/.freeze

def initialize(tag_name, variables, context)
super

@component_name, @params = variables.split(' ', 2)
end

# Jekyll tags don't have built-in support for variable references, but Jekyll's built-in `include`
# tag has a syntax we can use as a starting point.
#
# @see https://github.com/jekyll/jekyll/blob/master/lib/jekyll/tags/include.rb
#
# Example:
#
# {% component link url=page.url text="Home" current %}
#
# In this example, `url` would be assigned from the page context variable nested value, `text`
# would be assigned to a string literal, and `current` would be `true`.
def parse_params(context)
params = {}
@params.scan(PARAM_SYNTAX) do |key, string, variable|
if string
params[key] = string
elsif variable
parts = variable.split('.')
value = context
while (part = parts.shift)
value = value[part]
end
params[key] = value
else
params[key] = true
end
end
params
end

def render(context)
content = super.html_safe

component_class = "#{@component_name.camelize}Component".constantize
component = component_class.new(**parse_params(context).symbolize_keys).with_content(content)
ActionController::Base.new.render_to_string(component)
end
end

Liquid::Template.register_tag('component', ComponentTag)

0 comments on commit fbb6281

Please sign in to comment.