Deploy to GitHub pages

This commit is contained in:
github-actions[bot]
2025-08-02 18:18:10 +00:00
committed by GitHub
commit 29b7fb4ab9
569 changed files with 53028 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
window.addEventListener('load', () => {
document.querySelectorAll('span.copy-icon').forEach(element => {
element.addEventListener('click', (el) => copyElementsContentToClipboard(element));
})
document.querySelectorAll('span.anchor-icon').forEach(element => {
element.addEventListener('click', (el) => {
if(element.hasAttribute('pointing-to')){
const location = hrefWithoutCurrentlyUsedAnchor() + '#' + element.getAttribute('pointing-to')
copyTextToClipboard(element, location)
}
});
})
})
const copyElementsContentToClipboard = (element) => {
const selection = window.getSelection();
const range = document.createRange();
range.selectNodeContents(element.parentNode.parentNode);
selection.removeAllRanges();
selection.addRange(range);
copyAndShowPopup(element, () => selection.removeAllRanges())
}
const copyTextToClipboard = (element, text) => {
var textarea = document.createElement("textarea");
textarea.textContent = text;
textarea.style.position = "fixed";
document.body.appendChild(textarea);
textarea.select();
copyAndShowPopup(element, () => document.body.removeChild(textarea))
}
const copyAndShowPopup = (element, after) => {
try {
document.execCommand('copy');
element.nextElementSibling.classList.add('active-popup');
setTimeout(() => {
element.nextElementSibling.classList.remove('active-popup');
}, 1200);
} catch (e) {
console.error('Failed to write to clipboard:', e)
}
finally {
if(after) after()
}
}
const hrefWithoutCurrentlyUsedAnchor = () => window.location.href.split('#')[0]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
navigationPageText = fetch(pathToRoot + "navigation.html").then(response => response.text())
displayNavigationFromPage = () => {
navigationPageText.then(data => {
document.getElementById("sideMenu").innerHTML = data;
}).then(() => {
document.querySelectorAll(".overview > a").forEach(link => {
link.setAttribute("href", pathToRoot + link.getAttribute("href"));
})
}).then(() => {
document.querySelectorAll(".sideMenuPart").forEach(nav => {
if (!nav.classList.contains("hidden"))
nav.classList.add("hidden")
})
}).then(() => {
revealNavigationForCurrentPage()
}).then(() => {
scrollNavigationToSelectedElement()
})
document.querySelectorAll('.footer a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth'
});
});
});
}
revealNavigationForCurrentPage = () => {
let pageId = document.getElementById("content").attributes["pageIds"].value.toString();
let parts = document.querySelectorAll(".sideMenuPart");
let found = 0;
do {
parts.forEach(part => {
if (part.attributes['pageId'].value.indexOf(pageId) !== -1 && found === 0) {
found = 1;
if (part.classList.contains("hidden")) {
part.classList.remove("hidden");
part.setAttribute('data-active', "");
}
revealParents(part)
}
});
pageId = pageId.substring(0, pageId.lastIndexOf("/"))
} while (pageId.indexOf("/") !== -1 && found === 0)
};
revealParents = (part) => {
if (part.classList.contains("sideMenuPart")) {
if (part.classList.contains("hidden"))
part.classList.remove("hidden");
revealParents(part.parentNode)
}
};
scrollNavigationToSelectedElement = () => {
let selectedElement = document.querySelector('div.sideMenuPart[data-active]')
if (selectedElement == null) { // nothing selected, probably just the main page opened
return
}
let hasIcon = selectedElement.querySelectorAll(":scope > div.overview span.nav-icon").length > 0
// for instance enums also have children and are expandable, but are not package/module elements
let isPackageElement = selectedElement.children.length > 1 && !hasIcon
if (isPackageElement) {
// if package is selected or linked, it makes sense to align it to top
// so that you can see all the members it contains
selectedElement.scrollIntoView(true)
} else {
// if a member within a package is linked, it makes sense to center it since it,
// this should make it easier to look at surrounding members
selectedElement.scrollIntoView({
behavior: 'auto',
block: 'center',
inline: 'center'
})
}
}
/*
This is a work-around for safari being IE of our times.
It doesn't fire a DOMContentLoaded, presumabely because eventListener is added after it wants to do it
*/
if (document.readyState == 'loading') {
window.addEventListener('DOMContentLoaded', () => {
displayNavigationFromPage()
})
} else {
displayNavigationFromPage()
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,400 @@
/*
* Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
filteringContext = {
dependencies: {},
restrictedDependencies: [],
activeFilters: []
}
let highlightedAnchor;
let topNavbarOffset;
let instances = [];
let sourcesetNotification;
const samplesDarkThemeName = 'darcula'
const samplesLightThemeName = 'idea'
window.addEventListener('load', () => {
document.querySelectorAll("div[data-platform-hinted]")
.forEach(elem => elem.addEventListener('click', (event) => togglePlatformDependent(event, elem)))
const filterSection = document.getElementById('filter-section')
if (filterSection) {
filterSection.addEventListener('click', (event) => filterButtonHandler(event))
initializeFiltering()
}
initTabs()
handleAnchor()
initHidingLeftNavigation()
topNavbarOffset = document.getElementById('navigation-wrapper')
darkModeSwitch()
})
const darkModeSwitch = () => {
const localStorageKey = "dokka-dark-mode"
const storage = localStorage.getItem(localStorageKey)
const osDarkSchemePreferred = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
const darkModeEnabled = storage ? JSON.parse(storage) : osDarkSchemePreferred
const element = document.getElementById("theme-toggle-button")
initPlayground(darkModeEnabled ? samplesDarkThemeName : samplesLightThemeName)
element.addEventListener('click', () => {
const enabledClasses = document.getElementsByTagName("html")[0].classList
enabledClasses.toggle("theme-dark")
//if previously we had saved dark theme then we set it to light as this is what we save in local storage
const darkModeEnabled = enabledClasses.contains("theme-dark")
if (darkModeEnabled) {
initPlayground(samplesDarkThemeName)
} else {
initPlayground(samplesLightThemeName)
}
localStorage.setItem(localStorageKey, JSON.stringify(darkModeEnabled))
})
}
const initPlayground = (theme) => {
if (!samplesAreEnabled()) return
instances.forEach(instance => instance.destroy())
instances = []
// Manually tag code fragments as not processed by playground since we also manually destroy all of its instances
document.querySelectorAll('code.runnablesample').forEach(node => {
node.removeAttribute("data-kotlin-playground-initialized");
})
KotlinPlayground('code.runnablesample', {
getInstance: playgroundInstance => {
instances.push(playgroundInstance)
},
theme: theme
});
}
// We check if type is accessible from the current scope to determine if samples script is present
// As an alternative we could extract this samples-specific script to new js file but then we would handle dark mode in 2 separate files which is not ideal
const samplesAreEnabled = () => {
try {
KotlinPlayground
return true
} catch (e) {
return false
}
}
const initHidingLeftNavigation = () => {
document.getElementById("menu-toggle").onclick = function (event) {
//Events need to be prevented from bubbling since they will trigger next handler
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
document.getElementById("leftColumn").classList.toggle("open");
}
document.getElementById("main").onclick = () => {
document.getElementById("leftColumn").classList.remove("open");
}
}
// Hash change is needed in order to allow for linking inside the same page with anchors
// If this is not present user is forced to refresh the site in order to use an anchor
window.onhashchange = handleAnchor
function scrollToElementInContent(element) {
const scrollToElement = () => document.getElementById('main').scrollTo({
top: element.offsetTop - topNavbarOffset.offsetHeight,
behavior: "smooth"
})
const waitAndScroll = () => {
setTimeout(() => {
if (topNavbarOffset) {
scrollToElement()
} else {
waitForScroll()
}
}, 50)
}
if (topNavbarOffset) {
scrollToElement()
} else {
waitAndScroll()
}
}
function handleAnchor() {
if (highlightedAnchor) {
highlightedAnchor.classList.remove('anchor-highlight')
highlightedAnchor = null;
}
let searchForContentTarget = function (element) {
if (element && element.hasAttribute) {
if (element.hasAttribute("data-togglable")) return element.getAttribute("data-togglable");
else return searchForContentTarget(element.parentNode)
} else return null
}
let findAnyTab = function (target) {
let result = null
document.querySelectorAll('div[tabs-section] > button[data-togglable]')
.forEach(node => {
if(node.getAttribute("data-togglable").split(",").includes(target)) {
result = node
}
})
return result
}
let anchor = window.location.hash
if (anchor != "") {
anchor = anchor.substring(1)
let element = document.querySelector('a[data-name="' + anchor + '"]')
if (element) {
const content = element.nextElementSibling
const contentStyle = window.getComputedStyle(content)
if(contentStyle.display == 'none') {
let tab = findAnyTab(searchForContentTarget(content))
if (tab) {
toggleSections(tab)
}
}
if (content) {
content.classList.add('anchor-highlight')
highlightedAnchor = content
}
scrollToElementInContent(element)
}
}
}
function initTabs() {
// we could have only a single type of data - classlike or package
const mainContent = document.querySelector('.main-content');
const type = mainContent ? mainContent.getAttribute("data-page-type") : null;
const localStorageKey = "active-tab-" + type;
document.querySelectorAll('div[tabs-section]').forEach(element => {
showCorrespondingTabBody(element);
element.addEventListener('click', ({target}) => {
const togglable = target ? target.getAttribute("data-togglable") : null;
if (!togglable) return;
localStorage.setItem(localStorageKey, JSON.stringify(togglable));
toggleSections(target);
});
});
const cached = localStorage.getItem(localStorageKey);
if (!cached) return;
const tab = document.querySelector(
'div[tabs-section] > button[data-togglable="' + JSON.parse(cached) + '"]'
);
if (!tab) return;
toggleSections(tab);
}
function showCorrespondingTabBody(element) {
const buttonWithKey = element.querySelector("button[data-active]")
if (buttonWithKey) {
toggleSections(buttonWithKey)
}
}
function filterButtonHandler(event) {
if (event.target.tagName == "BUTTON" && event.target.hasAttribute("data-filter")) {
let sourceset = event.target.getAttribute("data-filter")
if (filteringContext.activeFilters.indexOf(sourceset) != -1) {
filterSourceset(sourceset)
} else {
unfilterSourceset(sourceset)
}
}
}
function initializeFiltering() {
filteringContext.dependencies = JSON.parse(sourceset_dependencies)
document.querySelectorAll("#filter-section > button")
.forEach(p => filteringContext.restrictedDependencies.push(p.getAttribute("data-filter")))
Object.keys(filteringContext.dependencies).forEach(p => {
filteringContext.dependencies[p] = filteringContext.dependencies[p]
.filter(q => -1 !== filteringContext.restrictedDependencies.indexOf(q))
})
let cached = window.localStorage.getItem('inactive-filters')
if (cached) {
let parsed = JSON.parse(cached)
filteringContext.activeFilters = filteringContext.restrictedDependencies
.filter(q => parsed.indexOf(q) == -1)
} else {
filteringContext.activeFilters = filteringContext.restrictedDependencies
}
refreshFiltering()
}
function filterSourceset(sourceset) {
filteringContext.activeFilters = filteringContext.activeFilters.filter(p => p != sourceset)
refreshFiltering()
addSourcesetFilterToCache(sourceset)
}
function unfilterSourceset(sourceset) {
if (filteringContext.activeFilters.length == 0) {
filteringContext.activeFilters = filteringContext.dependencies[sourceset].concat([sourceset])
refreshFiltering()
filteringContext.dependencies[sourceset].concat([sourceset]).forEach(p => removeSourcesetFilterFromCache(p))
} else {
filteringContext.activeFilters.push(sourceset)
refreshFiltering()
removeSourcesetFilterFromCache(sourceset)
}
}
function addSourcesetFilterToCache(sourceset) {
let cached = localStorage.getItem('inactive-filters')
if (cached) {
let parsed = JSON.parse(cached)
localStorage.setItem('inactive-filters', JSON.stringify(parsed.concat([sourceset])))
} else {
localStorage.setItem('inactive-filters', JSON.stringify([sourceset]))
}
}
function removeSourcesetFilterFromCache(sourceset) {
let cached = localStorage.getItem('inactive-filters')
if (cached) {
let parsed = JSON.parse(cached)
localStorage.setItem('inactive-filters', JSON.stringify(parsed.filter(p => p != sourceset)))
}
}
function toggleSections(target) {
const activateTabs = (containerClass) => {
for (const element of document.getElementsByClassName(containerClass)) {
for (const child of element.children) {
if (child.getAttribute("data-togglable") === target.getAttribute("data-togglable")) {
child.setAttribute("data-active", "")
} else {
child.removeAttribute("data-active")
}
}
}
}
const toggleTargets = target.getAttribute("data-togglable").split(",")
const activateTabsBody = (containerClass) => {
document.querySelectorAll("." + containerClass + " *[data-togglable]")
.forEach(child => {
if (toggleTargets.includes(child.getAttribute("data-togglable"))) {
child.setAttribute("data-active", "")
} else if(!child.classList.contains("sourceset-dependent-content")) { // data-togglable is used to switch source set as well, ignore it
child.removeAttribute("data-active")
}
})
}
activateTabs("tabs-section")
activateTabsBody("tabs-section-body")
}
function togglePlatformDependent(e, container) {
let target = e.target
if (target.tagName != 'BUTTON') return;
let index = target.getAttribute('data-toggle')
for (let child of container.children) {
if (child.hasAttribute('data-toggle-list')) {
for (let bm of child.children) {
if (bm == target) {
bm.setAttribute('data-active', "")
} else if (bm != target) {
bm.removeAttribute('data-active')
}
}
} else if (child.getAttribute('data-togglable') == index) {
child.setAttribute('data-active', "")
} else {
child.removeAttribute('data-active')
}
}
}
function refreshFiltering() {
let sourcesetList = filteringContext.activeFilters
document.querySelectorAll("[data-filterable-set]")
.forEach(
elem => {
let platformList = elem.getAttribute("data-filterable-set").split(',').filter(v => -1 !== sourcesetList.indexOf(v))
elem.setAttribute("data-filterable-current", platformList.join(','))
}
)
refreshFilterButtons()
refreshPlatformTabs()
refreshNoContentNotification()
refreshPlaygroundSamples()
}
function refreshPlaygroundSamples() {
document.querySelectorAll('code.runnablesample').forEach(node => {
const playground = node.KotlinPlayground;
/* Some samples may be hidden by filter, they have 0px height for visible code area
* after rendering. Call this method for re-calculate code area height */
playground && playground.view.codemirror.refresh();
});
}
function refreshNoContentNotification() {
const element = document.getElementsByClassName("main-content")[0]
if(filteringContext.activeFilters.length === 0){
element.style.display = "none";
const appended = document.createElement("div")
appended.className = "filtered-message"
appended.innerText = "All documentation is filtered, please adjust your source set filters in top-right corner of the screen"
sourcesetNotification = appended
element.parentNode.prepend(appended)
} else {
if(sourcesetNotification) sourcesetNotification.remove()
element.style.display = "block"
}
}
function refreshPlatformTabs() {
document.querySelectorAll(".platform-hinted > .platform-bookmarks-row").forEach(
p => {
let active = false;
let firstAvailable = null
p.childNodes.forEach(
element => {
if (element.getAttribute("data-filterable-current") != '') {
if (firstAvailable == null) {
firstAvailable = element
}
if (element.hasAttribute("data-active")) {
active = true;
}
}
}
)
if (active == false && firstAvailable) {
firstAvailable.click()
}
}
)
}
function refreshFilterButtons() {
document.querySelectorAll("#filter-section > button")
.forEach(f => {
if (filteringContext.activeFilters.indexOf(f.getAttribute("data-filter")) != -1) {
f.setAttribute("data-active", "")
} else {
f.removeAttribute("data-active")
}
})
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
sourceset_dependencies='{":kavaref-core:dokkaHtml/main":[]}'

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
// helps with some corner cases where <wbr> starts working already,
// but the signature is not yet long enough to be wrapped
(function() {
const leftPaddingPx = 60;
function createNbspIndent() {
let indent = document.createElement("span");
indent.append(document.createTextNode("\u00A0\u00A0\u00A0\u00A0"));
indent.classList.add("nbsp-indent");
return indent;
}
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,
// 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");
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());
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);
// 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 symbolsObserver = new ResizeObserver(entries => entries.forEach(wrapSymbolParameters));
function initHandlers() {
document.querySelectorAll("div.symbol").forEach(symbol => symbolsObserver.observe(symbol));
}
if (document.readyState === 'loading') window.addEventListener('DOMContentLoaded', initHandlers);
else initHandlers();
// ToDo: Add `unobserve` if dokka will be SPA-like:
// https://github.com/w3c/csswg-drafts/issues/5155
})();