willamette 0.5.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/.gitignore +37 -0
- data/.rubocop.yml +54 -0
- data/CHANGELOG.md +14 -0
- data/CODE_OF_CONDUCT.md +92 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +250 -0
- data/LICENSE.txt +22 -0
- data/README.md +3 -0
- data/Rakefile +11 -0
- data/automations/components.automation.rb +123 -0
- data/automations/frontend.automation.rb +30 -0
- data/automations/layouts.automation.rb +122 -0
- data/bridgetown.automation.rb +7 -0
- data/components/willamette/back_to_top.css +35 -0
- data/components/willamette/back_to_top.js +32 -0
- data/components/willamette/code_element.css +10 -0
- data/components/willamette/code_element.js +49 -0
- data/components/willamette/header_navbar.dsd.css +19 -0
- data/components/willamette/header_navbar.rb +20 -0
- data/components/willamette/holy_grail_layout.dsd.css +81 -0
- data/components/willamette/holy_grail_layout.rb +17 -0
- data/components/willamette/pagination.erb +12 -0
- data/components/willamette/pagination.rb +7 -0
- data/components/willamette/post_item.css +102 -0
- data/components/willamette/post_item.rb +90 -0
- data/components/willamette/previous_next.erb +12 -0
- data/components/willamette/previous_next.rb +7 -0
- data/components/willamette/search_dialog.rb +18 -0
- data/components/willamette/search_dialog_element.js +90 -0
- data/content/search.erb +29 -0
- data/content/willamette/style-guide.md +93 -0
- data/layouts/willamette/default.erb +44 -0
- data/lib/willamette/builders/inspectors.rb +28 -0
- data/lib/willamette/builders/toc.rb +11 -0
- data/lib/willamette/locales/en.yml +22 -0
- data/lib/willamette/strategies/link.rb +20 -0
- data/lib/willamette/strategies/sidebar.rb +83 -0
- data/lib/willamette/version.rb +5 -0
- data/lib/willamette.rb +83 -0
- data/package-lock.json +303 -0
- data/package.json +22 -0
- data/setup.automation.rb +14 -0
- data/willamette.gemspec +30 -0
- metadata +143 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const { default: _default } = require("hotkeys-js")
|
|
2
|
+
|
|
3
|
+
class SearchDialogElement extends HTMLElement {
|
|
4
|
+
static {
|
|
5
|
+
customElements.define("wll-search-dialog", this)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
connectedCallback() {
|
|
9
|
+
setTimeout(() => {
|
|
10
|
+
this.querySelector(":scope > wa-dialog").addEventListener("wa-show", this)
|
|
11
|
+
this.querySelector(":scope > wa-dialog").addEventListener("wa-after-hide", this)
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
handleEvent(event) {
|
|
16
|
+
if (event.type === "wa-show") {
|
|
17
|
+
this.handleShow()
|
|
18
|
+
} else if (event.type == "wa-after-hide") {
|
|
19
|
+
this.handleHide()
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async handleShow() {
|
|
24
|
+
const html = await (await fetch("/search")).text()
|
|
25
|
+
this.querySelector("wll-dialog-inner").replaceWith(Document.parseHTMLUnsafe(html).querySelector("wll-search-page"))
|
|
26
|
+
setTimeout(() => this.querySelector("wa-input").focus()) // queue task to focus, otherwise control isn't loaded or something
|
|
27
|
+
const source = this.querySelector("script").textContent
|
|
28
|
+
this.querySelector("script").remove()
|
|
29
|
+
const newScript = document.createElement("script")
|
|
30
|
+
newScript.type = "module"
|
|
31
|
+
newScript.textContent = source
|
|
32
|
+
document.body.append(newScript)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
handleHide() {
|
|
36
|
+
this.querySelector("wll-search-page").replaceWith(document.createElement("wll-dialog-inner"))
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
customElements.define("wll-search-page", class extends HTMLElement {
|
|
41
|
+
connectedCallback() {
|
|
42
|
+
this.addEventListener("input", this)
|
|
43
|
+
this.addEventListener("keydown", (event) => {
|
|
44
|
+
if (event.key === "ArrowDown") {
|
|
45
|
+
if (document.activeElement.localName === "wa-input") {
|
|
46
|
+
event.preventDefault()
|
|
47
|
+
this.querySelector("a")?.focus()
|
|
48
|
+
} else if (document.activeElement.localName === "a") {
|
|
49
|
+
event.preventDefault()
|
|
50
|
+
document.activeElement.closest("li").nextElementSibling?.querySelector("a")?.focus()
|
|
51
|
+
}
|
|
52
|
+
} else if (event.key === "ArrowUp") {
|
|
53
|
+
if (document.activeElement.localName === "a") {
|
|
54
|
+
event.preventDefault()
|
|
55
|
+
const previousItem = document.activeElement.closest("li").previousElementSibling
|
|
56
|
+
if (previousItem) {
|
|
57
|
+
previousItem.querySelector("a").focus()
|
|
58
|
+
} else {
|
|
59
|
+
this.querySelector("wa-input").focus()
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
this.tmpl = this.querySelector("template#search-result-template")
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async handleEvent(event) {
|
|
68
|
+
console.log(event.target.value)
|
|
69
|
+
const resultsList = this.querySelector("wll-search-results > ul")
|
|
70
|
+
const search = await pagefind.debouncedSearch(event.target.value)
|
|
71
|
+
if (search === null) {
|
|
72
|
+
// a more recent search call has been made, nothing to do
|
|
73
|
+
} else {
|
|
74
|
+
resultsList.replaceChildren()
|
|
75
|
+
if (search.results.length > 0) {
|
|
76
|
+
search.results.forEach(async (result) => {
|
|
77
|
+
const data = await result.data()
|
|
78
|
+
const tmplInstance = this.tmpl.content.cloneNode(true)
|
|
79
|
+
tmplInstance.querySelector("[data-title]").innerHTML = `<a href="${data.url}">${data.meta.title}</a>`
|
|
80
|
+
tmplInstance.querySelector("[data-excerpt").innerHTML = data.excerpt
|
|
81
|
+
this.querySelector("wll-search-results > ul").append(tmplInstance)
|
|
82
|
+
})
|
|
83
|
+
} else {
|
|
84
|
+
resultsList.setHTMLUnsafe(`
|
|
85
|
+
<li><p><wa-icon name="search"></wa-icon> <em>No results could be found.</em></p></li>
|
|
86
|
+
`)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
})
|
data/content/search.erb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: page
|
|
3
|
+
title: Search
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<wll-search-page>
|
|
7
|
+
<!-- input type="search" / -->
|
|
8
|
+
<wa-input size="large" placeholder="<%= t("labels.search") %>…" pill>
|
|
9
|
+
<wa-icon name="search" slot="start"></wa-icon>
|
|
10
|
+
</wa-input>
|
|
11
|
+
|
|
12
|
+
<wll-search-results>
|
|
13
|
+
<ul>
|
|
14
|
+
</ul>
|
|
15
|
+
</wll-search-results>
|
|
16
|
+
|
|
17
|
+
<template id="search-result-template">
|
|
18
|
+
<li>
|
|
19
|
+
<p data-title></p>
|
|
20
|
+
<p data-excerpt></p>
|
|
21
|
+
</li>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script type="module">
|
|
25
|
+
const pagefind = await import("/pagefind/pagefind.js")
|
|
26
|
+
pagefind.init()
|
|
27
|
+
window.pagefind = pagefind
|
|
28
|
+
</script>
|
|
29
|
+
</wll-search-page>
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: page
|
|
3
|
+
title: This is the Willamette Theme
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<style>
|
|
7
|
+
.swatch {
|
|
8
|
+
wa-copy-button::part(button) {
|
|
9
|
+
background: var(--color);
|
|
10
|
+
border-radius: var(--wa-border-radius-m);
|
|
11
|
+
padding: 1rem;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
</style>
|
|
15
|
+
|
|
16
|
+
<wa-callout variant="brand">
|
|
17
|
+
<wa-icon slot="icon" name="circle-check" variant="regular"></wa-icon>
|
|
18
|
+
Welcome to your new home on the Internet!
|
|
19
|
+
</wa-callout>
|
|
20
|
+
|
|
21
|
+
<hr />
|
|
22
|
+
|
|
23
|
+
<wa-color-picker label="Chose your brand color:" size="large" oninput='
|
|
24
|
+
document.documentElement.style.setProperty("--wll-color-brand", event.target.value)
|
|
25
|
+
this.querySelector("output").textContent = `--wll-color-brand: ${event.target.value};`
|
|
26
|
+
this.querySelector("wa-copy-button").slot = "hint"
|
|
27
|
+
'>
|
|
28
|
+
<output id="color-hint" slot="hint"></output>
|
|
29
|
+
<wa-copy-button from="color-hint"></wa-copy-button>
|
|
30
|
+
</wa-color-picker>
|
|
31
|
+
|
|
32
|
+
<hr />
|
|
33
|
+
|
|
34
|
+
## Brand Color Scale
|
|
35
|
+
|
|
36
|
+
<ul class="color-group" style="display: flex; flex-wrap: wrap; list-style: none">
|
|
37
|
+
<li class="color-preview">
|
|
38
|
+
<div class="color swatch" style="--color: var(--wa-color-brand-95)">
|
|
39
|
+
<wa-copy-button value="--wa-color-brand-95" copy-label="--wa-color-brand-95"></wa-copy-button>
|
|
40
|
+
</div>
|
|
41
|
+
<small>95</small>
|
|
42
|
+
</li><li class="color-preview">
|
|
43
|
+
<div class="color swatch" style="--color: var(--wa-color-brand-90)">
|
|
44
|
+
<wa-copy-button value="--wa-color-brand-90" copy-label="--wa-color-brand-90"></wa-copy-button>
|
|
45
|
+
</div>
|
|
46
|
+
<small>90</small>
|
|
47
|
+
</li><li class="color-preview">
|
|
48
|
+
<div class="color swatch" style="--color: var(--wa-color-brand-80)">
|
|
49
|
+
<wa-copy-button value="--wa-color-brand-80" copy-label="--wa-color-brand-80"></wa-copy-button>
|
|
50
|
+
</div>
|
|
51
|
+
<small>80</small>
|
|
52
|
+
</li><li class="color-preview">
|
|
53
|
+
<div class="color swatch" style="--color: var(--wa-color-brand-70)">
|
|
54
|
+
<wa-copy-button value="--wa-color-brand-70" copy-label="--wa-color-brand-70"></wa-copy-button>
|
|
55
|
+
</div>
|
|
56
|
+
<small>70</small>
|
|
57
|
+
</li><li class="color-preview">
|
|
58
|
+
<div class="color swatch" style="--color: var(--wa-color-brand-60)">
|
|
59
|
+
<wa-copy-button value="--wa-color-brand-60" copy-label="--wa-color-brand-60"></wa-copy-button>
|
|
60
|
+
</div>
|
|
61
|
+
<small>60</small>
|
|
62
|
+
</li><li class="color-preview">
|
|
63
|
+
<div class="color swatch" style="--color: var(--wa-color-brand-50)">
|
|
64
|
+
<wa-copy-button value="--wa-color-brand-50" copy-label="--wa-color-brand-50"></wa-copy-button>
|
|
65
|
+
</div>
|
|
66
|
+
<small>50</small>
|
|
67
|
+
</li><li class="color-preview">
|
|
68
|
+
<div class="color swatch" style="--color: var(--wa-color-brand-40)">
|
|
69
|
+
<wa-copy-button value="--wa-color-brand-40" copy-label="--wa-color-brand-40"></wa-copy-button>
|
|
70
|
+
</div>
|
|
71
|
+
<small>40</small>
|
|
72
|
+
</li><li class="color-preview">
|
|
73
|
+
<div class="color swatch" style="--color: var(--wa-color-brand-30)">
|
|
74
|
+
<wa-copy-button value="--wa-color-brand-30" copy-label="--wa-color-brand-30"></wa-copy-button>
|
|
75
|
+
</div>
|
|
76
|
+
<small>30</small>
|
|
77
|
+
</li><li class="color-preview">
|
|
78
|
+
<div class="color swatch" style="--color: var(--wa-color-brand-20)">
|
|
79
|
+
<wa-copy-button value="--wa-color-brand-20" copy-label="--wa-color-brand-20"></wa-copy-button>
|
|
80
|
+
</div>
|
|
81
|
+
<small>20</small>
|
|
82
|
+
</li><li class="color-preview">
|
|
83
|
+
<div class="color swatch" style="--color: var(--wa-color-brand-10)">
|
|
84
|
+
<wa-copy-button value="--wa-color-brand-10" copy-label="--wa-color-brand-10"></wa-copy-button>
|
|
85
|
+
</div>
|
|
86
|
+
<small>10</small>
|
|
87
|
+
</li><li class="color-preview">
|
|
88
|
+
<div class="color swatch" style="--color: var(--wa-color-brand-05)">
|
|
89
|
+
<wa-copy-button value="--wa-color-brand-05" copy-label="--wa-color-brand-05"></wa-copy-button>
|
|
90
|
+
</div>
|
|
91
|
+
<small>05</small>
|
|
92
|
+
</li>
|
|
93
|
+
</ul>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="<%= site.locale %>" class="wa-palette-default">
|
|
3
|
+
<head>
|
|
4
|
+
<%= render "head", metadata: site.metadata, title: data.title %>
|
|
5
|
+
</head>
|
|
6
|
+
<body class="OFF:wll-grid-lines OFF:wll-code-dark <%= data.layout %> <%= data.page_class %>">
|
|
7
|
+
<%= dsd do %>
|
|
8
|
+
<%= render Willamette::HolyGrailLayout.new %>
|
|
9
|
+
<% end %>
|
|
10
|
+
<%= render Shared::Navbar.new(metadata: site.metadata, resource:) %>
|
|
11
|
+
|
|
12
|
+
<main slot="content" id="content">
|
|
13
|
+
<div hidden class="show-for-tablet" style="position: absolute; right: var(--wa-space-m)"><button type="button" class="wa-outlined" onclick="document.body.classList.toggle('sidebar-end-open')"><wa-icon name="list"></wa-icon></button></div>
|
|
14
|
+
|
|
15
|
+
<main-contents <%= "data-pagefind-body" unless data.exclude_from_pagefind %>>
|
|
16
|
+
<%= yield %>
|
|
17
|
+
</main-contents>
|
|
18
|
+
|
|
19
|
+
<wll-back-to-top>
|
|
20
|
+
<button><wa-icon name="circle-chevron-up"></wa-icon></button>
|
|
21
|
+
</wll-back-to-top>
|
|
22
|
+
</main>
|
|
23
|
+
|
|
24
|
+
<aside slot="sidebar-start">
|
|
25
|
+
<%= render Shared::Sidebar.new(metadata: site.metadata, resource:) %>
|
|
26
|
+
</aside>
|
|
27
|
+
|
|
28
|
+
<aside slot="sidebar-end" hidden>
|
|
29
|
+
<!-- TODO: this should be in a shared component -->
|
|
30
|
+
<div class="show-for-tablet" style="position: absolute; right: var(--wa-space-m)"><button type="button" class="wa-outlined" onclick="document.body.classList.toggle('sidebar-end-open')"><wa-icon name="close"></wa-icon></button></div>
|
|
31
|
+
<h2><%= t "documentation.contents" %></h2>
|
|
32
|
+
|
|
33
|
+
<%= slotted :toc %>
|
|
34
|
+
|
|
35
|
+
<hr />
|
|
36
|
+
|
|
37
|
+
<!-- TOC will be relocated here -->
|
|
38
|
+
</aside>
|
|
39
|
+
|
|
40
|
+
<%= render "footer", metadata: site.metadata %>
|
|
41
|
+
<a slot="skip-to-content" class="skip-to-content-link" href="#content"><%= t "content.skip_to_content" %></a>
|
|
42
|
+
<%= render Willamette::SearchDialog.new %>
|
|
43
|
+
</body>
|
|
44
|
+
</html>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Willamette
|
|
2
|
+
class Builders::Inspectors < Bridgetown::Builder
|
|
3
|
+
def build # rubocop:disable Metrics/CyclomaticComplexity
|
|
4
|
+
inspect_html do |document|
|
|
5
|
+
document.query_selector_all("a").each do |anchor|
|
|
6
|
+
next if anchor[:target]
|
|
7
|
+
|
|
8
|
+
unless anchor[:href]&.starts_with?("http") && !anchor[:href]&.include?(site.config.url)
|
|
9
|
+
next
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
anchor[:target] = "_blank"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
inspect_html do |document|
|
|
17
|
+
document.query_selector_all("article h2[id], article h3[id]").each do |heading|
|
|
18
|
+
heading << document.create_text_node(" ")
|
|
19
|
+
heading << document.create_element(
|
|
20
|
+
"a", "#",
|
|
21
|
+
href: "##{heading[:id]}",
|
|
22
|
+
class: "heading-anchor"
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
en:
|
|
2
|
+
content:
|
|
3
|
+
featured_post_image: featured post image
|
|
4
|
+
skip_to_content: Skip to content
|
|
5
|
+
posts:
|
|
6
|
+
more_posts: More Posts
|
|
7
|
+
newer_posts: Newer Posts
|
|
8
|
+
labels:
|
|
9
|
+
close: Close
|
|
10
|
+
email_address: Email Address
|
|
11
|
+
first_name: First Name (Optional)
|
|
12
|
+
next: Next
|
|
13
|
+
previous: Previous
|
|
14
|
+
search: Search
|
|
15
|
+
subscribe: Subscribe
|
|
16
|
+
documentation:
|
|
17
|
+
contents: Contents
|
|
18
|
+
explore: Explore
|
|
19
|
+
marketing:
|
|
20
|
+
follow: Follow Us
|
|
21
|
+
subscribe: Subscribe
|
|
22
|
+
see_also: See Also
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Willamette
|
|
2
|
+
# Contain logic for rendering
|
|
3
|
+
Strategies::Link = Data.define(:depth, :current, :icon, :icon_family, :title, :url)
|
|
4
|
+
|
|
5
|
+
def self.link(depth: 1, current: false, icon: nil, icon_family: nil, **) # rubocop:disable Metrics/ParameterLists
|
|
6
|
+
Strategies::Link.new(depth:, current:, icon:, icon_family:, **)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.links_for(base_resource)
|
|
10
|
+
base_resource.collection.map do |resource|
|
|
11
|
+
depth = resource.relative_path.each_filename.count - 1
|
|
12
|
+
Willamette.link(
|
|
13
|
+
current: resource == base_resource,
|
|
14
|
+
title: resource.data.title,
|
|
15
|
+
url: resource.relative_url,
|
|
16
|
+
depth:
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module Willamette
|
|
2
|
+
# Contain logic for rendering
|
|
3
|
+
# rubocop:disable Metrics/ParameterLists
|
|
4
|
+
class Strategies::Sidebar
|
|
5
|
+
attr_reader :description
|
|
6
|
+
|
|
7
|
+
# Use the `sidebar` module method on `Willamette`
|
|
8
|
+
def initialize(
|
|
9
|
+
component, description:, explore_links:, follow_links:, subscribe:, see_also_links:
|
|
10
|
+
)
|
|
11
|
+
@component = component
|
|
12
|
+
@description = description
|
|
13
|
+
@explore_links = explore_links || []
|
|
14
|
+
@follow_links = follow_links || []
|
|
15
|
+
@subscribe = subscribe
|
|
16
|
+
@see_also_links = see_also_links || []
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def explore? = !@explore_links.empty?
|
|
20
|
+
|
|
21
|
+
def explore_links = links_html(@explore_links)
|
|
22
|
+
|
|
23
|
+
def description? = @description && !explore?
|
|
24
|
+
|
|
25
|
+
def follow? = !@follow_links.empty?
|
|
26
|
+
|
|
27
|
+
def follow_links = links_html(@follow_links)
|
|
28
|
+
|
|
29
|
+
def subscribe? = @subscribe
|
|
30
|
+
|
|
31
|
+
def see_also? = !@see_also_links.empty?
|
|
32
|
+
|
|
33
|
+
def see_also_links = links_html(@see_also_links)
|
|
34
|
+
|
|
35
|
+
def default_link_icon(folder: false)
|
|
36
|
+
folder ? "folder-open" : "file-lines"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def links_html(links)
|
|
42
|
+
doc = Nokolexbor::HTML("<ul></ul>")
|
|
43
|
+
list = doc.at_css("ul")
|
|
44
|
+
links.each_with_index do |link, index|
|
|
45
|
+
list << link_node(doc:, link:, folder: (links[index + 1]&.depth || 1) > link.depth)
|
|
46
|
+
end
|
|
47
|
+
list.to_html.html_safe
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def link_node(doc:, link:, folder: false) # rubocop:disable Metrics/AbcSize
|
|
51
|
+
item = doc.create_element("li")
|
|
52
|
+
item[:"item-depth"] = link.depth
|
|
53
|
+
anchor = doc.create_element("a")
|
|
54
|
+
anchor[:href] = @component.relative_url(link.url)
|
|
55
|
+
anchor[:"aria-current"] = "page" if link.current
|
|
56
|
+
|
|
57
|
+
icon = doc.create_element("wa-icon")
|
|
58
|
+
icon[:name] = link.icon || default_link_icon(folder:)
|
|
59
|
+
icon[:family] = link.icon_family if link.icon_family
|
|
60
|
+
anchor << icon
|
|
61
|
+
|
|
62
|
+
anchor << doc.create_text_node(" ")
|
|
63
|
+
anchor << doc.create_text_node(link.title)
|
|
64
|
+
|
|
65
|
+
item << anchor
|
|
66
|
+
item
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.sidebar(
|
|
71
|
+
component,
|
|
72
|
+
description:,
|
|
73
|
+
explore_links: nil,
|
|
74
|
+
follow_links: nil,
|
|
75
|
+
subscribe: false,
|
|
76
|
+
see_also_links: nil
|
|
77
|
+
)
|
|
78
|
+
Willamette::Strategies::Sidebar.new(
|
|
79
|
+
component, description:, explore_links:, follow_links:, subscribe:, see_also_links:
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
# rubocop:enable Metrics/ParameterLists
|
|
83
|
+
end
|
data/lib/willamette.rb
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bridgetown"
|
|
4
|
+
|
|
5
|
+
module Willamette
|
|
6
|
+
module Builders
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module Strategies
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
require "willamette/builders/inspectors"
|
|
14
|
+
require "willamette/builders/toc"
|
|
15
|
+
require "willamette/strategies/link"
|
|
16
|
+
require "willamette/strategies/sidebar"
|
|
17
|
+
|
|
18
|
+
# use `<wll-code>` element instead of `<div>`
|
|
19
|
+
Kramdown::Converter::Html.class_eval do
|
|
20
|
+
alias_method :__old_convert_codeblock, :convert_codeblock
|
|
21
|
+
|
|
22
|
+
def convert_codeblock(elem, indent)
|
|
23
|
+
output = __old_convert_codeblock(elem, indent)
|
|
24
|
+
return output unless @options[:syntax_highlighter]
|
|
25
|
+
|
|
26
|
+
output.sub(%r!^(\s*)<div!, "\\1<wll-code").sub("</div>\n", "</wll-code>\n")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @param config [Bridgetown::Configuration::ConfigurationDSL]
|
|
31
|
+
Bridgetown.initializer :willamette do |config, docs_url_segment: "docs"|
|
|
32
|
+
# Add code here which will run when a site includes
|
|
33
|
+
# `init :willamette`
|
|
34
|
+
# in its configuration
|
|
35
|
+
|
|
36
|
+
# Add default configuration data:
|
|
37
|
+
config.willamette ||= {}
|
|
38
|
+
config.willamette.my_setting ||= 123
|
|
39
|
+
|
|
40
|
+
# Register your builders:
|
|
41
|
+
config.builder Willamette::Builders::Inspectors
|
|
42
|
+
config.builder Willamette::Builders::Toc
|
|
43
|
+
config.builder :WillametteRegisterPermalinkPlaceholders do
|
|
44
|
+
def build
|
|
45
|
+
permalink_placeholder :unordered_path do |resource|
|
|
46
|
+
{
|
|
47
|
+
raw_value:
|
|
48
|
+
placeholder_processors[:path].(resource)[:raw_value].gsub(%r!(^|/)[0-9]+_!, "\\1"),
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
config.collections do
|
|
55
|
+
docs do
|
|
56
|
+
output true
|
|
57
|
+
permalink "/:locale/#{docs_url_segment ? "#{docs_url_segment}/" : ""}:unordered_path/"
|
|
58
|
+
name "Documentation"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
config.keep_files << "pagefind"
|
|
63
|
+
|
|
64
|
+
# You can optionally supply a source manifest:
|
|
65
|
+
config.source_manifest(
|
|
66
|
+
origin: Willamette,
|
|
67
|
+
components: File.expand_path("../components", __dir__),
|
|
68
|
+
layouts: File.expand_path("../layouts", __dir__),
|
|
69
|
+
content: File.expand_path("../content", __dir__)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
I18n.load_path += Gem.find_files_from_load_path("willamette/locales/en.*")
|
|
73
|
+
|
|
74
|
+
skip_pagefind_write = false
|
|
75
|
+
config.hook :site, :post_write do
|
|
76
|
+
next if config.fast_refresh && skip_pagefind_write
|
|
77
|
+
|
|
78
|
+
skip_pagefind_write = true
|
|
79
|
+
|
|
80
|
+
`rm -rf output/pagefind && npx --yes pagefind --site output`
|
|
81
|
+
Bridgetown.logger.info "Pagefind:", "Wrote search index"
|
|
82
|
+
end
|
|
83
|
+
end
|