diff --git a/README.md b/README.md
index 97b5c770d..1e8edf958 100644
--- a/README.md
+++ b/README.md
@@ -128,7 +128,7 @@ Have a bug or a feature request? Please first read the [issue guidelines](https:
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/src/search.js` file.
+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
diff --git a/js/src/alert.js b/js/src/alert.js
index 724cda017..f1f612232 100644
--- a/js/src/alert.js
+++ b/js/src/alert.js
@@ -15,6 +15,7 @@ import {
} from './util/index'
import Data from './dom/data'
import EventHandler from './dom/event-handler'
+import BaseComponent from './base-component'
/**
* ------------------------------------------------------------------------
@@ -23,7 +24,6 @@ import EventHandler from './dom/event-handler'
*/
const NAME = 'alert'
-const VERSION = '5.0.0-alpha3'
const DATA_KEY = 'bs.alert'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
@@ -44,19 +44,11 @@ const CLASSNAME_SHOW = 'show'
* ------------------------------------------------------------------------
*/
-class Alert {
- constructor(element) {
- this._element = element
-
- if (this._element) {
- Data.setData(element, DATA_KEY, this)
- }
- }
-
+class Alert extends BaseComponent {
// Getters
- static get VERSION() {
- return VERSION
+ static get DATA_KEY() {
+ return DATA_KEY
}
// Public
@@ -72,11 +64,6 @@ class Alert {
this._removeElement(rootElement)
}
- dispose() {
- Data.removeData(this._element, DATA_KEY)
- this._element = null
- }
-
// Private
_getRootElement(element) {
@@ -134,10 +121,6 @@ class Alert {
alertInstance.close(this)
}
}
-
- static getInstance(element) {
- return Data.getData(element, DATA_KEY)
- }
}
/**
diff --git a/js/src/base-component.js b/js/src/base-component.js
new file mode 100644
index 000000000..776a0052b
--- /dev/null
+++ b/js/src/base-component.js
@@ -0,0 +1,44 @@
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.0.0-alpha3): base-component.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+import Data from './dom/data'
+
+/**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+
+const VERSION = '5.0.0-alpha3'
+
+class BaseComponent {
+ constructor(element) {
+ if (!element) {
+ return
+ }
+
+ this._element = element
+ Data.setData(element, this.constructor.DATA_KEY, this)
+ }
+
+ dispose() {
+ Data.removeData(this._element, this.constructor.DATA_KEY)
+ this._element = null
+ }
+
+ /** Static */
+
+ static getInstance(element) {
+ return Data.getData(element, this.DATA_KEY)
+ }
+
+ static get VERSION() {
+ return VERSION
+ }
+}
+
+export default BaseComponent
diff --git a/js/src/button.js b/js/src/button.js
index 42376943d..240995564 100644
--- a/js/src/button.js
+++ b/js/src/button.js
@@ -8,6 +8,7 @@
import { getjQuery, onDOMContentLoaded } from './util/index'
import Data from './dom/data'
import EventHandler from './dom/event-handler'
+import BaseComponent from './base-component'
/**
* ------------------------------------------------------------------------
@@ -16,7 +17,6 @@ import EventHandler from './dom/event-handler'
*/
const NAME = 'button'
-const VERSION = '5.0.0-alpha3'
const DATA_KEY = 'bs.button'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
@@ -33,16 +33,11 @@ const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
* ------------------------------------------------------------------------
*/
-class Button {
- constructor(element) {
- this._element = element
- Data.setData(element, DATA_KEY, this)
- }
-
+class Button extends BaseComponent {
// Getters
- static get VERSION() {
- return VERSION
+ static get DATA_KEY() {
+ return DATA_KEY
}
// Public
@@ -52,11 +47,6 @@ class Button {
this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE))
}
- dispose() {
- Data.removeData(this._element, DATA_KEY)
- this._element = null
- }
-
// Static
static jQueryInterface(config) {
@@ -72,10 +62,6 @@ class Button {
}
})
}
-
- static getInstance(element) {
- return Data.getData(element, DATA_KEY)
- }
}
/**
diff --git a/js/src/carousel.js b/js/src/carousel.js
index c663efbea..6443ef094 100644
--- a/js/src/carousel.js
+++ b/js/src/carousel.js
@@ -21,6 +21,7 @@ import Data from './dom/data'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
import SelectorEngine from './dom/selector-engine'
+import BaseComponent from './base-component'
/**
* ------------------------------------------------------------------------
@@ -29,7 +30,6 @@ import SelectorEngine from './dom/selector-engine'
*/
const NAME = 'carousel'
-const VERSION = '5.0.0-alpha3'
const DATA_KEY = 'bs.carousel'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
@@ -104,8 +104,10 @@ const PointerType = {
* Class Definition
* ------------------------------------------------------------------------
*/
-class Carousel {
+class Carousel extends BaseComponent {
constructor(element, config) {
+ super(element)
+
this._items = null
this._interval = null
this._activeElement = null
@@ -116,25 +118,23 @@ class Carousel {
this.touchDeltaX = 0
this._config = this._getConfig(config)
- this._element = element
this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element)
this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0
this._pointerEvent = Boolean(window.PointerEvent)
this._addEventListeners()
- Data.setData(element, DATA_KEY, this)
}
// Getters
- static get VERSION() {
- return VERSION
- }
-
static get Default() {
return Default
}
+ static get DATA_KEY() {
+ return DATA_KEY
+ }
+
// Public
next() {
@@ -218,12 +218,11 @@ class Carousel {
}
dispose() {
+ super.dispose()
EventHandler.off(this._element, EVENT_KEY)
- Data.removeData(this._element, DATA_KEY)
this._items = null
this._config = null
- this._element = null
this._interval = null
this._isPaused = null
this._isSliding = null
@@ -590,10 +589,6 @@ class Carousel {
event.preventDefault()
}
-
- static getInstance(element) {
- return Data.getData(element, DATA_KEY)
- }
}
/**
diff --git a/js/src/collapse.js b/js/src/collapse.js
index 2ddcb0c04..feff6c917 100644
--- a/js/src/collapse.js
+++ b/js/src/collapse.js
@@ -21,6 +21,7 @@ import Data from './dom/data'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
import SelectorEngine from './dom/selector-engine'
+import BaseComponent from './base-component'
/**
* ------------------------------------------------------------------------
@@ -29,7 +30,6 @@ import SelectorEngine from './dom/selector-engine'
*/
const NAME = 'collapse'
-const VERSION = '5.0.0-alpha3'
const DATA_KEY = 'bs.collapse'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
@@ -67,10 +67,11 @@ const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="collapse"]'
* ------------------------------------------------------------------------
*/
-class Collapse {
+class Collapse extends BaseComponent {
constructor(element, config) {
+ super(element)
+
this._isTransitioning = false
- this._element = element
this._config = this._getConfig(config)
this._triggerArray = SelectorEngine.find(
`${SELECTOR_DATA_TOGGLE}[href="#${element.id}"],` +
@@ -100,20 +101,18 @@ class Collapse {
if (this._config.toggle) {
this.toggle()
}
-
- Data.setData(element, DATA_KEY, this)
}
// Getters
- static get VERSION() {
- return VERSION
- }
-
static get Default() {
return Default
}
+ static get DATA_KEY() {
+ return DATA_KEY
+ }
+
// Public
toggle() {
@@ -266,11 +265,9 @@ class Collapse {
}
dispose() {
- Data.removeData(this._element, DATA_KEY)
-
+ super.dispose()
this._config = null
this._parent = null
- this._element = null
this._triggerArray = null
this._isTransitioning = null
}
@@ -368,10 +365,6 @@ class Collapse {
Collapse.collapseInterface(this, config)
})
}
-
- static getInstance(element) {
- return Data.getData(element, DATA_KEY)
- }
}
/**
diff --git a/js/src/dropdown.js b/js/src/dropdown.js
index b9f5a4cd3..5b8ae0645 100644
--- a/js/src/dropdown.js
+++ b/js/src/dropdown.js
@@ -19,6 +19,7 @@ import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
import Popper from 'popper.js'
import SelectorEngine from './dom/selector-engine'
+import BaseComponent from './base-component'
/**
* ------------------------------------------------------------------------
@@ -27,7 +28,6 @@ import SelectorEngine from './dom/selector-engine'
*/
const NAME = 'dropdown'
-const VERSION = '5.0.0-alpha3'
const DATA_KEY = 'bs.dropdown'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
@@ -96,24 +96,20 @@ const DefaultType = {
* ------------------------------------------------------------------------
*/
-class Dropdown {
+class Dropdown extends BaseComponent {
constructor(element, config) {
- this._element = element
+ super(element)
+
this._popper = null
this._config = this._getConfig(config)
this._menu = this._getMenuElement()
this._inNavbar = this._detectNavbar()
this._addEventListeners()
- Data.setData(element, DATA_KEY, this)
}
// Getters
- static get VERSION() {
- return VERSION
- }
-
static get Default() {
return Default
}
@@ -122,6 +118,10 @@ class Dropdown {
return DefaultType
}
+ static get DATA_KEY() {
+ return DATA_KEY
+ }
+
// Public
toggle() {
@@ -229,9 +229,8 @@ class Dropdown {
}
dispose() {
- Data.removeData(this._element, DATA_KEY)
+ super.dispose()
EventHandler.off(this._element, EVENT_KEY)
- this._element = null
this._menu = null
if (this._popper) {
this._popper.destroy()
@@ -489,10 +488,6 @@ class Dropdown {
items[index].focus()
}
-
- static getInstance(element) {
- return Data.getData(element, DATA_KEY)
- }
}
/**
diff --git a/js/src/modal.js b/js/src/modal.js
index 4309cbd9a..fdca48213 100644
--- a/js/src/modal.js
+++ b/js/src/modal.js
@@ -20,6 +20,7 @@ import Data from './dom/data'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
import SelectorEngine from './dom/selector-engine'
+import BaseComponent from './base-component'
/**
* ------------------------------------------------------------------------
@@ -28,7 +29,6 @@ import SelectorEngine from './dom/selector-engine'
*/
const NAME = 'modal'
-const VERSION = '5.0.0-alpha3'
const DATA_KEY = 'bs.modal'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
@@ -37,15 +37,13 @@ const ESCAPE_KEY = 'Escape'
const Default = {
backdrop: true,
keyboard: true,
- focus: true,
- show: true
+ focus: true
}
const DefaultType = {
backdrop: '(boolean|string)',
keyboard: 'boolean',
- focus: 'boolean',
- show: 'boolean'
+ focus: 'boolean'
}
const EVENT_HIDE = `hide${EVENT_KEY}`
@@ -81,10 +79,11 @@ const SELECTOR_STICKY_CONTENT = '.sticky-top'
* ------------------------------------------------------------------------
*/
-class Modal {
+class Modal extends BaseComponent {
constructor(element, config) {
+ super(element)
+
this._config = this._getConfig(config)
- this._element = element
this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, element)
this._backdrop = null
this._isShown = false
@@ -92,19 +91,18 @@ class Modal {
this._ignoreBackdropClick = false
this._isTransitioning = false
this._scrollbarWidth = 0
- Data.setData(element, DATA_KEY, this)
}
// Getters
- static get VERSION() {
- return VERSION
- }
-
static get Default() {
return Default
}
+ static get DATA_KEY() {
+ return DATA_KEY
+ }
+
// Public
toggle(relatedTarget) {
@@ -201,6 +199,8 @@ class Modal {
[window, this._element, this._dialog]
.forEach(htmlElement => EventHandler.off(htmlElement, EVENT_KEY))
+ super.dispose()
+
/**
* `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API`
* Do not move `document` in `htmlElements` array
@@ -208,10 +208,7 @@ class Modal {
*/
EventHandler.off(document, EVENT_FOCUSIN)
- Data.removeData(this._element, DATA_KEY)
-
this._config = null
- this._element = null
this._dialog = null
this._backdrop = null
this._isShown = null
@@ -558,15 +555,9 @@ class Modal {
}
data[config](relatedTarget)
- } else if (_config.show) {
- data.show(relatedTarget)
}
})
}
-
- static getInstance(element) {
- return Data.getData(element, DATA_KEY)
- }
}
/**
diff --git a/js/src/popover.js b/js/src/popover.js
index 46b693e69..97db9a3f7 100644
--- a/js/src/popover.js
+++ b/js/src/popover.js
@@ -17,7 +17,6 @@ import Tooltip from './tooltip'
*/
const NAME = 'popover'
-const VERSION = '5.0.0-alpha3'
const DATA_KEY = 'bs.popover'
const EVENT_KEY = `.${DATA_KEY}`
const CLASS_PREFIX = 'bs-popover'
@@ -67,10 +66,6 @@ const SELECTOR_CONTENT = '.popover-body'
class Popover extends Tooltip {
// Getters
- static get VERSION() {
- return VERSION
- }
-
static get Default() {
return Default
}
@@ -108,7 +103,7 @@ class Popover extends Tooltip {
this.setElementContent(SelectorEngine.findOne(SELECTOR_TITLE, tip), this.getTitle())
let content = this._getContent()
if (typeof content === 'function') {
- content = content.call(this.element)
+ content = content.call(this._element)
}
this.setElementContent(SelectorEngine.findOne(SELECTOR_CONTENT, tip), content)
@@ -123,7 +118,7 @@ class Popover extends Tooltip {
}
_getContent() {
- return this.element.getAttribute('data-bs-content') ||
+ return this._element.getAttribute('data-bs-content') ||
this.config.content
}
@@ -161,10 +156,6 @@ class Popover extends Tooltip {
}
})
}
-
- static getInstance(element) {
- return Data.getData(element, DATA_KEY)
- }
}
/**
diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js
index de456e080..e3e5e76b9 100644
--- a/js/src/scrollspy.js
+++ b/js/src/scrollspy.js
@@ -17,6 +17,7 @@ import Data from './dom/data'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
import SelectorEngine from './dom/selector-engine'
+import BaseComponent from './base-component'
/**
* ------------------------------------------------------------------------
@@ -25,7 +26,6 @@ import SelectorEngine from './dom/selector-engine'
*/
const NAME = 'scrollspy'
-const VERSION = '5.0.0-alpha3'
const DATA_KEY = 'bs.scrollspy'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
@@ -66,9 +66,9 @@ const METHOD_POSITION = 'position'
* ------------------------------------------------------------------------
*/
-class ScrollSpy {
+class ScrollSpy extends BaseComponent {
constructor(element, config) {
- this._element = element
+ super(element)
this._scrollElement = element.tagName === 'BODY' ? window : element
this._config = this._getConfig(config)
this._selector = `${this._config.target} ${SELECTOR_NAV_LINKS}, ${this._config.target} ${SELECTOR_LIST_ITEMS}, ${this._config.target} .${CLASS_NAME_DROPDOWN_ITEM}`
@@ -81,20 +81,18 @@ class ScrollSpy {
this.refresh()
this._process()
-
- Data.setData(element, DATA_KEY, this)
}
// Getters
- static get VERSION() {
- return VERSION
- }
-
static get Default() {
return Default
}
+ static get DATA_KEY() {
+ return DATA_KEY
+ }
+
// Public
refresh() {
@@ -141,10 +139,9 @@ class ScrollSpy {
}
dispose() {
- Data.removeData(this._element, DATA_KEY)
+ super.dispose()
EventHandler.off(this._scrollElement, EVENT_KEY)
- this._element = null
this._scrollElement = null
this._config = null
this._selector = null
@@ -301,10 +298,6 @@ class ScrollSpy {
}
})
}
-
- static getInstance(element) {
- return Data.getData(element, DATA_KEY)
- }
}
/**
diff --git a/js/src/tab.js b/js/src/tab.js
index 56269e2fa..0e9755ea0 100644
--- a/js/src/tab.js
+++ b/js/src/tab.js
@@ -17,6 +17,7 @@ import {
import Data from './dom/data'
import EventHandler from './dom/event-handler'
import SelectorEngine from './dom/selector-engine'
+import BaseComponent from './base-component'
/**
* ------------------------------------------------------------------------
@@ -25,7 +26,6 @@ import SelectorEngine from './dom/selector-engine'
*/
const NAME = 'tab'
-const VERSION = '5.0.0-alpha3'
const DATA_KEY = 'bs.tab'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
@@ -56,17 +56,11 @@ const SELECTOR_DROPDOWN_ACTIVE_CHILD = ':scope > .dropdown-menu .active'
* ------------------------------------------------------------------------
*/
-class Tab {
- constructor(element) {
- this._element = element
-
- Data.setData(this._element, DATA_KEY, this)
- }
-
+class Tab extends BaseComponent {
// Getters
- static get VERSION() {
- return VERSION
+ static get DATA_KEY() {
+ return DATA_KEY
}
// Public
@@ -127,11 +121,6 @@ class Tab {
}
}
- dispose() {
- Data.removeData(this._element, DATA_KEY)
- this._element = null
- }
-
// Private
_activate(element, container, callback) {
@@ -217,10 +206,6 @@ class Tab {
}
})
}
-
- static getInstance(element) {
- return Data.getData(element, DATA_KEY)
- }
}
/**
diff --git a/js/src/toast.js b/js/src/toast.js
index 1e50b0669..30df4606a 100644
--- a/js/src/toast.js
+++ b/js/src/toast.js
@@ -17,6 +17,7 @@ import {
import Data from './dom/data'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
+import BaseComponent from './base-component'
/**
* ------------------------------------------------------------------------
@@ -25,7 +26,6 @@ import Manipulator from './dom/manipulator'
*/
const NAME = 'toast'
-const VERSION = '5.0.0-alpha3'
const DATA_KEY = 'bs.toast'
const EVENT_KEY = `.${DATA_KEY}`
@@ -60,21 +60,17 @@ const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="toast"]'
* ------------------------------------------------------------------------
*/
-class Toast {
+class Toast extends BaseComponent {
constructor(element, config) {
- this._element = element
+ super(element)
+
this._config = this._getConfig(config)
this._timeout = null
this._setListeners()
- Data.setData(element, DATA_KEY, this)
}
// Getters
- static get VERSION() {
- return VERSION
- }
-
static get DefaultType() {
return DefaultType
}
@@ -83,6 +79,10 @@ class Toast {
return Default
}
+ static get DATA_KEY() {
+ return DATA_KEY
+ }
+
// Public
show() {
@@ -159,9 +159,8 @@ class Toast {
}
EventHandler.off(this._element, EVENT_CLICK_DISMISS)
- Data.removeData(this._element, DATA_KEY)
- this._element = null
+ super.dispose()
this._config = null
}
@@ -208,10 +207,6 @@ class Toast {
}
})
}
-
- static getInstance(element) {
- return Data.getData(element, DATA_KEY)
- }
}
/**
diff --git a/js/src/tooltip.js b/js/src/tooltip.js
index 368e04b30..62b338839 100644
--- a/js/src/tooltip.js
+++ b/js/src/tooltip.js
@@ -26,6 +26,7 @@ import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
import Popper from 'popper.js'
import SelectorEngine from './dom/selector-engine'
+import BaseComponent from './base-component'
/**
* ------------------------------------------------------------------------
@@ -34,7 +35,6 @@ import SelectorEngine from './dom/selector-engine'
*/
const NAME = 'tooltip'
-const VERSION = '5.0.0-alpha3'
const DATA_KEY = 'bs.tooltip'
const EVENT_KEY = `.${DATA_KEY}`
const CLASS_PREFIX = 'bs-tooltip'
@@ -124,12 +124,14 @@ const TRIGGER_MANUAL = 'manual'
* ------------------------------------------------------------------------
*/
-class Tooltip {
+class Tooltip extends BaseComponent {
constructor(element, config) {
if (typeof Popper === 'undefined') {
throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)')
}
+ super(element)
+
// private
this._isEnabled = true
this._timeout = 0
@@ -138,20 +140,14 @@ class Tooltip {
this._popper = null
// Protected
- this.element = element
this.config = this._getConfig(config)
this.tip = null
this._setListeners()
- Data.setData(element, this.constructor.DATA_KEY, this)
}
// Getters
- static get VERSION() {
- return VERSION
- }
-
static get Default() {
return Default
}
@@ -227,10 +223,8 @@ class Tooltip {
dispose() {
clearTimeout(this._timeout)
- Data.removeData(this.element, this.constructor.DATA_KEY)
-
- EventHandler.off(this.element, this.constructor.EVENT_KEY)
- EventHandler.off(this.element.closest(`.${CLASS_NAME_MODAL}`), 'hide.bs.modal', this._hideModalHandler)
+ EventHandler.off(this._element, this.constructor.EVENT_KEY)
+ EventHandler.off(this._element.closest(`.${CLASS_NAME_MODAL}`), 'hide.bs.modal', this._hideModalHandler)
if (this.tip) {
this.tip.parentNode.removeChild(this.tip)
@@ -245,22 +239,22 @@ class Tooltip {
}
this._popper = null
- this.element = null
this.config = null
this.tip = null
+ super.dispose()
}
show() {
- if (this.element.style.display === 'none') {
+ if (this._element.style.display === 'none') {
throw new Error('Please use show on visible elements')
}
if (this.isWithContent() && this._isEnabled) {
- const showEvent = EventHandler.trigger(this.element, this.constructor.Event.SHOW)
- const shadowRoot = findShadowRoot(this.element)
+ const showEvent = EventHandler.trigger(this._element, this.constructor.Event.SHOW)
+ const shadowRoot = findShadowRoot(this._element)
const isInTheDom = shadowRoot === null ?
- this.element.ownerDocument.documentElement.contains(this.element) :
- shadowRoot.contains(this.element)
+ this._element.ownerDocument.documentElement.contains(this._element) :
+ shadowRoot.contains(this._element)
if (showEvent.defaultPrevented || !isInTheDom) {
return
@@ -270,7 +264,7 @@ class Tooltip {
const tipId = getUID(this.constructor.NAME)
tip.setAttribute('id', tipId)
- this.element.setAttribute('aria-describedby', tipId)
+ this._element.setAttribute('aria-describedby', tipId)
this.setContent()
@@ -279,7 +273,7 @@ class Tooltip {
}
const placement = typeof this.config.placement === 'function' ?
- this.config.placement.call(this, tip, this.element) :
+ this.config.placement.call(this, tip, this._element) :
this.config.placement
const attachment = this._getAttachment(placement)
@@ -288,13 +282,13 @@ class Tooltip {
const container = this._getContainer()
Data.setData(tip, this.constructor.DATA_KEY, this)
- if (!this.element.ownerDocument.documentElement.contains(this.tip)) {
+ if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
container.appendChild(tip)
}
- EventHandler.trigger(this.element, this.constructor.Event.INSERTED)
+ EventHandler.trigger(this._element, this.constructor.Event.INSERTED)
- this._popper = new Popper(this.element, tip, this._getPopperConfig(attachment))
+ this._popper = new Popper(this._element, tip, this._getPopperConfig(attachment))
tip.classList.add(CLASS_NAME_SHOW)
@@ -321,7 +315,7 @@ class Tooltip {
const prevHoverState = this._hoverState
this._hoverState = null
- EventHandler.trigger(this.element, this.constructor.Event.SHOWN)
+ EventHandler.trigger(this._element, this.constructor.Event.SHOWN)
if (prevHoverState === HOVER_STATE_OUT) {
this._leave(null, this)
@@ -350,12 +344,12 @@ class Tooltip {
}
this._cleanTipClass()
- this.element.removeAttribute('aria-describedby')
- EventHandler.trigger(this.element, this.constructor.Event.HIDDEN)
+ this._element.removeAttribute('aria-describedby')
+ EventHandler.trigger(this._element, this.constructor.Event.HIDDEN)
this._popper.destroy()
}
- const hideEvent = EventHandler.trigger(this.element, this.constructor.Event.HIDE)
+ const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE)
if (hideEvent.defaultPrevented) {
return
}
@@ -450,11 +444,11 @@ class Tooltip {
}
getTitle() {
- let title = this.element.getAttribute('data-bs-original-title')
+ let title = this._element.getAttribute('data-bs-original-title')
if (!title) {
title = typeof this.config.title === 'function' ?
- this.config.title.call(this.element) :
+ this.config.title.call(this._element) :
this.config.title
}
@@ -503,7 +497,7 @@ class Tooltip {
offset.fn = data => {
data.offsets = {
...data.offsets,
- ...(this.config.offset(data.offsets, this.element) || {})
+ ...(this.config.offset(data.offsets, this._element) || {})
}
return data
@@ -536,7 +530,7 @@ class Tooltip {
triggers.forEach(trigger => {
if (trigger === 'click') {
- EventHandler.on(this.element,
+ EventHandler.on(this._element,
this.constructor.Event.CLICK,
this.config.selector,
event => this.toggle(event)
@@ -549,12 +543,12 @@ class Tooltip {
this.constructor.Event.MOUSELEAVE :
this.constructor.Event.FOCUSOUT
- EventHandler.on(this.element,
+ EventHandler.on(this._element,
eventIn,
this.config.selector,
event => this._enter(event)
)
- EventHandler.on(this.element,
+ EventHandler.on(this._element,
eventOut,
this.config.selector,
event => this._leave(event)
@@ -563,12 +557,12 @@ class Tooltip {
})
this._hideModalHandler = () => {
- if (this.element) {
+ if (this._element) {
this.hide()
}
}
- EventHandler.on(this.element.closest(`.${CLASS_NAME_MODAL}`),
+ EventHandler.on(this._element.closest(`.${CLASS_NAME_MODAL}`),
'hide.bs.modal',
this._hideModalHandler
)
@@ -585,12 +579,16 @@ class Tooltip {
}
_fixTitle() {
- const title = this.element.getAttribute('title')
- const originalTitleType = typeof this.element.getAttribute('data-bs-original-title')
+ const title = this._element.getAttribute('title')
+ const originalTitleType = typeof this._element.getAttribute('data-bs-original-title')
if (title || originalTitleType !== 'string') {
- this.element.setAttribute('data-bs-original-title', title || '')
- this.element.setAttribute('title', '')
+ this._element.setAttribute('data-bs-original-title', title || '')
+ if (title && !this._element.getAttribute('aria-label') && !this._element.textContent) {
+ this._element.setAttribute('aria-label', title)
+ }
+
+ this._element.setAttribute('title', '')
}
}
@@ -683,7 +681,7 @@ class Tooltip {
}
_getConfig(config) {
- const dataAttributes = Manipulator.getDataAttributes(this.element)
+ const dataAttributes = Manipulator.getDataAttributes(this._element)
Object.keys(dataAttributes).forEach(dataAttr => {
if (DISALLOWED_ATTRIBUTES.has(dataAttr)) {
@@ -792,10 +790,6 @@ class Tooltip {
}
})
}
-
- static getInstance(element) {
- return Data.getData(element, DATA_KEY)
- }
}
/**
diff --git a/js/tests/unit/alert.spec.js b/js/tests/unit/alert.spec.js
index a746d8501..a1322f1c7 100644
--- a/js/tests/unit/alert.spec.js
+++ b/js/tests/unit/alert.spec.js
@@ -170,4 +170,24 @@ describe('Alert', () => {
expect(fixtureEl.querySelector('.alert')).not.toBeNull()
})
})
+
+ describe('getInstance', () => {
+ it('should return alert instance', () => {
+ fixtureEl.innerHTML = '
'
+
+ const div = fixtureEl.querySelector('div')
+ const alert = new Alert(div)
+
+ expect(Alert.getInstance(div)).toEqual(alert)
+ expect(Alert.getInstance(div)).toBeInstanceOf(Alert)
+ })
+
+ it('should return null when there is no alert instance', () => {
+ fixtureEl.innerHTML = '
'
+
+ const div = fixtureEl.querySelector('div')
+
+ expect(Alert.getInstance(div)).toEqual(null)
+ })
+ })
})
diff --git a/js/tests/unit/button.spec.js b/js/tests/unit/button.spec.js
index 44d7b54b1..51aa73774 100644
--- a/js/tests/unit/button.spec.js
+++ b/js/tests/unit/button.spec.js
@@ -128,4 +128,24 @@ describe('Button', () => {
expect(btnEl.classList.contains('active')).toEqual(false)
})
})
+
+ describe('getInstance', () => {
+ it('should return button instance', () => {
+ fixtureEl.innerHTML = '
'
+
+ const div = fixtureEl.querySelector('div')
+ const button = new Button(div)
+
+ expect(Button.getInstance(div)).toEqual(button)
+ expect(Button.getInstance(div)).toBeInstanceOf(Button)
+ })
+
+ it('should return null when there is no button instance', () => {
+ fixtureEl.innerHTML = '
'
+
+ const div = fixtureEl.querySelector('div')
+
+ expect(Button.getInstance(div)).toEqual(null)
+ })
+ })
})
diff --git a/js/tests/unit/carousel.spec.js b/js/tests/unit/carousel.spec.js
index 8c928c429..07b8fc311 100644
--- a/js/tests/unit/carousel.spec.js
+++ b/js/tests/unit/carousel.spec.js
@@ -1062,6 +1062,26 @@ describe('Carousel', () => {
})
})
+ describe('getInstance', () => {
+ it('should return carousel instance', () => {
+ fixtureEl.innerHTML = '
'
+
+ const div = fixtureEl.querySelector('div')
+ const carousel = new Carousel(div)
+
+ expect(Carousel.getInstance(div)).toEqual(carousel)
+ expect(Carousel.getInstance(div)).toBeInstanceOf(Carousel)
+ })
+
+ it('should return null when there is no carousel instance', () => {
+ fixtureEl.innerHTML = '
'
+
+ const div = fixtureEl.querySelector('div')
+
+ expect(Carousel.getInstance(div)).toEqual(null)
+ })
+ })
+
describe('jQueryInterface', () => {
it('should create a carousel', () => {
fixtureEl.innerHTML = '
'
diff --git a/js/tests/unit/collapse.spec.js b/js/tests/unit/collapse.spec.js
index c1ead859a..d53ab5964 100644
--- a/js/tests/unit/collapse.spec.js
+++ b/js/tests/unit/collapse.spec.js
@@ -812,6 +812,7 @@ describe('Collapse', () => {
const collapse = new Collapse(div)
expect(Collapse.getInstance(div)).toEqual(collapse)
+ expect(Collapse.getInstance(div)).toBeInstanceOf(Collapse)
})
it('should return null when there is no collapse instance', () => {
diff --git a/js/tests/unit/dropdown.spec.js b/js/tests/unit/dropdown.spec.js
index f5f41636c..145763d20 100644
--- a/js/tests/unit/dropdown.spec.js
+++ b/js/tests/unit/dropdown.spec.js
@@ -1612,6 +1612,7 @@ describe('Dropdown', () => {
const dropdown = new Dropdown(div)
expect(Dropdown.getInstance(div)).toEqual(dropdown)
+ expect(Dropdown.getInstance(div)).toBeInstanceOf(Dropdown)
})
it('should return null when there is no dropdown instance', () => {
diff --git a/js/tests/unit/modal.spec.js b/js/tests/unit/modal.spec.js
index 084f78ad1..f645e9892 100644
--- a/js/tests/unit/modal.spec.js
+++ b/js/tests/unit/modal.spec.js
@@ -1108,6 +1108,7 @@ describe('Modal', () => {
const modal = new Modal(div)
expect(Modal.getInstance(div)).toEqual(modal)
+ expect(Modal.getInstance(div)).toBeInstanceOf(Modal)
})
it('should return null when there is no modal instance', () => {
diff --git a/js/tests/unit/popover.spec.js b/js/tests/unit/popover.spec.js
index e87ed1214..3c04e7ac1 100644
--- a/js/tests/unit/popover.spec.js
+++ b/js/tests/unit/popover.spec.js
@@ -253,6 +253,7 @@ describe('Popover', () => {
const popover = new Popover(popoverEl)
expect(Popover.getInstance(popoverEl)).toEqual(popover)
+ expect(Popover.getInstance(popoverEl)).toBeInstanceOf(Popover)
})
it('should return null when there is no popover instance', () => {
diff --git a/js/tests/unit/scrollspy.spec.js b/js/tests/unit/scrollspy.spec.js
index 33298300c..45de56fbe 100644
--- a/js/tests/unit/scrollspy.spec.js
+++ b/js/tests/unit/scrollspy.spec.js
@@ -634,6 +634,16 @@ describe('ScrollSpy', () => {
})
describe('getInstance', () => {
+ it('should return scrollspy instance', () => {
+ fixtureEl.innerHTML = '
'
+
+ const div = fixtureEl.querySelector('div')
+ const scrollSpy = new ScrollSpy(div)
+
+ expect(ScrollSpy.getInstance(div)).toEqual(scrollSpy)
+ expect(ScrollSpy.getInstance(div)).toBeInstanceOf(ScrollSpy)
+ })
+
it('should return null if there is no instance', () => {
expect(ScrollSpy.getInstance(fixtureEl)).toEqual(null)
})
diff --git a/js/tests/unit/tab.spec.js b/js/tests/unit/tab.spec.js
index 324c4a09b..67a85b2e4 100644
--- a/js/tests/unit/tab.spec.js
+++ b/js/tests/unit/tab.spec.js
@@ -417,6 +417,7 @@ describe('Tab', () => {
const tab = new Tab(divEl)
expect(Tab.getInstance(divEl)).toEqual(tab)
+ expect(Tab.getInstance(divEl)).toBeInstanceOf(Tab)
})
})
diff --git a/js/tests/unit/toast.spec.js b/js/tests/unit/toast.spec.js
index c4cb69a7f..a4ab4f76c 100644
--- a/js/tests/unit/toast.spec.js
+++ b/js/tests/unit/toast.spec.js
@@ -384,6 +384,7 @@ describe('Toast', () => {
const toast = new Toast(div)
expect(Toast.getInstance(div)).toEqual(toast)
+ expect(Toast.getInstance(div)).toBeInstanceOf(Toast)
})
it('should return null when there is no toast instance', () => {
diff --git a/js/tests/unit/tooltip.spec.js b/js/tests/unit/tooltip.spec.js
index da2abba31..b11980751 100644
--- a/js/tests/unit/tooltip.spec.js
+++ b/js/tests/unit/tooltip.spec.js
@@ -1030,6 +1030,79 @@ describe('Tooltip', () => {
})
})
+ describe('getInstance', () => {
+ it('should return tooltip instance', () => {
+ fixtureEl.innerHTML = '
'
+
+ const div = fixtureEl.querySelector('div')
+ const alert = new Tooltip(div)
+
+ expect(Tooltip.getInstance(div)).toEqual(alert)
+ expect(Tooltip.getInstance(div)).toBeInstanceOf(Tooltip)
+ })
+
+ it('should return null when there is no tooltip instance', () => {
+ fixtureEl.innerHTML = '
'
+
+ const div = fixtureEl.querySelector('div')
+
+ expect(Tooltip.getInstance(div)).toEqual(null)
+ })
+ })
+
+ describe('aria-label', () => {
+ it('should add the aria-label attribute for referencing original title', done => {
+ fixtureEl.innerHTML = ' '
+
+ const tooltipEl = fixtureEl.querySelector('a')
+ const tooltip = new Tooltip(tooltipEl)
+
+ tooltipEl.addEventListener('shown.bs.tooltip', () => {
+ const tooltipShown = document.querySelector('.tooltip')
+
+ expect(tooltipShown).toBeDefined()
+ expect(tooltipEl.getAttribute('aria-label')).toEqual('Another tooltip')
+ done()
+ })
+
+ tooltip.show()
+ })
+
+ it('should not add the aria-label attribute if the attribute already exists', done => {
+ fixtureEl.innerHTML = ' '
+
+ const tooltipEl = fixtureEl.querySelector('a')
+ const tooltip = new Tooltip(tooltipEl)
+
+ tooltipEl.addEventListener('shown.bs.tooltip', () => {
+ const tooltipShown = document.querySelector('.tooltip')
+
+ expect(tooltipShown).toBeDefined()
+ expect(tooltipEl.getAttribute('aria-label')).toEqual('Different label')
+ done()
+ })
+
+ tooltip.show()
+ })
+
+ it('should not add the aria-label attribute if the element has text content', done => {
+ fixtureEl.innerHTML = 'text content '
+
+ const tooltipEl = fixtureEl.querySelector('a')
+ const tooltip = new Tooltip(tooltipEl)
+
+ tooltipEl.addEventListener('shown.bs.tooltip', () => {
+ const tooltipShown = document.querySelector('.tooltip')
+
+ expect(tooltipShown).toBeDefined()
+ expect(tooltipEl.getAttribute('aria-label')).toBeNull()
+ done()
+ })
+
+ tooltip.show()
+ })
+ })
+
describe('jQueryInterface', () => {
it('should create a tooltip', () => {
fixtureEl.innerHTML = '
'
diff --git a/package-lock.json b/package-lock.json
index caa899ea1..6ad038d6f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -38,9 +38,9 @@
"dev": true
},
"@babel/core": {
- "version": "7.12.8",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.8.tgz",
- "integrity": "sha512-ra28JXL+5z73r1IC/t+FT1ApXU5LsulFDnTDntNfLQaScJUJmcHL5Qxm/IWanCToQk3bPWQo5bflbplU5r15pg==",
+ "version": "7.12.9",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz",
+ "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",
@@ -49,7 +49,7 @@
"@babel/helpers": "^7.12.5",
"@babel/parser": "^7.12.7",
"@babel/template": "^7.12.7",
- "@babel/traverse": "^7.12.8",
+ "@babel/traverse": "^7.12.9",
"@babel/types": "^7.12.7",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
@@ -1006,9 +1006,9 @@
}
},
"@babel/traverse": {
- "version": "7.12.8",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.8.tgz",
- "integrity": "sha512-EIRQXPTwFEGRZyu6gXbjfpNORN1oZvwuzJbxcXjAgWV0iqXYDszN1Hx3FVm6YgZfu1ZQbCVAk3l+nIw95Xll9Q==",
+ "version": "7.12.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.9.tgz",
+ "integrity": "sha512-iX9ajqnLdoU1s1nHt36JDI9KG4k+vmI8WgjK5d+aDTwQbL2fUnzedNedssA645Ede3PM2ma1n8Q4h2ohwXgMXw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",
@@ -1141,9 +1141,9 @@
}
},
"@rollup/plugin-babel": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.2.1.tgz",
- "integrity": "sha512-Jd7oqFR2dzZJ3NWANDyBjwTtX/lYbZpVcmkHrfQcpvawHs9E4c0nYk5U2mfZ6I/DZcIvy506KZJi54XK/jxH7A==",
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.2.2.tgz",
+ "integrity": "sha512-MjmH7GvFT4TW8xFdIeFS3wqIX646y5tACdxkTO+khbHvS3ZcVJL6vkAHLw2wqPmkhwCfWHoNsp15VYNwW6JEJA==",
"dev": true,
"requires": {
"@babel/helper-module-imports": "^7.10.4",
@@ -1151,9 +1151,9 @@
}
},
"@rollup/plugin-commonjs": {
- "version": "16.0.0",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz",
- "integrity": "sha512-LuNyypCP3msCGVQJ7ki8PqYdpjfEkE/xtFa5DqlF+7IBD0JsfMZ87C58heSwIMint58sAUZbt3ITqOmdQv/dXw==",
+ "version": "17.0.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-17.0.0.tgz",
+ "integrity": "sha512-/omBIJG1nHQc+bgkYDuLpb/V08QyutP9amOrJRUSlYJZP+b/68gM//D8sxJe3Yry2QnYIr3QjR3x4AlxJEN3GA==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.1.0",
@@ -1174,9 +1174,9 @@
}
},
"@rollup/plugin-node-resolve": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-10.0.0.tgz",
- "integrity": "sha512-sNijGta8fqzwA1VwUEtTvWCx2E7qC70NMsDh4ZG13byAXYigBNZMxALhKUSycBks5gupJdq0lFrKumFrRZ8H3A==",
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.0.0.tgz",
+ "integrity": "sha512-8Hrmwjn1pLYjUxcv7U7IPP0qfnzEJWHyHE6CaZ8jbLM+8axaarJRB1jB6JgKTDp5gNga+TpsgX6F8iuvgOerKQ==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.1.0",
@@ -1184,7 +1184,7 @@
"builtin-modules": "^3.1.0",
"deepmerge": "^4.2.2",
"is-module": "^1.0.0",
- "resolve": "^1.17.0"
+ "resolve": "^1.19.0"
}
},
"@rollup/pluginutils": {
@@ -1260,9 +1260,9 @@
"dev": true
},
"@types/node": {
- "version": "14.14.9",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.9.tgz",
- "integrity": "sha512-JsoLXFppG62tWTklIoO4knA+oDTYsmqWxHRvd4lpmfQRNhX6osheUOWETP2jMoV/2bEHuMra8Pp3Dmo/stBFcw==",
+ "version": "14.14.10",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.10.tgz",
+ "integrity": "sha512-J32dgx2hw8vXrSbu4ZlVhn1Nm3GbeCFNw2FWL8S5QKucHGY0cyNwjdQdO+KMBZ4wpmC7KhLCiNsdk1RFRIYUQQ==",
"dev": true
},
"@types/normalize-package-data": {
@@ -1468,14 +1468,22 @@
"dev": true,
"optional": true
},
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
+ "dev": true
+ },
"array-includes": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz",
- "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==",
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz",
+ "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==",
"dev": true,
"requires": {
+ "call-bind": "^1.0.0",
"define-properties": "^1.1.3",
- "es-abstract": "^1.17.0",
+ "es-abstract": "^1.18.0-next.1",
+ "get-intrinsic": "^1.0.1",
"is-string": "^1.0.5"
}
},
@@ -1501,28 +1509,6 @@
"call-bind": "^1.0.0",
"define-properties": "^1.1.3",
"es-abstract": "^1.18.0-next.1"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.18.0-next.1",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
- "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.2",
- "is-negative-zero": "^2.0.0",
- "is-regex": "^1.1.1",
- "object-inspect": "^1.8.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.1",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
- }
- }
}
},
"arraybuffer.slice": {
@@ -1577,13 +1563,13 @@
"optional": true
},
"autoprefixer": {
- "version": "10.0.2",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.0.2.tgz",
- "integrity": "sha512-okBmu9OMdt6DNEcZmnl0IYVv8Xl/xYWRSnc2OJ9UJEOt1u30opG1B8aLsViqKryBaYv1SKB4f85fOGZs5zYxHQ==",
+ "version": "10.0.4",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.0.4.tgz",
+ "integrity": "sha512-hmjYejN/WTyPP9cdNmiwtwqM8/ACVJPD5ExtwoOceQohNbgnFNiwpL2+U4bXS8aXozBL00WvH6WhqbuHf0Fgfg==",
"dev": true,
"requires": {
"browserslist": "^4.14.7",
- "caniuse-lite": "^1.0.30001157",
+ "caniuse-lite": "^1.0.30001161",
"colorette": "^1.2.1",
"normalize-range": "^0.1.2",
"num2fraction": "^1.2.2",
@@ -2479,9 +2465,9 @@
}
},
"caniuse-lite": {
- "version": "1.0.30001159",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001159.tgz",
- "integrity": "sha512-w9Ph56jOsS8RL20K9cLND3u/+5WASWdhC/PPrf+V3/HsM3uHOavWOR1Xzakbv4Puo/srmPHudkmCRWM7Aq+/UA==",
+ "version": "1.0.30001164",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001164.tgz",
+ "integrity": "sha512-G+A/tkf4bu0dSp9+duNiXc7bGds35DioCyC6vgK2m/rjA4Krpy5WeZgZyfH2f0wj2kI6yAWWucyap6oOwmY1mg==",
"dev": true
},
"caw": {
@@ -2974,6 +2960,12 @@
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
"dev": true
},
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
+ "dev": true
+ },
"copy-descriptor": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
@@ -2982,18 +2974,18 @@
"optional": true
},
"core-js": {
- "version": "2.6.11",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
- "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==",
+ "version": "2.6.12",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
+ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
"dev": true
},
"core-js-compat": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.7.0.tgz",
- "integrity": "sha512-V8yBI3+ZLDVomoWICO6kq/CD28Y4r1M7CWeO4AGpMdMfseu8bkSubBmUPySMGKRTS+su4XQ07zUkAsiu9FCWTg==",
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.0.tgz",
+ "integrity": "sha512-o9QKelQSxQMYWHXc/Gc4L8bx/4F7TTraE5rhuN8I7mKBt5dBIUpXpIR3omv70ebr8ST5R3PqbDQr+ZI3+Tt1FQ==",
"dev": true,
"requires": {
- "browserslist": "^4.14.6",
+ "browserslist": "^4.14.7",
"semver": "7.0.0"
},
"dependencies": {
@@ -3551,9 +3543,9 @@
"dev": true
},
"electron-to-chromium": {
- "version": "1.3.605",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.605.tgz",
- "integrity": "sha512-PDZlEh6qelLaFLXYuIvB0aeqNoq7JS7i7aSHFds/ZnHosxyrTZftD8o84K9OwZWR+tnQFwoL76Yd5ROAhIWojQ==",
+ "version": "1.3.612",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.612.tgz",
+ "integrity": "sha512-CdrdX1B6mQqxfw+51MPWB5qA6TKWjza9f5voBtUlRfEZEwZiFaxJLrhFI8zHE9SBAuGt4h84rQU6Ho9Bauo1LA==",
"dev": true
},
"emoji-regex": {
@@ -3703,9 +3695,9 @@
}
},
"es-abstract": {
- "version": "1.17.7",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
- "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
+ "version": "1.18.0-next.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
+ "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
"dev": true,
"requires": {
"es-to-primitive": "^1.2.1",
@@ -3713,6 +3705,7 @@
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
+ "is-negative-zero": "^2.0.0",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
@@ -4350,6 +4343,52 @@
}
}
},
+ "express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.7",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.19.0",
+ "content-disposition": "0.5.3",
+ "content-type": "~1.0.4",
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.1.2",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.5",
+ "qs": "6.7.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.1.2",
+ "send": "0.17.1",
+ "serve-static": "1.14.1",
+ "setprototypeof": "1.1.1",
+ "statuses": "~1.5.0",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
+ "dev": true
+ }
+ }
+ },
"ext-list": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz",
@@ -4801,6 +4840,12 @@
"dev": true,
"optional": true
},
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
+ "dev": true
+ },
"fragment-cache": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -5408,9 +5453,9 @@
}
},
"hugo-bin": {
- "version": "0.66.2",
- "resolved": "https://registry.npmjs.org/hugo-bin/-/hugo-bin-0.66.2.tgz",
- "integrity": "sha512-T/U35qAnzKubHzMi10uolB50e+RgHigHyAEnhGy6upCEp2H1sbDtsmqyzIhc+gMK8VIzJoU3vg/nqfpkFKOwsA==",
+ "version": "0.67.0",
+ "resolved": "https://registry.npmjs.org/hugo-bin/-/hugo-bin-0.67.0.tgz",
+ "integrity": "sha512-EvNzhWGqE2Pb1idPPLlyIIK2VC3so3sdYShC2ohxsHCGNVWoe/D25KPJ5oIVpakxTu4SSH7Kr37RUMsa0yGQ+g==",
"dev": true,
"requires": {
"bin-wrapper": "^4.1.0",
@@ -5582,6 +5627,12 @@
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
"dev": true
},
+ "ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "dev": true
+ },
"is-accessor-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
@@ -5659,9 +5710,9 @@
}
},
"is-core-module": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz",
- "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
+ "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==",
"dev": true,
"requires": {
"has": "^1.0.3"
@@ -6423,19 +6474,19 @@
"dev": true
},
"linkinator": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/linkinator/-/linkinator-2.2.2.tgz",
- "integrity": "sha512-mcMMbo8n8p6qDuCQ5zZaBbxKK9jq79oWsoduBIGc0rRzukDmfLr7t6Ok1jJA7aHHFX251NmtbX2LdQvD54UHow==",
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/linkinator/-/linkinator-2.4.0.tgz",
+ "integrity": "sha512-YSecbj3/LF2xAnC4jDHEunu5Xa88lWgMemcOX4VFjtnKmYyQqhFOP5rNzqVodFUBiEgDKfNWCB9AxqfL3qMbbQ==",
"dev": true,
"requires": {
"chalk": "^4.0.0",
"cheerio": "^1.0.0-rc.2",
- "finalhandler": "^1.1.2",
+ "express": "^4.17.1",
"gaxios": "^4.0.0",
"jsonexport": "^3.0.0",
+ "marked": "^1.2.5",
"meow": "^8.0.0",
"p-queue": "^6.2.1",
- "serve-static": "^1.14.1",
"server-destroy": "^1.0.1",
"update-notifier": "^5.0.0"
},
@@ -6803,6 +6854,12 @@
"object-visit": "^1.0.0"
}
},
+ "marked": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.5.tgz",
+ "integrity": "sha512-2AlqgYnVPOc9WDyWu7S5DJaEZsfk6dNh/neatQ3IHUW4QLutM/VPSH9lG7bif+XjFWc9K9XR3QvR+fXuECmfdA==",
+ "dev": true
+ },
"mathml-tag-names": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
@@ -6936,12 +6993,24 @@
}
}
},
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
+ "dev": true
+ },
"merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true
},
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+ "dev": true
+ },
"micromark": {
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-2.10.1.tgz",
@@ -7115,9 +7184,9 @@
"dev": true
},
"nanoid": {
- "version": "3.1.18",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.18.tgz",
- "integrity": "sha512-rndlDjbbHbcV3xi+R2fpJ+PbGMdfBxz5v1fATIQFq0DP64FsicQdwnKLy47K4kZHdRpmQXtz24eGsxQqamzYTA==",
+ "version": "3.1.19",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.19.tgz",
+ "integrity": "sha512-giCapaolEGFzITf00P2rSIjWoY3aWS3bb7AzjnfFJH4EOaAPLtyUrr3C5nQ//x4v1wTcU1JgtBpOKPOqqHrakg==",
"dev": true
},
"nanomatch": {
@@ -7563,9 +7632,9 @@
"dev": true
},
"object-inspect": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
- "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz",
+ "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==",
"dev": true
},
"object-keys": {
@@ -7607,14 +7676,14 @@
}
},
"object.values": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz",
- "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz",
+ "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==",
"dev": true,
"requires": {
+ "call-bind": "^1.0.0",
"define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1",
- "function-bind": "^1.1.1",
+ "es-abstract": "^1.18.0-next.1",
"has": "^1.0.3"
}
},
@@ -8026,6 +8095,12 @@
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"dev": true
},
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
+ "dev": true
+ },
"path-type": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
@@ -8525,9 +8600,9 @@
"dev": true
},
"postcss-reporter": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.1.tgz",
- "integrity": "sha512-R9AK80KIqqMb+lwGRBcRkXS7r96VCTxrZvvrfibyA/dWjqctwx7leHMCC05A9HbW8PnChwOWwrmISwp5HQu5wg==",
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.2.tgz",
+ "integrity": "sha512-JyQ96NTQQsso42y6L1H1RqHfWH1C3Jr0pt91mVv5IdYddZAE9DUZxuferNgk6q0o6vBVOrfVJb10X1FgDzjmDw==",
"dev": true,
"requires": {
"colorette": "^1.2.1",
@@ -8535,8 +8610,7 @@
"lodash.forown": "^4.4.0",
"lodash.get": "^4.4.2",
"lodash.groupby": "^4.6.0",
- "lodash.sortby": "^4.7.0",
- "log-symbols": "^4.0.0"
+ "lodash.sortby": "^4.7.0"
}
},
"postcss-resolve-nested-selector": {
@@ -8727,6 +8801,16 @@
"integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=",
"dev": true
},
+ "proxy-addr": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
+ "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
+ "dev": true,
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.9.1"
+ }
+ },
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@@ -9198,9 +9282,9 @@
}
},
"rollup": {
- "version": "2.33.3",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.33.3.tgz",
- "integrity": "sha512-RpayhPTe4Gu/uFGCmk7Gp5Z9Qic2VsqZ040G+KZZvsZYdcuWaJg678JeDJJvJeEQXminu24a2au+y92CUWVd+w==",
+ "version": "2.34.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.34.0.tgz",
+ "integrity": "sha512-dW5iLvttZzdVehjEuNJ1bWvuMEJjOWGmnuFS82WeKHTGXDkRHQeq/ExdifkSyJv9dLcR86ysKRmrIDyR6O0X8g==",
"dev": true,
"requires": {
"fsevents": "~2.1.2"
@@ -9957,9 +10041,9 @@
}
},
"spdx-license-ids": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz",
- "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==",
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz",
+ "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==",
"dev": true
},
"specificity": {
@@ -10090,28 +10174,6 @@
"call-bind": "^1.0.0",
"define-properties": "^1.1.3",
"es-abstract": "^1.18.0-next.1"
- },
- "dependencies": {
- "es-abstract": {
- "version": "1.18.0-next.1",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
- "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.2",
- "is-negative-zero": "^2.0.0",
- "is-regex": "^1.1.1",
- "object-inspect": "^1.8.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.1",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
- }
- }
}
},
"string.prototype.trimend": {
@@ -11123,9 +11185,9 @@
}
},
"unist-util-is": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.3.tgz",
- "integrity": "sha512-bTofCFVx0iQM8Jqb1TBDVRIQW03YkD3p66JOd/aCWuqzlLyUtx1ZAGw/u+Zw+SttKvSVcvTiKYbfrtLoLefykw==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.4.tgz",
+ "integrity": "sha512-3dF39j/u423v4BBQrk1AQ2Ve1FxY5W3JKwXxVFzBODQ6WEvccguhgp802qQLKSnxPODE6WuRZtV+ohlUg4meBA==",
"dev": true
},
"unist-util-stringify-position": {
@@ -11368,6 +11430,12 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+ "dev": true
+ },
"vfile": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.0.tgz",
@@ -11593,9 +11661,9 @@
"dev": true
},
"y18n": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
- "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
+ "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
"dev": true
},
"yallist": {
diff --git a/package.json b/package.json
index b4545406c..30b34ba6b 100644
--- a/package.json
+++ b/package.json
@@ -94,12 +94,12 @@
},
"devDependencies": {
"@babel/cli": "^7.12.8",
- "@babel/core": "^7.12.8",
+ "@babel/core": "^7.12.9",
"@babel/preset-env": "^7.12.7",
- "@rollup/plugin-babel": "^5.2.1",
- "@rollup/plugin-commonjs": "^16.0.0",
- "@rollup/plugin-node-resolve": "^10.0.0",
- "autoprefixer": "^10.0.2",
+ "@rollup/plugin-babel": "^5.2.2",
+ "@rollup/plugin-commonjs": "^17.0.0",
+ "@rollup/plugin-node-resolve": "^11.0.0",
+ "autoprefixer": "^10.0.4",
"bundlewatch": "^0.3.1",
"clean-css-cli": "^4.3.0",
"cross-env": "^7.0.2",
@@ -110,7 +110,7 @@
"find-unused-sass-variables": "^3.0.0",
"glob": "^7.1.6",
"hammer-simulator": "0.0.1",
- "hugo-bin": "^0.66.2",
+ "hugo-bin": "^0.67.0",
"ip": "^1.1.5",
"jquery": "^3.5.1",
"karma": "^5.2.3",
@@ -122,14 +122,14 @@
"karma-jasmine": "^4.0.1",
"karma-jasmine-html-reporter": "^1.5.4",
"karma-rollup-preprocessor": "^7.0.5",
- "linkinator": "^2.2.2",
+ "linkinator": "^2.4.0",
"lockfile-lint": "^4.3.7",
"nodemon": "^2.0.6",
"npm-run-all": "^4.1.5",
"popper.js": "^1.16.1",
"postcss": "^8.1.10",
"postcss-cli": "^8.3.0",
- "rollup": "^2.33.3",
+ "rollup": "^2.34.0",
"rollup-plugin-istanbul": "^2.0.1",
"sass": "^1.29.0",
"shelljs": "^0.8.4",
diff --git a/scss/_breadcrumb.scss b/scss/_breadcrumb.scss
index b30668b5d..f1ab3e8b9 100644
--- a/scss/_breadcrumb.scss
+++ b/scss/_breadcrumb.scss
@@ -18,7 +18,7 @@
float: left; // Suppress inline spacings and underlining of the separator
padding-right: $breadcrumb-item-padding-x;
color: $breadcrumb-divider-color;
- content: escape-svg($breadcrumb-divider);
+ content: var(--#{$variable-prefix}breadcrumb-divider, escape-svg($breadcrumb-divider));
}
}
diff --git a/scss/_button-group.scss b/scss/_button-group.scss
index 1571d1ea9..abb363a84 100644
--- a/scss/_button-group.scss
+++ b/scss/_button-group.scss
@@ -132,7 +132,7 @@
@include border-bottom-radius(0);
}
- > .btn:not(:first-child),
+ > .btn ~ .btn,
> .btn-group:not(:first-child) > .btn {
@include border-top-radius(0);
}
diff --git a/scss/_tables.scss b/scss/_tables.scss
index 1b2db3008..506c60be0 100644
--- a/scss/_tables.scss
+++ b/scss/_tables.scss
@@ -4,7 +4,6 @@
.table {
--#{$variable-prefix}table-bg: #{$table-bg};
- --#{$variable-prefix}table-accent-bg: transparent;
--#{$variable-prefix}table-striped-color: #{$table-striped-color};
--#{$variable-prefix}table-striped-bg: #{$table-striped-bg};
--#{$variable-prefix}table-active-color: #{$table-active-color};
diff --git a/scss/_variables.scss b/scss/_variables.scss
index 98ca77e41..777955175 100644
--- a/scss/_variables.scss
+++ b/scss/_variables.scss
@@ -1245,15 +1245,15 @@ $figure-caption-color: $gray-600 !default;
// Breadcrumbs
$breadcrumb-font-size: null !default;
-$breadcrumb-padding-y: $spacer / 2 !default;
-$breadcrumb-padding-x: $spacer !default;
+$breadcrumb-padding-y: 0 !default;
+$breadcrumb-padding-x: 0 !default;
$breadcrumb-item-padding-x: .5rem !default;
$breadcrumb-margin-bottom: 1rem !default;
-$breadcrumb-bg: $gray-200 !default;
+$breadcrumb-bg: null !default;
$breadcrumb-divider-color: $gray-600 !default;
$breadcrumb-active-color: $gray-600 !default;
$breadcrumb-divider: quote("/") !default;
-$breadcrumb-border-radius: $border-radius !default;
+$breadcrumb-border-radius: null !default;
// Carousel
diff --git a/site/content/docs/5.0/components/breadcrumb.md b/site/content/docs/5.0/components/breadcrumb.md
index a6e953bb5..893f1f009 100644
--- a/site/content/docs/5.0/components/breadcrumb.md
+++ b/site/content/docs/5.0/components/breadcrumb.md
@@ -3,10 +3,13 @@ layout: docs
title: Breadcrumb
description: Indicate the current page's location within a navigational hierarchy that automatically adds separators via CSS.
group: components
+toc: true
---
## Example
+Use an ordered or unordered list with linked list items to create a minimally styled breadcrumb. Use our utilities to add additional styles as desired.
+
{{< example >}}
@@ -30,21 +33,51 @@ group: components
{{< /example >}}
-## Changing the separator
+## Dividers
-Separators are automatically added in CSS through [`::before`](https://developer.mozilla.org/en-US/docs/Web/CSS/::before) and [`content`](https://developer.mozilla.org/en-US/docs/Web/CSS/content). They can be changed by changing `$breadcrumb-divider`. The [quote](https://sass-lang.com/documentation/modules/string#quote) function is needed to generate the quotes around a string, so if you want `>` as separator, you can use this:
+Dividers are automatically added in CSS through [`::before`](https://developer.mozilla.org/en-US/docs/Web/CSS/::before) and [`content`](https://developer.mozilla.org/en-US/docs/Web/CSS/content). They can be changed by modifying a local CSS custom property `--bs-breadcrumb-divider`, or through the `$breadcrumb-divider` Sass variable. We default to our Sass variable, which is set as a fallback to the custom property. This way, you get a global divider that you can override without recompiling CSS at any time.
+
+{{< example >}}
+
+
+ Home
+ Library
+
+
+{{< /example >}}
+
+When modifying via Sass, the [quote](https://sass-lang.com/documentation/modules/string#quote) function is required to generate the quotes around a string. For example, using `>` as the divider, you can use this:
```scss
$breadcrumb-divider: quote(">");
```
-It's also possible to use an **embedded SVG icon**:
+It's also possible to use an **embedded SVG icon**. Apply it via our CSS custom property, or use the Sass variable.
+
+{{< example >}}
+
+
+ Home
+ Library
+
+
+{{< /example >}}
```scss
$breadcrumb-divider: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='currentColor'/%3E%3C/svg%3E");
```
-The separator can be removed by setting `$breadcrumb-divider` to `none`:
+You can also remove the divider setting `--bs-breadcrumb-divider: '';` (empty strings in CSS custom properties counts as a value), or setting the Sass variable to `$breadcrumb-divider: none;`.
+
+{{< example >}}
+
+
+ Home
+ Library
+
+
+{{< /example >}}
+
```scss
$breadcrumb-divider: none;
diff --git a/site/content/docs/5.0/components/modal.md b/site/content/docs/5.0/components/modal.md
index 5bd116c8e..36dc3b548 100644
--- a/site/content/docs/5.0/components/modal.md
+++ b/site/content/docs/5.0/components/modal.md
@@ -877,12 +877,6 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
true
Puts the focus on the modal when initialized.
-
- show
- boolean
- true
- Shows the modal when initialized.
-
diff --git a/site/content/docs/5.0/content/typography.md b/site/content/docs/5.0/content/typography.md
index b8e4f558a..d93702eea 100644
--- a/site/content/docs/5.0/content/typography.md
+++ b/site/content/docs/5.0/content/typography.md
@@ -13,7 +13,7 @@ Bootstrap sets basic global display, typography, and link styles. When more cont
- Use a [native font stack]({{< docsref "/content/reboot#native-font-stack" >}}) that selects the best `font-family` for each OS and device.
- For a more inclusive and accessible type scale, we use the browser's default root `font-size` (typically 16px) so visitors can customize their browser defaults as needed.
- Use the `$font-family-base`, `$font-size-base`, and `$line-height-base` attributes as our typographic base applied to the ``.
-- Set the global link color via `$link-color` and apply link underlines only on `:hover`.
+- Set the global link color via `$link-color`.
- Use `$body-bg` to set a `background-color` on the `` (`#fff` by default).
These styles can be found within `_reboot.scss`, and the global variables are defined in `_variables.scss`. Make sure to set `$font-size-base` in `rem`.
diff --git a/site/content/docs/5.0/migration.md b/site/content/docs/5.0/migration.md
index dab1bd7df..7691d20c1 100644
--- a/site/content/docs/5.0/migration.md
+++ b/site/content/docs/5.0/migration.md
@@ -17,6 +17,13 @@ toc: true
- Renamed `scale-color()` function to `shift-color()` to avoid collision with Sass's own color scaling function.
+### Components
+
+#### Breadcrumbs
+
+- Simplified the default appearance of breadcrumbs by removing `padding`, `background-color`, and `border-radius`.
+- Added new CSS custom property `--bs-breadcrumb-divider` for easy customization without needing to recompile CSS.
+
## v5.0.0-alpha3
### Browser support
@@ -267,6 +274,7 @@ Changes to Reboot, typography, tables, and more.
- Removed individual `$display-*-weight` variables for a single `$display-font-weight`.
- Added two new `.display-*` heading styles, `.display-5` and `.display-6`.
- Resized existing display headings for a slightly more consistent set of `font-size`s.
+- Links are underlined by default (not just on hover), unless they're part of specific components.
### Forms