diff --git a/.eslintrc.json b/.eslintrc.json
index d5a54d46b..680642ac6 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -43,6 +43,7 @@
],
"unicorn/consistent-function-scoping": "off",
"unicorn/explicit-length-check": "off",
+ "unicorn/import-index": "off",
"unicorn/no-array-callback-reference": "off",
"unicorn/no-for-loop": "off",
"unicorn/no-null": "off",
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/workflows/browserstack.yml b/.github/workflows/browserstack.yml
index a12bffcf7..00831721d 100644
--- a/.github/workflows/browserstack.yml
+++ b/.github/workflows/browserstack.yml
@@ -4,8 +4,9 @@ on:
push:
env:
+ CI: true
FORCE_COLOR: 2
- NODE: 14
+ NODE: 14.x
jobs:
browserstack:
@@ -18,7 +19,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 }}"
@@ -28,8 +29,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/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-css.js b/build/build-css.js
new file mode 100644
index 000000000..738b553a9
--- /dev/null
+++ b/build/build-css.js
@@ -0,0 +1,71 @@
+#!/usr/bin/env node
+
+'use strict'
+
+const fs = require('fs/promises')
+const path = require('path')
+const postcss = require('postcss')
+const glob = require('glob')
+const sass = require('sass')
+const autoprefixer = require('autoprefixer')
+const Cleancss = require('clean-css')
+
+const postcssPlugins = [
+ autoprefixer({ cascade: false })
+]
+
+const FILES = [
+ 'bootstrap',
+ 'bootstrap-grid',
+ 'bootstrap-reboot',
+ 'bootstrap-utilities'
+]
+
+async function processFile(filename) {
+ const sassOptions = {
+ file: path.resolve(`./scss/${filename}.scss`),
+ outputStyle: 'expanded',
+ sourceMap: true,
+ sourceMapContents: true,
+ outFile: `./dist/css/${filename}.css`
+ }
+
+ const css = await sass.renderSync(sassOptions)
+
+ // Fix postcss to use and output sourcemaps
+ const processedCss = await postcss(postcssPlugins)
+ .process(css.css, {
+ from: `./dist/css/${filename}.css`,
+ map: `./dist/css/${filename}.css.map`
+ })
+
+ const minifiedCss = await new Cleancss().minify(processedCss.css).styles
+
+ await fs.writeFile(`./dist/css/${filename}.css`, processedCss.css)
+ await fs.writeFile(`./dist/css/${filename}.css.map`, processedCss.map.toString())
+ await fs.writeFile(`./dist/css/${filename}.min.css`, minifiedCss)
+}
+
+(async () => {
+ try {
+ await Promise.all(FILES.map(file => processFile(file)))
+ } catch (error) {
+ console.error(error)
+ process.exit(1)
+ }
+})()
+
+// Prefix examples
+glob('./site/content/**/*.css', {}, (error, files) => {
+ files.forEach(file => {
+ fs.readFile(file, (err, css) => {
+ postcss(postcssPlugins)
+ .process(css, { from: file, to: file })
+ .then(result => {
+ if (css.toString('utf8') !== result.css) {
+ fs.writeFile(file, result.css, () => true)
+ }
+ })
+ })
+ })
+})
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/postcss.config.js b/build/postcss.config.js
deleted file mode 100644
index b179a0e77..000000000
--- a/build/postcss.config.js
+++ /dev/null
@@ -1,19 +0,0 @@
-'use strict'
-
-module.exports = ctx => {
- return {
- map: ctx.file.dirname.includes('examples') ?
- false :
- {
- inline: false,
- annotation: true,
- sourcesContent: true
- },
- plugins: {
- autoprefixer: {
- cascade: false
- },
- rtlcss: ctx.env === 'RTL' ? {} : false
- }
- }
-}
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/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/dropdown.js b/js/src/dropdown.js
index bada537c9..008294e9b 100644
--- a/js/src/dropdown.js
+++ b/js/src/dropdown.js
@@ -263,7 +263,7 @@ class Dropdown extends BaseComponent {
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.`)
+ throw new Error(`${NAME}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`)
}
return config
diff --git a/js/src/modal.js b/js/src/modal.js
index fe1b5a4c6..87c22943a 100644
--- a/js/src/modal.js
+++ b/js/src/modal.js
@@ -590,7 +590,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/util/index.js b/js/src/util/index.js
index 22d0a578b..9ccad1cbb 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}".`)
}
})
}
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/karma.conf.js b/js/tests/karma.conf.js
index cd4946525..38c7003bb 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')
@@ -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..0286762fa 100644
--- a/js/tests/unit/carousel.spec.js
+++ b/js/tests/unit/carousel.spec.js
@@ -1136,9 +1136,11 @@ describe('Carousel', () => {
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
- expect(() => {
+ try {
jQueryMock.fn.carousel.call(jQueryMock, action)
- }).toThrowError(TypeError, `No method named "${action}"`)
+ } catch (error) {
+ expect(error.message).toEqual(`No method named "${action}"`)
+ }
})
})
diff --git a/js/tests/unit/collapse.spec.js b/js/tests/unit/collapse.spec.js
index ff493cf51..4af21e13f 100644
--- a/js/tests/unit/collapse.spec.js
+++ b/js/tests/unit/collapse.spec.js
@@ -819,9 +819,11 @@ describe('Collapse', () => {
jQueryMock.fn.collapse = Collapse.jQueryInterface
jQueryMock.elements = [div]
- expect(() => {
+ try {
jQueryMock.fn.collapse.call(jQueryMock, action)
- }).toThrowError(TypeError, `No method named "${action}"`)
+ } catch (error) {
+ expect(error.message).toEqual(`No method named "${action}"`)
+ }
})
})
diff --git a/js/tests/unit/dropdown.spec.js b/js/tests/unit/dropdown.spec.js
index cc4139603..ba1d0f443 100644
--- a/js/tests/unit/dropdown.spec.js
+++ b/js/tests/unit/dropdown.spec.js
@@ -393,13 +393,13 @@ describe('Dropdown', () => {
expect(() => new Dropdown(btnDropdown, {
reference: {}
- })).toThrowError(TypeError, 'DROPDOWN: Option "reference" provided type "object" without a required "getBoundingClientRect" method.')
+ })).toThrow()
expect(() => new Dropdown(btnDropdown, {
reference: {
getBoundingClientRect: 'not-a-function'
}
- })).toThrowError(TypeError, 'DROPDOWN: Option "reference" provided type "object" without a required "getBoundingClientRect" method.')
+ })).toThrow()
// use onFirstUpdate as Poppers internal update is executed async
const dropdown = new Dropdown(btnDropdown, {
@@ -1557,9 +1557,11 @@ describe('Dropdown', () => {
jQueryMock.fn.dropdown = Dropdown.jQueryInterface
jQueryMock.elements = [div]
- expect(() => {
+ try {
jQueryMock.fn.dropdown.call(jQueryMock, action)
- }).toThrowError(TypeError, `No method named "${action}"`)
+ } catch (error) {
+ expect(error.message).toEqual(`No method named "${action}"`)
+ }
})
})
diff --git a/js/tests/unit/modal.spec.js b/js/tests/unit/modal.spec.js
index 29c90bbf1..f645e9892 100644
--- a/js/tests/unit/modal.spec.js
+++ b/js/tests/unit/modal.spec.js
@@ -870,7 +870,7 @@ describe('Modal', () => {
})
describe('data-api', () => {
- it('should toggle modal', done => {
+ it('should open modal', done => {
fixtureEl.innerHTML = [
'',
'
'
@@ -885,15 +885,6 @@ describe('Modal', () => {
expect(modalEl.getAttribute('aria-hidden')).toEqual(null)
expect(modalEl.style.display).toEqual('block')
expect(document.querySelector('.modal-backdrop')).toBeDefined()
- setTimeout(() => trigger.click(), 10)
- })
-
- modalEl.addEventListener('hidden.bs.modal', () => {
- expect(modalEl.getAttribute('aria-modal')).toEqual(null)
- expect(modalEl.getAttribute('role')).toEqual(null)
- expect(modalEl.getAttribute('aria-hidden')).toEqual('true')
- expect(modalEl.style.display).toEqual('none')
- expect(document.querySelector('.modal-backdrop')).toEqual(null)
done()
})
@@ -1070,9 +1061,11 @@ describe('Modal', () => {
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
- expect(() => {
+ try {
jQueryMock.fn.modal.call(jQueryMock, action)
- }).toThrowError(TypeError, `No method named "${action}"`)
+ } catch (error) {
+ expect(error.message).toEqual(`No method named "${action}"`)
+ }
})
it('should call show method', () => {
diff --git a/js/tests/unit/popover.spec.js b/js/tests/unit/popover.spec.js
index e5c235e2a..3c04e7ac1 100644
--- a/js/tests/unit/popover.spec.js
+++ b/js/tests/unit/popover.spec.js
@@ -206,9 +206,11 @@ describe('Popover', () => {
jQueryMock.fn.popover = Popover.jQueryInterface
jQueryMock.elements = [popoverEl]
- expect(() => {
+ try {
jQueryMock.fn.popover.call(jQueryMock, action)
- }).toThrowError(TypeError, `No method named "${action}"`)
+ } catch (error) {
+ expect(error.message).toEqual(`No method named "${action}"`)
+ }
})
it('should should call show method', () => {
diff --git a/js/tests/unit/scrollspy.spec.js b/js/tests/unit/scrollspy.spec.js
index 0d175aafa..45de56fbe 100644
--- a/js/tests/unit/scrollspy.spec.js
+++ b/js/tests/unit/scrollspy.spec.js
@@ -68,7 +68,7 @@ describe('ScrollSpy', () => {
fixtureEl.innerHTML = [
'