0
0
mirror of https://github.com/twbs/bootstrap.git synced 2024-11-28 10:24:19 +01:00

Merge branch 'main' into xmr/docs-sass
Some checks failed
BrowserStack / browserstack (push) Has been cancelled

This commit is contained in:
XhmikosR 2024-03-19 15:57:43 +02:00 committed by GitHub
commit 2538f04a2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 1433 additions and 9219 deletions

View File

@ -197,6 +197,15 @@
"unicorn/no-array-for-each": "off"
}
},
{
"files": [
"site/assets/js/**"
],
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2020
}
},
{
"files": [
"**/*.md"
@ -208,9 +217,10 @@
},
{
"files": [
"**/*.md/*.js"
"**/*.md/*.js",
"**/*.md/*.mjs"
],
"extends": "plugin:markdown/recommended",
"extends": "plugin:markdown/recommended-legacy",
"parserOptions": {
"sourceType": "module"
},

1
.npmrc
View File

@ -1 +0,0 @@
lockfile-version=2

View File

@ -177,7 +177,7 @@ Get updates on Bootstrap's development and chat with the project maintainers and
- Follow [@getbootstrap on Twitter](https://twitter.com/getbootstrap).
- Read and subscribe to [The Official Bootstrap Blog](https://blog.getbootstrap.com/).
- Ask questions and explore [our GitHub Discussions](https://github.com/twbs/bootstrap/discussions).
- Discuss, ask questions, and more on [the community Discord](https://discord.gg/bZUvakRU3M) or [Bootstrap subreddit](https://reddit.com/r/bootstrap).
- Discuss, ask questions, and more on [the community Discord](https://discord.gg/bZUvakRU3M) or [Bootstrap subreddit](https://www.reddit.com/r/bootstrap/).
- Chat with fellow Bootstrappers in IRC. On the `irc.libera.chat` server, in the `#bootstrap` channel.
- Implementation help may be found at Stack Overflow (tagged [`bootstrap-5`](https://stackoverflow.com/questions/tagged/bootstrap-5)).
- Developers should use the keyword `bootstrap` on packages which modify or add to the functionality of Bootstrap when distributing through [npm](https://www.npmjs.com/browse/keyword/bootstrap) or similar delivery mechanisms for maximum discoverability.

View File

@ -9,7 +9,7 @@
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { babel } from '@rollup/plugin-babel'
import globby from 'globby'
import { globby } from 'globby'
import { rollup } from 'rollup'
import banner from './banner.mjs'
@ -17,7 +17,7 @@ const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const sourcePath = path.resolve(__dirname, '../js/src/').replace(/\\/g, '/')
const jsFiles = globby.sync(`${sourcePath}/**/*.js`)
const jsFiles = await globby(`${sourcePath}/**/*.js`)
// Array which holds the resolved plugins
const resolvedPlugins = []
@ -37,6 +37,9 @@ for (const file of jsFiles) {
}
const build = async plugin => {
/**
* @type {import('rollup').GlobalsOption}
*/
const globals = {}
const bundle = await rollup({

View File

@ -8,8 +8,6 @@ security:
getenv:
- ^HUGO_
- NETLIFY
gotemplates:
allowActionJSTmpl: true
markup:
goldmark:
@ -21,6 +19,9 @@ markup:
startLevel: 2
endLevel: 6
build:
noJSConfigInAssets: true
buildDrafts: true
buildFuture: true
@ -44,6 +45,8 @@ module:
target: layouts
- source: site/static
target: static
- source: node_modules/@docsearch/css
target: assets/scss/@docsearch/css
- source: site/static/docs/5.3/assets/img/favicons/apple-touch-icon.png
target: static/apple-touch-icon.png
- source: site/static/docs/5.3/assets/img/favicons/favicon.ico
@ -67,6 +70,14 @@ params:
icons: "https://icons.getbootstrap.com/"
swag: "https://cottonbureau.com/people/bootstrap"
analytics:
fathom_site: "ITUSEYJG"
algolia:
appId: "AK7KMZKZHQ"
apiKey: "3151f502c7b9e9dafd5e6372b691a24e"
indexName: "bootstrap"
download:
source: "https://github.com/twbs/bootstrap/archive/v5.3.3.zip"
dist: "https://github.com/twbs/bootstrap/releases/download/v5.3.3/bootstrap-5.3.3-dist.zip"

View File

@ -170,7 +170,7 @@ const noop = () => {}
* @param {HTMLElement} element
* @return void
*
* @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight // eslint-disable-line no-unused-expressions

9881
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -82,7 +82,7 @@
"docs-serve": "hugo server --port 9001 --disableFastRender --noHTTPCache --renderToMemory --printPathWarnings --printUnusedTemplates",
"docs-serve-only": "npx sirv-cli _site --port 9001",
"lockfile-lint": "lockfile-lint --allowed-hosts npm --allowed-schemes https: --empty-hostname false --type npm --path package-lock.json",
"update-deps": "ncu -u -x globby,jasmine,karma-browserstack-launcher,karma-rollup-preprocessor && echo Manually update site/assets/js/vendor",
"update-deps": "ncu -u -x jasmine,karma-browserstack-launcher,karma-rollup-preprocessor",
"release": "npm-run-all dist release-sri docs-build release-zip*",
"release-sri": "node build/generate-sri.mjs",
"release-version": "node build/change-version.mjs",
@ -104,27 +104,30 @@
},
"devDependencies": {
"@babel/cli": "^7.23.9",
"@babel/core": "^7.24.0",
"@babel/core": "^7.24.1",
"@babel/preset-env": "^7.24.0",
"@docsearch/js": "^3.6.0",
"@popperjs/core": "^2.11.8",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-replace": "^5.0.5",
"@stackblitz/sdk": "^1.9.0",
"autoprefixer": "^10.4.18",
"bundlewatch": "^0.3.3",
"clean-css-cli": "^5.6.3",
"clipboard": "^2.0.11",
"cross-env": "^7.0.3",
"eslint": "^8.57.0",
"eslint-config-xo": "^0.44.0",
"eslint-plugin-html": "^8.0.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-markdown": "^3.0.1",
"eslint-plugin-markdown": "^4.0.1",
"eslint-plugin-unicorn": "^51.0.1",
"find-unused-sass-variables": "^5.0.0",
"globby": "^11.1.0",
"globby": "^14.0.1",
"hammer-simulator": "0.0.1",
"hugo-bin": "^0.120.7",
"hugo-bin": "^0.121.0",
"ip": "^2.0.1",
"jasmine": "^5.1.0",
"jquery": "^3.7.1",
@ -140,17 +143,17 @@
"lockfile-lint": "^4.13.2",
"nodemon": "^3.1.0",
"npm-run-all2": "^6.1.2",
"postcss": "^8.4.35",
"postcss": "^8.4.36",
"postcss-cli": "^11.0.0",
"rollup": "^4.12.0",
"rollup": "^4.13.0",
"rollup-plugin-istanbul": "^5.0.0",
"rtlcss": "^4.1.1",
"sass": "^1.71.1",
"sass": "^1.72.0",
"sass-true": "^8.0.0",
"shelljs": "^0.8.5",
"stylelint": "^16.2.1",
"stylelint-config-twbs-bootstrap": "^14.0.0",
"terser": "^5.27.2",
"terser": "^5.29.2",
"vnu-jar": "23.4.11"
},
"files": [

View File

@ -17,6 +17,7 @@
height: 100%; // allow textareas
padding: $form-floating-padding-y $form-floating-padding-x;
overflow: hidden;
color: rgba(var(--#{$prefix}body-color-rgb), #{$form-floating-label-opacity});
text-align: start;
text-overflow: ellipsis;
white-space: nowrap;
@ -56,7 +57,6 @@
> .form-control-plaintext,
> .form-select {
~ label {
color: rgba(var(--#{$prefix}body-color-rgb), #{$form-floating-label-opacity});
transform: $form-floating-label-transform;
&::after {
@ -73,7 +73,6 @@
// Duplicated because `:-webkit-autofill` invalidates other selectors when grouped
> .form-control:-webkit-autofill {
~ label {
color: rgba(var(--#{$prefix}body-color-rgb), #{$form-floating-label-opacity});
transform: $form-floating-label-transform;
}
}

View File

@ -9,22 +9,12 @@
* For details, see https://creativecommons.org/licenses/by/3.0/.
*/
(() => {
'use strict'
/* eslint-disable import/no-unresolved */
import sidebarScroll from 'js/partials/sidebar.js'
import codeExamples from 'js/partials/code-examples.js'
import snippets from 'js/partials/snippets.js'
/* eslint-enable import/no-unresolved */
// Scroll the active sidebar link into view
const sidenav = document.querySelector('.bd-sidebar')
const sidenavActiveLink = document.querySelector('.bd-links-nav .active')
if (sidenav && sidenavActiveLink) {
const sidenavHeight = sidenav.clientHeight
const sidenavActiveLinkTop = sidenavActiveLink.offsetTop
const sidenavActiveLinkHeight = sidenavActiveLink.clientHeight
const viewportTop = sidenavActiveLinkTop
const viewportBottom = viewportTop - sidenavHeight + sidenavActiveLinkHeight
if (sidenav.scrollTop > viewportTop || sidenav.scrollTop < viewportBottom) {
sidenav.scrollTop = viewportTop - (sidenavHeight / 2) + (sidenavActiveLinkHeight / 2)
}
}
})()
sidebarScroll()
codeExamples()
snippets()

View File

@ -2,18 +2,18 @@
// IT'S ALL JUST JUNK FOR OUR DOCS!
// ++++++++++++++++++++++++++++++++++++++++++
/*!
/*
* JavaScript for Bootstrap's docs (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
* For details, see https://creativecommons.org/licenses/by/3.0/.
*/
/* global ClipboardJS: false, bootstrap: false */
/* global bootstrap: false */
(() => {
'use strict'
import ClipboardJS from 'clipboard'
export default () => {
// Insert copy to clipboard button before .highlight
const btnTitle = 'Copy to clipboard'
const btnEdit = 'Edit on StackBlitz'
@ -87,4 +87,4 @@
tooltipBtn.setContent({ '.tooltip-inner': btnTitle })
}, { once: true })
})
})()
}

View File

@ -0,0 +1,30 @@
// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT
// IT'S ALL JUST JUNK FOR OUR DOCS!
// ++++++++++++++++++++++++++++++++++++++++++
/*
* JavaScript for Bootstrap's docs (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
* For details, see https://creativecommons.org/licenses/by/3.0/.
*/
export default () => {
// Scroll the active sidebar link into view
const sidenav = document.querySelector('.bd-sidebar')
const sidenavActiveLink = document.querySelector('.bd-links-nav .active')
if (!sidenav || !sidenavActiveLink) {
return
}
const sidenavHeight = sidenav.clientHeight
const sidenavActiveLinkTop = sidenavActiveLink.offsetTop
const sidenavActiveLinkHeight = sidenavActiveLink.clientHeight
const viewportTop = sidenavActiveLinkTop
const viewportBottom = viewportTop - sidenavHeight + sidenavActiveLinkHeight
if (sidenav.scrollTop > viewportTop || sidenav.scrollTop < viewportBottom) {
sidenav.scrollTop = viewportTop - (sidenavHeight / 2) + (sidenavActiveLinkHeight / 2)
}
}

View File

@ -0,0 +1,168 @@
// NOTICE!!! Initially embedded in our docs this JavaScript
// file contains elements that can help you create reproducible
// use cases in StackBlitz for instance.
// In a real project please adapt this content to your needs.
// ++++++++++++++++++++++++++++++++++++++++++
/*
* JavaScript for Bootstrap's docs (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
* For details, see https://creativecommons.org/licenses/by/3.0/.
*/
/* global bootstrap: false */
export default () => {
// --------
// Tooltips
// --------
// Instantiate all tooltips in a docs or StackBlitz
document.querySelectorAll('[data-bs-toggle="tooltip"]')
.forEach(tooltip => {
new bootstrap.Tooltip(tooltip)
})
// --------
// Popovers
// --------
// Instantiate all popovers in docs or StackBlitz
document.querySelectorAll('[data-bs-toggle="popover"]')
.forEach(popover => {
new bootstrap.Popover(popover)
})
// -------------------------------
// Toasts
// -------------------------------
// Used by 'Placement' example in docs or StackBlitz
const toastPlacement = document.getElementById('toastPlacement')
if (toastPlacement) {
document.getElementById('selectToastPlacement').addEventListener('change', function () {
if (!toastPlacement.dataset.originalClass) {
toastPlacement.dataset.originalClass = toastPlacement.className
}
toastPlacement.className = `${toastPlacement.dataset.originalClass} ${this.value}`
})
}
// Instantiate all toasts in docs pages only
document.querySelectorAll('.bd-example .toast')
.forEach(toastNode => {
const toast = new bootstrap.Toast(toastNode, {
autohide: false
})
toast.show()
})
// Instantiate all toasts in docs pages only
// js-docs-start live-toast
const toastTrigger = document.getElementById('liveToastBtn')
const toastLiveExample = document.getElementById('liveToast')
if (toastTrigger) {
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample)
toastTrigger.addEventListener('click', () => {
toastBootstrap.show()
})
}
// js-docs-end live-toast
// -------------------------------
// Alerts
// -------------------------------
// Used in 'Show live alert' example in docs or StackBlitz
// js-docs-start live-alert
const alertPlaceholder = document.getElementById('liveAlertPlaceholder')
const appendAlert = (message, type) => {
const wrapper = document.createElement('div')
wrapper.innerHTML = [
`<div class="alert alert-${type} alert-dismissible" role="alert">`,
` <div>${message}</div>`,
' <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>',
'</div>'
].join('')
alertPlaceholder.append(wrapper)
}
const alertTrigger = document.getElementById('liveAlertBtn')
if (alertTrigger) {
alertTrigger.addEventListener('click', () => {
appendAlert('Nice, you triggered this alert message!', 'success')
})
}
// js-docs-end live-alert
// --------
// Carousels
// --------
// Instantiate all non-autoplaying carousels in docs or StackBlitz
document.querySelectorAll('.carousel:not([data-bs-ride="carousel"])')
.forEach(carousel => {
bootstrap.Carousel.getOrCreateInstance(carousel)
})
// -------------------------------
// Checks & Radios
// -------------------------------
// Indeterminate checkbox example in docs and StackBlitz
document.querySelectorAll('.bd-example-indeterminate [type="checkbox"]')
.forEach(checkbox => {
if (checkbox.id.includes('Indeterminate')) {
checkbox.indeterminate = true
}
})
// -------------------------------
// Links
// -------------------------------
// Disable empty links in docs examples only
document.querySelectorAll('.bd-content [href="#"]')
.forEach(link => {
link.addEventListener('click', event => {
event.preventDefault()
})
})
// -------------------------------
// Modal
// -------------------------------
// Modal 'Varying modal content' example in docs and StackBlitz
// js-docs-start varying-modal-content
const exampleModal = document.getElementById('exampleModal')
if (exampleModal) {
exampleModal.addEventListener('show.bs.modal', event => {
// Button that triggered the modal
const button = event.relatedTarget
// Extract info from data-bs-* attributes
const recipient = button.getAttribute('data-bs-whatever')
// If necessary, you could initiate an Ajax request here
// and then do the updating in a callback.
// Update the modal's content.
const modalTitle = exampleModal.querySelector('.modal-title')
const modalBodyInput = exampleModal.querySelector('.modal-body input')
modalTitle.textContent = `New message to ${recipient}`
modalBodyInput.value = recipient
})
}
// js-docs-end varying-modal-content
// -------------------------------
// Offcanvas
// -------------------------------
// 'Offcanvas components' example in docs only
const myOffcanvas = document.querySelectorAll('.bd-example-offcanvas .offcanvas')
if (myOffcanvas) {
myOffcanvas.forEach(offcanvas => {
offcanvas.addEventListener('show.bs.offcanvas', event => {
event.preventDefault()
}, false)
})
}
}

View File

@ -2,21 +2,31 @@
// IT'S ALL JUST JUNK FOR OUR DOCS!
// ++++++++++++++++++++++++++++++++++++++++++
(() => {
'use strict'
/*!
* JavaScript for Bootstrap's docs (https://getbootstrap.com/)
* Copyright 2024 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
* For details, see https://creativecommons.org/licenses/by/3.0/.
*/
import docsearch from '@docsearch/js'
// https://gohugo.io/hugo-pipes/js/#options
// eslint-disable-next-line import/no-unresolved
import { appId, apiKey, indexName } from '@params';
(() => {
const searchElement = document.getElementById('docsearch')
if (!window.docsearch || !searchElement) {
if (!searchElement) {
return
}
const siteDocsVersion = searchElement.getAttribute('data-bd-docs-version')
window.docsearch({
apiKey: '3151f502c7b9e9dafd5e6372b691a24e',
indexName: 'bootstrap',
appId: 'AK7KMZKZHQ',
docsearch({
apiKey,
indexName,
appId,
container: searchElement,
searchParameters: {
facetFilters: [`version:${siteDocsVersion}`]

View File

@ -1,170 +1,15 @@
// NOTICE!!! Initially embedded in our docs this JavaScript
// file contains elements that can help you create reproducible
// use cases in StackBlitz for instance.
// In a real project please adapt this content to your needs.
// ++++++++++++++++++++++++++++++++++++++++++
/*!
/*
* JavaScript for Bootstrap's docs (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
* For details, see https://creativecommons.org/licenses/by/3.0/.
*/
/* global bootstrap: false */
// Note that this file is not published; we only include it in scrpts.html
// for StackBlitz to work
(() => {
'use strict'
/* eslint-disable import/no-unresolved */
import snippets from 'js/partials/snippets.js'
/* eslint-enable import/no-unresolved */
// --------
// Tooltips
// --------
// Instantiate all tooltips in a docs or StackBlitz
document.querySelectorAll('[data-bs-toggle="tooltip"]')
.forEach(tooltip => {
new bootstrap.Tooltip(tooltip)
})
// --------
// Popovers
// --------
// Instantiate all popovers in docs or StackBlitz
document.querySelectorAll('[data-bs-toggle="popover"]')
.forEach(popover => {
new bootstrap.Popover(popover)
})
// -------------------------------
// Toasts
// -------------------------------
// Used by 'Placement' example in docs or StackBlitz
const toastPlacement = document.getElementById('toastPlacement')
if (toastPlacement) {
document.getElementById('selectToastPlacement').addEventListener('change', function () {
if (!toastPlacement.dataset.originalClass) {
toastPlacement.dataset.originalClass = toastPlacement.className
}
toastPlacement.className = `${toastPlacement.dataset.originalClass} ${this.value}`
})
}
// Instantiate all toasts in docs pages only
document.querySelectorAll('.bd-example .toast')
.forEach(toastNode => {
const toast = new bootstrap.Toast(toastNode, {
autohide: false
})
toast.show()
})
// Instantiate all toasts in docs pages only
// js-docs-start live-toast
const toastTrigger = document.getElementById('liveToastBtn')
const toastLiveExample = document.getElementById('liveToast')
if (toastTrigger) {
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample)
toastTrigger.addEventListener('click', () => {
toastBootstrap.show()
})
}
// js-docs-end live-toast
// -------------------------------
// Alerts
// -------------------------------
// Used in 'Show live alert' example in docs or StackBlitz
// js-docs-start live-alert
const alertPlaceholder = document.getElementById('liveAlertPlaceholder')
const appendAlert = (message, type) => {
const wrapper = document.createElement('div')
wrapper.innerHTML = [
`<div class="alert alert-${type} alert-dismissible" role="alert">`,
` <div>${message}</div>`,
' <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>',
'</div>'
].join('')
alertPlaceholder.append(wrapper)
}
const alertTrigger = document.getElementById('liveAlertBtn')
if (alertTrigger) {
alertTrigger.addEventListener('click', () => {
appendAlert('Nice, you triggered this alert message!', 'success')
})
}
// js-docs-end live-alert
// --------
// Carousels
// --------
// Instantiate all non-autoplaying carousels in docs or StackBlitz
document.querySelectorAll('.carousel:not([data-bs-ride="carousel"])')
.forEach(carousel => {
bootstrap.Carousel.getOrCreateInstance(carousel)
})
// -------------------------------
// Checks & Radios
// -------------------------------
// Indeterminate checkbox example in docs and StackBlitz
document.querySelectorAll('.bd-example-indeterminate [type="checkbox"]')
.forEach(checkbox => {
if (checkbox.id.includes('Indeterminate')) {
checkbox.indeterminate = true
}
})
// -------------------------------
// Links
// -------------------------------
// Disable empty links in docs examples only
document.querySelectorAll('.bd-content [href="#"]')
.forEach(link => {
link.addEventListener('click', event => {
event.preventDefault()
})
})
// -------------------------------
// Modal
// -------------------------------
// Modal 'Varying modal content' example in docs and StackBlitz
// js-docs-start varying-modal-content
const exampleModal = document.getElementById('exampleModal')
if (exampleModal) {
exampleModal.addEventListener('show.bs.modal', event => {
// Button that triggered the modal
const button = event.relatedTarget
// Extract info from data-bs-* attributes
const recipient = button.getAttribute('data-bs-whatever')
// If necessary, you could initiate an Ajax request here
// and then do the updating in a callback.
// Update the modal's content.
const modalTitle = exampleModal.querySelector('.modal-title')
const modalBodyInput = exampleModal.querySelector('.modal-body input')
modalTitle.textContent = `New message to ${recipient}`
modalBodyInput.value = recipient
})
}
// js-docs-end varying-modal-content
// -------------------------------
// Offcanvas
// -------------------------------
// 'Offcanvas components' example in docs only
const myOffcanvas = document.querySelectorAll('.bd-example-offcanvas .offcanvas')
if (myOffcanvas) {
myOffcanvas.forEach(offcanvas => {
offcanvas.addEventListener('show.bs.offcanvas', event => {
event.preventDefault()
}, false)
})
}
})()
snippets()

View File

@ -0,0 +1,66 @@
// NOTICE!!! Initially embedded in our docs this JavaScript
// file contains elements that can help you create reproducible
// use cases in StackBlitz for instance.
// In a real project please adapt this content to your needs.
// ++++++++++++++++++++++++++++++++++++++++++
/*!
* JavaScript for Bootstrap's docs (https://getbootstrap.com/)
* Copyright 2024 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
* For details, see https://creativecommons.org/licenses/by/3.0/.
*/
import sdk from '@stackblitz/sdk'
// https://gohugo.io/hugo-pipes/js/#options
import {
cssCdn, docsVersion, jsBundleCdn, jsSnippetFile
} from '@params' // eslint-disable-line import/no-unresolved
// Open in StackBlitz logic
document.querySelectorAll('.btn-edit').forEach(btn => {
btn.addEventListener('click', event => {
const codeSnippet = event.target.closest('.bd-code-snippet')
const exampleEl = codeSnippet.querySelector('.bd-example')
const htmlSnippet = exampleEl.innerHTML
const jsSnippet = codeSnippet.querySelector('.btn-edit').getAttribute('data-sb-js-snippet')
// Get extra classes for this example
const classes = Array.from(exampleEl.classList).join(' ')
openBootstrapSnippet(htmlSnippet, jsSnippet, classes)
})
})
const openBootstrapSnippet = (htmlSnippet, jsSnippet, classes) => {
const indexHtml = `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="${cssCdn}" rel="stylesheet">
<link href="https://getbootstrap.com/docs/${docsVersion}/assets/css/docs.css" rel="stylesheet">
<title>Bootstrap Example</title>
<${'script'} defer src="${jsBundleCdn}"></${'script'}>
</head>
<body class="p-3 m-0 border-0 ${classes}">
<!-- Example Code Start-->
${htmlSnippet.trimStart().replace(/^/gm, ' ').replace(/^ {4}$/gm, '').trimEnd()}
<!-- Example Code End -->
</body>
</html>
`
const project = {
files: {
'index.html': indexHtml,
...(jsSnippet && { 'index.js': jsSnippetFile })
},
title: 'Bootstrap Example',
description: `Official example from ${window.location.href}`,
template: jsSnippet ? 'javascript' : 'html',
tags: ['bootstrap']
}
sdk.openProject(project, { openFile: 'index.html' })
}

File diff suppressed because one or more lines are too long

View File

@ -36,7 +36,6 @@ $enable-cssgrid: true;
// Load docs components
@import "variables";
@import "navbar";
@import "search";
@import "masthead";
@import "ads";
@import "content";

View File

@ -0,0 +1,14 @@
/*!
* Bootstrap Docs (https://getbootstrap.com/)
* Copyright 2024 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
* For details, see https://creativecommons.org/licenses/by/3.0/.
*/
@import "../../../scss/functions";
@import "../../../scss/variables";
@import "../../../scss/mixins";
@import "variables";
@import "@docsearch/css/dist/style";
@import "search";

View File

@ -38,7 +38,7 @@ Click the button below to show an alert (hidden with inline styles to start), th
We use the following JavaScript to trigger our live alert demo:
{{< js-docs name="live-alert" file="site/assets/js/snippets.js" >}}
{{< js-docs name="live-alert" file="site/assets/js/partials/snippets.js" >}}
### Link color

View File

@ -481,7 +481,7 @@ Below is a live demo followed by example HTML and JavaScript. For more informati
</div>
{{< /example >}}
{{< js-docs name="varying-modal-content" file="site/assets/js/snippets.js" >}}
{{< js-docs name="varying-modal-content" file="site/assets/js/partials/snippets.js" >}}
### Toggle between modals

View File

@ -87,7 +87,7 @@ Click the button below to show a toast (positioned with our utilities in the low
We use the following JavaScript to trigger our live toast demo:
{{< js-docs name="live-toast" file="site/assets/js/snippets.js" >}}
{{< js-docs name="live-toast" file="site/assets/js/partials/snippets.js" >}}
### Translucent

View File

@ -46,4 +46,4 @@ sitemap_exclude: true
{{< scss-docs name="variable-gradient" file="scss/_variables.scss" >}}
{{< js-docs name="live-toast" file="site/assets/js/snippets.js" >}}
{{< js-docs name="live-toast" file="site/assets/js/partials/snippets.js" >}}

View File

@ -21,12 +21,12 @@ aliases: "/examples/"
{{ range $i, $example := $entry.examples -}}
{{- $len := len $entry.examples -}}
{{ if (eq $i 0) }}<div class="row">{{ end }}
{{ if $entry.external }}
{{ if $entry.external -}}
<div class="col-md-6 col-lg-4 mb-3 d-flex gap-3">
<svg class="bi fs-5 flex-shrink-0 mt-1"><use xlink:href="#box-seam"></use></svg>
<div>
<h3 class="h5 mb-1">
<a class="d-block link-offset-1" href="{{ $.Site.Params.github_org }}{{ $example.url }}/" target="_blank" rel="noopener">
<a class="d-block link-offset-1" href="{{ urls.JoinPath $.Site.Params.github_org $example.url }}" target="_blank" rel="noopener">
{{ $example.name }}
</a>
</h3>
@ -43,23 +43,29 @@ aliases: "/examples/"
</p>
</div>
</div>
{{ else }}
{{ else -}}
<div class="col-sm-6 col-md-3 mb-3">
<a class="d-block link-offset-1" href="/docs/{{ $.Site.Params.docs_version }}/examples/{{ $example.name | urlize }}/"{{ if in $example.name "RTL" }} hreflang="ar"{{ end }}>
<img class="img-thumbnail mb-3" srcset="/docs/{{ $.Site.Params.docs_version }}/assets/img/examples/{{ $example.name | urlize }}.png,
/docs/{{ $.Site.Params.docs_version }}/assets/img/examples/{{ $example.name | urlize }}@2x.png 2x"
src="/docs/{{ $.Site.Params.docs_version }}/assets/img/examples/{{ $example.name | urlize }}.png"
alt=""
width="480" height="300"
loading="lazy">
<a class="d-block link-offset-1" href="{{ urls.JoinPath "/docs" $.Site.Params.docs_version "/examples" ($example.name | urlize) "/"}}"{{ if in $example.name "RTL" }} hreflang="ar"{{ end }}>
{{ $imageBasePath := urls.JoinPath "/docs" $.Site.Params.docs_version "assets/img/examples" -}}
{{- $imgPath := urls.JoinPath $imageBasePath (printf "%s%s" ($example.name | urlize) ".png") -}}
{{- $imgPath2x := urls.JoinPath $imageBasePath (printf "%s%s" ($example.name | urlize) "@2x.png") -}}
{{- with (imageConfig (path.Join "/site/static" $imgPath)) -}}
<img class="img-thumbnail mb-3"
srcset="{{ $imgPath }}, {{ $imgPath2x }} 2x"
src="{{ $imgPath }}"
alt=""
width="{{ .Width }}"
height="{{ .Height }}"
loading="lazy">
{{- end }}
<h3 class="h5 mb-1">
{{ $example.name }}
</h3>
</a>
<p class="text-body-secondary">{{ $example.description }}</p>
</div>
{{ end }}
{{ if (eq (add $i 1) $len) }}</div>{{ end }}
{{- end }}
{{ if (eq (add $i 1) $len) }}</div>{{ end -}}
{{ end -}}
</div>
{{ end -}}

View File

@ -5,6 +5,7 @@ extra_css:
- "../cheatsheet/cheatsheet.rtl.css"
extra_js:
- src: "../cheatsheet/cheatsheet.js"
defer: true
body_class: "bg-body-tertiary"
direction: rtl
---

View File

@ -5,6 +5,7 @@ extra_css:
- "cheatsheet.css"
extra_js:
- src: "cheatsheet.js"
defer: true
body_class: "bg-body-tertiary"
---

View File

@ -6,6 +6,7 @@ extra_css:
- "../checkout/checkout.css"
extra_js:
- src: "../checkout/checkout.js"
defer: true
body_class: "bg-body-tertiary"
---

View File

@ -5,6 +5,7 @@ extra_css:
- "checkout.css"
extra_js:
- src: "checkout.js"
defer: true
body_class: "bg-body-tertiary"
---

View File

@ -7,7 +7,9 @@ extra_css:
extra_js:
- src: "https://cdn.jsdelivr.net/npm/chart.js@4.3.2/dist/chart.umd.js"
integrity: "sha384-eI7PSr3L1XLISH8JdDII5YN/njoSsxfbrkCTnJrzXt+ENP5MOVBxD+l6sEG4zoLp"
defer: true
- src: "dashboard.js"
defer: true
---
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">

View File

@ -6,7 +6,9 @@ extra_css:
extra_js:
- src: "https://cdn.jsdelivr.net/npm/chart.js@4.3.2/dist/chart.umd.js"
integrity: "sha384-eI7PSr3L1XLISH8JdDII5YN/njoSsxfbrkCTnJrzXt+ENP5MOVBxD+l6sEG4zoLp"
defer: true
- src: "dashboard.js"
defer: true
---
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">

View File

@ -5,6 +5,7 @@ extra_css:
- "offcanvas-navbar.css"
extra_js:
- src: "offcanvas-navbar.js"
defer: true
body_class: "bg-body-tertiary"
aliases: "/docs/5.3/examples/offcanvas/"
---

View File

@ -5,6 +5,7 @@ extra_css:
- "sidebars.css"
extra_js:
- src: "sidebars.js"
defer: true
body_class: ""
---

View File

@ -58,7 +58,7 @@ Note that [breaking words isn't possible in Arabic](https://rtlstyling.com/posts
## Text transform
Transform text in components with text capitalization classes.
Transform text in components with our text capitalization classes: `text-lowercase`, `text-uppercase` or `text-capitalize`.
{{< example >}}
<p class="text-lowercase">Lowercased text.</p>

View File

@ -67,7 +67,7 @@
{{ end }}
{{ define "footer" }}
{{ range .Page.Params.extra_js -}}
<script{{ with .async }} async{{ end }} src="{{ .src }}"></script>
<script{{ with .async }} async{{ end }}{{ with .defer }} defer{{ end }} src="{{ .src }}"></script>
{{- end -}}
<div class="position-fixed" aria-hidden="true"><input type="text" tabindex="-1"></div>
{{ end }}

View File

@ -159,13 +159,13 @@
{{ .Content }}
{{- if hugo.IsProduction -}}
<script src="/docs/{{ .Site.Params.docs_version }}/dist/js/bootstrap.bundle.min.js" {{ printf "integrity=%q" .Site.Params.cdn.js_bundle_hash | safeHTMLAttr }}></script>
<script defer src="/docs/{{ .Site.Params.docs_version }}/dist/js/bootstrap.bundle.min.js" {{ printf "integrity=%q" .Site.Params.cdn.js_bundle_hash | safeHTMLAttr }}></script>
{{- else -}}
<script src="/docs/{{ .Site.Params.docs_version }}/dist/js/bootstrap.bundle.js"></script>
<script defer src="/docs/{{ .Site.Params.docs_version }}/dist/js/bootstrap.bundle.js"></script>
{{- end }}
{{ range .Page.Params.extra_js -}}
<script{{ with .async }} async{{ end }} src="{{ .src }}"{{ with .integrity }} {{ printf "integrity=%q" . | safeHTMLAttr }} crossorigin="anonymous"{{ end }}></script>
<script{{ with .async }} async{{ end }}{{ with .defer }} defer{{ end }} src="{{ .src }}"{{ with .integrity }} {{ printf "integrity=%q" . | safeHTMLAttr }} crossorigin="anonymous"{{ end }}></script>
{{- end -}}
</body>
</html>

View File

@ -1 +1 @@
<script defer src="https://cdn.usefathom.com/script.js" data-site="ITUSEYJG"></script>
<script defer src="https://cdn.usefathom.com/script.js" data-site="{{ .Site.Params.analytics.fathom_site }}"></script>

View File

@ -23,7 +23,7 @@
</button>
</div>
<div class="offcanvas-lg offcanvas-end flex-grow-1" tabindex="-1" id="bdNavbar" aria-labelledby="bdNavbarOffcanvasLabel" data-bs-scroll="true">
<div class="offcanvas-lg offcanvas-end flex-grow-1" tabindex="-1" id="bdNavbar" aria-labelledby="bdNavbarOffcanvasLabel">
<div class="offcanvas-header px-4 pb-0">
<h5 class="offcanvas-title text-white" id="bdNavbarOffcanvasLabel">Bootstrap</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas" aria-label="Close" data-bs-target="#bdNavbar"></button>

View File

@ -7,11 +7,13 @@
<meta name="docsearch:language" content="en">
<meta name="docsearch:version" content="{{ .Site.Params.docs_version }}">
<title>{{ if .IsHome }}{{ .Site.Title | markdownify }} · {{ .Site.Params.subtitle | markdownify }}{{ else }}{{ .Title | markdownify }} · {{ .Site.Title | markdownify }} v{{ .Site.Params.docs_version }}{{ end }}</title>
<link rel="canonical" href="{{ .Permalink }}">
<link rel="preconnect" href="https://AK7KMZKZHQ-dsn.algolia.net" crossorigin>
{{ if (ne .Page.Layout "examples") -}}
<link rel="preconnect" href="https://{{ .Site.Params.algolia.appId | lower }}-dsn.algolia.net" crossorigin>
{{- end }}
<title>{{ if .IsHome }}{{ .Site.Title | markdownify }} · {{ .Site.Params.subtitle | markdownify }}{{ else }}{{ .Title | markdownify }} · {{ .Site.Title | markdownify }} v{{ .Site.Params.docs_version }}{{ end }}</title>
{{ with .Params.robots -}}
<meta name="robots" content="{{ . }}">

View File

@ -1,9 +1,14 @@
<div class="bd-masthead mb-3" id="content">
<div class="container-xxl bd-gutter">
<div class="col-md-8 mx-auto text-center">
<a class="d-flex flex-column flex-lg-row justify-content-center align-items-center mb-4 text-dark lh-sm text-decoration-none" href="https://blog.getbootstrap.com/">
<strong class="d-sm-inline-block p-2 me-2 mb-2 mb-lg-0 rounded-3 masthead-notice">New in v5.3</strong>
<span class="text-body-secondary">Color mode support, expanded color palette, and more!</span>
<a class="d-flex flex-column flex-lg-row justify-content-center align-items-center mb-4 text-dark lh-sm text-decoration-none" href="https://www.herodevs.com/support/nes-bootstrap?utm_source=Bootstrap_site&utm_medium=Banner&utm_campaign=v3and4_eol">
<span class="d-sm-inline-flex align-items-center gap-1 py-2 px-3 me-2 mb-2 mb-lg-0 rounded-5 masthead-notice">
<span class="fw-semibold">
New!
</span>
Never-Ending Support for Bootstrap
<svg class="bi" style="width: 20px; height: 20px;"><use xlink:href="#arrow-right-short"></use></svg>
</span>
</a>
<img class="d-none d-sm-block mx-auto mb-3"
srcset="/docs/{{ .Site.Params.docs_version }}/assets/brand/bootstrap-logo-shadow.png,

View File

@ -2,6 +2,9 @@
<symbol id="arrow-right" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/>
</symbol>
<symbol id="arrow-right-short" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M4 8a.5.5 0 0 1 .5-.5h5.793L8.146 5.354a.5.5 0 1 1 .708-.708l3 3a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708-.708L10.293 8.5H4.5A.5.5 0 0 1 4 8"/>
</symbol>
<symbol id="book-half" viewBox="0 0 16 16">
<path d="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z"/>
</symbol>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,73 +1,40 @@
{{ if hugo.IsProduction -}}
<script src="/docs/{{ .Site.Params.docs_version }}/dist/js/bootstrap.bundle.min.js" {{ printf "integrity=%q" .Site.Params.cdn.js_bundle_hash | safeHTMLAttr }}></script>
<script defer src="/docs/{{ .Site.Params.docs_version }}/dist/js/bootstrap.bundle.min.js" {{ printf "integrity=%q" .Site.Params.cdn.js_bundle_hash | safeHTMLAttr }}></script>
{{ else -}}
<script src="/docs/{{ .Site.Params.docs_version }}/dist/js/bootstrap.bundle.js"></script>
<script defer src="/docs/{{ .Site.Params.docs_version }}/dist/js/bootstrap.bundle.js"></script>
{{- end }}
<script src="https://cdn.jsdelivr.net/npm/@docsearch/js@3"></script>
{{ if eq .Page.Layout "docs" -}}
<script src="https://cdn.jsdelivr.net/npm/@stackblitz/sdk@1/bundles/sdk.umd.js"></script>
{{- end }}
{{- $vendor := resources.Match "js/vendor/*.js" -}}
{{- $js := resources.Match "js/*.js" -}}
{{- $targetDocsJSPath := path.Join "/docs" .Site.Params.docs_version "assets/js/docs.js" -}}
{{- $docsJs := append $js $vendor | resources.Concat $targetDocsJSPath -}}
{{- $esbuildOptions := dict "target" "es2019" -}}
{{- $targetDocsJSPath := path.Join "/docs" .Site.Params.docs_version -}}
{{- if hugo.IsProduction -}}
{{- $docsJs = $docsJs | resources.Minify -}}
{{- $esbuildOptions = merge $esbuildOptions (dict "minify" "true") -}}
{{- end }}
<script src="{{ $docsJs.Permalink | relURL }}"></script>
{{- $applicationJs := resources.Get "js/application.js" | js.Build $esbuildOptions | resources.Copy (path.Join $targetDocsJSPath "/assets/js/application.js") }}
<script defer src="{{ $applicationJs.RelPermalink }}"></script>
{{- if (ne .Page.Layout "examples") -}}
{{- $esbuildParams := dict
"apiKey" .Site.Params.algolia.apiKey
"appId" .Site.Params.algolia.appId
"indexName" .Site.Params.algolia.indexName
-}}
{{- $esbuildOptions = merge $esbuildOptions (dict "params" $esbuildParams) -}}
{{- $searchJs := resources.Get "js/search.js" | js.Build $esbuildOptions | resources.Copy (path.Join $targetDocsJSPath "/assets/js/search.js") }}
<script defer src="{{ $searchJs.RelPermalink }}"></script>
{{- end -}}
{{ if eq .Page.Layout "docs" -}}
<script>
// Open in StackBlitz logic
document.querySelectorAll('.btn-edit').forEach(btn => {
btn.addEventListener('click', event => {
const htmlSnippet = event.target.closest('.bd-code-snippet').querySelector('.bd-example').innerHTML
// Get extra classes for this example
const classes = Array.from(event.target.closest('.bd-code-snippet').querySelector('.bd-example').classList).join(' ')
const jsSnippet = event.target.closest('.bd-code-snippet').querySelector('.btn-edit').getAttribute('data-sb-js-snippet')
StackBlitzSDK.openBootstrapSnippet(htmlSnippet, jsSnippet, classes)
})
})
StackBlitzSDK.openBootstrapSnippet = (htmlSnippet, jsSnippet, classes) => {
const markup = `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="{{ .Site.Params.cdn.css }}" rel="stylesheet">
<link href="https://getbootstrap.com/docs/{{ .Site.Params.docs_version }}/assets/css/docs.css" rel="stylesheet">
<title>Bootstrap Example</title>
<${'script'} src="{{ .Site.Params.cdn.js_bundle }}"></${'script'}>
</head>
<body class="p-3 m-0 border-0 ${classes}">
<!-- Example Code -->
${htmlSnippet.replace(/^/gm, ' ')}
<!-- End Example Code -->
</body>
</html>`
const jsSnippetContent = jsSnippet ? '{{ os.ReadFile "site/assets/js/snippets.js" }}' : null
const project = {
files: {
'index.html': markup,
'index.js': jsSnippetContent
},
title: 'Bootstrap Example',
description: `Official example from ${window.location.href}`,
template: jsSnippet ? 'javascript' : 'html',
tags: ['bootstrap']
}
StackBlitzSDK.openProject(project, { openFile: 'index.html' })
}
</script>
{{- end }}
{{- /* Disable minify options for snippets.js so that the file's readable on StackBlitz */ -}}
{{- $snippetsFile := resources.Get "js/snippets.js" | js.Build (merge $esbuildOptions (dict "minify" "false")) -}}
{{- $esbuildParams := dict
"cssCdn" .Site.Params.cdn.css
"jsBundleCdn" .Site.Params.cdn.js_bundle
"docsVersion" .Site.Params.docs_version
"jsSnippetFile" $snippetsFile.Content
-}}
{{- $esbuildOptions = merge $esbuildOptions (dict "params" $esbuildParams) -}}
{{- $stackblitzJs := resources.Get "js/stackblitz.js" | js.Build $esbuildOptions | resources.Copy (path.Join $targetDocsJSPath "/assets/js/stackblitz.js") }}
<script defer src="{{ $stackblitzJs.RelPermalink }}"></script>
{{- end -}}

View File

@ -1,5 +1,3 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3">
{{ if hugo.IsProduction -}}
{{ if eq .Page.Params.direction "rtl" -}}
<link href="/docs/{{ .Site.Params.docs_version }}/dist/css/bootstrap.rtl.min.css" rel="stylesheet" {{ printf "integrity=%q" .Site.Params.cdn.css_rtl_hash | safeHTMLAttr }}>
@ -11,15 +9,19 @@
{{- end }}
{{- if (ne .Page.Layout "examples") }}
{{- $targetDocsCssPath := path.Join "/docs" .Site.Params.docs_version "assets/css/docs.css" -}}
{{- $sassOptions := dict "transpiler" "dartsass" "targetPath" $targetDocsCssPath "outputStyle" "expanded" -}}
{{- $sassOptions := dict "transpiler" "dartsass" "outputStyle" "expanded" -}}
{{- $postcssOptions := dict "use" "autoprefixer" "noMap" true -}}
{{- $targetDocsCssPath := path.Join "/docs" .Site.Params.docs_version "assets/css/docs.css" -}}
{{- $targetSearchCssPath := path.Join "/docs" .Site.Params.docs_version "assets/css/search.css" -}}
{{ if hugo.IsProduction -}}
{{- $sassOptions = merge $sassOptions (dict "outputStyle" "compressed") -}}
{{- end -}}
{{- $style := resources.Get "scss/docs.scss" | toCSS $sassOptions | postCSS $postcssOptions }}
{{- $docsCss := resources.Get "scss/docs.scss" | toCSS (merge (dict "targetPath" $targetDocsCssPath) $sassOptions) | postCSS $postcssOptions -}}
{{- $searchCss := resources.Get "scss/search.scss" | toCSS (merge (dict "targetPath" $targetSearchCssPath) $sassOptions) | postCSS $postcssOptions -}}
<link href="{{ $style.Permalink | relURL }}" rel="stylesheet">
<link href="{{ $docsCss.RelPermalink }}" rel="stylesheet">
<link href="{{ $searchCss.RelPermalink }}" rel="stylesheet">
{{- end }}