diff --git a/package-lock.json b/package-lock.json index 5aa6f1df0d..d27f239d43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12026,16 +12026,6 @@ "@popperjs/core": "^2.9.2" } }, - "node_modules/@types/bootstrap-5": { - "name": "@types/bootstrap", - "version": "5.2.10", - "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.10.tgz", - "integrity": "sha512-F2X+cd6551tep0MvVZ6nM8v7XgGN/twpdNDjqS1TUM7YFNEtQYWk+dKAnH+T1gr6QgCoGMPl487xw/9hXooa2g==", - "dev": true, - "dependencies": { - "@popperjs/core": "^2.9.2" - } - }, "node_modules/@types/bunyan": { "version": "1.8.8", "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.8.tgz", @@ -16591,19 +16581,9 @@ "dev": true }, "node_modules/bootstrap": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz", - "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/bootstrap-5": { - "name": "bootstrap", - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.6.tgz", - "integrity": "sha512-jX0GAcRzvdwISuvArXn3m7KZscWWFAf1MKBcnzaN02qWMb3jpMoUX4/qgeiGzqyIb4ojulRzs89UCUmGcFSzTA==", + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.7.tgz", + "integrity": "sha512-7KgiD8UHjfcPBHEpDNg+zGz8L3LqR3GVwqZiBRFX04a1BCArZOz1r2kjly2HQ0WokqTO0v1nF+QAt8dsW4lKlw==", "dev": true, "funding": [ { @@ -43614,7 +43594,7 @@ "@overleaf/o-error": "*", "aws-sdk": "^2.1174.0", "body-parser": "^1.20.3", - "bootstrap": "^5.3.3", + "bootstrap": "5.3.3", "compression": "^1.7.1", "cookie-parser": "^1.4.6", "cross-env": "^7.0.3", @@ -45171,7 +45151,6 @@ "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.4.3", "@types/bootstrap": "^5.2.10", - "@types/bootstrap-5": "npm:@types/bootstrap@^5.2.10", "@types/chai": "^4.3.0", "@types/dateformat": "^5.0.2", "@types/diff": "^5.0.9", @@ -45206,8 +45185,7 @@ "babel-plugin-macros": "^3.1.0", "babel-plugin-module-resolver": "^5.0.2", "backbone": "^1.6.0", - "bootstrap": "^3.4.1", - "bootstrap-5": "npm:bootstrap@^5.3.6", + "bootstrap": "^5.3.7", "c8": "^7.2.0", "chai": "^4.3.6", "chai-as-promised": "^7.1.1", diff --git a/services/web/app/src/infrastructure/ExpressLocals.js b/services/web/app/src/infrastructure/ExpressLocals.js index 0be0ef313b..0047cd3d0d 100644 --- a/services/web/app/src/infrastructure/ExpressLocals.js +++ b/services/web/app/src/infrastructure/ExpressLocals.js @@ -186,32 +186,6 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) { res.locals.moment = moment - res.locals.isIEEE = brandId => brandId === IEEE_BRAND_ID - - res.locals.getCssThemeModifier = function ( - userSettings, - brandVariation, - enableIeeeBranding - ) { - // Themes only exist in OL v2 - if (Settings.overleaf != null) { - // The IEEE theme is no longer applied in the editor, which sets - // enableIeeeBranding to false, but is used in the IEEE portal. If - // this is an IEEE-branded page and IEEE branding is disabled in this - // page, always use the default theme (i.e. no light theme in the - // IEEE-branded editor) - if (res.locals.isIEEE(brandVariation?.brand_id)) { - return enableIeeeBranding ? 'ieee-' : '' - } else if (userSettings && userSettings.overallTheme != null) { - if (!['', 'light-'].includes(userSettings.overallTheme)) { - return '' - } - return userSettings.overallTheme - } - } - return '' - } - res.locals.buildStylesheetPath = function (cssFileName) { return staticFilesBase + webpackManifest[cssFileName] } diff --git a/services/web/app/views/_mixins/bootstrap_js.pug b/services/web/app/views/_mixins/bootstrap_js.pug index 746e811bf7..c2b9791936 100644 --- a/services/web/app/views/_mixins/bootstrap_js.pug +++ b/services/web/app/views/_mixins/bootstrap_js.pug @@ -1,3 +1,3 @@ -mixin bootstrap-js(bootstrapVersion) - each file in entrypointScripts(bootstrapVersion === 5 ? 'bootstrap-5' : 'bootstrap-3') +mixin bootstrap-js + each file in entrypointScripts('bootstrap') script(type='text/javascript' nonce=scriptNonce src=file) diff --git a/services/web/app/views/layout-base.pug b/services/web/app/views/layout-base.pug index 99fd4244f5..bf98fdb207 100644 --- a/services/web/app/views/layout-base.pug +++ b/services/web/app/views/layout-base.pug @@ -6,8 +6,6 @@ html( class=fixedSizeDocument ? 'fixed-size-document' : undefined ) - metadata = metadata || {} - - let bootstrap5PageStatus = 'enabled' // One of 'disabled' and 'enabled' - - let bootstrap5PageSplitTest = '' // Limits Bootstrap 5 usage on this page to users with an assignment of "enabled" for the specified split test. If left empty and bootstrap5PageStatus is "enabled", the page always uses Bootstrap 5. - let isWebsiteRedesign = false - let isApplicationPage = false - let enableIeeeBranding = true @@ -21,14 +19,8 @@ html( head include ./_metadata.pug - - const bootstrapVersion = bootstrap5PageStatus !== 'disabled' && (bootstrap5Override || bootstrap5PageSplitTest === '' || splitTestVariants[bootstrap5PageSplitTest] === 'enabled') ? 5 : 3 - //- Stylesheet - link( - rel='stylesheet' - href=buildCssPath(getCssThemeModifier(userSettings, brandVariation, enableIeeeBranding), bootstrapVersion) - id='main-stylesheet' - ) + link(rel='stylesheet' href=buildCssPath() id='main-stylesheet') block css each file in entrypointStyles(entrypoint) link(rel='stylesheet' href=file) @@ -103,7 +95,6 @@ html( ) each restriction in userRestrictions || [] meta(name='ol-cannot-' + restriction data-type='boolean' content) - meta(name='ol-bootstrapVersion' data-type='json' content=bootstrapVersion) block head-scripts diff --git a/services/web/app/views/layout-marketing.pug b/services/web/app/views/layout-marketing.pug index 26e4eb539d..1e11fefa15 100644 --- a/services/web/app/views/layout-marketing.pug +++ b/services/web/app/views/layout-marketing.pug @@ -8,29 +8,20 @@ block entrypointVar block body if typeof suppressNavbar === 'undefined' - if bootstrapVersion === 5 - include layout/navbar-marketing-bootstrap-5 - else - include layout/navbar-marketing + include layout/navbar-marketing-bootstrap-5 block content if typeof suppressFooter === 'undefined' if showThinFooter - if bootstrapVersion === 5 - include layout/thin-footer-bootstrap-5 - else - include layout/thin-footer + include layout/thin-footer-bootstrap-5 else include layout/fat-footer if typeof suppressPugCookieBanner == 'undefined' include _cookie_banner - if bootstrapVersion === 5 - != moduleIncludes('contactModal-marketing-bootstrap-5', locals) - else - != moduleIncludes('contactModal-marketing', locals) + != moduleIncludes('contactModal-marketing-bootstrap-5', locals) block prepend foot-scripts - +bootstrap-js(bootstrapVersion) + +bootstrap-js diff --git a/services/web/app/views/layout-website-redesign.pug b/services/web/app/views/layout-website-redesign.pug index aa7fea9f07..599be45754 100644 --- a/services/web/app/views/layout-website-redesign.pug +++ b/services/web/app/views/layout-website-redesign.pug @@ -11,19 +11,13 @@ block append meta block body if typeof suppressNavbar == 'undefined' - if bootstrapVersion === 5 - include layout/navbar-marketing-bootstrap-5 - else - include layout/navbar-website-redesign + include layout/navbar-marketing-bootstrap-5 block content if typeof suppressFooter == 'undefined' if showThinFooter - if bootstrapVersion === 5 - include layout/thin-footer-bootstrap-5 - else - include layout/thin-footer + include layout/thin-footer-bootstrap-5 else include layout/fat-footer-website-redesign @@ -31,10 +25,7 @@ block body include _cookie_banner block contactModal - if bootstrapVersion === 5 - != moduleIncludes('contactModal-marketing-bootstrap-5', locals) - else - != moduleIncludes('contactModal-marketing', locals) + != moduleIncludes('contactModal-marketing-bootstrap-5', locals) block prepend foot-scripts - +bootstrap-js(bootstrapVersion) + +bootstrap-js diff --git a/services/web/app/views/layout/fat-footer-base.pug b/services/web/app/views/layout/fat-footer-base.pug index e8380939f6..2f5759f3c3 100644 --- a/services/web/app/views/layout/fat-footer-base.pug +++ b/services/web/app/views/layout/fat-footer-base.pug @@ -5,10 +5,7 @@ a(href='/legal') #{translate('privacy_and_terms')} a(href='https://www.digital-science.com/security-certifications/') #{translate('compliance')} ul.fat-footer-base-item.list-unstyled.fat-footer-base-language - if bootstrapVersion === 5 - include language-picker-bootstrap-5 - else - include language-picker + include language-picker-bootstrap-5 .fat-footer-base-section.fat-footer-base-social .fat-footer-base-item a.fat-footer-social.x-logo(href='https://x.com/overleaf') diff --git a/services/web/app/views/layout/layout-no-js.pug b/services/web/app/views/layout/layout-no-js.pug index 76a31b72a5..c80f9150ac 100644 --- a/services/web/app/views/layout/layout-no-js.pug +++ b/services/web/app/views/layout/layout-no-js.pug @@ -15,6 +15,6 @@ html(lang='en') link(rel='icon' href='/favicon.ico') if buildCssPath - link(rel='stylesheet' href=buildCssPath('', 5)) + link(rel='stylesheet' href=buildCssPath()) block body diff --git a/services/web/app/views/subscriptions/team/invite_logged_out.pug b/services/web/app/views/subscriptions/team/invite_logged_out.pug index 3e471fb4c9..5db16ee082 100644 --- a/services/web/app/views/subscriptions/team/invite_logged_out.pug +++ b/services/web/app/views/subscriptions/team/invite_logged_out.pug @@ -4,12 +4,10 @@ block append meta meta(name='ol-user' data-type='json' content=user) block content - - var colClass = bootstrapVersion === 5 ? 'col-lg-8 m-auto' : 'col-md-8 col-md-offset-2' - main#main-content.content.content-alt.team-invite .container .row - div(class=colClass) + .col-lg-8.m-auto .card.text-center .card-body .page-header diff --git a/services/web/cypress/support/component.ts b/services/web/cypress/support/component.ts index 9ded533da3..f55a83d7f9 100644 --- a/services/web/cypress/support/component.ts +++ b/services/web/cypress/support/component.ts @@ -5,7 +5,7 @@ import './shared/commands' import './shared/exceptions' import './ct/commands' import './ct/codemirror' -import '../../test/frontend/helpers/bootstrap-5' +import '../../test/frontend/helpers/bootstrap' beforeEach(function () { cy.wrap(localesPromise).then(resetMeta) diff --git a/services/web/frontend/js/bootstrap-5.ts b/services/web/frontend/js/bootstrap-5.ts deleted file mode 100644 index 4b4b09ecfe..0000000000 --- a/services/web/frontend/js/bootstrap-5.ts +++ /dev/null @@ -1,4 +0,0 @@ -import './features/bookmarkable-tab/index-bs5' -import './features/tooltip/index-bs5' -import './features/navbar/index' -import 'bootstrap-5' diff --git a/services/web/frontend/js/bootstrap-3.ts b/services/web/frontend/js/bootstrap.ts similarity index 57% rename from services/web/frontend/js/bootstrap-3.ts rename to services/web/frontend/js/bootstrap.ts index e9012b7555..2525e080d2 100644 --- a/services/web/frontend/js/bootstrap-3.ts +++ b/services/web/frontend/js/bootstrap.ts @@ -1,5 +1,4 @@ -import 'bootstrap' -import './features/contact-form' import './features/bookmarkable-tab/index' -import './features/tooltip/index-bs3' +import './features/tooltip/index' import './features/navbar/index' +import 'bootstrap' diff --git a/services/web/frontend/js/features/bookmarkable-tab/index.js b/services/web/frontend/js/features/bookmarkable-tab/index.js deleted file mode 100644 index 76855e970e..0000000000 --- a/services/web/frontend/js/features/bookmarkable-tab/index.js +++ /dev/null @@ -1,21 +0,0 @@ -function bookmarkableTab(tabEl) { - tabEl.addEventListener('click', () => { - window.location.hash = tabEl.getAttribute('href') - }) -} - -function handleHashChange() { - const hash = window.location.hash - if (!hash) return - - // Find the bookmarkable tab that links to the hash - const $tabEl = $(`[data-ol-bookmarkable-tab][href="${hash}"]`) - if (!$tabEl) return - - // Select the tab via Bootstrap - $tabEl.tab('show') -} - -document.querySelectorAll('[data-ol-bookmarkable-tab]').forEach(bookmarkableTab) -window.addEventListener('hashchange', handleHashChange) -handleHashChange() diff --git a/services/web/frontend/js/features/bookmarkable-tab/index-bs5.ts b/services/web/frontend/js/features/bookmarkable-tab/index.ts similarity index 90% rename from services/web/frontend/js/features/bookmarkable-tab/index-bs5.ts rename to services/web/frontend/js/features/bookmarkable-tab/index.ts index 51f43925a6..28cc805cd2 100644 --- a/services/web/frontend/js/features/bookmarkable-tab/index-bs5.ts +++ b/services/web/frontend/js/features/bookmarkable-tab/index.ts @@ -1,4 +1,4 @@ -import { Tab } from 'bootstrap-5' +import { Tab } from 'bootstrap' function bookmarkableTab(tabEl: HTMLElement) { tabEl.addEventListener('click', () => { @@ -17,7 +17,6 @@ function handleHashChange() { if (!tabEl) return - // Select the tab via Bootstrap 5 const tab = new Tab(tabEl) tab.show() } diff --git a/services/web/frontend/js/features/form-helpers/hydrate-form.js b/services/web/frontend/js/features/form-helpers/hydrate-form.js index f3d968b89e..99a28a2431 100644 --- a/services/web/frontend/js/features/form-helpers/hydrate-form.js +++ b/services/web/frontend/js/features/form-helpers/hydrate-form.js @@ -3,7 +3,6 @@ import { FetchError, postJSON } from '../../infrastructure/fetch-json' import { canSkipCaptcha, validateCaptchaV2 } from './captcha' import inputValidator from './input-validator' import { disableElement, enableElement } from '../utils/disableElement' -import { isBootstrap5 } from '@/features/utils/bootstrap-5' import { materialIcon as createMaterialIcon } from '@/features/utils/material-icon' // Form helper(s) to handle: @@ -136,7 +135,7 @@ function hideFormElements(formEl) { } /** - * Creates a notification element from a message object, with BS5 classes. + * Creates a notification element from a message object. * * @param {Object} message * @param {'error' | 'success' | 'warning' | 'info'} message.type @@ -145,7 +144,7 @@ function hideFormElements(formEl) { * @param {string[]} message.hints * @returns {HTMLDivElement} */ -function createNotificationFromMessageBS5(message) { +function createNotificationFromMessage(message) { const messageEl = document.createElement('div') messageEl.className = classNames('mb-3 notification', { 'notification-type-error': message.type === 'error', @@ -216,32 +215,9 @@ function showMessages(formEl, messageBag) { customErrorElements.forEach(el => { el.hidden = false }) - } else if (isBootstrap5()) { - const notification = createNotificationFromMessageBS5(message) - messagesEl.append(notification) } else { - // No custom error element for key on page, append a new error message - const messageEl = document.createElement('div') - messageEl.className = classNames('alert mb-2', { - 'alert-danger': message.type === 'error', - 'alert-success': message.type !== 'error', - }) - messageEl.textContent = message.text || `Error: ${message.key}` - messageEl.setAttribute('aria-live', 'assertive') - messageEl.setAttribute( - 'role', - message.type === 'error' ? 'alert' : 'status' - ) - if (message.hints && message.hints.length) { - const listEl = document.createElement('ul') - message.hints.forEach(hint => { - const listItemEl = document.createElement('li') - listItemEl.textContent = hint - listEl.append(listItemEl) - }) - messageEl.append(listEl) - } - messagesEl.append(messageEl) + const notification = createNotificationFromMessage(message) + messagesEl.append(notification) } if (message.key) { // Hide the form elements on specific message types diff --git a/services/web/frontend/js/features/form-helpers/input-validator.js b/services/web/frontend/js/features/form-helpers/input-validator.js index 25038b6a1a..e724cad441 100644 --- a/services/web/frontend/js/features/form-helpers/input-validator.js +++ b/services/web/frontend/js/features/form-helpers/input-validator.js @@ -1,4 +1,3 @@ -import { isBootstrap5 } from '@/features/utils/bootstrap-5' import { materialIcon } from '@/features/utils/material-icon' export default function inputValidator(inputEl) { @@ -13,11 +12,8 @@ export default function inputValidator(inputEl) { const messageTextNode = document.createTextNode('') - // In Bootstrap 5, add an icon - if (isBootstrap5()) { - const iconEl = materialIcon('error') - messageInnerEl.append(iconEl) - } + const iconEl = materialIcon('error') + messageInnerEl.append(iconEl) messageInnerEl.append(messageTextNode) inputEl.insertAdjacentElement('afterend', messageEl) diff --git a/services/web/frontend/js/features/tooltip/index-bs3.ts b/services/web/frontend/js/features/tooltip/index-bs3.ts deleted file mode 100644 index e71965bcd1..0000000000 --- a/services/web/frontend/js/features/tooltip/index-bs3.ts +++ /dev/null @@ -1,2 +0,0 @@ -$('[data-ol-lang-selector-tooltip]').tooltip({ trigger: 'hover' }) -$('[data-toggle="tooltip"]').tooltip() diff --git a/services/web/frontend/js/features/tooltip/index-bs5.ts b/services/web/frontend/js/features/tooltip/index.ts similarity index 97% rename from services/web/frontend/js/features/tooltip/index-bs5.ts rename to services/web/frontend/js/features/tooltip/index.ts index 43d6bc015f..73f5456134 100644 --- a/services/web/frontend/js/features/tooltip/index-bs5.ts +++ b/services/web/frontend/js/features/tooltip/index.ts @@ -1,4 +1,4 @@ -import { Tooltip } from 'bootstrap-5' +import { Tooltip } from 'bootstrap' function getElementWidth(el: Element) { const elComputedStyle = window.getComputedStyle(el) diff --git a/services/web/frontend/js/features/utils/bootstrap-5.ts b/services/web/frontend/js/features/utils/bootstrap-5.ts deleted file mode 100644 index 6e8dd26076..0000000000 --- a/services/web/frontend/js/features/utils/bootstrap-5.ts +++ /dev/null @@ -1,5 +0,0 @@ -import getMeta from '@/utils/meta' - -// The reason this is a function is to ensure that the meta tag is read before -// any isBootstrap5 check is performed -export const isBootstrap5 = () => getMeta('ol-bootstrapVersion') === 5 diff --git a/services/web/frontend/js/features/utils/disableElement.js b/services/web/frontend/js/features/utils/disableElement.js index 7d423a26a3..fc28a35c04 100644 --- a/services/web/frontend/js/features/utils/disableElement.js +++ b/services/web/frontend/js/features/utils/disableElement.js @@ -1,7 +1,5 @@ -import { isBootstrap5 } from './bootstrap-5' - export function disableElement(el) { - if (isBootstrap5() && el.tagName.toLowerCase() === 'a') { + if (el.tagName.toLowerCase() === 'a') { el.classList.add('disabled') } else { el.disabled = true @@ -10,7 +8,7 @@ export function disableElement(el) { } export function enableElement(el) { - if (isBootstrap5() && el.tagName.toLowerCase() === 'a') { + if (el.tagName.toLowerCase() === 'a') { el.classList.remove('disabled') } else { el.disabled = false diff --git a/services/web/frontend/js/utils/meta.ts b/services/web/frontend/js/utils/meta.ts index 153ea52815..5c7bf64fa8 100644 --- a/services/web/frontend/js/utils/meta.ts +++ b/services/web/frontend/js/utils/meta.ts @@ -75,7 +75,6 @@ export interface Meta { 'ol-allowedImageNames': AllowedImageName[] 'ol-anonymous': boolean 'ol-baseAssetPath': string - 'ol-bootstrapVersion': 3 | 5 'ol-brandVariation': Record // dynamic keys based on permissions diff --git a/services/web/frontend/stylesheets/base/bootstrap.scss b/services/web/frontend/stylesheets/base/bootstrap.scss index d45d3a6a06..f89a6f190b 100644 --- a/services/web/frontend/stylesheets/base/bootstrap.scss +++ b/services/web/frontend/stylesheets/base/bootstrap.scss @@ -1,9 +1,9 @@ // Only include the parts of Bootstrap we need to minimize bundle size // Include functions first (enabling manipulation of colors, SVGs, calc, etc. in the variable overrides) -@import 'bootstrap-5/scss/functions'; +@import 'bootstrap/scss/functions'; -// Overrides for Bootstrap 5 Sass variables. These have to be included before +// Overrides for Bootstrap Sass variables. These have to be included before // Bootstrap itself because Bootstrap uses them to create the CSS variables it // uses, and in calculations to determine, for example, what color text to use // on a button based on contrast. @@ -11,44 +11,44 @@ @import '../abstracts/all'; // Include remainder of required Bootstrap stylesheets (including any separate color mode stylesheets) -@import 'bootstrap-5/scss/variables'; -@import 'bootstrap-5/scss/variables-dark'; +@import 'bootstrap/scss/variables'; +@import 'bootstrap/scss/variables-dark'; // Include remainder of required parts -@import 'bootstrap-5/scss/maps'; -@import 'bootstrap-5/scss/mixins'; -@import 'bootstrap-5/scss/utilities'; +@import 'bootstrap/scss/maps'; +@import 'bootstrap/scss/mixins'; +@import 'bootstrap/scss/utilities'; // Layout & components -@import 'bootstrap-5/scss/root'; -@import 'bootstrap-5/scss/reboot'; -@import 'bootstrap-5/scss/transitions'; -@import 'bootstrap-5/scss/type'; -@import 'bootstrap-5/scss/images'; -@import 'bootstrap-5/scss/containers'; -@import 'bootstrap-5/scss/grid'; -@import 'bootstrap-5/scss/tables'; -@import 'bootstrap-5/scss/forms'; -@import 'bootstrap-5/scss/buttons'; -@import 'bootstrap-5/scss/dropdown'; -@import 'bootstrap-5/scss/button-group'; -@import 'bootstrap-5/scss/badge'; -@import 'bootstrap-5/scss/list-group'; -@import 'bootstrap-5/scss/modal'; -@import 'bootstrap-5/scss/tooltip'; -@import 'bootstrap-5/scss/popover'; -@import 'bootstrap-5/scss/spinners'; -@import 'bootstrap-5/scss/card'; -@import 'bootstrap-5/scss/close'; -@import 'bootstrap-5/scss/nav'; -@import 'bootstrap-5/scss/navbar'; -@import 'bootstrap-5/scss/offcanvas'; +@import 'bootstrap/scss/root'; +@import 'bootstrap/scss/reboot'; +@import 'bootstrap/scss/transitions'; +@import 'bootstrap/scss/type'; +@import 'bootstrap/scss/images'; +@import 'bootstrap/scss/containers'; +@import 'bootstrap/scss/grid'; +@import 'bootstrap/scss/tables'; +@import 'bootstrap/scss/forms'; +@import 'bootstrap/scss/buttons'; +@import 'bootstrap/scss/dropdown'; +@import 'bootstrap/scss/button-group'; +@import 'bootstrap/scss/badge'; +@import 'bootstrap/scss/list-group'; +@import 'bootstrap/scss/modal'; +@import 'bootstrap/scss/tooltip'; +@import 'bootstrap/scss/popover'; +@import 'bootstrap/scss/spinners'; +@import 'bootstrap/scss/card'; +@import 'bootstrap/scss/close'; +@import 'bootstrap/scss/nav'; +@import 'bootstrap/scss/navbar'; +@import 'bootstrap/scss/offcanvas'; // Helpers -@import 'bootstrap-5/scss/helpers'; +@import 'bootstrap/scss/helpers'; // Utilities -@import 'bootstrap-5/scss/utilities/api'; +@import 'bootstrap/scss/utilities/api'; // Mixins -@import 'bootstrap-5/scss/mixins/breakpoints'; +@import 'bootstrap/scss/mixins/breakpoints'; diff --git a/services/web/frontend/stylesheets/components/nav.scss b/services/web/frontend/stylesheets/components/nav.scss index 7be306c4b2..b8abfa651c 100644 --- a/services/web/frontend/stylesheets/components/nav.scss +++ b/services/web/frontend/stylesheets/components/nav.scss @@ -1,4 +1,4 @@ -@import 'bootstrap-5/scss/functions'; +@import 'bootstrap/scss/functions'; :root { // Basics diff --git a/services/web/package.json b/services/web/package.json index d8c14cad1d..8ef0e2eab9 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -232,7 +232,6 @@ "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.4.3", "@types/bootstrap": "^5.2.10", - "@types/bootstrap-5": "npm:@types/bootstrap@^5.2.10", "@types/chai": "^4.3.0", "@types/dateformat": "^5.0.2", "@types/diff": "^5.0.9", @@ -267,8 +266,7 @@ "babel-plugin-macros": "^3.1.0", "babel-plugin-module-resolver": "^5.0.2", "backbone": "^1.6.0", - "bootstrap": "^3.4.1", - "bootstrap-5": "npm:bootstrap@^5.3.6", + "bootstrap": "^5.3.7", "c8": "^7.2.0", "chai": "^4.3.6", "chai-as-promised": "^7.1.1", diff --git a/services/web/test/frontend/helpers/bootstrap-5.ts b/services/web/test/frontend/helpers/bootstrap.ts similarity index 100% rename from services/web/test/frontend/helpers/bootstrap-5.ts rename to services/web/test/frontend/helpers/bootstrap.ts diff --git a/services/web/webpack.config.js b/services/web/webpack.config.js index cc0a65f20c..042c926b72 100644 --- a/services/web/webpack.config.js +++ b/services/web/webpack.config.js @@ -16,8 +16,7 @@ invalidateBabelCacheIfNeeded() // Generate a hash of entry points, including modules const entryPoints = { - 'bootstrap-3': './frontend/js/bootstrap-3.ts', - 'bootstrap-5': './frontend/js/bootstrap-5.ts', + bootstrap: './frontend/js/bootstrap.ts', devToolbar: './frontend/js/dev-toolbar.ts', 'ide-detached': './frontend/js/ide-detached.ts', marketing: './frontend/js/marketing.ts',