Code copy (Take 2) (#237)

Adds a copy to clipboard button using Clipboard.js
Optional support for defining which lines to copy out of the code box.
Adds styling and anchor links to the line numbers
Adds support to link to line number anchors inside tabs
Removes line numbers from tables (no user impact, changes styling and JS element targeting)
Makes the top NAV not sticky. This is required to make the line number anchors work. Otherwise the line number linked to will go under the navbar and not be in view. Fixing this with a sticky nav is a very large lift (for me). Also note, the side bars are still sticky.
Removes clipboard scsss files. All clipboard related styles are merged into code-theme-base.scss
Also applies Hugo caching fixes that can cause the stylesheet not to load in local dev (discovered in this PR)
This commit is contained in:
Pete Lumbis 2022-12-16 09:23:53 -05:00 committed by GitHub
parent 37748344fa
commit a1f6f69bcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 307 additions and 125 deletions

View File

@ -27,8 +27,8 @@ markup:
codeFences: true codeFences: true
noClasses: false noClasses: false
linenos: true linenos: true
LineNumbersInTable: true anchorLineNos: true
anchorLineNos: false # Need to fix the line number ID generation. lineNumbersInTable: false
module: module:
mounts: mounts:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,4 +4,11 @@
* Licensed under MIT (https://github.com/coliff/dark-mode-switch/blob/main/LICENSE) * Licensed under MIT (https://github.com/coliff/dark-mode-switch/blob/main/LICENSE)
*/ */
/*!
* clipboard.js v2.0.11
* https://clipboardjs.com/
*
* Licensed MIT © Zeno Rocha
*/
/*! instant.page v5.1.1 - (C) 2019-2020 Alexandre Dieulot - https://instant.page/license */ /*! instant.page v5.1.1 - (C) 2019-2020 Alexandre Dieulot - https://instant.page/license */

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,12 @@
.bd-content { .bd-content {
// Offset content from fixed navbar when jumping to headings
:target > .anchor-link {
text-decoration: none !important;
opacity: 1 !important;
}
.anchor-link { .anchor-link {
padding: 0 .175rem; padding: 0 .175rem;
font-weight: 400; font-weight: 400;
@ -18,5 +25,6 @@
opacity: 1; opacity: 1;
} }
} }
} }

View File

@ -1,44 +0,0 @@
// clipboard.js
//
// JS-based `Copy` buttons for code snippets.
.bd-clipboard,
.bd-edit {
position: relative;
display: none;
float: right;
+ .highlight {
margin-top: 0;
}
@include media-breakpoint-up(md) {
display: block;
}
}
.btn-clipboard,
.btn-edit {
display: block;
padding: .5em;
line-height: 1;
color: $gray-900;
background-color: $gray-100;
border: 0;
@include border-radius(.25rem);
&:hover {
color: $primary;
}
&:focus {
z-index: 3;
}
}
.btn-clipboard {
position: relative;
z-index: 2;
margin-top: .75rem;
margin-right: .75rem;
}

View File

@ -1,47 +1,78 @@
@mixin code-theme-base { @mixin code-theme-base {
//.chroma is applied to the entire code block div and the line number and // Code box div
// code pre elements. .highlight {
.chroma { overflow-x: auto;
font-size: .95rem !important; width: 100% !important;
line-height: 1.45em; background-color: var(--code-block-background-color);
margin-bottom: .5rem; display: flex !important;
margin-top: 1rem; // prevent boxes from running together
margin-bottom: 1rem;
// Applied to the top-level table :target{
.lntable { margin-top: 0;
border-spacing: 0; padding-top: 0;
width: 100%; }
display: block;
overflow: auto;
// Apply to both line numbers and code lines // Clipboard div
code { .bd-clipboard{
display: block;
color: #f8f9fa;
}
// Line numbers background-color: var(--code-block-background-color);
td:first-child { display: flex !important;
padding-right: 10px;
a:hover{ .btn-clipboard{
text-decoration: none !important; border: 0;
} color: $gray-500;
background-color: inherit;
code { &:hover {
padding-right: 0px; color: #fff;
margin-right: 5px;
background-color: var(--code-line-numbers-background-color);
}
}
td:nth-child(2) {
code {
background-color: var(--code-box-background-color);
padding-left: 1rem;
} }
} }
} }
}
}
//.highlight.chroma is applied to the entire code block div and the line number and
// code pre elements.
.chroma {
width: 100%;
font-size: .95rem !important;
line-height: 1.45em;
display: flex !important;
background-color: var(--code-block-background-color);
margin-bottom: 0;
padding-bottom: .5rem;
padding-top: .5rem;
code {
color: #f8f9fa; // Code color if there is no defined highlighter style
background-color: var(--code-block-background-color);
// Line numbers
.ln {
background-color: var(--code-line-numbers-background-color);
border-right: 1px solid #505a72;
// Line number anchors
a {
color: var(--code-line-number-color);
scroll-margin-top: 90px;
&:hover{
// text-decoration: none !important;
color: #fff;
font-weight: 800;
text-decoration: none !important;
}
}
}
// code line
.cl {
background-color: var(--code-block-background-color);
padding-left: 1rem;
}
}
}
}
}

View File

@ -1,7 +1,7 @@
@mixin code-theme-light { @mixin code-theme-light {
--code-block-background-color: #19212C; --code-block-background-color: #19212C;
--code-line-numbers-background-color: #{darken(#19212C, 2)}; --code-line-numbers-background-color: #{lighten(#19212C, 3)};
// --code-background: #{$code-background-dark}; // --code-background: #{$code-background-dark};
// --code-accent-color: #{darken($code-background-dark, 4)}; // --code-accent-color: #{darken($code-background-dark, 4)};
@ -24,7 +24,7 @@
/* PreWrapper */ /* PreWrapper */
.chroma { .chroma {
color: #f8f8f2; color: #f8f8f2;
background-color: #1b1c16; //background-color: #1b1c16;
} }
/* Other */ /* Other */
.chroma .x { .chroma .x {

View File

@ -11,11 +11,15 @@ body {
font-size: $body-font-size; font-size: $body-font-size;
line-height: 1.8em; line-height: 1.8em;
h6, .h6, h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 {
margin-top: 1rem !important;
margin-bottom: 1rem !important;
}
code { code {
background-color: var(--code-background); background-color: var(--code-background);
color: var(--code-color); color: var(--code-color);
padding: 0.2em 0.4em; padding: 0.2em 0.4em;
} }
a { a {

View File

@ -1,7 +1,6 @@
.bd-sidebar-container { .bd-sidebar-container {
background-color: var(--body-background) !important; background-color: var(--body-background) !important;
top: 5rem; top: 0;
@include media-breakpoint-up(lg) { @include media-breakpoint-up(lg) {
position: sticky; position: sticky;
@ -14,7 +13,6 @@
} }
.bd-links-nav { .bd-links-nav {
margin-top: 1rem;
font-size: .95rem !important; font-size: .95rem !important;
@include media-breakpoint-down(lg) { @include media-breakpoint-down(lg) {

View File

@ -10,6 +10,7 @@
z-index: 2; z-index: 2;
height: subtract(100vh, 7rem); height: subtract(100vh, 7rem);
overflow-y: auto; overflow-y: auto;
top: 0;
} }
nav { nav {

View File

@ -8,6 +8,7 @@
// Single code lines inside text. Code blocks are in _code_theme_dark.scss // Single code lines inside text. Code blocks are in _code_theme_dark.scss
--code-background: #3D4856; --code-background: #3D4856;
--code-color: #f8f9fa; --code-color: #f8f9fa;
--code-line-number-color: #8bcbe6;
//Tabs //Tabs
--nav-tab-background-color: var(--body-background); --nav-tab-background-color: var(--body-background);

View File

@ -46,6 +46,5 @@
@import "search-results"; @import "search-results";
/* purgecss end ignore */ /* purgecss end ignore */
@import "skippy"; @import "skippy";
@import "clipboard-js";
@import "fonts"; @import "fonts";
@import "survey"; @import "survey";

View File

@ -8,6 +8,7 @@
// Single code lines inside text. Code blocks are in _code_theme_light.scss // Single code lines inside text. Code blocks are in _code_theme_light.scss
--code-background: #e9ecef; --code-background: #e9ecef;
--code-color: #505a72; --code-color: #505a72;
--code-line-number-color: #8bcbe6;
//Tabs //Tabs
--nav-tab-background-color: var(--body-background); --nav-tab-background-color: var(--body-background);

View File

@ -1,8 +1,8 @@
{ {
"main.js": { "main.js": {
"src": "js/main-47ecc909.bundle.min.js" "src": "js/main-82dca918.bundle.min.js"
}, },
"main-47ecc909.bundle.min.js.map": { "main-82dca918.bundle.min.js.map": {
"src": "js/main-47ecc909.bundle.min.js.map" "src": "js/main-82dca918.bundle.min.js.map"
} }
} }

View File

@ -15,7 +15,7 @@
<main class="bd-main order-1"> <main class="bd-main order-1">
<div class="bd-intro pt-2 ps-lg-2"> <div class="bd-intro pt-2 ps-lg-2">
{{- if eq .Title "Overview"}} {{- if eq .Title "Overview"}}
{{ partial "survey" . }} {{ partialCached "survey" . }}
{{ end }} {{ end }}
<div class="d-md-flex flex-md-row-reverse align-items-center justify-content-between"> <div class="d-md-flex flex-md-row-reverse align-items-center justify-content-between">
<div class="mb-3 mb-md-0 d-flex"> <div class="mb-3 mb-md-0 d-flex">

View File

@ -1,4 +1,4 @@
<header class="navbar docs-navbar navbar-expand-lg sticky-top py-0 align-items-center"> <header class="navbar docs-navbar navbar-expand-lg py-0 align-items-center">
<div class="docs-left-toggle"> <div class="docs-left-toggle">
<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas"

View File

@ -1,4 +1,6 @@
{{ partialCached "meta-common" . }} {{ partialCached "meta-common" . }}
<meta name="description" content="{{ .Page.Params.description | default .Site.Params.description | markdownify }}">
<meta property="og:url" content="{{ .Permalink }}" />
{{ if .Page.Params.version }} {{ if .Page.Params.version }}
{{if eq .Page.Params.version "master" }} {{if eq .Page.Params.version "master" }}
<!-- "master" is not a SemVer version. Set it to 0.0.0 to derank it in search --> <!-- "master" is not a SemVer version. Set it to 0.0.0 to derank it in search -->
@ -8,10 +10,11 @@
{{ end }} {{ end }}
{{ end }} {{ end }}
<title>{{ if .IsHome }}{{ .Site.Title | markdownify }} · {{ .Site.Params.subtitle | markdownify }}{{ else }}{{ .Title | markdownify }} · {{ .Site.Title | markdownify }} v{{ .Site.Params.docs_version }}{{ end }}</title> <title>{{ if .IsHome }}{{ .Site.Title | markdownify }} · {{ .Site.Params.subtitle | markdownify }}{{ else }}{{ .Title | markdownify }} · {{ .Site.Title | markdownify }} v{{ .Page.Params.version }}{{ end }}</title>
<link rel="canonical" href="https://docs.crossplane.io{{ .Permalink }}"> <link rel="canonical" href="https://docs.crossplane.io{{ .Permalink }}">
{{ partialCached "stylesheet" . }} {{ partialCached "stylesheet-cached" . }}
{{ partial "stylesheet-dynamic" . }}
{{ partialCached "favicons" . }} {{ partialCached "favicons" . }}
{{ partial "social" . }} {{ partial "social" . }}

View File

@ -1,6 +1,6 @@
<div class="offcanvas-body"> <div class="offcanvas-body">
<div class="container-fluid p-0"> <div class="container-fluid p-0">
{{ partial "search-button" . }} {{ partialCached "search-button" . }}
{{ partial "docs-sidebar" . }} {{ partial "docs-sidebar" . }}
</div> </div>
</div> </div>

View File

@ -1,13 +1,11 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="{{ .Page.Params.description | default .Site.Params.description | markdownify }}">
<meta name="author" content="Crossplane Community"> <meta name="author" content="Crossplane Community">
<meta name="color-scheme" content="light dark"> <meta name="color-scheme" content="light dark">
<meta name="docsearch:language" content="en" /> <meta name="docsearch:language" content="en" />
{{ hugo.Generator }} {{ hugo.Generator }}
<link rel="preload" href="/fonts/Avenir-Roman.woff2" as="font" type="font/woff2" <link rel="preload" href="/fonts/Avenir-Roman.woff2" as="font" type="font/woff2"
crossorigin> crossorigin>
<meta property="og:url" content="{{ .Permalink }}" />
<meta property="og:image" content="/img/crossplane-logo-og.webp" /> <meta property="og:image" content="/img/crossplane-logo-og.webp" />
<meta property="twitter:card" content="/img/crossplane-logo-og.webp" /> <meta property="twitter:card" content="/img/crossplane-logo-og.webp" />
<meta property="og:image:width" content="600" /> <meta property="og:image:width" content="600" />

View File

@ -10,18 +10,6 @@
})(); })();
</script> </script>
{{ $style := false }}
{{ $sassOptions := (dict "outputStyle" "expanded" "precision" 6 "enableSourceMap" true ) }}
{{ if eq hugo.Environment "production" -}}
{{ $style = resources.Get "scss/docs.scss" | toCSS $sassOptions | resources.PostCSS | resources.PostProcess }}
{{ else }}
{{ $style = resources.Get "scss/docs.scss" | toCSS $sassOptions }}
{{ end }}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3" media="print" onload="this.media='all'"/> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3" media="print" onload="this.media='all'"/>
<link href="{{ $style.Permalink}}" rel="stylesheet">
<link rel="preconnect" href="https://9UXKYX61NK-dsn.algolia.net" crossorigin /> <link rel="preconnect" href="https://9UXKYX61NK-dsn.algolia.net" crossorigin />

View File

@ -0,0 +1,9 @@
{{ $style := false }}
{{ $sassOptions := (dict "outputStyle" "expanded" "precision" 6 "enableSourceMap" true ) }}
{{ if eq hugo.Environment "production" -}}
{{ $style = resources.Get "scss/docs.scss" | toCSS $sassOptions | resources.PostCSS | fingerprint | resources.PostProcess }}
{{ else }}
{{ $style = resources.Get "scss/docs.scss" | toCSS $sassOptions | fingerprint }}
{{ end }}
<link href="{{ $style.Permalink}}" rel="stylesheet">

View File

@ -6,6 +6,7 @@
"": { "": {
"devDependencies": { "devDependencies": {
"@popperjs/core": "^2.11.6", "@popperjs/core": "^2.11.6",
"clipboard": "^2.0.11",
"instant.page": "^5.1.1", "instant.page": "^5.1.1",
"webpack": "^5.75.0", "webpack": "^5.75.0",
"webpack-cli": "^5.0.0", "webpack-cli": "^5.0.0",
@ -434,6 +435,17 @@
"node": ">=6.0" "node": ">=6.0"
} }
}, },
"node_modules/clipboard": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz",
"integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
"dev": true,
"dependencies": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"node_modules/clone-deep": { "node_modules/clone-deep": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
@ -474,6 +486,12 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
"dev": true
},
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.284", "version": "1.4.284",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
@ -618,6 +636,15 @@
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
"dev": true "dev": true
}, },
"node_modules/good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
"dev": true,
"dependencies": {
"delegate": "^3.1.2"
}
},
"node_modules/graceful-fs": { "node_modules/graceful-fs": {
"version": "4.2.10", "version": "4.2.10",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
@ -1012,6 +1039,12 @@
"url": "https://opencollective.com/webpack" "url": "https://opencollective.com/webpack"
} }
}, },
"node_modules/select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
"integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==",
"dev": true
},
"node_modules/serialize-javascript": { "node_modules/serialize-javascript": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
@ -1152,6 +1185,12 @@
} }
} }
}, },
"node_modules/tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
"dev": true
},
"node_modules/update-browserslist-db": { "node_modules/update-browserslist-db": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
@ -1715,6 +1754,17 @@
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
"dev": true "dev": true
}, },
"clipboard": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz",
"integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
"dev": true,
"requires": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"clone-deep": { "clone-deep": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
@ -1749,6 +1799,12 @@
"which": "^2.0.1" "which": "^2.0.1"
} }
}, },
"delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
"dev": true
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.4.284", "version": "1.4.284",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
@ -1862,6 +1918,15 @@
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
"dev": true "dev": true
}, },
"good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
"dev": true,
"requires": {
"delegate": "^3.1.2"
}
},
"graceful-fs": { "graceful-fs": {
"version": "4.2.10", "version": "4.2.10",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
@ -2149,6 +2214,12 @@
"ajv-keywords": "^3.5.2" "ajv-keywords": "^3.5.2"
} }
}, },
"select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
"integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==",
"dev": true
},
"serialize-javascript": { "serialize-javascript": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
@ -2241,6 +2312,12 @@
"terser": "^5.14.1" "terser": "^5.14.1"
} }
}, },
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
"dev": true
},
"update-browserslist-db": { "update-browserslist-db": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",

View File

@ -5,6 +5,7 @@
}, },
"devDependencies": { "devDependencies": {
"@popperjs/core": "^2.11.6", "@popperjs/core": "^2.11.6",
"clipboard": "^2.0.11",
"instant.page": "^5.1.1", "instant.page": "^5.1.1",
"webpack": "^5.75.0", "webpack": "^5.75.0",
"webpack-cli": "^5.0.0", "webpack-cli": "^5.0.0",

View File

@ -0,0 +1,95 @@
// Customize clipboard.js
import * as ClipboardJS from 'clipboard';
// Most of the following is directly from the Bootstrap Website.
// https://github.com/twbs/bootstrap/blob/main/site/assets/js/code-examples.js
const btnHtml = [
' <div class="bd-clipboard">',
' <button type="button" class="btn-clipboard">',
' <svg class="bi" role="img" title="Copy" aria-label="Copy"><use xlink:href="#clipboard"/></svg>',
' </button>',
' </div>'
].join('')
// wrap programmatically code blocks and add copy btn.
document.querySelectorAll('.highlight')
.forEach(element => {
element.insertAdjacentHTML('beforeend', btnHtml)
})
// use .parentNode.parentNode because the trigger is the <button> element.
// first parent is the .bd-clipboard div
// second parent is the .hightlight div
const clipboard = new ClipboardJS('.btn-clipboard', {
target: trigger => trigger.parentNode.parentNode,
}
)
clipboard.on('success', event => {
const iconFirstChild = event.trigger.querySelector('.bi').firstElementChild
const namespace = 'http://www.w3.org/1999/xlink'
const originalXhref = iconFirstChild.getAttributeNS(namespace, 'href')
const originalTitle = event.trigger.title
event.clearSelection()
iconFirstChild.setAttributeNS(namespace, 'href', originalXhref.replace('clipboard', 'check2'))
setTimeout(() => {
iconFirstChild.setAttributeNS(namespace, 'href', originalXhref)
event.trigger.title = originalTitle
}, 2000)
})
clipboard.on('error', event => {
const modifierKey = /mac/i.test(navigator.userAgent) ? '\u2318' : 'Ctrl-'
const fallbackMsg = `Press ${modifierKey}C to copy`
})
// Get the lines from the code box based on the optional `copy-lines` attribute.
// Defaults to copying all lines.
function getText(highlightDiv){
// Find the code lines inside the code table
var codeLines = highlightDiv.getElementsByClassName("line")
var codeText = []
for (var i = 0; i < codeLines.length; i++){
codeText.push(codeLines[i].innerText)
}
// default is only copy line 1
var startLines = 1
var endLines = codeText.length
// did they set the "copy-lines" value in the code box to identify what to copy?
if("copy-lines" in highlightDiv.attributes){
var copyVal = highlightDiv.attributes["copy-lines"].value
// if it's a single digit then start == end
if(copyVal.length === 1){
startLines = parseInt(copyVal, 10)
endLines = parseInt(copyVal, 10)
}
// If the default copy is 1 instead of all, the following is required.
// else if(copyVal.localeCompare("all") === 0){
// endLines = codeContent.length
// }
else {
// look for a value like 1-10. Split on the dash.
var startendLines = copyVal.split("-")
startLines = parseInt(startendLines[0], 10)
endLines = parseInt(startendLines[1], 10)
}
if(startLines <= 0 || isNaN(startLines)) {
startLines = 1
}
if(endLines <= 0 || endLines > codeText.length - 1 || isNaN(endLines)){
endLines = codeText.length
}
}
return codeText.slice((startLines - 1), endLines).join('')
}

View File

@ -1,6 +1,7 @@
// The collection of things to load on all pages // The collection of things to load on all pages
import ColorMode from './colorMode' import ColorMode from './colorMode';
import 'instant.page' import 'instant.page';
import './bootstrap/src/base-component'; import './bootstrap/src/base-component';
import './bootstrap/src/button'; import './bootstrap/src/button';
@ -10,4 +11,5 @@ import './bootstrap/src/popover';
import './bootstrap/src/tab'; import './bootstrap/src/tab';
import './bootstrap/src/offcanvas'; import './bootstrap/src/offcanvas';
import './tabDeepAnchor.js'; import './tabDeepAnchor.js';
import './customClipboard.js';

View File

@ -36,8 +36,8 @@ function getParents(elem, selector) {
// Update the anchor link if the anchor is inside a tab // Update the anchor link if the anchor is inside a tab
// The updated link will create a query string with the name of the tab. // The updated link will create a query string with the name of the tab.
function tabDeepLink(){ function tabDeepLink(anchorName){
var anchorCollection = document.getElementsByClassName("anchor-link"); var anchorCollection = document.getElementsByClassName(anchorName);
if(anchorCollection.length == 0){ if(anchorCollection.length == 0){
return return
@ -53,8 +53,9 @@ function tabDeepLink(){
if(parentTab.length == 1){ if(parentTab.length == 1){
tabID = parentTab[0].id.replace("-pane", ""); tabID = parentTab[0].id.replace("-pane", "");
link = '?tab=' + tabID + '#' + anchor.id; link = '?tab=' + tabID + anchor.hash;
anchor.setAttribute('href', link); anchor.setAttribute('href', link);
anchor.setAttribute('id', (tabID + anchor.hash));
} }
} }
} }
@ -63,11 +64,13 @@ function tabDeepLink(){
function openTab(){ function openTab(){
var urlParams = new URLSearchParams(window.location.search); var urlParams = new URLSearchParams(window.location.search);
if(urlParams.get('tab')){ if(urlParams.get('tab')){
document.getElementById(urlParams.get('tab')).click(); tabID = urlParams.get('tab')
document.getElementById(tabID).click();
document.getElementById(tabID + location.hash).scrollIntoView();
} }
//document.getElementById('tab-367').click();
} }
window.onload = tabDeepLink(); window.onload = tabDeepLink("anchor-link");
window.onload = tabDeepLink("lnlinks");
window.onload = openTab(); window.onload = openTab();