diff --git a/.babelrc.js b/.babelrc.js
new file mode 100644
index 000000000000..1d6404edbe5f
--- /dev/null
+++ b/.babelrc.js
@@ -0,0 +1,17 @@
+module.exports = {
+ presets: [
+ [
+ '@babel/preset-env',
+ {
+ loose: true,
+ bugfixes: true,
+ modules: false
+ }
+ ]
+ ],
+ env: {
+ test: {
+ plugins: [ 'istanbul' ]
+ }
+ }
+};
diff --git a/.browserslistrc b/.browserslistrc
new file mode 100644
index 000000000000..1bfd19753050
--- /dev/null
+++ b/.browserslistrc
@@ -0,0 +1,13 @@
+# https://github.com/browserslist/browserslist#readme
+
+>= 1%
+last 1 major version
+not dead
+Chrome >= 45
+Firefox >= 38
+Edge >= 12
+Explorer >= 10
+iOS >= 9
+Safari >= 9
+Android >= 4.4
+Opera >= 30
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/.editorconfig b/.editorconfig
index c193ae07150c..9d5248e86f37 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -12,6 +12,3 @@ trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
-
-[*.py]
-indent_size = 4
diff --git a/.eslintignore b/.eslintignore
index 8e0f5225cf23..a18b03a5df54 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,3 +1,6 @@
**/*.min.js
-**/vendor/*
-**/dist/*
+**/dist/
+**/vendor/
+/_site/
+/js/coverage/
+/site/static/sw.js
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 000000000000..3d099fc9de80
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,76 @@
+{
+ "root": true,
+ "extends": [
+ "plugin:import/errors",
+ "plugin:import/warnings",
+ "plugin:unicorn/recommended",
+ "xo",
+ "xo/browser"
+ ],
+ "rules": {
+ "arrow-body-style": "off",
+ "capitalized-comments": "off",
+ "comma-dangle": [
+ "error",
+ "never"
+ ],
+ "indent": [
+ "error",
+ 2,
+ {
+ "MemberExpression": "off",
+ "SwitchCase": 1
+ }
+ ],
+ "max-params": [
+ "warn",
+ 5
+ ],
+ "new-cap": [
+ "error",
+ {
+ "properties": false
+ }
+ ],
+ "no-console": "error",
+ "no-mixed-operators": "off",
+ "no-negated-condition": "off",
+ "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 5788b1228904..40b1c37421a0 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,16 +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
-*.py text eol=lf
-*.rb text eol=lf
-*.scss text eol=lf
-*.svg 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/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 000000000000..7d3fa99046cc
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,3 @@
+*.js @twbs/js-review
+*.css @twbs/css-review
+*.scss @twbs/css-review
diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md
similarity index 62%
rename from CONTRIBUTING.md
rename to .github/CONTRIBUTING.md
index a0745d797f0c..c4de33669396 100644
--- a/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -18,20 +18,17 @@ 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.
* Please **do not** post comments consisting solely of "+1" or ":thumbsup:".
- Use [GitHub's "reactions" feature](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments)
+ Use [GitHub's "reactions" feature](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/)
instead. We reserve the right to delete comments which violate this rule.
-* Please **do not** open issues or pull requests regarding the code in
- [`Normalize`](https://github.com/necolas/normalize.css) (open them in
- its repository).
-
* Please **do not** open issues regarding the official themes offered on .
Instead, please email any questions or feedback regarding those themes to `themes AT getbootstrap DOT com`.
@@ -46,7 +43,7 @@ Our bug tracker utilizes several labels to help organize and identify issues. He
- `docs` - Issues for improving or updating our documentation.
- `examples` - Issues involving the example templates included in our docs.
- `feature` - Issues asking for a new feature to be added, or an existing one to be extended or modified. New features require a minor version bump (e.g., `v3.0.0` to `v3.1.0`).
-- `grunt` - Issues with our included JavaScript-based Gruntfile, which is used to run all our tests, concatenate and compile source files, and more.
+- `build` - Issues with our build system, which is used to run all our tests, concatenate and compile source files, and more.
- `help wanted` - Issues we need or would love help from the community to resolve.
- `js` - Issues stemming from our compiled or source JavaScript files.
- `meta` - Issues with the project itself or our GitHub repository.
@@ -61,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.
@@ -106,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://code.google.com/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
@@ -132,30 +124,32 @@ 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.
Adhering to the following process is the best way to get your work
included in the project:
-1. [Fork](https://help.github.com/fork-a-repo/) the project, clone your fork,
+1. [Fork](https://help.github.com/articles/fork-a-repo/) the project, clone your fork,
and configure the remotes:
```bash
@@ -170,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
@@ -182,15 +176,15 @@ included in the project:
```
4. Commit your changes in logical chunks. Please adhere to these [git commit
- message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
+ message guidelines](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
or your code is unlikely be merged into the main project. Use Git's
- [interactive rebase](https://help.github.com/articles/interactive-rebase)
+ [interactive rebase](https://help.github.com/articles/about-git-rebase/)
feature to tidy up your commits before making them public.
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:
@@ -199,30 +193,21 @@ included in the project:
git push origin
```
-7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
- with a clear title and description against the `master` branch.
+7. [Open a Pull Request](https://help.github.com/articles/about-pull-requests/)
+ 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).
-### Pull request bots
-
-[@twbs-rorschach](https://github.com/twbs-rorschach) is a Bootstrap bot that hangs out in our GitHub issue tracker and automatically checks all pull requests for a few simple common mistakes. It's possible that Rorschach might leave a comment on your pull request and then close it. If that happens, simply fix the problem(s) mentioned in the comment (there should be link(s) in the comment explaining the problem(s) in detail) and then either:
-
-* Push the revised version to your pull request's branch and post a comment on the pull request saying that you've fixed the problem(s). One of the Bootstrap Core Team members will then come along and reopen your pull request.
-* Or you can just open a new pull request for your revised version.
-
-[@twbs-savage](https://github.com/twbs-savage) is a Bootstrap bot that automatically runs cross-browser tests (via [Sauce](https://saucelabs.com) and Travis CI) on JavaScript pull requests. Savage will leave a comment on pull requests stating whether cross-browser JS tests passed or failed, with a link to the full Travis build details. If your pull request fails, check the Travis log to see which browser + OS combinations failed. Each browser test in the Travis log includes a link to a Sauce page with details about the test. On those details pages, you can watch a screencast of the test run to see exactly which unit tests failed.
-
## Code guidelines
### 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://`.
@@ -230,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](http://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
@@ -245,12 +230,12 @@ includes code changes) and under the terms of the
### Checking coding style
-Run `grunt test` before committing to ensure your changes follow our coding standards.
+Run `npm run test` before committing to ensure your changes follow our coding standards.
## 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_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 000000000000..4899d4de20a3
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +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/) 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)
+- 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_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 000000000000..db44076d91f2
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,18 @@
+---
+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/v4-dev/.github/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/SUPPORT.md b/.github/SUPPORT.md
new file mode 100644
index 000000000000..f54f4170dd15
--- /dev/null
+++ b/.github/SUPPORT.md
@@ -0,0 +1,11 @@
+### Bug reports
+
+See the [contributing guidelines](CONTRIBUTING.md) for sharing bug reports.
+
+### How-to
+
+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.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 1e00d3dd4ba9..2215d636addf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,8 @@
# Ignore docs files
-_gh_pages
-_site
-
-# Ignore ruby files
-.ruby-version
-.bundle
-vendor/cache
-vendor/bundle
+/_site/
+# Hugo files
+/resources/
+/.hugo_build.lock
# Numerous always-ignore extensions
*.diff
@@ -33,20 +29,14 @@ vendor/bundle
*.sublime-workspace
nbproject
Thumbs.db
+/.vscode/
+# Local Netlify folder
+.netlify
# Komodo
.komodotools
*.komodoproject
-# SCSS-Lint
-scss-lint-report.xml
-
-# grunt-contrib-sass cache
-.sass-cache
-
-# Jekyll metadata
-docs/.jekyll-metadata
-
# Folders to ignore
-bower_components
-node_modules
+/js/coverage/
+/node_modules/
diff --git a/.hound.yml b/.hound.yml
deleted file mode 100644
index 934a9a130709..000000000000
--- a/.hound.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-fail_on_violations: true
-
-scss:
- config_file: scss/.scss-lint.yml
- enabled: true
-
-javascript:
- enabled: false
-
-eslint:
- enabled: true
- config_file: js/.eslintrc.json
-
-jscs:
- enabled: true
- config_file: js/.jscsrc
-
-ruby:
- enabled: false
diff --git a/.stylelintignore b/.stylelintignore
new file mode 100644
index 000000000000..0759a69acead
--- /dev/null
+++ b/.stylelintignore
@@ -0,0 +1,5 @@
+**/*.min.css
+**/dist/
+**/vendor/
+/_site/
+/js/coverage/
diff --git a/.stylelintrc b/.stylelintrc
new file mode 100644
index 000000000000..b948fe8e298a
--- /dev/null
+++ b/.stylelintrc
@@ -0,0 +1,22 @@
+{
+ "extends": [
+ "stylelint-config-twbs-bootstrap"
+ ],
+ "rules": {
+ "declaration-property-value-disallowed-list": {
+ "border": "none",
+ "outline": "none"
+ },
+ "function-disallowed-list": [
+ "calc"
+ ],
+ "property-disallowed-list": [
+ "border-radius",
+ "border-top-left-radius",
+ "border-top-right-radius",
+ "border-bottom-right-radius",
+ "border-bottom-left-radius",
+ "transition"
+ ]
+ }
+}
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 238a6c0db422..000000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-sudo: false
-dist: trusty
-language: node_js
-git:
- depth: 3
-node_js:
- - "4"
- - "6"
-before_install:
- - if [[ `npm -v` != 3* ]]; then npm install -g npm@3; fi
- - "export TRAVIS_COMMIT_MSG=\"`git log --format=%B --no-merges -n 1`\""
- - echo "$TRAVIS_COMMIT_MSG" | grep '\[skip validator\]'; export TWBS_DO_VALIDATOR=$?; true
- - echo "$TRAVIS_COMMIT_MSG" | grep '\[skip sauce\]'; export TWBS_DO_SAUCE=$?; true
- - if [ "$TRAVIS_REPO_SLUG" = twbs-savage/bootstrap ]; then export TWBS_DO_VALIDATOR=0; fi
-install:
- - bundle install --deployment --jobs=3 --retry=3
- - cp grunt/npm-shrinkwrap.json ./
- - npm install
-after_success:
- - if [ "$TWBS_TEST" = sauce-js-unit ]; then grunt/upload-preview.sh; fi
-cache:
- directories:
- - node_modules
- - vendor/bundle
- - "$HOME/google-cloud-sdk"
-env:
- - TWBS_TEST=core
- - TWBS_TEST=validate-html
- - TWBS_TEST=sauce-js-unit
-matrix:
- exclude:
- - node_js: "4"
- env: TWBS_TEST=validate-html
- - node_js: "4"
- env: TWBS_TEST=sauce-js-unit
-notifications:
- slack: heybb:iz4wwosL0N0EdaX1gvgkU0NH
- webhooks:
- - http://savage.twbsapps.com/savage/travis
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 7b60d7c9a697..000000000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Bootstrap uses [GitHub's Releases feature](https://github.com/blog/1547-release-your-software) for its changelogs.
-
-See [the Releases section of our GitHub project](https://github.com/twbs/bootstrap/releases) for changelogs for each release version of Bootstrap.
-
-Release announcement posts on [the official Bootstrap blog](https://blog.getbootstrap.com) contain summaries of the most noteworthy changes made in each release.
diff --git a/CNAME b/CNAME
deleted file mode 100644
index 039362df61f9..000000000000
--- a/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-v4-alpha.getbootstrap.com
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..0d2e5269557a
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,43 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at mdo@getbootstrap.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 1.4, available at
diff --git a/Gemfile b/Gemfile
deleted file mode 100644
index a82dd93b03ec..000000000000
--- a/Gemfile
+++ /dev/null
@@ -1,8 +0,0 @@
-source 'https://rubygems.org'
-
-group :development, :test do
- gem 'jekyll', '~> 3.3.0'
- gem 'jekyll-redirect-from', '~> 0.11.0'
- gem 'jekyll-sitemap', '~> 0.11.0'
- gem 'scss_lint', '~> 0.50.2'
-end
diff --git a/Gemfile.lock b/Gemfile.lock
deleted file mode 100644
index c19955c72b38..000000000000
--- a/Gemfile.lock
+++ /dev/null
@@ -1,56 +0,0 @@
-GEM
- remote: https://rubygems.org/
- specs:
- addressable (2.4.0)
- colorator (1.1.0)
- ffi (1.9.14)
- forwardable-extended (2.6.0)
- jekyll (3.3.0)
- addressable (~> 2.4)
- colorator (~> 1.0)
- jekyll-sass-converter (~> 1.0)
- jekyll-watch (~> 1.1)
- kramdown (~> 1.3)
- liquid (~> 3.0)
- mercenary (~> 0.3.3)
- pathutil (~> 0.9)
- rouge (~> 1.7)
- safe_yaml (~> 1.0)
- jekyll-redirect-from (0.11.0)
- jekyll (>= 2.0)
- jekyll-sass-converter (1.4.0)
- sass (~> 3.4)
- jekyll-sitemap (0.11.0)
- addressable (~> 2.4.0)
- jekyll-watch (1.5.0)
- listen (~> 3.0, < 3.1)
- kramdown (1.12.0)
- liquid (3.0.6)
- listen (3.0.8)
- rb-fsevent (~> 0.9, >= 0.9.4)
- rb-inotify (~> 0.9, >= 0.9.7)
- mercenary (0.3.6)
- pathutil (0.14.0)
- forwardable-extended (~> 2.6)
- rake (11.3.0)
- rb-fsevent (0.9.7)
- rb-inotify (0.9.7)
- ffi (>= 0.5.0)
- rouge (1.11.1)
- safe_yaml (1.0.4)
- sass (3.4.22)
- scss_lint (0.50.2)
- rake (>= 0.9, < 12)
- sass (~> 3.4.20)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- jekyll (~> 3.3.0)
- jekyll-redirect-from (~> 0.11.0)
- jekyll-sitemap (~> 0.11.0)
- scss_lint (~> 0.50.2)
-
-BUNDLED WITH
- 1.13.2
diff --git a/Gruntfile.js b/Gruntfile.js
deleted file mode 100644
index ab52d5b069f0..000000000000
--- a/Gruntfile.js
+++ /dev/null
@@ -1,402 +0,0 @@
-/*!
- * Bootstrap's Gruntfile
- * https://getbootstrap.com
- * Copyright 2013-2016 The Bootstrap Authors
- * Copyright 2013-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- */
-
-module.exports = function (grunt) {
- 'use strict';
-
- // Force use of Unix newlines
- grunt.util.linefeed = '\n';
-
- RegExp.quote = function (string) {
- return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&');
- };
-
- var fs = require('fs');
- var path = require('path');
- var isTravis = require('is-travis');
-
- var configBridge = grunt.file.readJSON('./grunt/configBridge.json', { encoding: 'utf8' });
-
- Object.keys(configBridge.paths).forEach(function (key) {
- configBridge.paths[key].forEach(function (val, i, arr) {
- arr[i] = path.join('./docs', val);
- });
- });
-
- // Project configuration.
- grunt.initConfig({
-
- // Metadata.
- pkg: grunt.file.readJSON('package.json'),
- banner: '/*!\n' +
- ' * Bootstrap v<%= pkg.version %> (<%= pkg.homepage %>)\n' +
- ' * Copyright 2011-<%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
- ' * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n' +
- ' */\n',
- jqueryCheck: 'if (typeof jQuery === \'undefined\') {\n' +
- ' throw new Error(\'Bootstrap\\\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\\\'s JavaScript.\')\n' +
- '}\n',
- jqueryVersionCheck: '+function ($) {\n' +
- ' var version = $.fn.jquery.split(\' \')[0].split(\'.\')\n' +
- ' if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] >= 4)) {\n' +
- ' throw new Error(\'Bootstrap\\\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0\')\n' +
- ' }\n' +
- '}(jQuery);\n\n',
-
- // Task configuration.
- clean: {
- dist: 'dist',
- docs: 'docs/dist'
- },
-
- // JS build configuration
- babel: {
- dev: {
- options: {
- sourceMap: true
- },
- files: {
- 'js/dist/util.js' : 'js/src/util.js',
- 'js/dist/alert.js' : 'js/src/alert.js',
- 'js/dist/button.js' : 'js/src/button.js',
- 'js/dist/carousel.js' : 'js/src/carousel.js',
- 'js/dist/collapse.js' : 'js/src/collapse.js',
- 'js/dist/dropdown.js' : 'js/src/dropdown.js',
- 'js/dist/modal.js' : 'js/src/modal.js',
- 'js/dist/scrollspy.js' : 'js/src/scrollspy.js',
- 'js/dist/tab.js' : 'js/src/tab.js',
- 'js/dist/tooltip.js' : 'js/src/tooltip.js',
- 'js/dist/popover.js' : 'js/src/popover.js'
- }
- },
- dist: {
- options: {
- extends: '../../js/.babelrc'
- },
- files: {
- '<%= concat.bootstrap.dest %>' : '<%= concat.bootstrap.dest %>'
- }
- }
- },
-
- stamp: {
- options: {
- banner: '<%= banner %>\n<%= jqueryCheck %>\n<%= jqueryVersionCheck %>\n+function () {\n',
- footer: '\n}();'
- },
- bootstrap: {
- files: {
- src: '<%= concat.bootstrap.dest %>'
- }
- }
- },
-
- concat: {
- options: {
- // Custom function to remove all export and import statements
- process: function (src) {
- return src.replace(/^(export|import).*/gm, '');
- }
- },
- bootstrap: {
- src: [
- 'js/src/util.js',
- 'js/src/alert.js',
- 'js/src/button.js',
- 'js/src/carousel.js',
- 'js/src/collapse.js',
- 'js/src/dropdown.js',
- 'js/src/modal.js',
- 'js/src/scrollspy.js',
- 'js/src/tab.js',
- 'js/src/tooltip.js',
- 'js/src/popover.js'
- ],
- dest: 'dist/js/<%= pkg.name %>.js'
- }
- },
-
- uglify: {
- options: {
- compress: {
- warnings: false
- },
- mangle: true,
- preserveComments: /^!|@preserve|@license|@cc_on/i
- },
- core: {
- src: '<%= concat.bootstrap.dest %>',
- dest: 'dist/js/<%= pkg.name %>.min.js'
- },
- docsJs: {
- src: configBridge.paths.docsJs,
- dest: 'docs/assets/js/docs.min.js'
- }
- },
-
- qunit: {
- options: {
- inject: 'js/tests/unit/phantom.js'
- },
- files: 'js/tests/index.html'
- },
-
- // CSS build configuration
- scsslint: {
- options: {
- bundleExec: true,
- config: 'scss/.scss-lint.yml',
- reporterOutput: null
- },
- core: {
- src: ['scss/*.scss', '!scss/_normalize.scss']
- },
- docs: {
- src: ['docs/assets/scss/*.scss', '!docs/assets/scss/docs.scss']
- }
- },
-
- cssmin: {
- options: {
- compatibility: 'ie9,-properties.zeroUnits',
- sourceMap: true,
- // sourceMapInlineSources: true,
- advanced: false
- },
- core: {
- files: [
- {
- expand: true,
- cwd: 'dist/css',
- src: ['*.css', '!*.min.css'],
- dest: 'dist/css',
- ext: '.min.css'
- }
- ]
- },
- docs: {
- files: [
- {
- expand: true,
- cwd: 'docs/assets/css',
- src: ['*.css', '!*.min.css'],
- dest: 'docs/assets/css',
- ext: '.min.css'
- }
- ]
- }
- },
-
- copy: {
- docs: {
- expand: true,
- cwd: 'dist/',
- src: [
- '**/*'
- ],
- dest: 'docs/dist/'
- }
- },
-
- connect: {
- server: {
- options: {
- port: 3000,
- base: '.'
- }
- }
- },
-
- jekyll: {
- options: {
- bundleExec: true,
- config: '_config.yml',
- incremental: false
- },
- docs: {},
- github: {
- options: {
- raw: 'github: true'
- }
- }
- },
-
- htmllint: {
- options: {
- ignore: [
- 'Attribute “autocomplete” is only allowed when the input type is “color”, “date”, “datetime”, “datetime-local”, “email”, “hidden”, “month”, “number”, “password”, “range”, “search”, “tel”, “text”, “time”, “url”, or “week”.',
- 'Attribute “autocomplete” not allowed on element “button” at this point.',
- 'Consider using the “h1” element as a top-level heading only (all “h1” elements are treated as top-level headings by many screen readers and other tools).',
- 'Element “div” not allowed as child of element “progress” in this context. (Suppressing further errors from this subtree.)',
- 'Element “img” is missing required attribute “src”.',
- 'The “color” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
- 'The “date” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
- 'The “datetime” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
- 'The “datetime-local” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
- 'The “month” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
- 'The “time” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.',
- 'The “week” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.'
- ]
- },
- src: ['_gh_pages/**/*.html', 'js/tests/visual/*.html']
- },
-
- watch: {
- src: {
- files: '<%= concat.bootstrap.src %>',
- tasks: ['babel:dev']
- },
- sass: {
- files: 'scss/**/*.scss',
- tasks: ['dist-css', 'docs']
- },
- docs: {
- files: 'docs/assets/scss/**/*.scss',
- tasks: ['dist-css', 'docs']
- }
- },
-
- 'saucelabs-qunit': {
- all: {
- options: {
- build: process.env.TRAVIS_JOB_ID,
- concurrency: 10,
- maxRetries: 3,
- maxPollRetries: 4,
- urls: ['http://127.0.0.1:3000/js/tests/index.html?hidepassed'],
- browsers: grunt.file.readYAML('grunt/sauce_browsers.yml')
- }
- }
- },
-
- exec: {
- postcss: {
- command: 'npm run postcss'
- },
- 'postcss-docs': {
- command: 'npm run postcss-docs'
- },
- htmlhint: {
- command: 'npm run htmlhint'
- }
- },
-
- buildcontrol: {
- options: {
- dir: '_gh_pages',
- commit: true,
- push: true,
- message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
- },
- pages: {
- options: {
- remote: 'git@github.com:twbs/derpstrap.git',
- branch: 'gh-pages'
- }
- }
- },
-
- compress: {
- main: {
- options: {
- archive: 'bootstrap-<%= pkg.version %>-dist.zip',
- mode: 'zip',
- level: 9,
- pretty: true
- },
- files: [
- {
- expand: true,
- cwd: 'dist/',
- src: ['**'],
- dest: 'bootstrap-<%= pkg.version %>-dist'
- }
- ]
- }
- }
-
- });
-
-
- // These plugins provide necessary tasks.
- require('load-grunt-tasks')(grunt, { scope: 'devDependencies',
- // Exclude Sass compilers. We choose the one to load later on.
- pattern: ['grunt-*', '!grunt-sass', '!grunt-contrib-sass'] });
- require('time-grunt')(grunt);
-
- // Docs HTML validation task
- grunt.registerTask('validate-html', ['jekyll:docs', 'htmllint', 'exec:htmlhint']);
-
- var runSubset = function (subset) {
- return !process.env.TWBS_TEST || process.env.TWBS_TEST === subset;
- };
- var isUndefOrNonZero = function (val) {
- return val === undefined || val !== '0';
- };
-
- // Test task.
- var testSubtasks = [];
- // Skip core tests if running a different subset of the test suite
- if (runSubset('core') &&
- // Skip core tests if this is a Savage build
- process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') {
- testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'test-scss', 'qunit', 'docs']);
- }
- // Skip HTML validation if running a different subset of the test suite
- if (runSubset('validate-html') &&
- isTravis &&
- // Skip HTML5 validator when [skip validator] is in the commit message
- isUndefOrNonZero(process.env.TWBS_DO_VALIDATOR)) {
- testSubtasks.push('validate-html');
- }
- // Only run Sauce Labs tests if there's a Sauce access key
- if (typeof process.env.SAUCE_ACCESS_KEY !== 'undefined' &&
- // Skip Sauce if running a different subset of the test suite
- runSubset('sauce-js-unit')) {
- testSubtasks = testSubtasks.concat(['dist', 'docs-css', 'docs-js', 'clean:docs', 'copy:docs']);
- // Skip Sauce on Travis when [skip sauce] is in the commit message
- if (isUndefOrNonZero(process.env.TWBS_DO_SAUCE)) {
- testSubtasks.push('connect');
- testSubtasks.push('saucelabs-qunit');
- }
- }
- grunt.registerTask('test', testSubtasks);
-
- // JS distribution task.
- grunt.registerTask('dist-js', ['babel:dev', 'concat', 'babel:dist', 'stamp', 'uglify:core']);
-
- grunt.registerTask('test-scss', ['scsslint:core']);
-
- // CSS distribution task.
- // Supported Compilers: sass (Ruby) and libsass.
- (function (sassCompilerName) {
- require('./grunt/bs-sass-compile/' + sassCompilerName + '.js')(grunt);
- })(process.env.TWBS_SASS || 'libsass');
- // grunt.registerTask('sass-compile', ['sass:core', 'sass:extras', 'sass:docs']);
- grunt.registerTask('sass-compile', ['sass:core', 'sass:extras', 'sass:docs']);
-
- grunt.registerTask('dist-css', ['sass-compile', 'exec:postcss', 'cssmin:core', 'cssmin:docs']);
-
- // Full distribution task.
- grunt.registerTask('dist', ['clean:dist', 'dist-css', 'dist-js']);
-
- // Default task.
- grunt.registerTask('default', ['clean:dist', 'test']);
-
- // Docs task.
- grunt.registerTask('docs-css', ['cssmin:docs', 'exec:postcss-docs']);
- grunt.registerTask('lint-docs-css', ['scsslint:docs']);
- grunt.registerTask('docs-js', ['uglify:docsJs']);
- grunt.registerTask('docs', ['lint-docs-css', 'docs-css', 'docs-js', 'clean:docs', 'copy:docs']);
- grunt.registerTask('docs-github', ['jekyll:github']);
-
- grunt.registerTask('prep-release', ['dist', 'docs', 'docs-github', 'compress']);
-
- // Publish to GitHub
- grunt.registerTask('publish', ['buildcontrol:pages']);
-};
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
deleted file mode 100644
index d2a406f9c9fd..000000000000
--- a/ISSUE_TEMPLATE.md
+++ /dev/null
@@ -1,22 +0,0 @@
-Before opening an issue:
-
-- [Search for duplicate or closed issues](https://github.com/twbs/bootstrap/issues?utf8=%E2%9C%93&q=is%3Aissue)
-- [Validate](https://validator.w3.org/nu/) and [lint](https://github.com/twbs/bootlint#in-the-browser) any HTML to avoid common problems
-- Prepare a [reduced test case](https://css-tricks.com/reduced-test-cases/) for any bugs
-- Read the [contributing guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md)
-
-When asking general "how to" questions:
-
-- Please do not open an issue here
-- Instead, ask for help on [StackOverflow, IRC, or Slack](https://github.com/twbs/bootstrap/blob/master/README.md#community)
-
-When reporting a bug, include:
-
-- Operating system and version (Windows, Mac OS X, Android, iOS, Win10 Mobile)
-- Browser and version (Chrome, Firefox, Safari, IE, MS Edge, Opera 15+, Android Browser)
-- Reduced test cases and potential fixes using [JS Bin](https://jsbin.com)
-
-When suggesting a feature, 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/LICENSE b/LICENSE
index 4e32163c07fa..dda75ca9a5bb 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
The MIT License (MIT)
-Copyright (c) 2011-2016 Twitter, Inc.
-Copyright (c) 2011-2016 The Bootstrap Authors
+Copyright (c) 2011-2022 Twitter, Inc.
+Copyright (c) 2011-2022 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 9635d759f8d8..d7b707f1ba89 100644
--- a/README.md
+++ b/README.md
@@ -1,100 +1,144 @@
-# [Bootstrap](https://getbootstrap.com)
+
-[](https://bootstrap-slack.herokuapp.com)
-
-[](https://www.npmjs.com/package/bootstrap)
-[](https://rubygems.org/gems/bootstrap)
-[](https://travis-ci.org/twbs/bootstrap)
-[](https://david-dm.org/twbs/bootstrap?type=dev)
-[](https://atmospherejs.com/twbs/bootstrap)
-[](https://packagist.org/packages/twbs/bootstrap)
-[](https://www.nuget.org/packages/bootstrap/4.0.0-alpha5)
-
-[](https://saucelabs.com/u/bootstrap)
-
-Bootstrap is a sleek, intuitive, and powerful front-end framework for faster and easier web development, created by [Mark Otto](https://twitter.com/mdo) and [Jacob Thornton](https://twitter.com/fat), and maintained by the [core team](https://github.com/orgs/twbs/people) with the massive support and involvement of the community.
-
-To get started, check out !
## Table of contents
- [Quick start](#quick-start)
+- [Status](#status)
+- [What's included](#whats-included)
- [Bugs and feature requests](#bugs-and-feature-requests)
- [Documentation](#documentation)
- [Contributing](#contributing)
- [Community](#community)
- [Versioning](#versioning)
- [Creators](#creators)
+- [Thanks](#thanks)
- [Copyright and license](#copyright-and-license)
+
## Quick start
Several quick start options are available:
-- [Download the latest release.](https://github.com/twbs/bootstrap/archive/v4.0.0-alpha.5.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@4.0.0-alpha.5`
-- Install with [yarn](https://github.com/yarnpkg/yarn): `yarn add bootstrap@4.0.0-alpha.5`
-- Install with [Meteor](https://www.meteor.com): `meteor add twbs:bootstrap@=4.0.0-alpha.5`
-- Install with [Composer](https://getcomposer.org): `composer require twbs/bootstrap`
-- Install with [Bower](https://bower.io): `bower install bootstrap#v4.0.0-alpha.5`
-- Install with [NuGet](https://www.nuget.org): CSS: `Install-Package bootstrap -Pre` Sass: `Install-Package bootstrap.sass -Pre` (`-Pre` is only required until Bootstrap v4 has a stable release).
+- Install with [npm](https://www.npmjs.com/): `npm install bootstrap`
+- 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/getting-started/) 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.
-### 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:
+## Status
-```
+[](https://bootstrap-slack.herokuapp.com/)
+[](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)
+
+
+## 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.
+
+Download contents
+
+```text
bootstrap/
-├── css/
-│ ├── bootstrap.css
-│ ├── bootstrap.css.map
-│ ├── bootstrap.min.css
-│ └── bootstrap.min.css.map
-└── js/
- ├── bootstrap.js
- └── bootstrap.min.js
+└── dist/
+ ├── css/
+ │ ├── bootstrap-grid.css
+ │ ├── bootstrap-grid.css.map
+ │ ├── bootstrap-grid.min.css
+ │ ├── bootstrap-grid.min.css.map
+ │ ├── bootstrap-reboot.css
+ │ ├── bootstrap-reboot.css.map
+ │ ├── bootstrap-reboot.min.css
+ │ ├── bootstrap-reboot.min.css.map
+ │ ├── bootstrap.css
+ │ ├── bootstrap.css.map
+ │ ├── bootstrap.min.css
+ │ └── bootstrap.min.css.map
+ └── js/
+ ├── bootstrap.bundle.js
+ ├── bootstrap.bundle.js.map
+ ├── bootstrap.bundle.min.js
+ ├── bootstrap.bundle.min.js.map
+ ├── bootstrap.js
+ ├── bootstrap.js.map
+ ├── bootstrap.min.js
+ └── bootstrap.min.js.map
```
+
-We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). CSS [source maps](https://developer.chrome.com/devtools/docs/css-preprocessors) (`bootstrap.*.map`) are available for use with certain browsers' developer tools.
+We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). [Source maps](https://developers.google.com/web/tools/chrome-devtools/javascript/source-maps) (`bootstrap.*.map`) are available for use with certain browsers' developer tools. Bundled JS files (`bootstrap.bundle.js` and minified `bootstrap.bundle.min.js`) include [Popper](https://popper.js.org/), but not [jQuery](https://jquery.com/).
## Bugs and feature requests
-Have a bug or a feature request? Please first read the [issue guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md#using-the-issue-tracker) and search for existing and closed issues. If your problem or idea is not addressed yet, [please open a new issue](https://github.com/twbs/bootstrap/issues/new).
+Have a bug or a feature request? Please first read the [issue guidelines](https://github.com/twbs/bootstrap/blob/v4-dev/.github/CONTRIBUTING.md#using-the-issue-tracker) and search for existing and closed issues. If your problem or idea is not addressed yet, [please open a new issue](https://github.com/twbs/bootstrap/issues/new).
## Documentation
-Bootstrap's documentation, included in this repo in the root directory, is built with [Jekyll](https://jekyllrb.com) and publicly hosted on GitHub Pages at . The docs may also be run locally.
+Bootstrap's documentation, included in this repo in the root directory, is built with [Hugo](https://gohugo.io/) and publicly hosted on GitHub Pages at . The docs may also be run locally.
+
+Documentation search is powered by [Algolia's DocSearch](https://community.algolia.com/docsearch/). Working on our search? Be sure to set `debug: true` in `site/assets/js/search.js`.
### Running documentation locally
-1. Run through the [tooling setup](https://github.com/twbs/bootstrap/blob/v4-dev/docs/getting-started/build-tools.md#tooling-setup) to install Jekyll (the site builder) and other Ruby dependencies with `bundle install`.
-2. Run `grunt` (or a specific set of Grunt tasks) to rebuild distributed CSS and JavaScript files, as well as our docs assets.
-3. From the root `/bootstrap` directory, run `bundle exec jekyll serve` in the command line.
-4. Open in your browser, and voilà.
+1. Run `npm install` to install the Node.js dependencies, including Hugo (the site builder).
+2. Run `npm run test` (or a specific npm script) to rebuild distributed CSS and JavaScript files, as well as our docs assets.
+3. Run `npm start` to compile CSS and JavaScript files, generate our docs, and watch for changes.
+4. Open `http://localhost:9001/` in your browser, and voilà.
-Learn more about using Jekyll by reading its [documentation](https://jekyllrb.com/docs/home/).
+Learn more about using Hugo by reading its [documentation](https://gohugo.io/documentation/).
### Documentation for previous releases
-Documentation for v2.3.2 has been made available for the time being at while folks transition to Bootstrap 3.
+You can find all our previous releases docs on .
[Previous releases](https://github.com/twbs/bootstrap/releases) and their documentation are also available for download.
-
## Contributing
-Please read through our [contributing guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development.
-
-Moreover, if your pull request contains JavaScript patches or features, you must include [relevant unit tests](https://github.com/twbs/bootstrap/tree/master/js/tests). All HTML and CSS should conform to the [Code Guide](https://github.com/mdo/code-guide), maintained by [Mark Otto](https://github.com/mdo).
+Please read through our [contributing guidelines](https://github.com/twbs/bootstrap/blob/v4-dev/.github/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development.
-Editor preferences are available in the [editor config](https://github.com/twbs/bootstrap/blob/master/.editorconfig) for easy use in common text editors. Read more and download plugins at .
+Moreover, if your pull request contains JavaScript patches or features, you must include [relevant unit tests](https://github.com/twbs/bootstrap/tree/v4-dev/js/tests). All HTML and CSS should conform to the [Code Guide](https://github.com/mdo/code-guide), maintained by [Mark Otto](https://github.com/mdo).
+Editor preferences are available in the [editor config](https://github.com/twbs/bootstrap/blob/v4-dev/.editorconfig) for easy use in common text editors. Read more and download plugins at .
## Community
@@ -102,19 +146,18 @@ Editor preferences are available in the [editor config](https://github.com/twbs/
Get updates on Bootstrap's development and chat with the project maintainers and community members.
- Follow [@getbootstrap on Twitter](https://twitter.com/getbootstrap).
-- Read and subscribe to [The Official Bootstrap Blog](https://blog.getbootstrap.com).
-- 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.
+- Read and subscribe to [The Official Bootstrap Blog](https://blog.getbootstrap.com/).
+- Join [the official Slack room](https://bootstrap-slack.herokuapp.com/).
+- Chat with fellow Bootstrappers in IRC. On the `irc.libera.chat` server, in the `#bootstrap` channel.
- Implementation help may be found at Stack Overflow (tagged [`bootstrap-4`](https://stackoverflow.com/questions/tagged/bootstrap-4)).
- Developers should use the keyword `bootstrap` on packages which modify or add to the functionality of Bootstrap when distributing through [npm](https://www.npmjs.com/browse/keyword/bootstrap) or similar delivery mechanisms for maximum discoverability.
-
## Versioning
-For transparency into our release cycle and in striving to maintain backward compatibility, Bootstrap is maintained under [the Semantic Versioning guidelines](http://semver.org/). Sometimes we screw up, but we'll adhere to those rules whenever possible.
+For transparency into our release cycle and in striving to maintain backward compatibility, Bootstrap is maintained under [the Semantic Versioning guidelines](https://semver.org/). Sometimes we screw up, but we adhere to those rules whenever possible.
-See [the Releases section of our GitHub project](https://github.com/twbs/bootstrap/releases) for changelogs for each release version of Bootstrap. Release announcement posts on [the official Bootstrap blog](https://blog.getbootstrap.com) contain summaries of the most noteworthy changes made in each release.
+See [the Releases section of our GitHub project](https://github.com/twbs/bootstrap/releases) for changelogs for each release version of Bootstrap. Release announcement posts on [the official Bootstrap blog](https://blog.getbootstrap.com/) contain summaries of the most noteworthy changes made in each release.
## Creators
@@ -130,7 +173,38 @@ See [the Releases section of our GitHub project](https://github.com/twbs/bootstr
-
+## Thanks
+
+
+
+
+
+Thanks to [BrowserStack](https://www.browserstack.com/) for providing the infrastructure that allows us to test in real browsers!
+
+
+## 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)]
+
+[](https://opencollective.com/bootstrap/sponsor/0/website)
+[](https://opencollective.com/bootstrap/sponsor/1/website)
+[](https://opencollective.com/bootstrap/sponsor/2/website)
+[](https://opencollective.com/bootstrap/sponsor/3/website)
+[](https://opencollective.com/bootstrap/sponsor/4/website)
+[](https://opencollective.com/bootstrap/sponsor/5/website)
+[](https://opencollective.com/bootstrap/sponsor/6/website)
+[](https://opencollective.com/bootstrap/sponsor/7/website)
+[](https://opencollective.com/bootstrap/sponsor/8/website)
+[](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-2016 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 5013cf288584..000000000000
--- a/_config.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-# Dependencies
-markdown: kramdown
-highlighter: rouge
-
-kramdown:
- auto_ids: true
-
-# Permalinks
-permalink: pretty
-
-# Server
-source: docs
-destination: _gh_pages
-host: 0.0.0.0
-port: 9001
-baseurl: ""
-url: https://v4-alpha.getbootstrap.com
-encoding: UTF-8
-exclude: [assets/scss/]
-
-gems:
- - jekyll-redirect-from
- - jekyll-sitemap
-
-# Social
-title: Bootstrap
-description: The most popular HTML, CSS, and JS framework in the world.
-twitter: getbootstrap
-authors: Mark Otto, Jacob Thornton, and Bootstrap contributors
-social_logo_path: /assets/brand/bootstrap-social-logo.png
-social_image_path: /assets/brand/bootstrap-social.png
-
-# Custom vars
-current_version: 4.0.0-alpha.5
-repo: https://github.com/twbs/bootstrap
-slack: https://bootstrap-slack.herokuapp.com
-
-download:
- source: https://github.com/twbs/bootstrap/archive/v4.0.0-alpha.5.zip
- dist: https://github.com/twbs/bootstrap/releases/download/v4.0.0-alpha.5/bootstrap-4.0.0-alpha.5-dist.zip
-
-blog: https://blog.getbootstrap.com
-expo: https://expo.getbootstrap.com
-themes: https://themes.getbootstrap.com
-
-cdn:
- # See https://www.srihash.org for info on how to generate the hashes
- css: https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css
- css_hash: "sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi"
- js: https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js
- js_hash: "sha384-BLiI7JTZm+JWlgKa0M0kGRpJbF2J8q+qreVrKBC47e3K6BW78kGLrCkeRX6I9RoK"
- jquery: https://code.jquery.com/jquery-3.1.1.min.js
- jquery_hash: "sha384-3ceskX3iaEnIogmQchP8opvBy3Mi7Ce34nWjpBIwVTHfGYWQS9jwHDVRnpKKHJg7"
- tether: https://cdnjs.cloudflare.com/ajax/libs/tether/1.3.7/js/tether.min.js
- tether_hash: "sha384-XTs3FgkjiBgo8qjEjBk0tGmf3wPrWtA6coPfQDfFEY8AnYJwjalXCiosYRBIBZX8"
diff --git a/bower.json b/bower.json
deleted file mode 100644
index c51d71b2f736..000000000000
--- a/bower.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "name": "bootstrap",
- "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.",
- "keywords": [
- "css",
- "js",
- "sass",
- "mobile-first",
- "responsive",
- "front-end",
- "framework",
- "web"
- ],
- "homepage": "https://getbootstrap.com",
- "license": "MIT",
- "moduleType": "globals",
- "main": [
- "scss/bootstrap.scss",
- "dist/js/bootstrap.js"
- ],
- "ignore": [
- "/.*",
- "_config.yml",
- "CNAME",
- "composer.json",
- "CONTRIBUTING.md",
- "docs",
- "js/tests",
- "test-infra"
- ],
- "dependencies": {
- "jquery": "1.9.1 - 3",
- "tether": "^1.3.7"
- }
-}
diff --git a/build/.eslintrc.json b/build/.eslintrc.json
new file mode 100644
index 000000000000..679bd26f7ba2
--- /dev/null
+++ b/build/.eslintrc.json
@@ -0,0 +1,14 @@
+{
+ "env": {
+ "browser": false,
+ "node": true
+ },
+ "parserOptions": {
+ "sourceType": "script"
+ },
+ "extends": "../.eslintrc.json",
+ "rules": {
+ "no-console": "off",
+ "strict": "error"
+ }
+}
diff --git a/build/banner.js b/build/banner.js
new file mode 100644
index 000000000000..df82ff32edf3
--- /dev/null
+++ b/build/banner.js
@@ -0,0 +1,14 @@
+'use strict'
+
+const pkg = require('../package.json')
+const year = new Date().getFullYear()
+
+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/main/LICENSE)
+ */`
+}
+
+module.exports = getBanner
diff --git a/build/build-plugins.js b/build/build-plugins.js
new file mode 100644
index 000000000000..9e33ddb655c6
--- /dev/null
+++ b/build/build-plugins.js
@@ -0,0 +1,92 @@
+#!/usr/bin/env node
+
+/*!
+ * Script to build our plugins to use them separately.
+ * 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 TEST = process.env.NODE_ENV === 'test'
+const plugins = [
+ babel({
+ // Only transpile our source code
+ exclude: 'node_modules/**',
+ // Include the helpers in each file, at most one copy of each
+ babelHelpers: 'bundled'
+ })
+]
+const bsPlugins = {
+ Alert: path.resolve(__dirname, '../js/src/alert.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'),
+ Dropdown: path.resolve(__dirname, '../js/src/dropdown.js'),
+ Modal: path.resolve(__dirname, '../js/src/modal.js'),
+ Popover: path.resolve(__dirname, '../js/src/popover.js'),
+ ScrollSpy: path.resolve(__dirname, '../js/src/scrollspy.js'),
+ Tab: path.resolve(__dirname, '../js/src/tab.js'),
+ Toast: path.resolve(__dirname, '../js/src/toast.js'),
+ Tooltip: path.resolve(__dirname, '../js/src/tooltip.js'),
+ Util: path.resolve(__dirname, '../js/src/util.js')
+}
+const rootPath = TEST ? '../js/coverage/dist/' : '../js/dist/'
+
+const build = async plugin => {
+ console.log(`Building ${plugin} plugin...`)
+
+ const external = ['jquery', 'popper.js']
+ const globals = {
+ jquery: 'jQuery', // Ensure we use jQuery which is always available even in noConflict mode
+ 'popper.js': 'Popper'
+ }
+
+ // Do not bundle Util in plugins
+ if (plugin !== 'Util') {
+ external.push(bsPlugins.Util)
+ globals[bsPlugins.Util] = 'Util'
+ }
+
+ // Do not bundle Tooltip in Popover
+ if (plugin === 'Popover') {
+ external.push(bsPlugins.Tooltip)
+ globals[bsPlugins.Tooltip] = 'Tooltip'
+ }
+
+ const pluginFilename = `${plugin.toLowerCase()}.js`
+ const bundle = await rollup.rollup({
+ input: bsPlugins[plugin],
+ plugins,
+ external
+ })
+
+ 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)
+ }
+}
+
+main()
diff --git a/build/change-version.js b/build/change-version.js
new file mode 100644
index 000000000000..e035eba952ea
--- /dev/null
+++ b/build/change-version.js
@@ -0,0 +1,81 @@
+#!/usr/bin/env node
+
+/*!
+ * Script to update version number references in the project.
+ * 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').promises
+const path = require('path')
+const globby = require('globby')
+
+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, '\\$&')
+}
+
+function regExpQuoteReplacement(string) {
+ return string.replace(/\$/g, '$$')
+}
+
+async function replaceRecursively(file, oldVersion, newVersion) {
+ const originalString = await fs.readFile(file, 'utf8')
+ const newString = originalString.replace(
+ new RegExp(regExpQuote(oldVersion), 'g'), regExpQuoteReplacement(newVersion)
+ )
+
+ // No need to move any further if the strings are identical
+ if (originalString === newString) {
+ return
+ }
+
+ if (VERBOSE) {
+ console.log(`FILE: ${file}`)
+ }
+
+ if (DRY_RUN) {
+ return
+ }
+
+ await fs.writeFile(file, newString, 'utf8')
+}
+
+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)
+ }
+
+ // 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
new file mode 100644
index 000000000000..9685899261f8
--- /dev/null
+++ b/build/generate-sri.js
@@ -0,0 +1,66 @@
+#!/usr/bin/env node
+
+/*!
+ * Script to generate SRI hashes for use in our docs.
+ * Remember to use the same vendor files as the CDN ones,
+ * otherwise the hashes won't match!
+ *
+ * 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 crypto = require('crypto')
+const fs = require('fs')
+const path = require('path')
+const sh = require('shelljs')
+
+const pkg = require('../package.json')
+
+sh.config.fatal = true
+
+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
+const files = [
+ {
+ file: 'dist/css/bootstrap.min.css',
+ configPropertyName: 'css_hash'
+ },
+ {
+ file: 'dist/js/bootstrap.min.js',
+ configPropertyName: 'js_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 => {
+ fs.readFile(file.file, 'utf8', (err, data) => {
+ if (err) {
+ throw err
+ }
+
+ const algo = 'sha384'
+ const hash = crypto.createHash(algo).update(data, 'utf8').digest('base64')
+ const integrity = `${algo}-${hash}`
+
+ console.log(`${file.configPropertyName}: ${integrity}`)
+
+ 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
new file mode 100644
index 000000000000..ef416258f7fc
--- /dev/null
+++ b/build/postcss.config.js
@@ -0,0 +1,18 @@
+'use strict'
+
+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
new file mode 100644
index 000000000000..e2d2b125efe6
--- /dev/null
+++ b/build/rollup.config.js
@@ -0,0 +1,44 @@
+'use strict'
+
+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'
+
+let fileDest = 'bootstrap.js'
+const external = ['jquery', 'popper.js']
+const plugins = [
+ babel({
+ // Only transpile our source code
+ exclude: 'node_modules/**',
+ // Include the helpers in the bundle, at most one copy of each
+ babelHelpers: 'bundled'
+ })
+]
+const globals = {
+ jquery: 'jQuery', // Ensure we use jQuery which is always available even in noConflict mode
+ 'popper.js': 'Popper'
+}
+
+if (BUNDLE) {
+ fileDest = 'bootstrap.bundle.js'
+ // Remove last entry in external array to bundle Popper
+ external.pop()
+ delete globals['popper.js']
+ plugins.push(nodeResolve())
+}
+
+module.exports = {
+ input: path.resolve(__dirname, '../js/index.js'),
+ output: {
+ banner,
+ file: path.resolve(__dirname, `../dist/js/${fileDest}`),
+ format: 'umd',
+ globals,
+ name: 'bootstrap'
+ },
+ external,
+ plugins
+}
diff --git a/build/vnu-jar.js b/build/vnu-jar.js
new file mode 100644
index 000000000000..54a71d024f41
--- /dev/null
+++ b/build/vnu-jar.js
@@ -0,0 +1,60 @@
+#!/usr/bin/env node
+
+/*!
+ * Script to run vnu-jar if Java is available.
+ * 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 { execFile, spawn } = require('child_process')
+const vnu = require('vnu-jar')
+
+execFile('java', ['-version'], (error, stdout, stderr) => {
+ if (error) {
+ console.error('Skipping vnu-jar test; Java is missing.')
+ return
+ }
+
+ const is32bitJava = !/64-Bit/.test(stderr)
+
+ // vnu-jar accepts multiple ignores joined with a `|`.
+ // Also note that the ignores are string regular expressions.
+ const ignores = [
+ // "autocomplete" is included in