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/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..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/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/carousel.js b/js/src/carousel.js index 06a391419..a266ec10f 100644 --- a/js/src/carousel.js +++ b/js/src/carousel.js @@ -11,7 +11,6 @@ import { getElementFromSelector, getTransitionDurationFromElement, isVisible, - isRTL, reflow, triggerTransitionEnd, typeCheckConfig @@ -251,20 +250,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() } } @@ -348,18 +339,10 @@ class Carousel extends BaseComponent { if (event.key === ARROW_LEFT_KEY) { event.preventDefault() - if (isRTL) { - this.next() - } else { - this.prev() - } + this.prev() } else if (event.key === ARROW_RIGHT_KEY) { event.preventDefault() - if (isRTL) { - this.prev() - } else { - this.next() - } + this.next() } } diff --git a/js/src/collapse.js b/js/src/collapse.js index 0d3eeed54..90bab0ec9 100644 --- a/js/src/collapse.js +++ b/js/src/collapse.js @@ -371,7 +371,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/dropdown.js b/js/src/dropdown.js index bada537c9..4d65008f8 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 } 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/tooltip.js b/js/src/tooltip.js index 63a30cf2f..103524b8b 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -51,7 +51,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 +81,7 @@ const Default = { selector: false, placement: 'top', container: false, - fallbackPlacements: ['top', 'right', 'bottom', 'left'], + fallbackPlacements: null, boundary: 'clippingParents', customClass: '', sanitize: true, @@ -466,16 +466,22 @@ class Tooltip extends BaseComponent { // Private _getPopperConfig(attachment) { + const flipModifier = { + name: 'flip', + options: { + altBoundary: true, + fallbackPlacements: ['top', 'right', 'bottom', 'left'] + } + } + + 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..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/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 = [ '