Skip to content

Commit 6f66e07

Browse files
Add tabs to the documentation
1 parent 3561d2b commit 6f66e07

File tree

10 files changed

+269
-11
lines changed

10 files changed

+269
-11
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ build
44
build-pico-sdk-docs
55
documentation/html
66
documentation/asciidoc/pico-sdk
7+
.venv

Gemfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ gem "minima", "~> 2.0"
2121
group :jekyll_plugins do
2222
gem "jekyll-feed", "~> 0.17"
2323
gem 'jekyll-asciidoc'
24+
gem 'asciidoctor'
25+
gem 'asciidoctor-tabs', ">= 1.0.0.beta.6"
2426
end
2527

2628
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
@@ -37,4 +39,4 @@ gem "nokogiri", "~> 1.16"
3739

3840
# So we can add custom element templates
3941
gem 'slim', '~> 5.2.1'
40-
gem 'thread_safe', '~> 0.3.5'
42+
gem 'thread_safe', '~> 0.3.5'

Gemfile.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ GEM
44
addressable (2.8.6)
55
public_suffix (>= 2.0.2, < 6.0)
66
asciidoctor (2.0.20)
7+
asciidoctor-tabs (1.0.0.beta.6)
8+
asciidoctor (>= 2.0.0, < 3.0.0)
79
colorator (1.1.0)
810
concurrent-ruby (1.2.3)
911
em-websocket (0.5.3)
@@ -94,6 +96,8 @@ PLATFORMS
9496
ruby
9597

9698
DEPENDENCIES
99+
asciidoctor
100+
asciidoctor-tabs (>= 1.0.0.beta.6)
97101
jekyll (~> 4.3.3)
98102
jekyll-asciidoc
99103
jekyll-feed (~> 0.17)

_config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ githubbranch_edit: develop
2525
# Build settings
2626
theme: minima
2727
plugins:
28+
- asciidoctor-tabs
2829
- jekyll-asciidoc
2930
- jekyll-feed
3031

documentation/asciidoc/computers/remote-access/ssh.adoc

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,35 @@ You can access the terminal of a Raspberry Pi remotely from another computer on
77

88
By default, Raspberry Pi OS disables the SSH server. Enable SSH in one of the following ways:
99

10-
==== On the desktop
11-
10+
[tabs]
11+
======
12+
On the desktop::
13+
+
1214
. From the *Preferences* menu, launch *Raspberry Pi Configuration*.
1315
. Navigate to the *Interfaces* tab.
1416
. Select *Enabled* next to *SSH*.
1517
. Click *OK*.
1618
17-
==== While flashing a fresh OS image
18-
19+
While flashing a fresh OS image::
20+
+
1921
To configure SSH on a completely new installation of Raspberry Pi OS:
20-
22+
+
2123
. Follow the instructions in the xref:../computers/getting-started.adoc#raspberry-pi-imager[Install with Imager] guide.
2224
. During the **OS Customisation** step, navigate to the **Services** tab.
2325
. Tick the checkbox to **Enable SSH**.
2426
. Select **password authentication** to log in using the same username and password you use while physically using your Raspberry Pi. Select **Allow public-key authentication only** to xref:remote-access.adoc#configure-ssh-without-a-password[configure an SSH key] for passwordless login.
2527
26-
==== From the terminal
27-
28+
From the terminal::
29+
+
2830
. Enter `sudo raspi-config` in a terminal window.
2931
. Select `Interfacing Options`.
3032
. Navigate to and select `SSH`.
3133
. Choose `Yes`.
3234
. Select `Ok`.
3335
. Choose `Finish`.
3436
35-
==== Manually
36-
37+
Manually::
38+
+
3739
. Create an empty file named `ssh` in the boot partition:
3840
+
3941
[source,console]
@@ -46,6 +48,7 @@ $ sudo touch /boot/firmware/ssh
4648
----
4749
$ sudo reboot
4850
----
51+
======
4952

5053
=== Connect to an SSH server
5154

jekyll-assets/_includes/head.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3"/>
1919
<link rel="stylesheet" href="{{ site.baseurl }}/css/style.css?ver={{ site.time | date: '%s' }}">
2020
<link rel="stylesheet" href="{{ site.baseurl }}/css/tabs.css?ver={{ site.time | date: '%s' }}">
21+
<link rel="stylesheet" href="{{ site.baseurl }}/css/asciidoctor-tabs.css?ver={{ site.time | date: '%s' }}">
2122
<link rel="stylesheet" href="{{ site.baseurl }}/css/syntax-highlighting.css?ver={{ site.time | date: '%s' }}">
2223
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-180927933-8"></script>
2324
<script>

jekyll-assets/_includes/scripts.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<!-- Script for the TOC toggle -->
22
<script src="{{ site.baseurl }}/scripts/nav.js?ver={{ site.time | date: '%s' }}" type="text/javascript"></script>
33

4+
<!-- Asciidoctor tabs -->
5+
<script src="{{ site.baseurl }}/scripts/asciidoctor-tabs.js?ver={{ site.time | date: '%s' }}" type="text/javascript"></script>
6+
47
<!-- TOCify scripts -->
58
<script src="{{ site.baseurl }}/scripts/jquery-1.12.4.min.js"></script>
69
<script src="{{ site.baseurl }}/scripts/jquery-ui-1.13.0.custom.min.js"></script>
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
2+
/*! Asciidoctor Tabs | Copyright (c) 2018-present Dan Allen | MIT License */
3+
.tabs {
4+
margin-bottom: 1.25em;
5+
}
6+
7+
.tablist > ul {
8+
display: flex;
9+
flex-wrap: nowrap;
10+
overflow-x: scroll;
11+
overflow-y: hidden;
12+
list-style: none;
13+
margin: 0;
14+
padding: 0;
15+
}
16+
17+
.tablist > ul li {
18+
align-items: center;
19+
background-color: #eee;
20+
cursor: pointer;
21+
display: flex;
22+
font-weight: bold;
23+
line-height: 1.5;
24+
padding: 0.25em 1em;
25+
position: relative;
26+
}
27+
28+
.tablist > ul li p {
29+
margin-bottom: 0px !important;
30+
}
31+
32+
.tablist > ul li:focus-visible {
33+
outline: none;
34+
}
35+
36+
.tablist.ulist,
37+
.tablist.ulist > ul li {
38+
margin: 0;
39+
}
40+
41+
.tablist.ulist > ul li + li {
42+
margin-left: 0.25em;
43+
}
44+
45+
.tabs .tablist li::after {
46+
content: "";
47+
display: block;
48+
height: 1px;
49+
position: absolute;
50+
bottom: -1px;
51+
left: 0;
52+
right: 0;
53+
}
54+
55+
.tabs.is-loading .tablist li:not(:first-child),
56+
.tabs:not(.is-loading) .tablist li:not(.is-selected) {
57+
background-color: initial;
58+
border-left: 1px solid #eee;
59+
border-right: 1px solid #eee;
60+
border-top: 1px solid #eee;
61+
}
62+
63+
.tabs.is-loading .tablist li:first-child::after,
64+
.tabs:not(.is-loading) .tablist li.is-selected::after {
65+
background-color: #eee;
66+
border-top: 2px solid var(--red);
67+
}
68+
69+
/*
70+
.tabs:not(.is-loading) .tablist li,
71+
.tabs:not(.is-loading) .tablist li::after {
72+
transition: background-color 200ms ease-in-out;
73+
}
74+
*/
75+
76+
.tablist > ul p {
77+
line-height: inherit;
78+
margin: 0;
79+
}
80+
81+
.tabpanel {
82+
background-color: #eee;
83+
padding: 1.25em;
84+
}
85+
86+
.tablist > ul li {
87+
border-bottom: 0;
88+
}
89+
90+
.tabs.is-loading .tabpanel + .tabpanel,
91+
.tabs:not(.is-loading) .tabpanel.is-hidden {
92+
display: none;
93+
}
94+
95+
.tabpanel > :first-child {
96+
margin-top: 0;
97+
}
98+
99+
/* #content is a signature of the Asciidoctor standalone HTML output */
100+
#content .tabpanel > :last-child,
101+
#content .tabpanel > :last-child > :last-child,
102+
#content .tabpanel > :last-child > :last-child > li:last-child > :last-child {
103+
margin-bottom: 0;
104+
}
105+
106+
.tablecontainer {
107+
overflow-x: auto;
108+
}
109+
110+
#content .tablecontainer {
111+
margin-bottom: 1.25em;
112+
}
113+
114+
#content .tablecontainer > table.tableblock {
115+
margin-bottom: 0;
116+
}

jekyll-assets/css/tabs.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,4 @@ p#release + #container {
7979
display: block;
8080
width: 100%;
8181
}
82-
}
82+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
;(function () { /*! Asciidoctor Tabs | Copyright (c) 2018-present Dan Allen | MIT License */
2+
'use strict'
3+
4+
var config = (document.currentScript || {}).dataset || {}
5+
var forEach = Array.prototype.forEach
6+
7+
init(document.querySelectorAll('.tabs'))
8+
9+
function init (tabsBlocks) {
10+
if (!tabsBlocks.length) return
11+
forEach.call(tabsBlocks, function (tabs) {
12+
var syncIds = tabs.classList.contains('is-sync') ? {} : undefined
13+
var tablist = tabs.querySelector('.tablist ul')
14+
tablist.setAttribute('role', 'tablist')
15+
var start
16+
forEach.call(tablist.querySelectorAll('li'), function (tab, idx) {
17+
tab.tabIndex = -1
18+
tab.setAttribute('role', tab.classList.add('tab') || 'tab')
19+
var id, anchor, syncId
20+
if (!(id = tab.id) && (anchor = tab.querySelector('a[id]'))) {
21+
id = tab.id = anchor.parentNode.removeChild(anchor).id
22+
}
23+
var panel = id && tabs.querySelector('.tabpanel[aria-labelledby~="' + id + '"]')
24+
if (!panel) return idx ? undefined : toggleSelected(tab, true) // invalid state
25+
syncIds && (((syncId = tab.textContent.trim()) in syncIds) ? (syncId = undefined) : true) &&
26+
(syncIds[(tab.dataset.syncId = syncId)] = tab)
27+
idx || (syncIds && (start = { tab: tab, panel: panel })) ? toggleHidden(panel, true) : toggleSelected(tab, true)
28+
tab.setAttribute('aria-controls', panel.id)
29+
panel.setAttribute('role', 'tabpanel')
30+
var onClick = syncId === undefined ? activateTab : activateTabSync
31+
tab.addEventListener('click', onClick.bind({ tabs: tabs, tab: tab, panel: panel }))
32+
})
33+
if (!tabs.closest('.tabpanel')) {
34+
forEach.call(tabs.querySelectorAll('.tabpanel table.tableblock'), function (table) {
35+
var container = Object.assign(document.createElement('div'), { className: 'tablecontainer' })
36+
table.parentNode.insertBefore(container, table).appendChild(table)
37+
})
38+
}
39+
if (start) {
40+
var syncGroupId
41+
for (var i = 0, lst = tabs.classList, len = lst.length, className; i !== len; i++) {
42+
if (!(className = lst.item(i)).startsWith('data-sync-group-id=')) continue
43+
tabs.dataset.syncGroupId = syncGroupId = lst.remove(className) || className.slice(19).replace(/\u00a0/g, ' ')
44+
break
45+
}
46+
if (syncGroupId === undefined) tabs.dataset.syncGroupId = syncGroupId = Object.keys(syncIds).sort().join('|')
47+
var preferredSyncId = 'syncStorageKey' in config &&
48+
window[(config.syncStorageScope || 'local') + 'Storage'].getItem(config.syncStorageKey + '-' + syncGroupId)
49+
var tab = preferredSyncId && syncIds[preferredSyncId]
50+
tab && Object.assign(start, { tab: tab, panel: document.getElementById(tab.getAttribute('aria-controls')) })
51+
toggleSelected(start.tab, true) || toggleHidden(start.panel, false)
52+
}
53+
})
54+
onHashChange()
55+
toggleClassOnEach(tabsBlocks, 'is-loading', 'remove')
56+
window.setTimeout(toggleClassOnEach.bind(null, tabsBlocks, 'is-loaded', 'add'), 0)
57+
window.addEventListener('hashchange', onHashChange)
58+
}
59+
60+
function activateTab (e) {
61+
var tab = this.tab
62+
var tabs = this.tabs || (this.tabs = tab.closest('.tabs'))
63+
var panel = this.panel || (this.panel = document.getElementById(tab.getAttribute('aria-controls')))
64+
querySelectorWithSiblings(tabs, '.tablist .tab', 'tab').forEach(function (el) {
65+
toggleSelected(el, el === tab)
66+
})
67+
querySelectorWithSiblings(tabs, '.tabpanel', 'tabpanel').forEach(function (el) {
68+
toggleHidden(el, el !== panel)
69+
})
70+
if (!this.isSync && 'syncStorageKey' in config && 'syncGroupId' in tabs.dataset) {
71+
var storageKey = config.syncStorageKey + '-' + tabs.dataset.syncGroupId
72+
window[(config.syncStorageScope || 'local') + 'Storage'].setItem(storageKey, tab.dataset.syncId)
73+
}
74+
if (!e) return
75+
var loc = window.location
76+
var hashIdx = loc.hash ? loc.href.indexOf('#') : -1
77+
if (~hashIdx) window.history.replaceState(null, '', loc.href.slice(0, hashIdx))
78+
e.preventDefault()
79+
}
80+
81+
function activateTabSync (e) {
82+
activateTab.call(this, e)
83+
var thisTabs = this.tabs
84+
var thisTab = this.tab
85+
var initialY = thisTabs.getBoundingClientRect().y
86+
forEach.call(document.querySelectorAll('.tabs'), function (tabs) {
87+
if (tabs === thisTabs || tabs.dataset.syncGroupId !== thisTabs.dataset.syncGroupId) return
88+
querySelectorWithSiblings(tabs, '.tablist .tab', 'tab').forEach(function (tab) {
89+
if (tab.dataset.syncId === thisTab.dataset.syncId) activateTab.call({ tabs: tabs, tab: tab, isSync: true })
90+
})
91+
})
92+
var shiftedBy = thisTabs.getBoundingClientRect().y - initialY
93+
if (shiftedBy && (shiftedBy = Math.round(shiftedBy))) window.scrollBy({ top: shiftedBy, behavior: 'instant' })
94+
}
95+
96+
function querySelectorWithSiblings (scope, selector, siblingClass) {
97+
var el = scope.querySelector(selector)
98+
if (!el) return []
99+
var result = [el]
100+
while ((el = el.nextElementSibling) && el.classList.contains(siblingClass)) result.push(el)
101+
return result
102+
}
103+
104+
function toggleClassOnEach (elements, className, method) {
105+
forEach.call(elements, function (el) {
106+
el.classList[method](className)
107+
})
108+
}
109+
110+
function toggleHidden (el, state) {
111+
el.classList[(el.hidden = state) ? 'add' : 'remove']('is-hidden')
112+
}
113+
114+
function toggleSelected (el, state) {
115+
el.setAttribute('aria-selected', '' + state)
116+
el.classList[state ? 'add' : 'remove']('is-selected')
117+
el.tabIndex = state ? 0 : -1
118+
}
119+
120+
function onHashChange () {
121+
var id = window.location.hash.slice(1)
122+
if (!id) return
123+
var tab = document.getElementById(~id.indexOf('%') ? decodeURIComponent(id) : id)
124+
if (!(tab && tab.classList.contains('tab'))) return
125+
'syncId' in tab.dataset ? activateTabSync.call({ tab: tab }) : activateTab.call({ tab: tab })
126+
}
127+
})()

0 commit comments

Comments
 (0)