diff --git a/.bundlewatch.config.json b/.bundlewatch.config.json
index da47da480..074066390 100644
--- a/.bundlewatch.config.json
+++ b/.bundlewatch.config.json
@@ -18,11 +18,11 @@
},
{
"path": "./dist/css/bootstrap-utilities.css",
- "maxSize": "7.5 kB"
+ "maxSize": "7 kB"
},
{
"path": "./dist/css/bootstrap-utilities.min.css",
- "maxSize": "6.75 kB"
+ "maxSize": "6.25 kB"
},
{
"path": "./dist/css/bootstrap.css",
diff --git a/.eslintrc.json b/.eslintrc.json
index d5a54d46b..ec6aa589c 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -43,14 +43,15 @@
],
"unicorn/consistent-function-scoping": "off",
"unicorn/explicit-length-check": "off",
- "unicorn/no-array-callback-reference": "off",
+ "unicorn/import-index": "off",
+ "unicorn/no-fn-reference-in-iterator": "off",
"unicorn/no-for-loop": "off",
"unicorn/no-null": "off",
"unicorn/no-unused-properties": "error",
"unicorn/no-useless-undefined": "off",
- "unicorn/prefer-dom-node-append": "off",
- "unicorn/prefer-dom-node-dataset": "off",
- "unicorn/prefer-dom-node-remove": "off",
+ "unicorn/prefer-dataset": "off",
+ "unicorn/prefer-node-append": "off",
+ "unicorn/prefer-node-remove": "off",
"unicorn/prefer-optional-catch-binding": "off",
"unicorn/prefer-query-selector": "off",
"unicorn/prevent-abbreviations": "off"
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 32b30cdb3..0913b5b5b 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -101,12 +101,12 @@ Example:
Sometimes bugs reported to us are actually caused by bugs in the browser(s) themselves, not bugs in Bootstrap per se.
-| Vendor(s) | Browser(s) | Rendering engine | Bug reporting website(s) | Notes |
-| ------------- | ---------------------------- | ---------------- | ------------------------------------------------------ | -------------------------------------------------------- |
-| Mozilla | Firefox | Gecko | https://bugzilla.mozilla.org/enter_bug.cgi | "Core" is normally the right product option to choose. |
-| Apple | Safari | WebKit | https://bugs.webkit.org/enter_bug.cgi?product=WebKit | In Apple's bug reporter, choose "Safari" as the product. |
-| Google, Opera | Chrome, Chromium, Opera v15+ | Blink | https://bugs.chromium.org/p/chromium/issues/list | Click the "New issue" button. |
-| Microsoft | Edge | Blink | https://developer.microsoft.com/en-us/microsoft-edge/ | Go to "Help > Send Feedback" from the browser |
+| Vendor(s) | Browser(s) | Rendering engine | Bug reporting website(s) | Notes |
+| ------------- | ---------------------------- | ---------------- | --------------------------------------------------------------------- | -------------------------------------------------------- |
+| Mozilla | Firefox | Gecko | https://bugzilla.mozilla.org/enter_bug.cgi | "Core" is normally the right product option to choose. |
+| Apple | Safari | WebKit | https://bugs.webkit.org/enter_bug.cgi?product=WebKit | In Apple's bug reporter, choose "Safari" as the product. |
+| Google, Opera | Chrome, Chromium, Opera v15+ | Blink | https://bugs.chromium.org/p/chromium/issues/list | Click the "New issue" button. |
+| Microsoft | Edge | Blink | https://developer.microsoft.com/en-us/microsoft-edge/ | Go to "Help > Send Feedback" from the browser |
## Feature requests
@@ -134,9 +134,9 @@ Please adhere to the [coding guidelines](#code-guidelines) used throughout the
project (indentation, accurate comments, etc.) and any other requirements
(such as test coverage).
-**Do not edit `bootstrap.css` or `bootstrap.js`, and do not commit
-any dist files (`dist/` or `js/dist`).** Those files are automatically generated by our build tools. You should
-edit the source files in [`/bootstrap/scss/`](https://github.com/twbs/bootstrap/tree/main/scss)
+**Do not edit `bootstrap.css`, or `bootstrap.js`
+directly!** Those files are automatically generated. You should edit the
+source files in [`/bootstrap/scss/`](https://github.com/twbs/bootstrap/tree/main/scss)
and/or [`/bootstrap/js/src/`](https://github.com/twbs/bootstrap/tree/main/js/src) instead.
Similarly, when contributing to Bootstrap's documentation, you should edit the
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 29135b400..31976021e 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -15,10 +15,3 @@ updates:
- v5
versioning-strategy: increase
rebase-strategy: disabled
- - package-ecosystem: "github-actions"
- directory: "/"
- schedule:
- interval: weekly
- day: tuesday
- time: "12:00"
- timezone: Europe/Athens
diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml
index e2b70e03e..ae1367c89 100644
--- a/.github/release-drafter.yml
+++ b/.github/release-drafter.yml
@@ -4,9 +4,6 @@ prerelease: true
exclude-labels:
- 'skip-changelog'
categories:
- - title: '❗ Breaking Changes'
- labels:
- - 'breaking-change'
- title: '🚀 Features'
labels:
- 'new-feature'
@@ -17,9 +14,6 @@ categories:
- 'fix'
- 'bugfix'
- 'bug'
- - title: '⚡ Performance Improvements'
- labels:
- - 'performance'
- title: '🎨 CSS'
labels:
- 'css'
@@ -32,19 +26,11 @@ categories:
- title: '🌎 Accessibility'
labels:
- 'accessibility'
- - title: '🔧 Utility API'
- labels:
- - 'utility API'
- - 'utilities'
- - title: '🏭 Tests'
- labels:
- - 'tests'
- title: '🧰 Misc'
labels:
- 'build'
- 'meta'
- 'chore'
- - 'CI'
- title: '📦 Dependencies'
labels:
- 'dependencies'
diff --git a/.github/workflows/browserstack.yml b/.github/workflows/browserstack.yml
index a12bffcf7..0b4cfbdaa 100644
--- a/.github/workflows/browserstack.yml
+++ b/.github/workflows/browserstack.yml
@@ -4,21 +4,21 @@ on:
push:
env:
+ CI: true
FORCE_COLOR: 2
- NODE: 14
+ NODE: 14.x
jobs:
browserstack:
runs-on: ubuntu-latest
if: github.repository == 'twbs/bootstrap' && (!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]'))
- timeout-minutes: 30
steps:
- name: Clone repository
uses: actions/checkout@v2
- name: Set up Node.js
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE }}"
@@ -28,8 +28,8 @@ jobs:
path: ~/.npm
key: ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
- ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
- ${{ runner.os }}-node-v${{ env.NODE }}-
+ ${{ runner.OS }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
+ ${{ runner.OS }}-node-v${{ env.NODE }}-
- name: Install npm dependencies
run: npm ci
diff --git a/.github/workflows/bundlewatch.yml b/.github/workflows/bundlewatch.yml
index b2bd5eed5..966dfbf72 100644
--- a/.github/workflows/bundlewatch.yml
+++ b/.github/workflows/bundlewatch.yml
@@ -7,8 +7,9 @@ on:
pull_request:
env:
+ CI: true
FORCE_COLOR: 2
- NODE: 14
+ NODE: 14.x
jobs:
bundlewatch:
@@ -19,7 +20,7 @@ jobs:
uses: actions/checkout@v2
- name: Set up Node.js
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE }}"
@@ -29,8 +30,8 @@ jobs:
path: ~/.npm
key: ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
- ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
- ${{ runner.os }}-node-v${{ env.NODE }}-
+ ${{ runner.OS }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
+ ${{ runner.OS }}-node-v${{ env.NODE }}-
- name: Install npm dependencies
run: npm ci
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 469a5a4fc..f9dccfce0 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -22,6 +22,15 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
+ with:
+ # We must fetch at least the immediate parents so that if this is
+ # a pull request then we can checkout the head.
+ fetch-depth: 2
+
+ # If this run was triggered by a pull request event, then checkout
+ # the head of the pull request instead of the merge commit.
+ - run: git checkout HEAD^2
+ if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
diff --git a/.github/workflows/css.yml b/.github/workflows/css.yml
index a28059d79..a75f018c5 100644
--- a/.github/workflows/css.yml
+++ b/.github/workflows/css.yml
@@ -7,8 +7,9 @@ on:
pull_request:
env:
+ CI: true
FORCE_COLOR: 2
- NODE: 14
+ NODE: 14.x
jobs:
css:
@@ -19,7 +20,7 @@ jobs:
uses: actions/checkout@v2
- name: Set up Node.js
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE }}"
@@ -29,8 +30,8 @@ jobs:
path: ~/.npm
key: ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
- ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
- ${{ runner.os }}-node-v${{ env.NODE }}-
+ ${{ runner.OS }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
+ ${{ runner.OS }}-node-v${{ env.NODE }}-
- name: Install npm dependencies
run: npm ci
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 150e4d16c..58b55fc7c 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -7,8 +7,9 @@ on:
pull_request:
env:
+ CI: true
FORCE_COLOR: 2
- NODE: 14
+ NODE: 14.x
jobs:
docs:
@@ -19,7 +20,7 @@ jobs:
uses: actions/checkout@v2
- name: Set up Node.js
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE }}"
@@ -31,8 +32,8 @@ jobs:
path: ~/.npm
key: ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
- ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
- ${{ runner.os }}-node-v${{ env.NODE }}-
+ ${{ runner.OS }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
+ ${{ runner.OS }}-node-v${{ env.NODE }}-
- name: Install npm dependencies
run: npm ci
diff --git a/.github/workflows/js.yml b/.github/workflows/js.yml
index c56a2dfdd..1ec0d6909 100644
--- a/.github/workflows/js.yml
+++ b/.github/workflows/js.yml
@@ -7,6 +7,7 @@ on:
pull_request:
env:
+ CI: true
FORCE_COLOR: 2
jobs:
@@ -24,7 +25,7 @@ jobs:
uses: actions/checkout@v2
- name: Set up Node.js
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}
@@ -34,8 +35,8 @@ jobs:
path: ~/.npm
key: ${{ runner.os }}-node-v${{ matrix.node }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}}
restore-keys: |
- ${{ runner.os }}-node-v${{ matrix.node }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
- ${{ runner.os }}-node-v${{ matrix.node }}-
+ ${{ runner.OS }}-node-v${{ matrix.node }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
+ ${{ runner.OS }}-node-v${{ matrix.node }}-
- name: Install npm dependencies
run: npm ci
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 369aaced3..e850a1f1b 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -7,8 +7,9 @@ on:
pull_request:
env:
+ CI: true
FORCE_COLOR: 2
- NODE: 14
+ NODE: 14.x
jobs:
lint:
@@ -19,7 +20,7 @@ jobs:
uses: actions/checkout@v2
- name: Set up Node.js
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE }}"
@@ -29,8 +30,8 @@ jobs:
path: ~/.npm
key: ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
- ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
- ${{ runner.os }}-node-v${{ env.NODE }}-
+ ${{ runner.OS }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}
+ ${{ runner.OS }}-node-v${{ env.NODE }}-
- name: Install npm dependencies
run: npm ci
diff --git a/.github/workflows/node-sass.yml b/.github/workflows/node-sass.yml
index ee64b2152..2db55f0ff 100644
--- a/.github/workflows/node-sass.yml
+++ b/.github/workflows/node-sass.yml
@@ -7,8 +7,9 @@ on:
pull_request:
env:
+ CI: true
FORCE_COLOR: 2
- NODE: 14
+ NODE: 14.x
jobs:
css:
@@ -19,7 +20,7 @@ jobs:
uses: actions/checkout@v2
- name: Set up Node.js
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v1
with:
node-version: "${{ env.NODE }}"
diff --git a/.gitignore b/.gitignore
index 0a0f88d15..6208c57d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,19 @@
# Ignore docs files
/_gh_pages/
+# This is the old Jekyll docs dist folder;
+# keeping it here so that when we switch branches it doesn't show up
+/site/docs/**/dist/
+# Jekyll's cache folder; keeping it for the same reason as above
+/site/.jekyll-cache/
# Hugo resources folder
/resources/
+# Ignore ruby/bundler files;
+# keeping them here so that when we switch branches they don't show up
+/.bundle/
+/vendor/
+/.ruby-version
+
# Numerous always-ignore extensions
*.diff
*.err
diff --git a/.stylelintrc b/.stylelintrc
index c068d30b5..1c9ee1811 100644
--- a/.stylelintrc
+++ b/.stylelintrc
@@ -3,10 +3,6 @@
"stylelint-config-twbs-bootstrap/scss"
],
"rules": {
- "declaration-property-value-disallowed-list": {
- "border": "none",
- "outline": "none"
- },
"function-disallowed-list": [
"calc",
"lighten",
diff --git a/LICENSE b/LICENSE
index 72dda234e..173a9ebbb 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
The MIT License (MIT)
-Copyright (c) 2011-2021 Twitter, Inc.
-Copyright (c) 2011-2021 The Bootstrap Authors
+Copyright (c) 2011-2020 Twitter, Inc.
+Copyright (c) 2011-2020 The Bootstrap Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index f41498691..8a470260a 100644
--- a/README.md
+++ b/README.md
@@ -236,4 +236,4 @@ Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com
## Copyright and license
-Code and documentation copyright 2011–2021 the [Bootstrap Authors](https://github.com/twbs/bootstrap/graphs/contributors) and [Twitter, Inc.](https://twitter.com) Code released under the [MIT License](https://github.com/twbs/bootstrap/blob/main/LICENSE). Docs released under [Creative Commons](https://creativecommons.org/licenses/by/3.0/).
+Code and documentation copyright 2011–2020 the [Bootstrap Authors](https://github.com/twbs/bootstrap/graphs/contributors) and [Twitter, Inc.](https://twitter.com) Code released under the [MIT License](https://github.com/twbs/bootstrap/blob/main/LICENSE). Docs released under [Creative Commons](https://creativecommons.org/licenses/by/3.0/).
diff --git a/build/build-plugins.js b/build/build-plugins.js
index d1930b855..ea7477390 100644
--- a/build/build-plugins.js
+++ b/build/build-plugins.js
@@ -2,8 +2,8 @@
/*!
* Script to build our plugins to use them separately.
- * Copyright 2020-2021 The Bootstrap Authors
- * Copyright 2020-2021 Twitter, Inc.
+ * Copyright 2020 The Bootstrap Authors
+ * Copyright 2020 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
@@ -29,7 +29,6 @@ const bsPlugins = {
Manipulator: path.resolve(__dirname, '../js/src/dom/manipulator.js'),
SelectorEngine: path.resolve(__dirname, '../js/src/dom/selector-engine.js'),
Alert: path.resolve(__dirname, '../js/src/alert.js'),
- Base: path.resolve(__dirname, '../js/src/base-component.js'),
Button: path.resolve(__dirname, '../js/src/button.js'),
Carousel: path.resolve(__dirname, '../js/src/carousel.js'),
Collapse: path.resolve(__dirname, '../js/src/collapse.js'),
@@ -45,13 +44,11 @@ const bsPlugins = {
const defaultPluginConfig = {
external: [
bsPlugins.Data,
- bsPlugins.Base,
bsPlugins.EventHandler,
bsPlugins.SelectorEngine
],
globals: {
[bsPlugins.Data]: 'Data',
- [bsPlugins.Base]: 'Base',
[bsPlugins.EventHandler]: 'EventHandler',
[bsPlugins.SelectorEngine]: 'SelectorEngine'
}
@@ -76,7 +73,6 @@ const getConfigByPluginKey = pluginKey => {
}
if (
- pluginKey === 'Base' ||
pluginKey === 'Button' ||
pluginKey === 'Carousel' ||
pluginKey === 'Collapse' ||
@@ -116,13 +112,11 @@ const getConfigByPluginKey = pluginKey => {
return {
external: [
bsPlugins.Data,
- bsPlugins.Base,
bsPlugins.EventHandler,
bsPlugins.Manipulator
],
globals: {
[bsPlugins.Data]: 'Data',
- [bsPlugins.Base]: 'Base',
[bsPlugins.EventHandler]: 'EventHandler',
[bsPlugins.Manipulator]: 'Manipulator'
}
diff --git a/build/change-version.js b/build/change-version.js
index 8086ed774..b8a640fa8 100644
--- a/build/change-version.js
+++ b/build/change-version.js
@@ -2,8 +2,8 @@
/*!
* Script to update version number references in the project.
- * Copyright 2017-2021 The Bootstrap Authors
- * Copyright 2017-2021 Twitter, Inc.
+ * Copyright 2017-2020 The Bootstrap Authors
+ * Copyright 2017-2020 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
diff --git a/build/generate-sri.js b/build/generate-sri.js
index 221873b8f..8a2e59360 100644
--- a/build/generate-sri.js
+++ b/build/generate-sri.js
@@ -5,8 +5,8 @@
* Remember to use the same vendor files as the CDN ones,
* otherwise the hashes won't match!
*
- * Copyright 2017-2021 The Bootstrap Authors
- * Copyright 2017-2021 Twitter, Inc.
+ * Copyright 2017-2020 The Bootstrap Authors
+ * Copyright 2017-2020 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
diff --git a/build/vnu-jar.js b/build/vnu-jar.js
index c23b94d60..90c1a12ab 100644
--- a/build/vnu-jar.js
+++ b/build/vnu-jar.js
@@ -2,8 +2,8 @@
/*!
* Script to run vnu-jar if Java is available.
- * Copyright 2017-2021 The Bootstrap Authors
- * Copyright 2017-2021 Twitter, Inc.
+ * Copyright 2017-2020 The Bootstrap Authors
+ * Copyright 2017-2020 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
diff --git a/build/zip-examples.js b/build/zip-examples.js
index b2f156502..bf50a0af6 100644
--- a/build/zip-examples.js
+++ b/build/zip-examples.js
@@ -3,7 +3,7 @@
/*!
* Script to create the built examples zip archive;
* requires the `zip` command to be present!
- * Copyright 2020-2021 The Bootstrap Authors
+ * Copyright 2020 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
@@ -12,67 +12,36 @@
const path = require('path')
const sh = require('shelljs')
-const pkg = require('../package.json')
+const { version, version_short: versionShort } = require('../package.json')
-const versionShort = pkg.config.version_short
-const distFolder = `bootstrap-${pkg.version}-examples`
-const rootDocsDir = '_gh_pages'
-const docsDir = `${rootDocsDir}/docs/${versionShort}/`
-
-// these are the files we need in the examples
-const cssFiles = [
- 'bootstrap.min.css',
- 'bootstrap.min.css.map',
- 'bootstrap.rtl.min.css',
- 'bootstrap.rtl.min.css.map'
-]
-const jsFiles = [
- 'bootstrap.bundle.min.js',
- 'bootstrap.bundle.min.js.map'
-]
-const imgFiles = [
- 'bootstrap-logo.svg',
- 'bootstrap-logo-white.svg'
-]
+const folderName = `bootstrap-${version}-examples`
sh.config.fatal = true
-if (!sh.test('-d', rootDocsDir)) {
- throw new Error(`The "${rootDocsDir}" folder does not exist, did you forget building the docs?`)
+if (!sh.test('-d', '_gh_pages')) {
+ throw new Error('The "_gh_pages" folder does not exist, did you forget building the docs?')
}
// switch to the root dir
sh.cd(path.join(__dirname, '..'))
-// remove any previously created folder/zip with the same name
-sh.rm('-rf', [distFolder, `${distFolder}.zip`])
-
+// remove any previously created folder with the same name
+sh.rm('-rf', folderName)
// create any folders so that `cp` works
-sh.mkdir('-p', [
- distFolder,
- `${distFolder}/assets/brand/`,
- `${distFolder}/assets/dist/css/`,
- `${distFolder}/assets/dist/js/`
-])
+sh.mkdir('-p', folderName)
+sh.mkdir('-p', `${folderName}/assets/brand/`)
-sh.cp('-Rf', `${docsDir}/examples/*`, distFolder)
-
-cssFiles.forEach(file => {
- sh.cp('-f', `${docsDir}/dist/css/${file}`, `${distFolder}/assets/dist/css/`)
-})
-
-jsFiles.forEach(file => {
- sh.cp('-f', `${docsDir}/dist/js/${file}`, `${distFolder}/assets/dist/js/`)
-})
-
-imgFiles.forEach(file => {
- sh.cp('-f', `${docsDir}/assets/brand/${file}`, `${distFolder}/assets/brand/`)
-})
-
-sh.rm(`${distFolder}/index.html`)
+sh.cp('-Rf', `_gh_pages/docs/${versionShort}/examples/*`, folderName)
+sh.cp('-Rf', `_gh_pages/docs/${versionShort}/dist/`, `${folderName}/assets/`)
+// also copy the two brand images we use in the examples
+sh.cp('-f', [
+ `_gh_pages/docs/${versionShort}/assets/brand/bootstrap-logo.svg`,
+ `_gh_pages/docs/${versionShort}/assets/brand/bootstrap-logo-white.svg`
+], `${folderName}/assets/brand/`)
+sh.rm(`${folderName}/index.html`)
// get all examples' HTML files
-sh.find(`${distFolder}/**/*.html`).forEach(file => {
+sh.find(`${folderName}/**/*.html`).forEach(file => {
const fileContents = sh.cat(file)
.toString()
.replace(new RegExp(`"/docs/${versionShort}/`, 'g'), '"../')
@@ -84,7 +53,7 @@ sh.find(`${distFolder}/**/*.html`).forEach(file => {
})
// create the zip file
-sh.exec(`zip -r9 "${distFolder}.zip" "${distFolder}"`)
+sh.exec(`zip -r9 "${folderName}.zip" "${folderName}"`, { fatal: true })
// remove the folder we created
-sh.rm('-rf', distFolder)
+sh.rm('-rf', folderName)
diff --git a/config.yml b/config.yml
index a54d5bc6c..616993e15 100644
--- a/config.yml
+++ b/config.yml
@@ -75,5 +75,5 @@ params:
js_hash: "sha384-pQQkAEnwaBkjpqZ8RU1fF1AKtTcHJwFl3pblpTlHXybJjHpMYo79HY3hIi4NKxyj"
js_bundle: "https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"
js_bundle_hash: "sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW"
- popper: "https://cdn.jsdelivr.net/npm/@popperjs/core@2.6.0/dist/umd/popper.min.js"
- popper_hash: "sha384-KsvD1yqQ1/1+IA7gi3P0tyJcT3vR+NdBTt13hSJ2lnve8agRGXTTyNaBYmCR/Nwi"
+ popper: "https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"
+ popper_hash: "sha384-q2kxQ16AaE6UbzuKqyBE9/u/KzioAlnx2maXQHiDX9d4/zp8Ok3f+M7DPm+Ib6IU"
diff --git a/js/src/alert.js b/js/src/alert.js
index 96eda4c5f..e498d0324 100644
--- a/js/src/alert.js
+++ b/js/src/alert.js
@@ -7,6 +7,7 @@
import {
defineJQueryPlugin,
+ TRANSITION_END,
emulateTransitionEnd,
getElementFromSelector,
getTransitionDurationFromElement
@@ -32,9 +33,9 @@ const EVENT_CLOSE = `close${EVENT_KEY}`
const EVENT_CLOSED = `closed${EVENT_KEY}`
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
-const CLASS_NAME_ALERT = 'alert'
-const CLASS_NAME_FADE = 'fade'
-const CLASS_NAME_SHOW = 'show'
+const CLASSNAME_ALERT = 'alert'
+const CLASSNAME_FADE = 'fade'
+const CLASSNAME_SHOW = 'show'
/**
* ------------------------------------------------------------------------
@@ -65,7 +66,7 @@ class Alert extends BaseComponent {
// Private
_getRootElement(element) {
- return getElementFromSelector(element) || element.closest(`.${CLASS_NAME_ALERT}`)
+ return getElementFromSelector(element) || element.closest(`.${CLASSNAME_ALERT}`)
}
_triggerCloseEvent(element) {
@@ -73,16 +74,16 @@ class Alert extends BaseComponent {
}
_removeElement(element) {
- element.classList.remove(CLASS_NAME_SHOW)
+ element.classList.remove(CLASSNAME_SHOW)
- if (!element.classList.contains(CLASS_NAME_FADE)) {
+ if (!element.classList.contains(CLASSNAME_FADE)) {
this._destroyElement(element)
return
}
const transitionDuration = getTransitionDurationFromElement(element)
- EventHandler.one(element, 'transitionend', () => this._destroyElement(element))
+ EventHandler.one(element, TRANSITION_END, () => this._destroyElement(element))
emulateTransitionEnd(element, transitionDuration)
}
diff --git a/js/src/carousel.js b/js/src/carousel.js
index 06a391419..299aadeda 100644
--- a/js/src/carousel.js
+++ b/js/src/carousel.js
@@ -7,11 +7,11 @@
import {
defineJQueryPlugin,
+ TRANSITION_END,
emulateTransitionEnd,
getElementFromSelector,
getTransitionDurationFromElement,
isVisible,
- isRTL,
reflow,
triggerTransitionEnd,
typeCheckConfig
@@ -93,8 +93,10 @@ const SELECTOR_INDICATORS = '.carousel-indicators'
const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'
const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]'
-const POINTER_TYPE_TOUCH = 'touch'
-const POINTER_TYPE_PEN = 'pen'
+const PointerType = {
+ TOUCH: 'touch',
+ PEN: 'pen'
+}
/**
* ------------------------------------------------------------------------
@@ -251,20 +253,12 @@ class Carousel extends BaseComponent {
// swipe left
if (direction > 0) {
- if (isRTL) {
- this.next()
- } else {
- this.prev()
- }
+ this.prev()
}
// swipe right
if (direction < 0) {
- if (isRTL) {
- this.prev()
- } else {
- this.next()
- }
+ this.next()
}
}
@@ -285,7 +279,7 @@ class Carousel extends BaseComponent {
_addTouchEventListeners() {
const start = event => {
- if (this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)) {
+ if (this._pointerEvent && PointerType[event.pointerType.toUpperCase()]) {
this.touchStartX = event.clientX
} else if (!this._pointerEvent) {
this.touchStartX = event.touches[0].clientX
@@ -302,7 +296,7 @@ class Carousel extends BaseComponent {
}
const end = event => {
- if (this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)) {
+ if (this._pointerEvent && PointerType[event.pointerType.toUpperCase()]) {
this.touchDeltaX = event.clientX - this.touchStartX
}
@@ -346,20 +340,16 @@ class Carousel extends BaseComponent {
return
}
- if (event.key === ARROW_LEFT_KEY) {
- event.preventDefault()
- if (isRTL) {
- this.next()
- } else {
+ switch (event.key) {
+ case ARROW_LEFT_KEY:
+ event.preventDefault()
this.prev()
- }
- } else if (event.key === ARROW_RIGHT_KEY) {
- event.preventDefault()
- if (isRTL) {
- this.prev()
- } else {
+ break
+ case ARROW_RIGHT_KEY:
+ event.preventDefault()
this.next()
- }
+ break
+ default:
}
}
@@ -446,9 +436,19 @@ class Carousel extends BaseComponent {
const nextElementIndex = this._getItemIndex(nextElement)
const isCycling = Boolean(this._interval)
- const directionalClassName = direction === DIRECTION_NEXT ? CLASS_NAME_START : CLASS_NAME_END
- const orderClassName = direction === DIRECTION_NEXT ? CLASS_NAME_NEXT : CLASS_NAME_PREV
- const eventDirectionName = direction === DIRECTION_NEXT ? DIRECTION_LEFT : DIRECTION_RIGHT
+ let directionalClassName
+ let orderClassName
+ let eventDirectionName
+
+ if (direction === DIRECTION_NEXT) {
+ directionalClassName = CLASS_NAME_START
+ orderClassName = CLASS_NAME_NEXT
+ eventDirectionName = DIRECTION_LEFT
+ } else {
+ directionalClassName = CLASS_NAME_END
+ orderClassName = CLASS_NAME_PREV
+ eventDirectionName = DIRECTION_RIGHT
+ }
if (nextElement && nextElement.classList.contains(CLASS_NAME_ACTIVE)) {
this._isSliding = false
@@ -484,7 +484,7 @@ class Carousel extends BaseComponent {
const transitionDuration = getTransitionDurationFromElement(activeElement)
- EventHandler.one(activeElement, 'transitionend', () => {
+ EventHandler.one(activeElement, TRANSITION_END, () => {
nextElement.classList.remove(directionalClassName, orderClassName)
nextElement.classList.add(CLASS_NAME_ACTIVE)
diff --git a/js/src/collapse.js b/js/src/collapse.js
index 0d3eeed54..590615b72 100644
--- a/js/src/collapse.js
+++ b/js/src/collapse.js
@@ -7,6 +7,7 @@
import {
defineJQueryPlugin,
+ TRANSITION_END,
emulateTransitionEnd,
getSelectorFromElement,
getElementFromSelector,
@@ -202,7 +203,7 @@ class Collapse extends BaseComponent {
const scrollSize = `scroll${capitalizedDimension}`
const transitionDuration = getTransitionDurationFromElement(this._element)
- EventHandler.one(this._element, 'transitionend', complete)
+ EventHandler.one(this._element, TRANSITION_END, complete)
emulateTransitionEnd(this._element, transitionDuration)
this._element.style[dimension] = `${this._element[scrollSize]}px`
@@ -252,7 +253,7 @@ class Collapse extends BaseComponent {
this._element.style[dimension] = ''
const transitionDuration = getTransitionDurationFromElement(this._element)
- EventHandler.one(this._element, 'transitionend', complete)
+ EventHandler.one(this._element, TRANSITION_END, complete)
emulateTransitionEnd(this._element, transitionDuration)
}
@@ -371,7 +372,7 @@ class Collapse extends BaseComponent {
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
// preventDefault only for elements (which change the URL) not inside the collapsible element
- if (event.target.tagName === 'A' || (event.delegateTarget && event.delegateTarget.tagName === 'A')) {
+ if (event.target.tagName === 'A') {
event.preventDefault()
}
diff --git a/js/src/dom/event-handler.js b/js/src/dom/event-handler.js
index e3c685530..2ee13bafc 100644
--- a/js/src/dom/event-handler.js
+++ b/js/src/dom/event-handler.js
@@ -112,7 +112,6 @@ function bootstrapDelegationHandler(element, selector, fn) {
event.delegateTarget = target
if (handler.oneOff) {
- // eslint-disable-next-line unicorn/consistent-destructuring
EventHandler.off(element, event.type, fn)
}
diff --git a/js/src/dom/selector-engine.js b/js/src/dom/selector-engine.js
index 28287388e..727df7518 100644
--- a/js/src/dom/selector-engine.js
+++ b/js/src/dom/selector-engine.js
@@ -23,8 +23,9 @@ const SelectorEngine = {
},
children(element, selector) {
- return [].concat(...element.children)
- .filter(child => child.matches(selector))
+ const children = [].concat(...element.children)
+
+ return children.filter(child => child.matches(selector))
},
parents(element, selector) {
diff --git a/js/src/dropdown.js b/js/src/dropdown.js
index bada537c9..4720ed1ab 100644
--- a/js/src/dropdown.js
+++ b/js/src/dropdown.js
@@ -84,7 +84,7 @@ const DefaultType = {
offset: '(number|string|function)',
flip: 'boolean',
boundary: '(string|element)',
- reference: '(string|element|object)',
+ reference: '(string|element)',
display: 'string',
popperConfig: '(null|object)'
}
@@ -172,8 +172,6 @@ class Dropdown extends BaseComponent {
if (typeof this._config.reference.jquery !== 'undefined') {
referenceElement = this._config.reference[0]
}
- } else if (typeof this._config.reference === 'object') {
- referenceElement = this._config.reference
}
this._popper = Popper.createPopper(referenceElement, this._menu, this._getPopperConfig())
@@ -259,13 +257,6 @@ class Dropdown extends BaseComponent {
typeCheckConfig(NAME, config, this.constructor.DefaultType)
- if (typeof config.reference === 'object' && !isElement(config.reference) &&
- typeof config.reference.getBoundingClientRect !== 'function'
- ) {
- // Popper virtual elements require a getBoundingClientRect method
- throw new TypeError(`${NAME.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`)
- }
-
return config
}
@@ -307,12 +298,6 @@ class Dropdown extends BaseComponent {
altBoundary: this._config.flip,
rootBoundary: this._config.boundary
}
- },
- {
- name: 'flip',
- options: {
- fallbackPlacements: ['top', 'right', 'bottom', 'left']
- }
}]
}
diff --git a/js/src/modal.js b/js/src/modal.js
index fe1b5a4c6..20fb215c6 100644
--- a/js/src/modal.js
+++ b/js/src/modal.js
@@ -7,6 +7,7 @@
import {
defineJQueryPlugin,
+ TRANSITION_END,
emulateTransitionEnd,
getElementFromSelector,
getTransitionDurationFromElement,
@@ -183,7 +184,7 @@ class Modal extends BaseComponent {
if (transition) {
const transitionDuration = getTransitionDurationFromElement(this._element)
- EventHandler.one(this._element, 'transitionend', event => this._hideModal(event))
+ EventHandler.one(this._element, TRANSITION_END, event => this._hideModal(event))
emulateTransitionEnd(this._element, transitionDuration)
} else {
this._hideModal()
@@ -271,7 +272,7 @@ class Modal extends BaseComponent {
if (transition) {
const transitionDuration = getTransitionDurationFromElement(this._dialog)
- EventHandler.one(this._dialog, 'transitionend', transitionComplete)
+ EventHandler.one(this._dialog, TRANSITION_END, transitionComplete)
emulateTransitionEnd(this._dialog, transitionDuration)
} else {
transitionComplete()
@@ -376,7 +377,7 @@ class Modal extends BaseComponent {
const backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop)
- EventHandler.one(this._backdrop, 'transitionend', callback)
+ EventHandler.one(this._backdrop, TRANSITION_END, callback)
emulateTransitionEnd(this._backdrop, backdropTransitionDuration)
} else if (!this._isShown && this._backdrop) {
this._backdrop.classList.remove(CLASS_NAME_SHOW)
@@ -388,7 +389,7 @@ class Modal extends BaseComponent {
if (this._element.classList.contains(CLASS_NAME_FADE)) {
const backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop)
- EventHandler.one(this._backdrop, 'transitionend', callbackRemove)
+ EventHandler.one(this._backdrop, TRANSITION_END, callbackRemove)
emulateTransitionEnd(this._backdrop, backdropTransitionDuration)
} else {
callbackRemove()
@@ -412,11 +413,11 @@ class Modal extends BaseComponent {
this._element.classList.add(CLASS_NAME_STATIC)
const modalTransitionDuration = getTransitionDurationFromElement(this._dialog)
- EventHandler.off(this._element, 'transitionend')
- EventHandler.one(this._element, 'transitionend', () => {
+ EventHandler.off(this._element, TRANSITION_END)
+ EventHandler.one(this._element, TRANSITION_END, () => {
this._element.classList.remove(CLASS_NAME_STATIC)
if (!isModalOverflowing) {
- EventHandler.one(this._element, 'transitionend', () => {
+ EventHandler.one(this._element, TRANSITION_END, () => {
this._element.style.overflowY = ''
})
emulateTransitionEnd(this._element, modalTransitionDuration)
@@ -590,7 +591,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
data = new Modal(target, config)
}
- data.toggle(this)
+ data.show(this)
})
/**
diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js
index baea49443..a8770ef08 100644
--- a/js/src/scrollspy.js
+++ b/js/src/scrollspy.js
@@ -76,7 +76,7 @@ class ScrollSpy extends BaseComponent {
this._activeTarget = null
this._scrollHeight = 0
- EventHandler.on(this._scrollElement, EVENT_SCROLL, () => this._process())
+ EventHandler.on(this._scrollElement, EVENT_SCROLL, event => this._process(event))
this.refresh()
this._process()
diff --git a/js/src/tab.js b/js/src/tab.js
index f1b17ac79..3a48986c4 100644
--- a/js/src/tab.js
+++ b/js/src/tab.js
@@ -7,6 +7,7 @@
import {
defineJQueryPlugin,
+ TRANSITION_END,
emulateTransitionEnd,
getElementFromSelector,
getTransitionDurationFromElement,
@@ -81,11 +82,13 @@ class Tab extends BaseComponent {
previous = previous[previous.length - 1]
}
- const hideEvent = previous ?
- EventHandler.trigger(previous, EVENT_HIDE, {
+ let hideEvent = null
+
+ if (previous) {
+ hideEvent = EventHandler.trigger(previous, EVENT_HIDE, {
relatedTarget: this._element
- }) :
- null
+ })
+ }
const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, {
relatedTarget: previous
@@ -129,7 +132,7 @@ class Tab extends BaseComponent {
const transitionDuration = getTransitionDurationFromElement(active)
active.classList.remove(CLASS_NAME_SHOW)
- EventHandler.one(active, 'transitionend', complete)
+ EventHandler.one(active, TRANSITION_END, complete)
emulateTransitionEnd(active, transitionDuration)
} else {
complete()
diff --git a/js/src/toast.js b/js/src/toast.js
index e277cdc06..bda152af6 100644
--- a/js/src/toast.js
+++ b/js/src/toast.js
@@ -7,6 +7,7 @@
import {
defineJQueryPlugin,
+ TRANSITION_END,
emulateTransitionEnd,
getTransitionDurationFromElement,
reflow,
@@ -115,7 +116,7 @@ class Toast extends BaseComponent {
if (this._config.animation) {
const transitionDuration = getTransitionDurationFromElement(this._element)
- EventHandler.one(this._element, 'transitionend', complete)
+ EventHandler.one(this._element, TRANSITION_END, complete)
emulateTransitionEnd(this._element, transitionDuration)
} else {
complete()
@@ -142,7 +143,7 @@ class Toast extends BaseComponent {
if (this._config.animation) {
const transitionDuration = getTransitionDurationFromElement(this._element)
- EventHandler.one(this._element, 'transitionend', complete)
+ EventHandler.one(this._element, TRANSITION_END, complete)
emulateTransitionEnd(this._element, transitionDuration)
} else {
complete()
diff --git a/js/src/tooltip.js b/js/src/tooltip.js
index 63a30cf2f..df0f0c19c 100644
--- a/js/src/tooltip.js
+++ b/js/src/tooltip.js
@@ -9,6 +9,7 @@ import * as Popper from '@popperjs/core'
import {
defineJQueryPlugin,
+ TRANSITION_END,
emulateTransitionEnd,
findShadowRoot,
getTransitionDurationFromElement,
@@ -51,7 +52,7 @@ const DefaultType = {
selector: '(string|boolean)',
placement: '(string|function)',
container: '(string|element|boolean)',
- fallbackPlacements: 'array',
+ fallbackPlacements: '(null|array)',
boundary: '(string|element)',
customClass: '(string|function)',
sanitize: 'boolean',
@@ -81,7 +82,7 @@ const Default = {
selector: false,
placement: 'top',
container: false,
- fallbackPlacements: ['top', 'right', 'bottom', 'left'],
+ fallbackPlacements: null,
boundary: 'clippingParents',
customClass: '',
sanitize: true,
@@ -222,7 +223,7 @@ class Tooltip extends BaseComponent {
EventHandler.off(this._element, this.constructor.EVENT_KEY)
EventHandler.off(this._element.closest(`.${CLASS_NAME_MODAL}`), 'hide.bs.modal', this._hideModalHandler)
- if (this.tip && this.tip.parentNode) {
+ if (this.tip) {
this.tip.parentNode.removeChild(this.tip)
}
@@ -316,7 +317,7 @@ class Tooltip extends BaseComponent {
if (this.tip.classList.contains(CLASS_NAME_FADE)) {
const transitionDuration = getTransitionDurationFromElement(this.tip)
- EventHandler.one(this.tip, 'transitionend', complete)
+ EventHandler.one(this.tip, TRANSITION_END, complete)
emulateTransitionEnd(this.tip, transitionDuration)
} else {
complete()
@@ -366,7 +367,7 @@ class Tooltip extends BaseComponent {
if (this.tip.classList.contains(CLASS_NAME_FADE)) {
const transitionDuration = getTransitionDurationFromElement(tip)
- EventHandler.one(tip, 'transitionend', complete)
+ EventHandler.one(tip, TRANSITION_END, complete)
emulateTransitionEnd(tip, transitionDuration)
} else {
complete()
@@ -466,16 +467,21 @@ class Tooltip extends BaseComponent {
// Private
_getPopperConfig(attachment) {
+ const flipModifier = {
+ name: 'flip',
+ options: {
+ altBoundary: true
+ }
+ }
+
+ if (this.config.fallbackPlacements) {
+ flipModifier.options.fallbackPlacements = this.config.fallbackPlacements
+ }
+
const defaultBsConfig = {
placement: attachment,
modifiers: [
- {
- name: 'flip',
- options: {
- altBoundary: true,
- fallbackPlacements: this.config.fallbackPlacements
- }
- },
+ flipModifier,
{
name: 'preventOverflow',
options: {
diff --git a/js/src/util/index.js b/js/src/util/index.js
index 22d0a578b..1bf9fe954 100644
--- a/js/src/util/index.js
+++ b/js/src/util/index.js
@@ -111,14 +111,15 @@ const typeCheckConfig = (componentName, config, configTypes) => {
Object.keys(configTypes).forEach(property => {
const expectedTypes = configTypes[property]
const value = config[property]
- const valueType = value && isElement(value) ? 'element' : toType(value)
+ const valueType = value && isElement(value) ?
+ 'element' :
+ toType(value)
if (!new RegExp(expectedTypes).test(valueType)) {
- throw new TypeError(
+ throw new Error(
`${componentName.toUpperCase()}: ` +
`Option "${property}" provided type "${valueType}" ` +
- `but expected type "${expectedTypes}".`
- )
+ `but expected type "${expectedTypes}".`)
}
})
}
@@ -204,6 +205,7 @@ const defineJQueryPlugin = (name, plugin) => {
}
export {
+ TRANSITION_END,
getUID,
getSelectorFromElement,
getElementFromSelector,
diff --git a/js/src/util/sanitizer.js b/js/src/util/sanitizer.js
index ce3d455a6..d908dd661 100644
--- a/js/src/util/sanitizer.js
+++ b/js/src/util/sanitizer.js
@@ -37,7 +37,7 @@ const allowedAttribute = (attr, allowedAttributeList) => {
if (allowedAttributeList.includes(attrName)) {
if (uriAttrs.has(attrName)) {
- return Boolean(SAFE_URL_PATTERN.test(attr.nodeValue) || DATA_URL_PATTERN.test(attr.nodeValue))
+ return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
}
return true
@@ -47,7 +47,7 @@ const allowedAttribute = (attr, allowedAttributeList) => {
// Check if a regular expression validates the attribute.
for (let i = 0, len = regExp.length; i < len; i++) {
- if (regExp[i].test(attrName)) {
+ if (attrName.match(regExp[i])) {
return true
}
}
diff --git a/js/tests/browsers.js b/js/tests/browsers.js
index 2e1bd3a80..8df94cc53 100644
--- a/js/tests/browsers.js
+++ b/js/tests/browsers.js
@@ -5,21 +5,21 @@ const browsers = {
safariMac: {
base: 'BrowserStack',
os: 'OS X',
- os_version: 'Catalina',
+ os_version: 'High Sierra',
browser: 'Safari',
browser_version: 'latest'
},
chromeMac: {
base: 'BrowserStack',
os: 'OS X',
- os_version: 'Catalina',
+ os_version: 'High Sierra',
browser: 'Chrome',
browser_version: 'latest'
},
firefoxMac: {
base: 'BrowserStack',
os: 'OS X',
- os_version: 'Catalina',
+ os_version: 'High Sierra',
browser: 'Firefox',
browser_version: 'latest'
},
diff --git a/js/tests/karma.conf.js b/js/tests/karma.conf.js
index cd4946525..d0dd8bdd9 100644
--- a/js/tests/karma.conf.js
+++ b/js/tests/karma.conf.js
@@ -1,7 +1,5 @@
/* eslint-env node */
-'use strict'
-
const path = require('path')
const ip = require('ip')
const { babel } = require('@rollup/plugin-babel')
@@ -14,11 +12,10 @@ const {
browsersKeys
} = require('./browsers')
-const ENV = process.env
-const BROWSERSTACK = Boolean(ENV.BROWSERSTACK)
-const DEBUG = Boolean(ENV.DEBUG)
-const JQUERY_TEST = Boolean(ENV.JQUERY)
-
+const { env } = process
+const browserStack = env.BROWSER === 'true'
+const debug = env.DEBUG === 'true'
+const jQueryTest = env.JQUERY === 'true'
const frameworks = [
'jasmine'
]
@@ -33,16 +30,16 @@ const reporters = ['dots']
const detectBrowsers = {
usePhantomJS: false,
postDetection(availableBrowser) {
- if (ENV.CI === true || availableBrowser.includes('Chrome')) {
- return DEBUG ? ['Chrome'] : ['ChromeHeadless']
+ if (env.CI === true || availableBrowser.includes('Chrome')) {
+ return debug ? ['Chrome'] : ['ChromeHeadless']
}
if (availableBrowser.includes('Chromium')) {
- return DEBUG ? ['Chromium'] : ['ChromiumHeadless']
+ return debug ? ['Chromium'] : ['ChromiumHeadless']
}
if (availableBrowser.includes('Firefox')) {
- return DEBUG ? ['Firefox'] : ['FirefoxHeadless']
+ return debug ? ['Firefox'] : ['FirefoxHeadless']
}
throw new Error('Please install Chrome, Chromium or Firefox')
@@ -62,7 +59,7 @@ const conf = {
colors: true,
autoWatch: false,
singleRun: true,
- concurrency: Number.POSITIVE_INFINITY,
+ concurrency: Infinity,
client: {
clearContext: false
},
@@ -70,7 +67,7 @@ const conf = {
'node_modules/hammer-simulator/index.js',
{
pattern: 'js/tests/unit/**/!(jquery).spec.js',
- watched: !BROWSERSTACK
+ watched: !browserStack
}
],
preprocessors: {
@@ -104,11 +101,11 @@ const conf = {
}
}
-if (BROWSERSTACK) {
+if (browserStack) {
conf.hostname = ip.address()
conf.browserStack = {
- username: ENV.BROWSER_STACK_USERNAME,
- accessKey: ENV.BROWSER_STACK_ACCESS_KEY,
+ username: env.BROWSER_STACK_USERNAME,
+ accessKey: env.BROWSER_STACK_ACCESS_KEY,
build: `bootstrap-${new Date().toISOString()}`,
project: 'Bootstrap',
retryLimit: 2
@@ -117,7 +114,7 @@ if (BROWSERSTACK) {
conf.customLaunchers = browsers
conf.browsers = browsersKeys
reporters.push('BrowserStack', 'kjhtml')
-} else if (JQUERY_TEST) {
+} else if (jQueryTest) {
frameworks.push('detectBrowsers')
plugins.push(
'karma-chrome-launcher',
@@ -158,7 +155,7 @@ if (BROWSERSTACK) {
}
}
- if (DEBUG) {
+ if (debug) {
conf.hostname = ip.address()
plugins.push('karma-jasmine-html-reporter')
reporters.push('kjhtml')
@@ -172,6 +169,7 @@ conf.plugins = plugins
conf.reporters = reporters
module.exports = karmaConfig => {
- conf.logLevel = karmaConfig.LOG_ERROR
+ // possible values: karmaConfig.LOG_DISABLE || karmaConfig.LOG_ERROR || karmaConfig.LOG_WARN || karmaConfig.LOG_INFO || karmaConfig.LOG_DEBUG
+ conf.logLevel = karmaConfig.LOG_ERROR || karmaConfig.LOG_WARN
karmaConfig.set(conf)
}
diff --git a/js/tests/unit/carousel.spec.js b/js/tests/unit/carousel.spec.js
index 787a276de..07b8fc311 100644
--- a/js/tests/unit/carousel.spec.js
+++ b/js/tests/unit/carousel.spec.js
@@ -905,7 +905,7 @@ describe('Carousel', () => {
})
describe('to', () => {
- it('should go directly to the provided index', done => {
+ it('should go directement to the provided index', done => {
fixtureEl.innerHTML = [
'
@@ -206,34 +206,6 @@ Add `data-bs-interval=""` to a `.carousel-item` to change the amount of time to
{{< /example >}}
-### Disable touch swiping
-
-Carousels support swiping left/right on touchscreen devices to move between slides. This can be disabled using the `data-bs-touch` attribute. The example below also does not include the `data-bs-ride` attribute and has `data-bs-interval="false"` so it doesn't autoplay.
-
-{{< example >}}
-
-{{< /example >}}
-
## Dark variant
Add `.carousel-dark` to the `.carousel` for darker controls, indicators, and captions. Controls have been inverted from their default white fill with the `filter` CSS property. Captions and controls have additional Sass variables that customize the `color` and `background-color`.
@@ -250,21 +222,21 @@ Add `.carousel-dark` to the `.carousel` for darker controls, indicators, and cap
{{< placeholder width="800" height="400" class="bd-placeholder-img-lg d-block w-100" color="#aaa" background="#f5f5f5" text="First slide" >}}
Some representative placeholder content for the first slide. Nulla vitae elit libero, a pharetra augue mollis interdum. Some representative placeholder content for the second slide. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Some representative placeholder content for the third slide. Praesent commodo cursus magna, vel scelerisque nisl consectetur.First slide label
- Second slide label
- Third slide label
-
interval5000false, carousel will not automatically cycle.keyboardpause'hover'If set to 'hover', pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave. If set to false, hovering over the carousel won't pause it.
On touch-enabled devices, when set to 'hover', cycling will pause on touchend (once the user finished interacting with the carousel) for two intervals, before automatically resuming. Note that this is in addition to the above mouse behavior.
"hover"If set to "hover", pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave. If set to false, hovering over the carousel won't pause it.
On touch-enabled devices, when set to "hover", cycling will pause on touchend (once the user finished interacting with the carousel) for two intervals, before automatically resuming. Note that this is in addition to the above mouse behavior.
rideslidefalse'carousel', autoplays the carousel on load.wrap@@ -35,7 +35,7 @@ Generally, we recommend using a button with the `data-bs-target` attribute. Whil
reference'toggle''toggle', 'parent', an HTMLElement reference or an object providing getBoundingClientRect. For more information refer to Popper's constructor docs and virtual element docs.'toggle', 'parent', or an HTMLElement reference. For more information refer to Popper's constructor docs.displaypopperConfignull