diff --git a/.babelrc.js b/.babelrc.js
index 44a509954105..1d6404edbe5f 100644
--- a/.babelrc.js
+++ b/.babelrc.js
@@ -1,17 +1,14 @@
module.exports = {
presets: [
[
- '@babel/env',
+ '@babel/preset-env',
{
loose: true,
- modules: false,
- exclude: ['transform-typeof-symbol']
+ bugfixes: true,
+ modules: false
}
]
],
- plugins: [
- '@babel/plugin-proposal-object-rest-spread'
- ],
env: {
test: {
plugins: [ 'istanbul' ]
diff --git a/.bundlewatch.config.json b/.bundlewatch.config.json
new file mode 100644
index 000000000000..0576af92f564
--- /dev/null
+++ b/.bundlewatch.config.json
@@ -0,0 +1,50 @@
+{
+ "files": [
+ {
+ "path": "./dist/css/bootstrap-grid.css",
+ "maxSize": "7 kB"
+ },
+ {
+ "path": "./dist/css/bootstrap-grid.min.css",
+ "maxSize": "6.25 kB"
+ },
+ {
+ "path": "./dist/css/bootstrap-reboot.css",
+ "maxSize": "2 kB"
+ },
+ {
+ "path": "./dist/css/bootstrap-reboot.min.css",
+ "maxSize": "2 kB"
+ },
+ {
+ "path": "./dist/css/bootstrap.css",
+ "maxSize": "26 kB"
+ },
+ {
+ "path": "./dist/css/bootstrap.min.css",
+ "maxSize": "23.75 kB"
+ },
+ {
+ "path": "./dist/js/bootstrap.bundle.js",
+ "maxSize": "48 kB"
+ },
+ {
+ "path": "./dist/js/bootstrap.bundle.min.js",
+ "maxSize": "21.75 kB"
+ },
+ {
+ "path": "./dist/js/bootstrap.js",
+ "maxSize": "25.5 kB"
+ },
+ {
+ "path": "./dist/js/bootstrap.min.js",
+ "maxSize": "15 kB"
+ }
+ ],
+ "ci": {
+ "trackBranches": [
+ "main",
+ "v4-dev"
+ ]
+ }
+}
diff --git a/.eslintignore b/.eslintignore
index 96958b2ba864..a18b03a5df54 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,4 +1,6 @@
**/*.min.js
**/dist/
**/vendor/
-/_gh_pages/
+/_site/
+/js/coverage/
+/site/static/sw.js
diff --git a/.eslintrc.json b/.eslintrc.json
index bfd2d333ae60..3d099fc9de80 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,233 +1,76 @@
{
"root": true,
- "parser": "babel-eslint",
- "env": {
- "browser": true,
- "es6": true
- },
- "extends": ["eslint:recommended"],
+ "extends": [
+ "plugin:import/errors",
+ "plugin:import/warnings",
+ "plugin:unicorn/recommended",
+ "xo",
+ "xo/browser"
+ ],
"rules": {
- // Possible Errors
- "no-await-in-loop": "error",
- "no-extra-parens": "error",
- "no-prototype-builtins": "error",
- "no-template-curly-in-string": "error",
- "valid-jsdoc": "error",
-
- // Best Practices
- "accessor-pairs": "error",
- "array-callback-return": "error",
- "block-scoped-var": "error",
- "class-methods-use-this": "off",
- "complexity": "error",
- "consistent-return": "error",
- "curly": "error",
- "default-case": "error",
- "dot-location": ["error", "property"],
- "dot-notation": "error",
- "eqeqeq": "error",
- "guard-for-in": "error",
- "no-alert": "error",
- "no-caller": "error",
- "no-div-regex": "error",
- "no-else-return": "error",
- "no-empty-function": "error",
- "no-eq-null": "error",
- "no-eval": "error",
- "no-extend-native": "error",
- "no-extra-bind": "error",
- "no-extra-label": "error",
- "no-floating-decimal": "error",
- "no-implicit-coercion": "error",
- "no-implicit-globals": "error",
- "no-implied-eval": "error",
- "no-invalid-this": "off",
- "no-iterator": "error",
- "no-labels": "error",
- "no-lone-blocks": "error",
- "no-loop-func": "error",
- "no-magic-numbers": ["error", {
- "ignore": [-1, 0, 1],
- "ignoreArrayIndexes": true
+ "arrow-body-style": "off",
+ "capitalized-comments": "off",
+ "comma-dangle": [
+ "error",
+ "never"
+ ],
+ "indent": [
+ "error",
+ 2,
+ {
+ "MemberExpression": "off",
+ "SwitchCase": 1
}
],
- "no-multi-spaces": ["error", {
- "ignoreEOLComments": true,
- "exceptions": {
- "AssignmentExpression": true,
- "ArrowFunctionExpression": true,
- "CallExpression": true,
- "VariableDeclarator": true
- }
+ "max-params": [
+ "warn",
+ 5
+ ],
+ "new-cap": [
+ "error",
+ {
+ "properties": false
}
],
- "no-multi-str": "error",
- "no-new": "error",
- "no-new-func": "error",
- "no-new-wrappers": "error",
- "no-octal-escape": "error",
- "no-param-reassign": "off",
- "no-proto": "error",
- "no-restricted-properties": "error",
- "no-return-assign": "error",
- "no-return-await": "error",
- "no-script-url": "error",
- "no-self-compare": "error",
- "no-sequences": "error",
- "no-throw-literal": "error",
- "no-unmodified-loop-condition": "error",
- "no-unused-expressions": "error",
- "no-useless-call": "error",
- "no-useless-concat": "error",
- "no-useless-return": "error",
- "no-void": "error",
- "no-warning-comments": "off",
- "no-with": "error",
- "prefer-promise-reject-errors": "error",
- "radix": "error",
- "require-await": "error",
- "vars-on-top": "error",
- "wrap-iife": "error",
- "yoda": "error",
-
- // Strict Mode
- "strict": "error",
-
- // Variables
- "init-declarations": "off",
- "no-catch-shadow": "error",
- "no-label-var": "error",
- "no-restricted-globals": "error",
- "no-shadow": "off",
- "no-shadow-restricted-names": "error",
- "no-undef-init": "error",
- "no-undefined": "error",
- "no-use-before-define": "off",
-
- // Node.js and CommonJS
- "callback-return": "off",
- "global-require": "error",
- "handle-callback-err": "error",
- "no-mixed-requires": "error",
- "no-new-require": "error",
- "no-path-concat": "error",
- "no-process-env": "error",
- "no-process-exit": "error",
- "no-restricted-modules": "error",
- "no-sync": "error",
-
- // Stylistic Issues
- "array-bracket-spacing": "error",
- "block-spacing": "error",
- "brace-style": "error",
- "camelcase": "error",
- "capitalized-comments": "off",
- "comma-dangle": "error",
- "comma-spacing": "error",
- "comma-style": "error",
- "computed-property-spacing": "error",
- "consistent-this": "error",
- "eol-last": "error",
- "func-call-spacing": "error",
- "func-name-matching": "error",
- "func-names": "off",
- "func-style": ["error", "declaration"],
- "id-blacklist": "error",
- "id-length": "off",
- "id-match": "error",
- "indent": ["error", 2, { "SwitchCase": 1 }],
- "jsx-quotes": "error",
- "key-spacing": "off",
- "keyword-spacing": "error",
- "linebreak-style": ["error", "unix"],
- "line-comment-position": "off",
- "lines-around-comment": "off",
- "lines-around-directive": "error",
- "max-depth": ["error", 10],
- "max-len": "off",
- "max-lines": "off",
- "max-nested-callbacks": "error",
- "max-params": "off",
- "max-statements": "off",
- "max-statements-per-line": "error",
- "multiline-ternary": "off",
- "new-cap": ["error", { "capIsNewExceptionPattern": "$.*" }],
- "newline-after-var": "off",
- "newline-per-chained-call": ["error", { "ignoreChainWithDepth": 5 }],
- "new-parens": "error",
- "no-array-constructor": "error",
- "no-bitwise": "error",
- "no-continue": "off",
- "no-inline-comments": "off",
- "no-lonely-if": "error",
+ "no-console": "error",
"no-mixed-operators": "off",
- "no-multi-assign": "error",
- "no-multiple-empty-lines": "error",
- "nonblock-statement-body-position": "error",
"no-negated-condition": "off",
- "no-nested-ternary": "error",
- "no-new-object": "error",
- "no-plusplus": "off",
- "no-restricted-syntax": "error",
- "no-tabs": "error",
- "no-ternary": "off",
- "no-trailing-spaces": "error",
- "no-underscore-dangle": "off",
- "no-unneeded-ternary": "error",
- "no-whitespace-before-property": "error",
- "object-curly-newline": ["error", { "minProperties": 1 }],
- "object-curly-spacing": ["error", "always"],
- "object-property-newline": "error",
- "one-var": ["error", "never"],
- "one-var-declaration-per-line": "error",
- "operator-assignment": "error",
- "operator-linebreak": "error",
- "padded-blocks": ["error", "never"],
- "padding-line-between-statements": "off",
- "quote-props": ["error", "as-needed"],
- "quotes": ["error", "single"],
- "require-jsdoc": "off",
- "semi": ["error", "never"],
- "semi-spacing": "error",
- "sort-keys": "off",
- "sort-vars": "error",
- "space-before-blocks": "error",
- "space-before-function-paren": ["error", {
- "anonymous": "always",
- "named": "never"
- }],
- "space-in-parens": "error",
- "space-infix-ops": "error",
- "space-unary-ops": "error",
- "spaced-comment": "error",
- "template-tag-spacing": "error",
- "unicode-bom": "error",
- "wrap-regex": "off",
-
- // ECMAScript 6
- "arrow-body-style": ["error", "as-needed"],
- "arrow-parens": "error",
- "arrow-spacing": "error",
- "generator-star-spacing": "error",
- "no-confusing-arrow": "error",
- "no-duplicate-imports": "error",
- "no-restricted-imports": "error",
- "no-useless-computed-key": "error",
- "no-useless-constructor": "error",
- "no-useless-rename": "error",
- "no-var": "error",
- "object-shorthand": "error",
- "prefer-arrow-callback": "error",
- "prefer-const": "error",
- "prefer-destructuring": "off",
- "prefer-numeric-literals": "error",
- "prefer-rest-params": "error",
- "prefer-spread": "error",
- "prefer-template": "error",
- "rest-spread-spacing": "error",
- "sort-imports": "error",
- "symbol-description": "error",
- "template-curly-spacing": "error",
- "yield-star-spacing": "error"
+ "object-curly-spacing": [
+ "error",
+ "always"
+ ],
+ "operator-linebreak": [
+ "error",
+ "after"
+ ],
+ "semi": [
+ "error",
+ "never"
+ ],
+ "unicorn/consistent-function-scoping": "off",
+ "unicorn/explicit-length-check": "off",
+ "unicorn/no-array-callback-reference": "off",
+ "unicorn/no-array-for-each": "off",
+ "unicorn/no-array-method-this-argument": "off",
+ "unicorn/no-for-loop": "off",
+ "unicorn/no-null": "off",
+ "unicorn/no-unused-properties": "error",
+ "unicorn/no-useless-undefined": "off",
+ "unicorn/numeric-separators-style": "off",
+ "unicorn/prefer-array-find": "off",
+ "unicorn/prefer-array-flat": "off",
+ "unicorn/prefer-dom-node-append": "off",
+ "unicorn/prefer-dom-node-dataset": "off",
+ "unicorn/prefer-dom-node-remove": "off",
+ "unicorn/prefer-includes": "off",
+ "unicorn/prefer-math-trunc": "off",
+ "unicorn/prefer-module": "off",
+ "unicorn/prefer-number-properties": "off",
+ "unicorn/prefer-optional-catch-binding": "off",
+ "unicorn/prefer-prototype-methods": "off",
+ "unicorn/prefer-query-selector": "off",
+ "unicorn/prefer-reflect-apply": "off",
+ "unicorn/prefer-set-has": "off",
+ "unicorn/prevent-abbreviations": "off"
}
}
diff --git a/.gitattributes b/.gitattributes
index 39813c758947..40b1c37421a0 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,18 +1,8 @@
# Enforce Unix newlines
-*.css text eol=lf
-*.html text eol=lf
-*.js text eol=lf
-*.json text eol=lf
-*.md text eol=lf
-*.rb text eol=lf
-*.scss text eol=lf
-*.svg text eol=lf
-*.txt text eol=lf
-*.xml text eol=lf
-*.yml text eol=lf
+* text=auto eol=lf
# Don't diff or textually merge source maps
-*.map binary
+*.map binary
bootstrap.css linguist-vendored=false
bootstrap.js linguist-vendored=false
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index f579111bd41a..c4de33669396 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -18,8 +18,9 @@ the preferred channel for [bug reports](#bug-reports), [features requests](#feat
and [submitting pull requests](#pull-requests), but please respect the following
restrictions:
-* Please **do not** use the issue tracker for personal support requests. Stack
- Overflow ([`bootstrap-4`](https://stackoverflow.com/questions/tagged/bootstrap-4) tag), [Slack](https://bootstrap-slack.herokuapp.com/) or [IRC](README.md#community) are better places to get help.
+* Please **do not** use the issue tracker for personal support requests. Stack
+ Overflow ([`bootstrap-4`](https://stackoverflow.com/questions/tagged/bootstrap-4) tag),
+ [Slack](https://bootstrap-slack.herokuapp.com/) or [IRC](/README.md#community) are better places to get help.
* Please **do not** derail or troll issues. Keep the discussion on topic and
respect the opinions of others.
@@ -57,15 +58,14 @@ Good bug reports are extremely helpful, so thanks!
Guidelines for bug reports:
-0. **Validate and lint your code** — [validate your HTML](https://html5.validator.nu/)
- and [lint your HTML](https://github.com/twbs/bootlint) to ensure your
+0. **[validate your HTML](https://html5.validator.nu/)** to ensure your
problem isn't caused by a simple error in your own code.
1. **Use the GitHub issue search** — check if the issue has already been
reported.
2. **Check if the issue has been fixed** — try to reproduce it using the
- latest `master` or development branch in the repository.
+ latest `master` or `v4-dev` branch in the repository.
3. **Isolate the problem** — ideally create a [reduced test
case](https://css-tricks.com/reduced-test-cases/) and a live example.
@@ -102,16 +102,12 @@ Example:
Sometimes bugs reported to us are actually caused by bugs in the browser(s) themselves, not bugs in Bootstrap per se.
When feasible, we aim to report such upstream bugs to the relevant browser vendor(s), and then list them on our [Wall of Browser Bugs](https://getbootstrap.com/browser-bugs/) and [document them in MDN](https://developer.mozilla.org/en-US/docs/Web).
-| 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
https://bugreport.apple.com/ | 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 | EdgeHTML | https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/ | |
-
-### Issues bots
-
-[@twbs-lmvtfy](https://github.com/twbs-lmvtfy) is a Bootstrap bot that hangs out in our GitHub issue tracker and automatically checks for HTML validation errors in live examples (e.g. jsFiddles, JS Bins, Bootplys, Plunks, CodePens, etc.) posted in issue comments. If it finds any errors, it will post a follow-up comment on the issue and point out the errors. If this happens with an example you've posted, please fix the errors and post an updated live example. If you opened a bug report, please check whether the bug still occurs with your revised, valid live example. If the bug no longer occurs, it was probably due to your invalid HTML rather than something in Bootstrap and we'd appreciate it if you could close out the GitHub issue.
+| 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
@@ -128,23 +124,25 @@ Good pull requests—patches, improvements, new features—are a fantastic
help. They should remain focused in scope and avoid containing unrelated
commits.
-**Please ask first** before embarking on any significant pull request (e.g.
+**Please ask first** before embarking on any **significant** pull request (e.g.
implementing features, refactoring code, porting to a different language),
otherwise you risk spending a lot of time working on something that the
-project's developers might not want to merge into the project.
+project's developers might not want to merge into the project. For trivial
+things, or things that don't require a lot of your time, you can go ahead and
+make a PR.
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`
-directly!** Those files are automatically generated. You should edit the
-source files in [`/bootstrap/scss/`](https://github.com/twbs/bootstrap/tree/master/scss)
-and/or [`/bootstrap/js/`](https://github.com/twbs/bootstrap/tree/master/js) instead.
+**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/v4-dev/scss)
+and/or [`/bootstrap/js/src/`](https://github.com/twbs/bootstrap/tree/v4-dev/js/src) instead.
Similarly, when contributing to Bootstrap's documentation, you should edit the
documentation source files in
-[the `/bootstrap/docs/` directory of the `master` branch](https://github.com/twbs/bootstrap/tree/master/docs).
+[the `/bootstrap/site/content/docs/` directory of the `v4-dev` branch](https://github.com/twbs/bootstrap/tree/v4-dev/site/content/docs).
**Do not edit the `gh-pages` branch.** That branch is generated from the
documentation source files and is managed separately by the Bootstrap Core Team.
@@ -166,8 +164,8 @@ included in the project:
2. If you cloned a while ago, get the latest changes from upstream:
```bash
- git checkout master
- git pull upstream master
+ git checkout v4-dev
+ git pull upstream v4-dev
```
3. Create a new topic branch (off the main project development branch) to
@@ -186,7 +184,7 @@ included in the project:
5. Locally merge (or rebase) the upstream development branch into your topic branch:
```bash
- git pull [--rebase] upstream master
+ git pull [--rebase] upstream v4-dev
```
6. Push your topic branch up to your fork:
@@ -196,12 +194,12 @@ included in the project:
```
7. [Open a Pull Request](https://help.github.com/articles/about-pull-requests/)
- with a clear title and description against the `master` branch.
+ with a clear title and description against the `v4-dev` branch.
**IMPORTANT**: By submitting a patch, you agree to allow the project owners to
-license your work under the terms of the [MIT License](LICENSE) (if it
+license your work under the terms of the [MIT License](../LICENSE) (if it
includes code changes) and under the terms of the
-[Creative Commons Attribution 3.0 Unported License](docs/LICENSE)
+[Creative Commons Attribution 3.0 Unported License](https://creativecommons.org/licenses/by/3.0/)
(if it includes documentation changes).
@@ -209,7 +207,7 @@ includes code changes) and under the terms of the
### HTML
-[Adhere to the Code Guide.](http://codeguide.co/#html)
+[Adhere to the Code Guide.](https://codeguide.co/#html)
- Use tags and elements appropriate for an HTML5 doctype (e.g., self-closing tags).
- Use CDNs and HTTPS for third-party JS when possible. We don't use protocol-relative URLs in this case because they break when viewing the page locally via `file://`.
@@ -217,10 +215,10 @@ includes code changes) and under the terms of the
### CSS
-[Adhere to the Code Guide.](http://codeguide.co/#css)
+[Adhere to the Code Guide.](https://codeguide.co/#css)
- When feasible, default color palettes should comply with [WCAG color contrast guidelines](https://www.w3.org/TR/WCAG20/#visual-audio-contrast).
-- Except in rare cases, don't remove default `:focus` styles (via e.g. `outline: none;`) without providing alternative styles. See [this A11Y Project post](https://a11yproject.com/posts/never-remove-css-outlines/) for more details.
+- Except in rare cases, don't remove default `:focus` styles (via e.g. `outline: none;`) without providing alternative styles. See [this A11Y Project post](https://www.a11yproject.com/posts/2013-01-25-never-remove-css-outlines/) for more details.
### JS
@@ -237,7 +235,7 @@ Run `npm run test` before committing to ensure your changes follow our coding st
## License
-By contributing your code, you agree to license your contribution under the [MIT License](LICENSE).
-By contributing to the documentation, you agree to license your contribution under the [Creative Commons Attribution 3.0 Unported License](docs/LICENSE).
+By contributing your code, you agree to license your contribution under the [MIT License](../LICENSE).
+By contributing to the documentation, you agree to license your contribution under the [Creative Commons Attribution 3.0 Unported License](https://creativecommons.org/licenses/by/3.0/).
Prior to v3.1.0, Bootstrap's code was released under the Apache License v2.0.
diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md
deleted file mode 100644
index 8e1285515d00..000000000000
--- a/.github/ISSUE_TEMPLATE/bug.md
+++ /dev/null
@@ -1,11 +0,0 @@
-Before opening:
-
-- [Search for duplicate or closed issues](https://github.com/twbs/bootstrap/issues?utf8=%E2%9C%93&q=is%3Aissue)
-- [Validate](https://html5.validator.nu/) and [lint](https://github.com/twbs/bootlint#in-the-browser) any HTML to avoid common problems
-- Read the [contributing guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md)
-
-Bug reports must include:
-
-- Operating system and version (Windows, macOS, Android, iOS, Win10 Mobile)
-- Browser and version (Chrome, Firefox, Safari, IE, MS Edge, Opera 15+, Android Browser)
-- [Reduced test case](https://css-tricks.com/reduced-test-cases/) and suggested fix using [CodePen](https://codepen.io/) or [JS Bin](https://jsbin.com/)
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index ab363e0cac6c..4899d4de20a3 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -1,17 +1,20 @@
---
name: Bug report
about: Tell us about a bug you may have identified in Bootstrap.
+title: ''
+labels: ''
+assignees: ''
---
Before opening:
- [Search for duplicate or closed issues](https://github.com/twbs/bootstrap/issues?utf8=%E2%9C%93&q=is%3Aissue)
-- [Validate](https://html5.validator.nu/) and [lint](https://github.com/twbs/bootlint#in-the-browser) any HTML to avoid common problems
-- Read the [contributing guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md)
+- [Validate](https://html5.validator.nu/) any HTML to avoid common problems
+- Read the [contributing guidelines](https://github.com/twbs/bootstrap/blob/v4-dev/.github/CONTRIBUTING.md)
Bug reports must include:
-- Operating system and version (Windows, macOS, Android, iOS, Win10 Mobile)
-- Browser and version (Chrome, Firefox, Safari, IE, MS Edge, Opera 15+, Android Browser)
-- [Reduced test case](https://css-tricks.com/reduced-test-cases/) and suggested fix using [CodePen](https://codepen.io/) or [JS Bin](https://jsbin.com/)
+- Operating system and version (Windows, macOS, Android, iOS)
+- Browser and version (Chrome, Firefox, Safari, Internet Explorer, Microsoft Edge, Opera, Android Browser)
+- A [reduced test case](https://css-tricks.com/reduced-test-cases/) or suggested fix using [CodePen](https://codepen.io/) or [JS Bin](https://jsbin.com/)
diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md
deleted file mode 100644
index 4f866e2141e9..000000000000
--- a/.github/ISSUE_TEMPLATE/feature.md
+++ /dev/null
@@ -1,9 +0,0 @@
-Before opening:
-
-- [Search for duplicate or closed issues](https://github.com/twbs/bootstrap/issues?utf8=%E2%9C%93&q=is%3Aissue)
-- Read the [contributing guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md)
-
-Feature requests must include:
-
-- As much detail as possible for what we should add and why it's important to Bootstrap
-- Relevant links to prior art, screenshots, or live demos whenever possible
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 389bd4345ae8..db44076d91f2 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -1,13 +1,16 @@
---
name: Feature request
about: Suggest an idea for a new feature in Bootstrap.
+title: ''
+labels: feature
+assignees: ''
---
Before opening:
- [Search for duplicate or closed issues](https://github.com/twbs/bootstrap/issues?utf8=%E2%9C%93&q=is%3Aissue)
-- Read the [contributing guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md)
+- Read the [contributing guidelines](https://github.com/twbs/bootstrap/blob/v4-dev/.github/CONTRIBUTING.md)
Feature requests must include:
diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md
index de3c4b552e9a..f54f4170dd15 100644
--- a/.github/SUPPORT.md
+++ b/.github/SUPPORT.md
@@ -7,5 +7,5 @@ See the [contributing guidelines](CONTRIBUTING.md) for sharing bug reports.
For general troubleshooting or help getting started:
- Join [the official Slack room](https://bootstrap-slack.herokuapp.com/).
-- Chat with fellow Bootstrappers in IRC. On the `irc.freenode.net` server, in the `##bootstrap` channel.
+- Chat with fellow Bootstrappers in IRC. On the `irc.libera.chat` server, in the `#bootstrap` channel.
- Ask and explore Stack Overflow with the [`bootstrap-4`](https://stackoverflow.com/questions/tagged/bootstrap-4) tag.
diff --git a/.github/workflows/browserstack.yml b/.github/workflows/browserstack.yml
new file mode 100644
index 000000000000..03be3f76d69e
--- /dev/null
+++ b/.github/workflows/browserstack.yml
@@ -0,0 +1,37 @@
+name: BrowserStack
+
+on:
+ push:
+ workflow_dispatch:
+
+env:
+ FORCE_COLOR: 2
+ NODE: 16
+
+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@v3
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: "${{ env.NODE }}"
+ cache: npm
+
+ - name: Install npm dependencies
+ run: npm ci
+
+ - name: Run dist
+ run: npm run dist
+
+ - name: Run BrowserStack tests
+ run: npm run js-test-cloud
+ env:
+ BROWSER_STACK_ACCESS_KEY: "${{ secrets.BROWSER_STACK_ACCESS_KEY }}"
+ BROWSER_STACK_USERNAME: "${{ secrets.BROWSER_STACK_USERNAME }}"
diff --git a/.github/workflows/bundlewatch.yml b/.github/workflows/bundlewatch.yml
new file mode 100644
index 000000000000..70c8a575e590
--- /dev/null
+++ b/.github/workflows/bundlewatch.yml
@@ -0,0 +1,38 @@
+name: Bundlewatch
+
+on:
+ push:
+ branches-ignore:
+ - "dependabot/**"
+ pull_request:
+ workflow_dispatch:
+
+env:
+ FORCE_COLOR: 2
+ NODE: 16
+
+jobs:
+ bundlewatch:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@v3
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: "${{ env.NODE }}"
+ cache: npm
+
+ - name: Install npm dependencies
+ run: npm ci
+
+ - name: Run dist
+ run: npm run dist
+
+ - name: Run bundlewatch
+ run: npm run bundlewatch
+ env:
+ BUNDLEWATCH_GITHUB_TOKEN: "${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}"
+ CI_BRANCH_BASE: v4-dev
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 000000000000..70be0563c91e
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,38 @@
+name: "CodeQL"
+
+on:
+ push:
+ branches:
+ - main
+ - v4-dev
+ - "!dependabot/**"
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches:
+ - main
+ - v4-dev
+ - "!dependabot/**"
+ schedule:
+ - cron: "0 2 * * 5"
+ workflow_dispatch:
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: "javascript"
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
diff --git a/.github/workflows/css.yml b/.github/workflows/css.yml
new file mode 100644
index 000000000000..857a5672cb35
--- /dev/null
+++ b/.github/workflows/css.yml
@@ -0,0 +1,32 @@
+name: CSS
+
+on:
+ push:
+ branches-ignore:
+ - "dependabot/**"
+ pull_request:
+ workflow_dispatch:
+
+env:
+ FORCE_COLOR: 2
+ NODE: 16
+
+jobs:
+ css:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@v3
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: "${{ env.NODE }}"
+ cache: npm
+
+ - name: Install npm dependencies
+ run: npm ci
+
+ - name: Build CSS
+ run: npm run css
diff --git a/.github/workflows/dart-sass.yml b/.github/workflows/dart-sass.yml
new file mode 100644
index 000000000000..1b74bb5304ad
--- /dev/null
+++ b/.github/workflows/dart-sass.yml
@@ -0,0 +1,31 @@
+name: CSS (Dart Sass)
+
+on:
+ push:
+ branches-ignore:
+ - "dependabot/**"
+ pull_request:
+ workflow_dispatch:
+
+env:
+ FORCE_COLOR: 2
+ NODE: 16
+
+jobs:
+ css:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@v3
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: "${{ env.NODE }}"
+
+ - name: Build CSS with Dart Sass
+ run: |
+ npx --package sass@latest sass --version
+ npx --package sass@latest sass --style expanded --source-map --embed-sources --no-error-css scss/:dist-sass/css/
+ ls -Al dist-sass/css
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 000000000000..f33413eb4b93
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,45 @@
+name: Docs
+
+on:
+ push:
+ branches-ignore:
+ - "dependabot/**"
+ pull_request:
+ workflow_dispatch:
+
+env:
+ FORCE_COLOR: 2
+ NODE: 16
+
+jobs:
+ docs:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@v3
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: "${{ env.NODE }}"
+ cache: npm
+
+ - run: java -version
+
+ - name: Install npm dependencies
+ run: npm ci
+
+ - name: Build docs
+ run: npm run docs-build
+
+ - name: Validate HTML
+ run: npm run docs-vnu
+
+ - name: Run linkinator
+ uses: JustinBeckwith/linkinator-action@v1
+ with:
+ paths: _site
+ recurse: true
+ verbosity: error
+ skip: "^(?!http://localhost)"
diff --git a/.github/workflows/js.yml b/.github/workflows/js.yml
new file mode 100644
index 000000000000..82616c5743dd
--- /dev/null
+++ b/.github/workflows/js.yml
@@ -0,0 +1,42 @@
+name: JS Tests
+
+on:
+ push:
+ branches-ignore:
+ - "dependabot/**"
+ pull_request:
+ workflow_dispatch:
+
+env:
+ FORCE_COLOR: 2
+ NODE: 16
+
+jobs:
+ run:
+ name: JS Tests
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@v3
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: ${{ env.NODE }}
+ cache: npm
+
+ - name: Install npm dependencies
+ run: npm ci
+
+ - name: Run dist
+ run: npm run js
+
+ - name: Run JS tests
+ run: npm run js-test
+
+ - name: Run Coveralls
+ uses: coverallsapp/github-action@1.1.3
+ with:
+ github-token: "${{ secrets.GITHUB_TOKEN }}"
+ path-to-lcov: "./js/coverage/lcov.info"
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
new file mode 100644
index 000000000000..816694ec2864
--- /dev/null
+++ b/.github/workflows/lint.yml
@@ -0,0 +1,32 @@
+name: Lint
+
+on:
+ push:
+ branches-ignore:
+ - "dependabot/**"
+ pull_request:
+ workflow_dispatch:
+
+env:
+ FORCE_COLOR: 2
+ NODE: 16
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@v3
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: "${{ env.NODE }}"
+ cache: npm
+
+ - name: Install npm dependencies
+ run: npm ci
+
+ - name: Lint
+ run: npm run lint
diff --git a/.gitignore b/.gitignore
index 6b4387736144..2215d636addf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,8 @@
# Ignore docs files
-_gh_pages
-_site
-site/docs/**/dist/
-
-# Ignore ruby files
-.ruby-version
-.bundle
-vendor/cache
-vendor/bundle
+/_site/
+# Hugo files
+/resources/
+/.hugo_build.lock
# Numerous always-ignore extensions
*.diff
@@ -34,14 +29,14 @@ vendor/bundle
*.sublime-workspace
nbproject
Thumbs.db
+/.vscode/
+# Local Netlify folder
+.netlify
# Komodo
.komodotools
*.komodoproject
-# Jekyll metadata
-docs/.jekyll-metadata
-
# Folders to ignore
-node_modules
-js/coverage
+/js/coverage/
+/node_modules/
diff --git a/.stylelintignore b/.stylelintignore
index 7bc488e5f871..0759a69acead 100644
--- a/.stylelintignore
+++ b/.stylelintignore
@@ -1,4 +1,5 @@
**/*.min.css
**/dist/
**/vendor/
-/_gh_pages/
+/_site/
+/js/coverage/
diff --git a/.stylelintrc b/.stylelintrc
index fce97867fc27..b948fe8e298a 100644
--- a/.stylelintrc
+++ b/.stylelintrc
@@ -1,328 +1,22 @@
{
"extends": [
- "stylelint-config-standard",
- "stylelint-config-recommended-scss"
- ],
- "plugins": [
- "stylelint-order"
+ "stylelint-config-twbs-bootstrap"
],
"rules": {
- "at-rule-empty-line-before": null,
- "at-rule-name-space-after": "always",
- "at-rule-no-unknown": null,
- "at-rule-no-vendor-prefix": true,
- "at-rule-semicolon-space-before": "never",
- "block-closing-brace-empty-line-before": null,
- "block-closing-brace-newline-after": null,
- "block-opening-brace-space-before": null,
- "color-named": "never",
- "declaration-block-semicolon-newline-after": "always-multi-line",
- "declaration-block-semicolon-newline-before": "never-multi-line",
- "declaration-block-semicolon-space-after": "always-single-line",
- "declaration-empty-line-before": null,
- "declaration-no-important": true,
- "font-family-name-quotes": "always-where-recommended",
- "font-weight-notation": [
- "numeric",
- {
- "ignore": [
- "relative"
- ]
- }
- ],
- "function-url-no-scheme-relative": true,
- "function-url-quotes": "always",
- "length-zero-no-unit": true,
- "max-empty-lines": 2,
- "max-line-length": null,
- "media-feature-name-no-unknown": [
- true,
- {
- "ignoreMediaFeatureNames": [
- "prefers-reduced-motion"
- ]
- }
+ "declaration-property-value-disallowed-list": {
+ "border": "none",
+ "outline": "none"
+ },
+ "function-disallowed-list": [
+ "calc"
],
- "media-feature-name-no-vendor-prefix": true,
- "media-feature-parentheses-space-inside": "never",
- "media-feature-range-operator-space-after": "always",
- "media-feature-range-operator-space-before": "never",
- "no-descending-specificity": null,
- "no-duplicate-selectors": true,
- "number-leading-zero": "never",
- "order/properties-order": [
- "position",
- "top",
- "right",
- "bottom",
- "left",
- "z-index",
- "box-sizing",
- "display",
- "flex",
- "flex-align",
- "flex-basis",
- "flex-direction",
- "flex-wrap",
- "flex-flow",
- "flex-shrink",
- "flex-grow",
- "flex-order",
- "flex-pack",
- "align-content",
- "align-items",
- "align-self",
- "justify-content",
- "order",
- "float",
- "width",
- "min-width",
- "max-width",
- "height",
- "min-height",
- "max-height",
- "padding",
- "padding-top",
- "padding-right",
- "padding-bottom",
- "padding-left",
- "margin",
- "margin-top",
- "margin-right",
- "margin-bottom",
- "margin-left",
- "overflow",
- "overflow-x",
- "overflow-y",
- "-webkit-overflow-scrolling",
- "-ms-overflow-x",
- "-ms-overflow-y",
- "-ms-overflow-style",
- "columns",
- "column-count",
- "column-fill",
- "column-gap",
- "column-rule",
- "column-rule-width",
- "column-rule-style",
- "column-rule-color",
- "column-span",
- "column-width",
- "orphans",
- "widows",
- "clip",
- "clear",
- "font",
- "font-family",
- "font-size",
- "font-style",
- "font-weight",
- "font-variant",
- "font-size-adjust",
- "font-stretch",
- "font-effect",
- "font-emphasize",
- "font-emphasize-position",
- "font-emphasize-style",
- "font-smooth",
- "src",
- "hyphens",
- "line-height",
- "color",
- "text-align",
- "text-align-last",
- "text-emphasis",
- "text-emphasis-color",
- "text-emphasis-style",
- "text-emphasis-position",
- "text-decoration",
- "text-indent",
- "text-justify",
- "text-outline",
- "-ms-text-overflow",
- "text-overflow",
- "text-overflow-ellipsis",
- "text-overflow-mode",
- "text-shadow",
- "text-transform",
- "text-wrap",
- "-webkit-text-size-adjust",
- "-ms-text-size-adjust",
- "letter-spacing",
- "-ms-word-break",
- "word-break",
- "word-spacing",
- "-ms-word-wrap",
- "word-wrap",
- "overflow-wrap",
- "tab-size",
- "white-space",
- "vertical-align",
- "direction",
- "unicode-bidi",
- "list-style",
- "list-style-position",
- "list-style-type",
- "list-style-image",
- "pointer-events",
- "-ms-touch-action",
- "touch-action",
- "cursor",
- "visibility",
- "zoom",
- "table-layout",
- "empty-cells",
- "caption-side",
- "border-spacing",
- "border-collapse",
- "content",
- "quotes",
- "counter-reset",
- "counter-increment",
- "resize",
- "user-select",
- "nav-index",
- "nav-up",
- "nav-right",
- "nav-down",
- "nav-left",
- "background",
- "background-color",
- "background-image",
- "filter",
- "background-repeat",
- "background-attachment",
- "background-position",
- "background-position-x",
- "background-position-y",
- "background-clip",
- "background-origin",
- "background-size",
- "border",
- "border-color",
- "border-style",
- "border-width",
- "border-top",
- "border-top-color",
- "border-top-style",
- "border-top-width",
- "border-right",
- "border-right-color",
- "border-right-style",
- "border-right-width",
- "border-bottom",
- "border-bottom-color",
- "border-bottom-style",
- "border-bottom-width",
- "border-left",
- "border-left-color",
- "border-left-style",
- "border-left-width",
- "border-radius",
- "border-top-left-radius",
- "border-top-right-radius",
- "border-bottom-right-radius",
- "border-bottom-left-radius",
- "border-image",
- "border-image-source",
- "border-image-slice",
- "border-image-width",
- "border-image-outset",
- "border-image-repeat",
- "outline",
- "outline-width",
- "outline-style",
- "outline-color",
- "outline-offset",
- "box-shadow",
- "opacity",
- "-ms-interpolation-mode",
- "page-break-after",
- "page-break-before",
- "page-break-inside",
- "transition",
- "transition-delay",
- "transition-timing-function",
- "transition-duration",
- "transition-property",
- "transform",
- "transform-origin",
- "perspective",
- "appearance",
- "animation",
- "animation-name",
- "animation-duration",
- "animation-play-state",
- "animation-timing-function",
- "animation-delay",
- "animation-iteration-count",
- "animation-direction",
- "animation-fill-mode",
- "fill",
- "stroke"
- ],
- "property-blacklist": [
+ "property-disallowed-list": [
"border-radius",
"border-top-left-radius",
"border-top-right-radius",
"border-bottom-right-radius",
"border-bottom-left-radius",
"transition"
- ],
- "property-no-vendor-prefix": true,
- "rule-empty-line-before": null,
- "scss/at-function-named-arguments": "never",
- "scss/at-function-parentheses-space-before": "never",
- "scss/at-import-no-partial-leading-underscore": true,
- "scss/at-mixin-argumentless-call-parentheses": null,
- "scss/at-mixin-named-arguments": null,
- "scss/at-mixin-parentheses-space-before": "never",
- "scss/at-rule-no-unknown": true,
- "scss/dollar-variable-colon-space-after": "at-least-one-space",
- "scss/dollar-variable-colon-space-before": "never",
- "scss/dollar-variable-default": [
- true,
- {
- "ignore": "local"
- }
- ],
- "scss/dollar-variable-no-missing-interpolation": true,
- "scss/media-feature-value-dollar-variable": null,
- "scss/no-duplicate-dollar-variables": [
- null,
- {
- "ignoreInsideAtRules": [
- "if",
- "mixin"
- ]
- }
- ],
- "scss/operator-no-newline-after": true,
- "scss/operator-no-newline-before": true,
- "scss/operator-no-unspaced": true,
- "selector-attribute-quotes": "always",
- "selector-class-pattern": "^[a-z][a-z0-9\\-]*[a-z0-9]$",
- "selector-list-comma-newline-after": "always",
- "selector-list-comma-newline-before": "never-multi-line",
- "selector-list-comma-space-after": "always-single-line",
- "selector-list-comma-space-before": "never-single-line",
- "selector-max-attribute": 2,
- "selector-max-class": 4,
- "selector-max-combinators": 4,
- "selector-max-compound-selectors": 4,
- "selector-max-empty-lines": 1,
- "selector-max-id": 0,
- "selector-max-specificity": null,
- "selector-max-type": 2,
- "selector-max-universal": 1,
- "selector-no-qualifying-type": true,
- "selector-no-vendor-prefix": true,
- "shorthand-property-no-redundant-values": true,
- "string-quotes": "double",
- "value-keyword-case": "lower",
- "value-list-comma-newline-after": "never-multi-line",
- "value-list-comma-newline-before": "never-multi-line",
- "value-list-comma-space-after": "always",
- "value-no-vendor-prefix": true
+ ]
}
}
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index b8d19ad258ec..000000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-addons:
- chrome: stable
-language: node_js
-git:
- depth: 3
-node_js:
- - "6"
- - "8"
-install:
- - bundle install --deployment --jobs=3 --retry=3 --clean
- - npm install
-before_script:
- - google-chrome-stable --product-version
-script:
- - npm test || travis_terminate 1
- - if [[ "$TRAVIS_NODE_VERSION" = "8" ]]; then npm run check-broken-links; fi
- - if [[ "$TRAVIS_NODE_VERSION" = "8" && "$TRAVIS_EVENT_TYPE" = "push" && ! `git log --format=%B --no-merges -n 1 | grep '\[skip browser\]'` ]]; then npm run js-test-cloud; fi
-after_success:
- - if [[ "$TRAVIS_NODE_VERSION" = "8" ]]; then npm run coveralls; fi
-cache:
- directories:
- - node_modules
- - vendor/bundle
-notifications:
- email: false
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 9d9922f25f4d..0d2e5269557a 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -40,7 +40,4 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai
## Attribution
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html][version]
-
-[homepage]: https://www.contributor-covenant.org/
-[version]: https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 1.4, available at
Sleek, intuitive, and powerful front-end framework for faster and easier web development.
- Explore Bootstrap docs »
+ Explore Bootstrap docs »
- Report bug
+ Report bug
·
- Request feature
+ Request feature
·
Themes
·
@@ -41,38 +41,38 @@
Several quick start options are available:
-- [Download the latest release.](https://github.com/twbs/bootstrap/archive/v4.2.1.zip)
+- [Download the latest release.](https://github.com/twbs/bootstrap/archive/v4.6.2.zip)
- Clone the repo: `git clone https://github.com/twbs/bootstrap.git`
- Install with [npm](https://www.npmjs.com/): `npm install bootstrap`
-- Install with [yarn](https://yarnpkg.com/): `yarn add bootstrap@4.2.1`
-- Install with [Composer](https://getcomposer.org/): `composer require twbs/bootstrap:4.2.1`
+- Install with [yarn](https://yarnpkg.com/): `yarn add bootstrap@4.6.2`
+- Install with [Composer](https://getcomposer.org/): `composer require twbs/bootstrap:4.6.2`
- Install with [NuGet](https://www.nuget.org/): CSS: `Install-Package bootstrap` Sass: `Install-Package bootstrap.sass`
-Read the [Getting started page](https://getbootstrap.com/docs/4.2/getting-started/introduction/) for information on the framework contents, templates and examples, and more.
+Read the [Getting started page](https://getbootstrap.com/docs/4.6/getting-started/introduction/) for information on the framework contents, templates and examples, and more.
## Status
[](https://bootstrap-slack.herokuapp.com/)
-[](https://travis-ci.org/twbs/bootstrap)
-[](https://www.npmjs.com/package/bootstrap)
-[](https://rubygems.org/gems/bootstrap)
-[](https://atmospherejs.com/twbs/bootstrap)
-[](https://packagist.org/packages/twbs/bootstrap)
-[](https://www.nuget.org/packages/bootstrap/absoluteLatest)
-[](https://david-dm.org/twbs/bootstrap?type=peer)
-[](https://david-dm.org/twbs/bootstrap?type=dev)
-[](https://coveralls.io/github/twbs/bootstrap?branch=v4-dev)
-[](https://github.com/twbs/bootstrap/tree/v4-dev/dist/css/bootstrap.min.css)
-[](https://github.com/twbs/bootstrap/tree/v4-dev/dist/js/bootstrap.min.js)
+[](https://github.com/twbs/bootstrap/actions?query=workflow%3AJS+Tests+branch%3Av4-dev)
+[](https://www.npmjs.com/package/bootstrap)
+[](https://rubygems.org/gems/bootstrap)
+[](https://atmospherejs.com/twbs/bootstrap)
+[](https://packagist.org/packages/twbs/bootstrap)
+[](https://www.nuget.org/packages/bootstrap/absoluteLatest)
+[](https://coveralls.io/github/twbs/bootstrap?branch=v4-dev)
+[](https://github.com/twbs/bootstrap/blob/v4-dev/dist/css/bootstrap.min.css)
+[](https://github.com/twbs/bootstrap/blob/v4-dev/dist/js/bootstrap.min.js)
[](https://www.browserstack.com/automate/public-build/SkxZcStBeExEdVJqQ2hWYnlWckpkNmNEY213SFp6WHFETWk2bGFuY3pCbz0tLXhqbHJsVlZhQnRBdEpod3NLSDMzaHc9PQ==--3d0b75245708616eb93113221beece33e680b229)
-[](#backers)
-[](#sponsors)
+[](#backers)
+[](#sponsors)
## What's included
-Within the download you'll find the following directories and files, logically grouping common assets and providing both compiled and minified variations. You'll see something like this:
+Within the download you'll find the following directories and files, logically grouping common assets and providing both compiled and minified variations.
+
+Download contents
```text
bootstrap/
@@ -100,48 +100,45 @@ bootstrap/
├── bootstrap.min.js
└── bootstrap.min.js.map
```
+
+
Thanks to [BrowserStack](https://www.browserstack.com/) for providing the infrastructure that allows us to test in real browsers!
-## Backers
-
-Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/bootstrap#backer)]
-
-[](https://opencollective.com/bootstrap#backers)
-
-
## Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/bootstrap#sponsor)]
@@ -208,6 +198,13 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
[](https://opencollective.com/bootstrap/sponsor/9/website)
+## Backers
+
+Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/bootstrap#backer)]
+
+[](https://opencollective.com/bootstrap#backers)
+
+
## Copyright and license
-Code and documentation copyright 2011-2018 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/master/LICENSE). Docs released under [Creative Commons](https://github.com/twbs/bootstrap/blob/master/docs/LICENSE).
+Code and documentation copyright 2011-2022 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/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000000..e79dcd8d2038
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,7 @@
+# Reporting Security Issues
+
+The Bootstrap team and community take security issues in Bootstrap seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
+
+To report a security issue, email [security@getbootstrap.com](mailto:security@getbootstrap.com) and include the word "SECURITY" in the subject line.
+
+We'll endeavor to respond quickly, and will keep you updated throughout the process.
diff --git a/_config.yml b/_config.yml
deleted file mode 100644
index 10c4b4a58e40..000000000000
--- a/_config.yml
+++ /dev/null
@@ -1,68 +0,0 @@
-# Dependencies
-markdown: kramdown
-highlighter: rouge
-
-kramdown:
- auto_ids: true
-
-# Permalinks
-permalink: pretty
-
-# Server
-source: "site"
-destination: ./_gh_pages
-host: "localhost"
-port: 9001
-baseurl: ""
-url: "https://getbootstrap.com"
-encoding: UTF-8
-exclude:
- - docs/4.2/assets/scss/
-
-plugins:
- - jekyll-redirect-from
- - jekyll-sitemap
- - jekyll-toc
-
-# Social
-title: Bootstrap
-description: "The most popular HTML, CSS, and JS library in the world."
-twitter: getbootstrap
-authors: "Mark Otto, Jacob Thornton, and Bootstrap contributors"
-social_image_path: /docs/4.2/assets/brand/bootstrap-social.png
-social_logo_path: /docs/4.2/assets/brand/bootstrap-social-logo.png
-
-# Custom variables
-current_version: 4.2.1
-current_ruby_version: 4.2.1
-docs_version: 4.2
-repo: "https://github.com/twbs/bootstrap"
-slack: "https://bootstrap-slack.herokuapp.com"
-opencollective: "https://opencollective.com/bootstrap"
-blog: "https://blog.getbootstrap.com"
-expo: "https://expo.getbootstrap.com"
-themes: "https://themes.getbootstrap.com"
-
-download:
- source: "https://github.com/twbs/bootstrap/archive/v4.2.1.zip"
- dist: "https://github.com/twbs/bootstrap/releases/download/v4.2.1/bootstrap-4.2.1-dist.zip"
-
-cdn:
- # See https://www.srihash.org for info on how to generate the hashes
- css: "https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
- css_hash: "sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
- js: "https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"
- js_hash: "sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k"
- js_bundle: "https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.bundle.min.js"
- js_bundle_hash: "sha384-zDnhMsjVZfS3hiP7oCBRmfjkQC4fzxVxFhBx8Hkz2aZX8gEvA/jsP3eXRCvzTofP"
- jquery: "https://code.jquery.com/jquery-3.3.1.slim.min.js"
- jquery_hash: "sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
- popper: "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js"
- popper_hash: "sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut"
-
-toc:
- min_level: 2
- max_level: 4
- no_toc_section_class:
- - "bd-callout"
- - "bd-example"
diff --git a/build/.eslintrc.json b/build/.eslintrc.json
index 76e7f37b6348..679bd26f7ba2 100644
--- a/build/.eslintrc.json
+++ b/build/.eslintrc.json
@@ -8,13 +8,7 @@
},
"extends": "../.eslintrc.json",
"rules": {
- "consistent-return": "off",
- "func-style": "off",
"no-console": "off",
- "no-magic-numbers": "off",
- "no-process-env": "off",
- "no-process-exit": "off",
- "no-sync": "off",
- "spaced-comment": "off"
+ "strict": "error"
}
}
diff --git a/build/banner.js b/build/banner.js
index 453fc3b6e0b2..df82ff32edf3 100644
--- a/build/banner.js
+++ b/build/banner.js
@@ -7,7 +7,7 @@ function getBanner(pluginFilename) {
return `/*!
* Bootstrap${pluginFilename ? ` ${pluginFilename}` : ''} v${pkg.version} (${pkg.homepage})
* Copyright 2011-${year} ${pkg.author}
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/`
}
diff --git a/build/build-plugins.js b/build/build-plugins.js
index 3240ee5d0538..9e33ddb655c6 100644
--- a/build/build-plugins.js
+++ b/build/build-plugins.js
@@ -1,28 +1,26 @@
+#!/usr/bin/env node
+
/*!
* Script to build our plugins to use them separately.
- * Copyright 2018 The Bootstrap Authors
- * Copyright 2018 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * Copyright 2020-2022 The Bootstrap Authors
+ * Copyright 2020-2022 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
'use strict'
-const path = require('path')
-const rollup = require('rollup')
-const babel = require('rollup-plugin-babel')
-const banner = require('./banner.js')
+const path = require('path')
+const rollup = require('rollup')
+const { babel } = require('@rollup/plugin-babel')
+const banner = require('./banner.js')
-const TEST = process.env.NODE_ENV === 'test'
+const TEST = process.env.NODE_ENV === 'test'
const plugins = [
babel({
- exclude: 'node_modules/**', // Only transpile our source code
- externalHelpersWhitelist: [ // Include only required helpers
- 'defineProperties',
- 'createClass',
- 'inheritsLoose',
- 'defineProperty',
- 'objectSpread'
- ]
+ // Only transpile our source code
+ exclude: 'node_modules/**',
+ // Include the helpers in each file, at most one copy of each
+ babelHelpers: 'bundled'
})
]
const bsPlugins = {
@@ -41,7 +39,7 @@ const bsPlugins = {
}
const rootPath = TEST ? '../js/coverage/dist/' : '../js/dist/'
-function build(plugin) {
+const build = async plugin => {
console.log(`Building ${plugin} plugin...`)
const external = ['jquery', 'popper.js']
@@ -63,23 +61,32 @@ function build(plugin) {
}
const pluginFilename = `${plugin.toLowerCase()}.js`
-
- rollup.rollup({
+ const bundle = await rollup.rollup({
input: bsPlugins[plugin],
plugins,
external
- }).then((bundle) => {
- bundle.write({
- banner: banner(pluginFilename),
- format: 'umd',
- name: plugin,
- sourcemap: true,
- globals,
- file: path.resolve(__dirname, `${rootPath}${pluginFilename}`)
- })
- .then(() => console.log(`Building ${plugin} plugin... Done!`))
- .catch((err) => console.error(`${plugin}: ${err}`))
})
+
+ await bundle.write({
+ banner: banner(pluginFilename),
+ format: 'umd',
+ name: plugin,
+ sourcemap: true,
+ globals,
+ file: path.resolve(__dirname, `${rootPath}${pluginFilename}`)
+ })
+
+ console.log(`Building ${plugin} plugin... Done!`)
+}
+
+const main = async () => {
+ try {
+ await Promise.all(Object.keys(bsPlugins).map(plugin => build(plugin)))
+ } catch (error) {
+ console.error(error)
+
+ process.exit(1)
+ }
}
-Object.keys(bsPlugins).forEach((plugin) => build(plugin))
+main()
diff --git a/build/change-version.js b/build/change-version.js
old mode 100755
new mode 100644
index 7102dc0830d2..e035eba952ea
--- a/build/change-version.js
+++ b/build/change-version.js
@@ -2,103 +2,80 @@
/*!
* Script to update version number references in the project.
- * Copyright 2017-2018 The Bootstrap Authors
- * Copyright 2017-2018 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * Copyright 2017-2022 The Bootstrap Authors
+ * Copyright 2017-2022 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
'use strict'
-const fs = require('fs')
+const fs = require('fs').promises
const path = require('path')
-const sh = require('shelljs')
+const globby = require('globby')
-sh.config.fatal = true
+const VERBOSE = process.argv.includes('--verbose')
+const DRY_RUN = process.argv.includes('--dry') || process.argv.includes('--dry-run')
+
+// These are the filetypes we only care about replacing the version
+const GLOB = [
+ '**/*.{css,html,js,json,md,scss,txt,yml}'
+]
+const GLOBBY_OPTIONS = {
+ cwd: path.join(__dirname, '..'),
+ gitignore: true
+}
// Blame TC39... https://github.com/benjamingr/RegExp.escape/issues/37
function regExpQuote(string) {
- return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&')
+ return string.replace(/[$()*+.?[\\\]^{|}-]/g, '\\$&')
}
function regExpQuoteReplacement(string) {
- return string.replace(/[$]/g, '$$')
+ return string.replace(/\$/g, '$$')
}
-const DRY_RUN = false
+async function replaceRecursively(file, oldVersion, newVersion) {
+ const originalString = await fs.readFile(file, 'utf8')
+ const newString = originalString.replace(
+ new RegExp(regExpQuote(oldVersion), 'g'), regExpQuoteReplacement(newVersion)
+ )
-function walkAsync(directory, excludedDirectories, fileCallback, errback) {
- if (excludedDirectories.has(path.parse(directory).base)) {
+ // No need to move any further if the strings are identical
+ if (originalString === newString) {
return
}
- fs.readdir(directory, (err, names) => {
- if (err) {
- errback(err)
- return
- }
- names.forEach((name) => {
- const filepath = path.join(directory, name)
- fs.lstat(filepath, (err, stats) => {
- if (err) {
- process.nextTick(errback, err)
- return
- }
- if (stats.isDirectory()) {
- process.nextTick(walkAsync, filepath, excludedDirectories, fileCallback, errback)
- } else if (stats.isFile()) {
- process.nextTick(fileCallback, filepath)
- }
- })
- })
- })
-}
-function replaceRecursively(directory, excludedDirectories, allowedExtensions, original, replacement) {
- original = new RegExp(regExpQuote(original), 'g')
- replacement = regExpQuoteReplacement(replacement)
- const updateFile = DRY_RUN ? (filepath) => {
- if (allowedExtensions.has(path.parse(filepath).ext)) {
- console.log(`FILE: ${filepath}`)
- } else {
- console.log(`EXCLUDED:${filepath}`)
- }
- } : (filepath) => {
- if (allowedExtensions.has(path.parse(filepath).ext)) {
- sh.sed('-i', original, replacement, filepath)
- }
+ if (VERBOSE) {
+ console.log(`FILE: ${file}`)
}
- walkAsync(directory, excludedDirectories, updateFile, (err) => {
- console.error('ERROR while traversing directory!:')
- console.error(err)
- process.exit(1)
- })
+
+ if (DRY_RUN) {
+ return
+ }
+
+ await fs.writeFile(file, newString, 'utf8')
}
-function main(args) {
- if (args.length !== 2) {
- console.error('USAGE: change-version old_version new_version')
+async function main(args) {
+ let [oldVersion, newVersion] = args
+
+ if (!oldVersion || !newVersion) {
+ console.error('USAGE: change-version old_version new_version [--verbose] [--dry[-run]]')
console.error('Got arguments:', args)
process.exit(1)
}
- const oldVersion = args[0]
- const newVersion = args[1]
- const EXCLUDED_DIRS = new Set([
- '.git',
- 'node_modules',
- 'vendor'
- ])
- const INCLUDED_EXTENSIONS = new Set([
- // This extension whitelist is how we avoid modifying binary files
- '',
- '.css',
- '.html',
- '.js',
- '.json',
- '.md',
- '.scss',
- '.txt',
- '.yml'
- ])
- replaceRecursively('.', EXCLUDED_DIRS, INCLUDED_EXTENSIONS, oldVersion, newVersion)
+
+ // Strip any leading `v` from arguments because otherwise we will end up with duplicate `v`s
+ [oldVersion, newVersion] = [oldVersion, newVersion].map(arg => arg.startsWith('v') ? arg.slice(1) : arg)
+
+ try {
+ const files = await globby(GLOB, GLOBBY_OPTIONS)
+
+ await Promise.all(files.map(file => replaceRecursively(file, oldVersion, newVersion)))
+ } catch (error) {
+ console.error(error)
+ process.exit(1)
+ }
}
main(process.argv.slice(2))
diff --git a/build/generate-sri.js b/build/generate-sri.js
index 309f29bd287b..9685899261f8 100644
--- a/build/generate-sri.js
+++ b/build/generate-sri.js
@@ -5,9 +5,9 @@
* Remember to use the same vendor files as the CDN ones,
* otherwise the hashes won't match!
*
- * Copyright 2017-2018 The Bootstrap Authors
- * Copyright 2017-2018 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * Copyright 2017-2022 The Bootstrap Authors
+ * Copyright 2017-2022 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
'use strict'
@@ -21,11 +21,11 @@ const pkg = require('../package.json')
sh.config.fatal = true
-const configFile = path.join(__dirname, '../_config.yml')
+const configFile = path.join(__dirname, '../config.yml')
// Array of objects which holds the files to generate SRI hashes for.
// `file` is the path from the root folder
-// `configPropertyName` is the _config.yml variable's name of the file
+// `configPropertyName` is the config.yml variable's name of the file
const files = [
{
file: 'dist/css/bootstrap.min.css',
@@ -35,21 +35,21 @@ const files = [
file: 'dist/js/bootstrap.min.js',
configPropertyName: 'js_hash'
},
- {
- file: `site/docs/${pkg.version_short}/assets/js/vendor/jquery-slim.min.js`,
- configPropertyName: 'jquery_hash'
- },
{
file: 'dist/js/bootstrap.bundle.min.js',
configPropertyName: 'js_bundle_hash'
},
+ {
+ file: `site/static/docs/${pkg.config.version_short}/assets/js/vendor/jquery.slim.min.js`,
+ configPropertyName: 'jquery_hash'
+ },
{
file: 'node_modules/popper.js/dist/umd/popper.min.js',
configPropertyName: 'popper_hash'
}
]
-files.forEach((file) => {
+files.forEach(file => {
fs.readFile(file.file, 'utf8', (err, data) => {
if (err) {
throw err
@@ -61,6 +61,6 @@ files.forEach((file) => {
console.log(`${file.configPropertyName}: ${integrity}`)
- sh.sed('-i', new RegExp(`(\\s${file.configPropertyName}:\\s+"|')(\\S+)("|')`), `$1${integrity}$3`, configFile)
+ sh.sed('-i', new RegExp(`^(\\s+${file.configPropertyName}:\\s+["'])\\S*(["'])`), `$1${integrity}$2`, configFile)
})
})
diff --git a/build/postcss.config.js b/build/postcss.config.js
index 157291ffd2e2..ef416258f7fc 100644
--- a/build/postcss.config.js
+++ b/build/postcss.config.js
@@ -1,14 +1,18 @@
'use strict'
-module.exports = (ctx) => ({
- map: ctx.file.dirname.includes('examples') ? false : {
- inline: false,
- annotation: true,
- sourcesContent: true
- },
- plugins: {
- autoprefixer: {
- cascade: false
+module.exports = ctx => {
+ return {
+ map: ctx.file.dirname.includes('examples') ?
+ false :
+ {
+ inline: false,
+ annotation: true,
+ sourcesContent: true
+ },
+ plugins: {
+ autoprefixer: {
+ cascade: false
+ }
}
}
-})
+}
diff --git a/build/rollup.config.js b/build/rollup.config.js
index e81a07ef58b2..e2d2b125efe6 100644
--- a/build/rollup.config.js
+++ b/build/rollup.config.js
@@ -1,24 +1,20 @@
'use strict'
-const path = require('path')
-const babel = require('rollup-plugin-babel')
-const resolve = require('rollup-plugin-node-resolve')
-const banner = require('./banner.js')
+const path = require('path')
+const { babel } = require('@rollup/plugin-babel')
+const { nodeResolve } = require('@rollup/plugin-node-resolve')
+const banner = require('./banner.js')
-const BUNDLE = process.env.BUNDLE === 'true'
+const BUNDLE = process.env.BUNDLE === 'true'
-let fileDest = 'bootstrap.js'
+let fileDest = 'bootstrap.js'
const external = ['jquery', 'popper.js']
const plugins = [
babel({
- exclude: 'node_modules/**', // Only transpile our source code
- externalHelpersWhitelist: [ // Include only required helpers
- 'defineProperties',
- 'createClass',
- 'inheritsLoose',
- 'defineProperty',
- 'objectSpread'
- ]
+ // Only transpile our source code
+ exclude: 'node_modules/**',
+ // Include the helpers in the bundle, at most one copy of each
+ babelHelpers: 'bundled'
})
]
const globals = {
@@ -31,11 +27,11 @@ if (BUNDLE) {
// Remove last entry in external array to bundle Popper
external.pop()
delete globals['popper.js']
- plugins.push(resolve())
+ plugins.push(nodeResolve())
}
module.exports = {
- input: path.resolve(__dirname, '../js/src/index.js'),
+ input: path.resolve(__dirname, '../js/index.js'),
output: {
banner,
file: path.resolve(__dirname, `../dist/js/${fileDest}`),
diff --git a/build/ship.sh b/build/ship.sh
deleted file mode 100755
index 2892843839cd..000000000000
--- a/build/ship.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env bash
-#
-# Usage
-# ---------------
-# 1. Clone second version of Bootstrap in sibling directory named `bs-docs`.
-# 2. Within `bs-docs` copy, switch to `gh-pages` branch.
-# 3. Pull latest, re-bundle, re-npm.
-# 4. Run script.
-
-red=$'\e[1;31m'
-green=$'\e[1;32m'
-#blue=$'\e[1;34m'
-magenta=$'\e[1;35m'
-#cyan=$'\e[1;36m'
-end=$'\e[0m'
-
-# Get current version from package.json
-current_version=$(node -p "require('./package.json').version")
-
-if [[ $# -lt 1 ]]; then
- printf "\n%s⚠️ Shipping aborted. You must specify a version.\n%s" $red $end
- exit 1
-fi
-
-# Pulling latest changes, just to be sure
-printf "\n%s=======================================================%s" $magenta $end
-printf "\n%sPulling latest changes...%s" $magenta $end
-printf "\n%s=======================================================\n\n%s" $magenta $end
-git pull origin v4-dev
-
-# Update version number
-printf "\n%s=======================================================%s" $magenta $end
-printf "\n%sUpdating version number...%s" $magenta $end
-printf "\n%s=======================================================\n%s" $magenta $end
-npm run release-version "$current_version" "$1"
-
-# Build release
-printf "\n%s=======================================================%s" $magenta $end
-printf "\n%sBuilding release...%s" $magenta $end
-printf "\n%s=======================================================\n%s" $magenta $end
-npm run release
-
-# Copy the contents of the built docs site over to `bs-docs` repo
-printf "\n%s=======================================================%s" $magenta $end
-printf "\n%sCopy it over...%s" $magenta $end
-printf "\n%s=======================================================\n%s" $magenta $end
-cp -rf _gh_pages/. ../bs-docs/
-printf "\nDone!\n"
-
-printf "\n%s=======================================================%s" $green $end
-printf "\n%sSuccess, $1 is ready to review and publish.%s" $green $end
-printf "\n%s=======================================================\n\n%s" $green $end
diff --git a/build/svgo.yml b/build/svgo.yml
deleted file mode 100644
index 047e6947f0ce..000000000000
--- a/build/svgo.yml
+++ /dev/null
@@ -1,57 +0,0 @@
-# Usage:
-# install svgo globally: `npm i -g svgo`
-# svgo --config=build/svgo.yml --input=foo.svg
-
-# https://github.com/svg/svgo/blob/master/docs/how-it-works/en.md
-# replace default config
-
-multipass: true
-#full: true
-
-# https://github.com/svg/svgo/blob/master/lib/svgo/js2svg.js#L6 for more config options
-
-js2svg:
- pretty: true
- indent: 2
-
-plugins:
- # remove this with IE 11 is no longer supported
- - addAttributesToSVGElement:
- attributes:
- - focusable: false
- - cleanupAttrs: true
- - cleanupEnableBackground: true
- - cleanupIDs: true
- - cleanupListOfValues: true
- - cleanupNumericValues: true
- - collapseGroups: true
- - convertColors: true
- - convertPathData: true
- - convertShapeToPath: true
- - convertStyleToAttrs: true
- - convertTransform: true
- - inlineStyles: true
- - mergePaths: true
- - minifyStyles: true
- - moveElemsAttrsToGroup: true
- - moveGroupAttrsToElems: true
- - removeComments: true
- - removeDesc: true
- - removeDoctype: true
- - removeEditorsNSData: true
- - removeEmptyAttrs: true
- - removeEmptyContainers: true
- - removeEmptyText: true
- - removeHiddenElems: true
- - removeMetadata: true
- - removeNonInheritableGroupAttrs: true
- - removeTitle: false
- - removeUnknownsAndDefaults:
- keepRoleAttr: true
- - removeUnusedNS: true
- - removeUselessDefs: true
- - removeUselessStrokeAndFill: true
- - removeViewBox: false
- - removeXMLNS: false
- - removeXMLProcInst: true
- - sortAttrs: true
diff --git a/build/vnu-jar.js b/build/vnu-jar.js
index b990ba7b78ed..54a71d024f41 100644
--- a/build/vnu-jar.js
+++ b/build/vnu-jar.js
@@ -2,53 +2,48 @@
/*!
* Script to run vnu-jar if Java is available.
- * Copyright 2017-2018 The Bootstrap Authors
- * Copyright 2017-2018 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * Copyright 2017-2022 The Bootstrap Authors
+ * Copyright 2017-2022 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
'use strict'
-const childProcess = require('child_process')
+const { execFile, spawn } = require('child_process')
const vnu = require('vnu-jar')
-childProcess.exec('java -version', (error, stdout, stderr) => {
+execFile('java', ['-version'], (error, stdout, stderr) => {
if (error) {
console.error('Skipping vnu-jar test; Java is missing.')
return
}
- const is32bitJava = !stderr.match(/64-Bit/)
+ const is32bitJava = !/64-Bit/.test(stderr)
// vnu-jar accepts multiple ignores joined with a `|`.
- // Also note that the ignores are regular expressions.
+ // Also note that the ignores are string regular expressions.
const ignores = [
// "autocomplete" is included in