aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Chernenko <kb.chernenko@gmail.com>2023-09-05 12:33:26 +0200
committerGitHub <noreply@github.com>2023-09-05 12:33:26 +0200
commitb26c79cf8722cfd758b49e0740de20573fadf374 (patch)
treec246553c104e9d740fc0cf91c79ad42684da6bfd
parente9e8fbf59efc5eefdaef2a432dbdef299a89fde1 (diff)
downloaddokka-b26c79cf8722cfd758b49e0740de20573fadf374.tar.gz
dokka-b26c79cf8722cfd758b49e0740de20573fadf374.tar.bz2
dokka-b26c79cf8722cfd758b49e0740de20573fadf374.zip
fix(KTL-1177): Resize Observer has indefinite loop (#3116)
* fix(KTL-1177): Resize Observer has indefinite loop
-rw-r--r--plugins/base/src/main/resources/dokka/scripts/symbol-parameters-wrapper_deferred.js115
1 files changed, 46 insertions, 69 deletions
diff --git a/plugins/base/src/main/resources/dokka/scripts/symbol-parameters-wrapper_deferred.js b/plugins/base/src/main/resources/dokka/scripts/symbol-parameters-wrapper_deferred.js
index d363488d..7ecae7a6 100644
--- a/plugins/base/src/main/resources/dokka/scripts/symbol-parameters-wrapper_deferred.js
+++ b/plugins/base/src/main/resources/dokka/scripts/symbol-parameters-wrapper_deferred.js
@@ -4,84 +4,61 @@
// helps with some corner cases where <wbr> starts working already,
// but the signature is not yet long enough to be wrapped
-const leftPaddingPx = 60
+(function() {
+ const leftPaddingPx = 60;
-const symbolResizeObserver = new ResizeObserver(entries => {
- entries.forEach(entry => {
- const symbolElement = entry.target
- symbolResizeObserver.unobserve(symbolElement) // only need it once, otherwise will be executed multiple times
- wrapSymbolParameters(symbolElement);
- })
-});
-
-const wrapAllSymbolParameters = () => {
- document.querySelectorAll("div.symbol").forEach(symbol => wrapSymbolParameters(symbol))
-}
-
-const wrapSymbolParameters = (symbol) => {
- let parametersBlock = symbol.querySelector("span.parameters")
- if (parametersBlock == null) {
- return // nothing to wrap
+ function createNbspIndent() {
+ let indent = document.createElement("span");
+ indent.append(document.createTextNode("\u00A0\u00A0\u00A0\u00A0"));
+ indent.classList.add("nbsp-indent");
+ return indent;
}
- let symbolBlockWidth = symbol.clientWidth
+ function wrapSymbolParameters(entry) {
+ const symbol = entry.target;
+ const symbolBlockWidth = entry.borderBoxSize && entry.borderBoxSize[0] && entry.borderBoxSize[0].inlineSize;
- // Even though the script is marked as `defer` and we wait for `DOMContentLoaded` event,
- // it can happen that `symbolBlockWidth` is 0, indicating that something hasn't been loaded.
- // In this case, just retry once all styles have been applied and it has been resized correctly.
- if (symbolBlockWidth === 0) {
- symbolResizeObserver.observe(symbol)
- return
- }
+ // Even though the script is marked as `defer` and we wait for `DOMContentLoaded` event,
+ // or if this block is a part of hidden tab, it can happen that `symbolBlockWidth` is 0,
+ // indicating that something hasn't been loaded.
+ // In this case, observer will be triggered onсe again when it will be ready.
+ if (symbolBlockWidth > 0) {
+ const node = symbol.querySelector(".parameters");
- let innerTextWidth = Array.from(symbol.children)
- .filter(it => !it.classList.contains("block")) // blocks are usually on their own (like annotations), so ignore it
- .map(it => it.getBoundingClientRect().width).reduce((a, b) => a + b, 0)
+ if (node) {
+ // if window resize happened and observer was triggered, reset previously wrapped
+ // parameters as they might not need wrapping anymore, and check again
+ node.classList.remove("wrapped");
+ node.querySelectorAll(".parameter .nbsp-indent")
+ .forEach(indent => indent.remove());
- // if signature text takes up more than a single line, wrap params for readability
- let shouldWrapParams = innerTextWidth > (symbolBlockWidth - leftPaddingPx)
- if (shouldWrapParams) {
- parametersBlock.classList.add("wrapped")
- parametersBlock.querySelectorAll("span.parameter").forEach(param => {
- // has to be a physical indent so that it can be copied. styles like
- // paddings and `::before { content: " " }` do not work for that
- param.prepend(createNbspIndent())
- })
- }
-}
+ const innerTextWidth = Array.from(symbol.children)
+ .filter(it => !it.classList.contains("block")) // blocks are usually on their own (like annotations), so ignore it
+ .map(it => it.getBoundingClientRect().width)
+ .reduce((a, b) => a + b, 0);
-const createNbspIndent = () => {
- let indent = document.createElement("span")
- indent.append(document.createTextNode("\u00A0\u00A0\u00A0\u00A0"))
- indent.classList.add("nbsp-indent")
- return indent
-}
+ // if signature text takes up more than a single line, wrap params for readability
+ if (innerTextWidth > (symbolBlockWidth - leftPaddingPx)) {
+ node.classList.add("wrapped");
+ node.querySelectorAll(".parameter").forEach(param => {
+ // has to be a physical indent so that it can be copied. styles like
+ // paddings and `::before { content: " " }` do not work for that
+ param.prepend(createNbspIndent());
+ });
+ }
+ }
+ }
+ }
-const resetAllSymbolParametersWrapping = () => {
- document.querySelectorAll("div.symbol").forEach(symbol => resetSymbolParametersWrapping(symbol))
-}
+ const symbolsObserver = new ResizeObserver(entries => entries.forEach(wrapSymbolParameters));
-const resetSymbolParametersWrapping = (symbol) => {
- let parameters = symbol.querySelector("span.parameters")
- if (parameters != null) {
- parameters.classList.remove("wrapped")
- parameters.querySelectorAll("span.parameter").forEach(param => {
- let indent = param.querySelector("span.nbsp-indent")
- if (indent != null) indent.remove()
- })
+ function initHandlers() {
+ document.querySelectorAll("div.symbol").forEach(symbol => symbolsObserver.observe(symbol));
}
-}
-if (document.readyState === 'loading') {
- window.addEventListener('DOMContentLoaded', () => {
- wrapAllSymbolParameters()
- })
-} else {
- wrapAllSymbolParameters()
-}
+ if (document.readyState === 'loading') window.addEventListener('DOMContentLoaded', initHandlers);
+ else initHandlers();
-window.onresize = event => {
- // need to re-calculate if params need to be wrapped after resize
- resetAllSymbolParametersWrapping()
- wrapAllSymbolParameters()
-}
+ // ToDo: Add `unobserve` if dokka will be SPA-like:
+ // https://github.com/w3c/csswg-drafts/issues/5155
+})();