mirror of
https://github.com/orbbec/OrbbecSDK_ROS2.git
synced 2026-10-09 06:17:46 +08:00
deploy: 8888695c4c
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#22863a" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M5 12l5 5l10 -10" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 313 B |
Vendored
+7
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-copy" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<rect x="8" y="8" width="12" height="12" rx="2" />
|
||||
<path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 411 B |
@@ -0,0 +1,94 @@
|
||||
/* Copy buttons */
|
||||
button.copybtn {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
top: .3em;
|
||||
right: .3em;
|
||||
width: 1.7em;
|
||||
height: 1.7em;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s, border .3s, background-color .3s;
|
||||
user-select: none;
|
||||
padding: 0;
|
||||
border: none;
|
||||
outline: none;
|
||||
border-radius: 0.4em;
|
||||
/* The colors that GitHub uses */
|
||||
border: #1b1f2426 1px solid;
|
||||
background-color: #f6f8fa;
|
||||
color: #57606a;
|
||||
}
|
||||
|
||||
button.copybtn.success {
|
||||
border-color: #22863a;
|
||||
color: #22863a;
|
||||
}
|
||||
|
||||
button.copybtn svg {
|
||||
stroke: currentColor;
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
padding: 0.1em;
|
||||
}
|
||||
|
||||
div.highlight {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Show the copybutton */
|
||||
.highlight:hover button.copybtn, button.copybtn.success {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.highlight button.copybtn:hover {
|
||||
background-color: rgb(235, 235, 235);
|
||||
}
|
||||
|
||||
.highlight button.copybtn:active {
|
||||
background-color: rgb(187, 187, 187);
|
||||
}
|
||||
|
||||
/**
|
||||
* A minimal CSS-only tooltip copied from:
|
||||
* https://codepen.io/mildrenben/pen/rVBrpK
|
||||
*
|
||||
* To use, write HTML like the following:
|
||||
*
|
||||
* <p class="o-tooltip--left" data-tooltip="Hey">Short</p>
|
||||
*/
|
||||
.o-tooltip--left {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.o-tooltip--left:after {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
content: attr(data-tooltip);
|
||||
padding: .2em;
|
||||
font-size: .8em;
|
||||
left: -.2em;
|
||||
background: grey;
|
||||
color: white;
|
||||
white-space: nowrap;
|
||||
z-index: 2;
|
||||
border-radius: 2px;
|
||||
transform: translateX(-102%) translateY(0);
|
||||
transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1);
|
||||
}
|
||||
|
||||
.o-tooltip--left:hover:after {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateX(-100%) translateY(0);
|
||||
transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1);
|
||||
transition-delay: .5s;
|
||||
}
|
||||
|
||||
/* By default the copy button shouldn't show up when printing a page */
|
||||
@media print {
|
||||
button.copybtn {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
// Localization support
|
||||
const messages = {
|
||||
'en': {
|
||||
'copy': 'Copy',
|
||||
'copy_to_clipboard': 'Copy to clipboard',
|
||||
'copy_success': 'Copied!',
|
||||
'copy_failure': 'Failed to copy',
|
||||
},
|
||||
'es' : {
|
||||
'copy': 'Copiar',
|
||||
'copy_to_clipboard': 'Copiar al portapapeles',
|
||||
'copy_success': '¡Copiado!',
|
||||
'copy_failure': 'Error al copiar',
|
||||
},
|
||||
'de' : {
|
||||
'copy': 'Kopieren',
|
||||
'copy_to_clipboard': 'In die Zwischenablage kopieren',
|
||||
'copy_success': 'Kopiert!',
|
||||
'copy_failure': 'Fehler beim Kopieren',
|
||||
},
|
||||
'fr' : {
|
||||
'copy': 'Copier',
|
||||
'copy_to_clipboard': 'Copier dans le presse-papier',
|
||||
'copy_success': 'Copié !',
|
||||
'copy_failure': 'Échec de la copie',
|
||||
},
|
||||
'ru': {
|
||||
'copy': 'Скопировать',
|
||||
'copy_to_clipboard': 'Скопировать в буфер',
|
||||
'copy_success': 'Скопировано!',
|
||||
'copy_failure': 'Не удалось скопировать',
|
||||
},
|
||||
'zh-CN': {
|
||||
'copy': '复制',
|
||||
'copy_to_clipboard': '复制到剪贴板',
|
||||
'copy_success': '复制成功!',
|
||||
'copy_failure': '复制失败',
|
||||
},
|
||||
'it' : {
|
||||
'copy': 'Copiare',
|
||||
'copy_to_clipboard': 'Copiato negli appunti',
|
||||
'copy_success': 'Copiato!',
|
||||
'copy_failure': 'Errore durante la copia',
|
||||
}
|
||||
}
|
||||
|
||||
let locale = 'en'
|
||||
if( document.documentElement.lang !== undefined
|
||||
&& messages[document.documentElement.lang] !== undefined ) {
|
||||
locale = document.documentElement.lang
|
||||
}
|
||||
|
||||
let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT;
|
||||
if (doc_url_root == '#') {
|
||||
doc_url_root = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* SVG files for our copy buttons
|
||||
*/
|
||||
let iconCheck = `<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#22863a" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<title>${messages[locale]['copy_success']}</title>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M5 12l5 5l10 -10" />
|
||||
</svg>`
|
||||
|
||||
// If the user specified their own SVG use that, otherwise use the default
|
||||
let iconCopy = ``;
|
||||
if (!iconCopy) {
|
||||
iconCopy = `<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-copy" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<title>${messages[locale]['copy_to_clipboard']}</title>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<rect x="8" y="8" width="12" height="12" rx="2" />
|
||||
<path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2" />
|
||||
</svg>`
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up copy/paste for code blocks
|
||||
*/
|
||||
|
||||
const runWhenDOMLoaded = cb => {
|
||||
if (document.readyState != 'loading') {
|
||||
cb()
|
||||
} else if (document.addEventListener) {
|
||||
document.addEventListener('DOMContentLoaded', cb)
|
||||
} else {
|
||||
document.attachEvent('onreadystatechange', function() {
|
||||
if (document.readyState == 'complete') cb()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const codeCellId = index => `codecell${index}`
|
||||
|
||||
// Clears selected text since ClipboardJS will select the text when copying
|
||||
const clearSelection = () => {
|
||||
if (window.getSelection) {
|
||||
window.getSelection().removeAllRanges()
|
||||
} else if (document.selection) {
|
||||
document.selection.empty()
|
||||
}
|
||||
}
|
||||
|
||||
// Changes tooltip text for a moment, then changes it back
|
||||
// We want the timeout of our `success` class to be a bit shorter than the
|
||||
// tooltip and icon change, so that we can hide the icon before changing back.
|
||||
var timeoutIcon = 2000;
|
||||
var timeoutSuccessClass = 1500;
|
||||
|
||||
const temporarilyChangeTooltip = (el, oldText, newText) => {
|
||||
el.setAttribute('data-tooltip', newText)
|
||||
el.classList.add('success')
|
||||
// Remove success a little bit sooner than we change the tooltip
|
||||
// So that we can use CSS to hide the copybutton first
|
||||
setTimeout(() => el.classList.remove('success'), timeoutSuccessClass)
|
||||
setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon)
|
||||
}
|
||||
|
||||
// Changes the copy button icon for two seconds, then changes it back
|
||||
const temporarilyChangeIcon = (el) => {
|
||||
el.innerHTML = iconCheck;
|
||||
setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon)
|
||||
}
|
||||
|
||||
const addCopyButtonToCodeCells = () => {
|
||||
// If ClipboardJS hasn't loaded, wait a bit and try again. This
|
||||
// happens because we load ClipboardJS asynchronously.
|
||||
if (window.ClipboardJS === undefined) {
|
||||
setTimeout(addCopyButtonToCodeCells, 250)
|
||||
return
|
||||
}
|
||||
|
||||
// Add copybuttons to all of our code cells
|
||||
const COPYBUTTON_SELECTOR = 'div.highlight pre';
|
||||
const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR)
|
||||
codeCells.forEach((codeCell, index) => {
|
||||
const id = codeCellId(index)
|
||||
codeCell.setAttribute('id', id)
|
||||
|
||||
const clipboardButton = id =>
|
||||
`<button class="copybtn o-tooltip--left" data-tooltip="${messages[locale]['copy']}" data-clipboard-target="#${id}">
|
||||
${iconCopy}
|
||||
</button>`
|
||||
codeCell.insertAdjacentHTML('afterend', clipboardButton(id))
|
||||
})
|
||||
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes excluded text from a Node.
|
||||
*
|
||||
* @param {Node} target Node to filter.
|
||||
* @param {string} exclude CSS selector of nodes to exclude.
|
||||
* @returns {DOMString} Text from `target` with text removed.
|
||||
*/
|
||||
function filterText(target, exclude) {
|
||||
const clone = target.cloneNode(true); // clone as to not modify the live DOM
|
||||
if (exclude) {
|
||||
// remove excluded nodes
|
||||
clone.querySelectorAll(exclude).forEach(node => node.remove());
|
||||
}
|
||||
return clone.innerText;
|
||||
}
|
||||
|
||||
// Callback when a copy button is clicked. Will be passed the node that was clicked
|
||||
// should then grab the text and replace pieces of text that shouldn't be used in output
|
||||
function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") {
|
||||
var regexp;
|
||||
var match;
|
||||
|
||||
// Do we check for line continuation characters and "HERE-documents"?
|
||||
var useLineCont = !!lineContinuationChar
|
||||
var useHereDoc = !!hereDocDelim
|
||||
|
||||
// create regexp to capture prompt and remaining line
|
||||
if (isRegexp) {
|
||||
regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)')
|
||||
} else {
|
||||
regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)')
|
||||
}
|
||||
|
||||
const outputLines = [];
|
||||
var promptFound = false;
|
||||
var gotLineCont = false;
|
||||
var gotHereDoc = false;
|
||||
const lineGotPrompt = [];
|
||||
for (const line of textContent.split('\n')) {
|
||||
match = line.match(regexp)
|
||||
if (match || gotLineCont || gotHereDoc) {
|
||||
promptFound = regexp.test(line)
|
||||
lineGotPrompt.push(promptFound)
|
||||
if (removePrompts && promptFound) {
|
||||
outputLines.push(match[2])
|
||||
} else {
|
||||
outputLines.push(line)
|
||||
}
|
||||
gotLineCont = line.endsWith(lineContinuationChar) & useLineCont
|
||||
if (line.includes(hereDocDelim) & useHereDoc)
|
||||
gotHereDoc = !gotHereDoc
|
||||
} else if (!onlyCopyPromptLines) {
|
||||
outputLines.push(line)
|
||||
} else if (copyEmptyLines && line.trim() === '') {
|
||||
outputLines.push(line)
|
||||
}
|
||||
}
|
||||
|
||||
// If no lines with the prompt were found then just use original lines
|
||||
if (lineGotPrompt.some(v => v === true)) {
|
||||
textContent = outputLines.join('\n');
|
||||
}
|
||||
|
||||
// Remove a trailing newline to avoid auto-running when pasting
|
||||
if (textContent.endsWith("\n")) {
|
||||
textContent = textContent.slice(0, -1)
|
||||
}
|
||||
return textContent
|
||||
}
|
||||
|
||||
|
||||
var copyTargetText = (trigger) => {
|
||||
var target = document.querySelector(trigger.attributes['data-clipboard-target'].value);
|
||||
|
||||
// get filtered text
|
||||
let exclude = '.linenos, .gp, .go';
|
||||
|
||||
let text = filterText(target, exclude);
|
||||
return formatCopyText(text, '>>> |\\.\\.\\. |\\$ |# ', true, true, true, true, '', '')
|
||||
}
|
||||
|
||||
// Initialize with a callback so we can modify the text before copy
|
||||
const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText})
|
||||
|
||||
// Update UI with error/success messages
|
||||
clipboard.on('success', event => {
|
||||
clearSelection()
|
||||
temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success'])
|
||||
temporarilyChangeIcon(event.trigger)
|
||||
})
|
||||
|
||||
clipboard.on('error', event => {
|
||||
temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure'])
|
||||
})
|
||||
}
|
||||
|
||||
runWhenDOMLoaded(addCopyButtonToCodeCells)
|
||||
@@ -0,0 +1,73 @@
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes excluded text from a Node.
|
||||
*
|
||||
* @param {Node} target Node to filter.
|
||||
* @param {string} exclude CSS selector of nodes to exclude.
|
||||
* @returns {DOMString} Text from `target` with text removed.
|
||||
*/
|
||||
export function filterText(target, exclude) {
|
||||
const clone = target.cloneNode(true); // clone as to not modify the live DOM
|
||||
if (exclude) {
|
||||
// remove excluded nodes
|
||||
clone.querySelectorAll(exclude).forEach(node => node.remove());
|
||||
}
|
||||
return clone.innerText;
|
||||
}
|
||||
|
||||
// Callback when a copy button is clicked. Will be passed the node that was clicked
|
||||
// should then grab the text and replace pieces of text that shouldn't be used in output
|
||||
export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") {
|
||||
var regexp;
|
||||
var match;
|
||||
|
||||
// Do we check for line continuation characters and "HERE-documents"?
|
||||
var useLineCont = !!lineContinuationChar
|
||||
var useHereDoc = !!hereDocDelim
|
||||
|
||||
// create regexp to capture prompt and remaining line
|
||||
if (isRegexp) {
|
||||
regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)')
|
||||
} else {
|
||||
regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)')
|
||||
}
|
||||
|
||||
const outputLines = [];
|
||||
var promptFound = false;
|
||||
var gotLineCont = false;
|
||||
var gotHereDoc = false;
|
||||
const lineGotPrompt = [];
|
||||
for (const line of textContent.split('\n')) {
|
||||
match = line.match(regexp)
|
||||
if (match || gotLineCont || gotHereDoc) {
|
||||
promptFound = regexp.test(line)
|
||||
lineGotPrompt.push(promptFound)
|
||||
if (removePrompts && promptFound) {
|
||||
outputLines.push(match[2])
|
||||
} else {
|
||||
outputLines.push(line)
|
||||
}
|
||||
gotLineCont = line.endsWith(lineContinuationChar) & useLineCont
|
||||
if (line.includes(hereDocDelim) & useHereDoc)
|
||||
gotHereDoc = !gotHereDoc
|
||||
} else if (!onlyCopyPromptLines) {
|
||||
outputLines.push(line)
|
||||
} else if (copyEmptyLines && line.trim() === '') {
|
||||
outputLines.push(line)
|
||||
}
|
||||
}
|
||||
|
||||
// If no lines with the prompt were found then just use original lines
|
||||
if (lineGotPrompt.some(v => v === true)) {
|
||||
textContent = outputLines.join('\n');
|
||||
}
|
||||
|
||||
// Remove a trailing newline to avoid auto-running when pasting
|
||||
if (textContent.endsWith("\n")) {
|
||||
textContent = textContent.slice(0, -1)
|
||||
}
|
||||
return textContent
|
||||
}
|
||||
+640
-3
@@ -39,11 +39,648 @@
|
||||
margin-left: 8px !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .wy-side-nav-search {
|
||||
padding: 1rem 0.95rem 1.1rem !important;
|
||||
background: linear-gradient(180deg, #1678b8 0%, #0f6aa5 100%) !important;
|
||||
box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.12) !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .wy-side-nav-search > a.icon {
|
||||
display: block !important;
|
||||
margin-bottom: 0.9rem !important;
|
||||
font-size: 1.02rem !important;
|
||||
line-height: 1.35 !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .sidebar-search-entry {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .sidebar-search-entry__shortcut {
|
||||
display: flex !important;
|
||||
align-items: flex-start !important;
|
||||
gap: 0.7rem !important;
|
||||
padding: 0.85rem 0.9rem !important;
|
||||
color: #ffffff !important;
|
||||
text-decoration: none !important;
|
||||
background: rgba(255, 255, 255, 0.12) !important;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2) !important;
|
||||
border-radius: 14px !important;
|
||||
box-shadow: 0 10px 24px rgba(11, 53, 84, 0.18) !important;
|
||||
transition: transform 0.18s ease, background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .sidebar-search-entry__shortcut:hover {
|
||||
color: #ffffff !important;
|
||||
background: rgba(255, 255, 255, 0.18) !important;
|
||||
border-color: rgba(255, 255, 255, 0.34) !important;
|
||||
transform: translateY(-1px) !important;
|
||||
box-shadow: 0 14px 30px rgba(11, 53, 84, 0.22) !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .sidebar-search-entry__shortcut-icon {
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
width: 2rem !important;
|
||||
height: 2rem !important;
|
||||
min-width: 2rem !important;
|
||||
border-radius: 999px !important;
|
||||
background: rgba(255, 255, 255, 0.18) !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .sidebar-search-entry__shortcut-icon svg {
|
||||
width: 1rem !important;
|
||||
height: 1rem !important;
|
||||
fill: none !important;
|
||||
stroke: currentColor !important;
|
||||
stroke-width: 2 !important;
|
||||
stroke-linecap: round !important;
|
||||
stroke-linejoin: round !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .sidebar-search-entry__shortcut-copy {
|
||||
display: grid !important;
|
||||
gap: 0.18rem !important;
|
||||
min-width: 0 !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .sidebar-search-entry__shortcut-title {
|
||||
display: block !important;
|
||||
font-size: 0.96rem !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.3 !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .sidebar-search-entry__shortcut-text {
|
||||
display: block !important;
|
||||
font-size: 0.78rem !important;
|
||||
line-height: 1.45 !important;
|
||||
color: rgba(255, 255, 255, 0.88) !important;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.lang-switch {
|
||||
top: 10px !important;
|
||||
right: 10px !important;
|
||||
font-size: 0.8em !important;
|
||||
padding: 6px 8px !important;
|
||||
font-size: 0.8em !important;
|
||||
padding: 6px 8px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Markdown-like reading experience for the main content area. */
|
||||
.wy-body-for-nav {
|
||||
background: #f6f8fa !important;
|
||||
}
|
||||
|
||||
.wy-nav-content-wrap {
|
||||
background: #f6f8fa !important;
|
||||
}
|
||||
|
||||
.wy-nav-content {
|
||||
max-width: 960px !important;
|
||||
margin: 28px auto !important;
|
||||
padding: 40px 56px 56px !important;
|
||||
background: #ffffff !important;
|
||||
border: 1px solid #d8dee4 !important;
|
||||
border-radius: 18px !important;
|
||||
box-shadow: 0 1px 3px rgba(31, 35, 40, 0.08), 0 12px 32px rgba(31, 35, 40, 0.08) !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content {
|
||||
color: #24292f !important;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif !important;
|
||||
font-size: 16px !important;
|
||||
line-height: 1.75 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content h1,
|
||||
.wy-nav-content .rst-content h2,
|
||||
.wy-nav-content .rst-content h3,
|
||||
.wy-nav-content .rst-content h4,
|
||||
.wy-nav-content .rst-content h5,
|
||||
.wy-nav-content .rst-content h6 {
|
||||
color: #1f2328 !important;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif !important;
|
||||
font-weight: 700 !important;
|
||||
letter-spacing: -0.02em !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content h1 {
|
||||
font-size: 2.15rem !important;
|
||||
line-height: 1.25 !important;
|
||||
margin: 0 0 1rem !important;
|
||||
padding-bottom: 0.45rem !important;
|
||||
border-bottom: 1px solid #d8dee4 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content h2 {
|
||||
font-size: 1.7rem !important;
|
||||
line-height: 1.35 !important;
|
||||
margin-top: 2.3rem !important;
|
||||
margin-bottom: 1rem !important;
|
||||
padding-bottom: 0.35rem !important;
|
||||
border-bottom: 1px solid #d8dee4 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content h3 {
|
||||
font-size: 1.35rem !important;
|
||||
line-height: 1.4 !important;
|
||||
margin-top: 1.8rem !important;
|
||||
margin-bottom: 0.8rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content h4 {
|
||||
font-size: 1.1rem !important;
|
||||
line-height: 1.45 !important;
|
||||
margin-top: 1.4rem !important;
|
||||
margin-bottom: 0.6rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content p,
|
||||
.wy-nav-content .rst-content ul,
|
||||
.wy-nav-content .rst-content ol,
|
||||
.wy-nav-content .rst-content dl,
|
||||
.wy-nav-content .rst-content table,
|
||||
.wy-nav-content .rst-content blockquote {
|
||||
margin-bottom: 1rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content ul,
|
||||
.wy-nav-content .rst-content ol {
|
||||
padding-left: 1.4rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content li {
|
||||
margin: 0.35rem 0 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content li > p {
|
||||
margin-bottom: 0.45rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content a {
|
||||
color: #0969da !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content a:hover {
|
||||
color: #0550ae !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .search mark,
|
||||
.wy-nav-content .rst-content mark.section-search-match,
|
||||
.wy-nav-content .rst-content mark.section-search-hit {
|
||||
background: #fff3a3 !important;
|
||||
color: inherit !important;
|
||||
border-radius: 3px !important;
|
||||
padding: 0 0.12em !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-panel {
|
||||
margin: 1.35rem 0 1rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form {
|
||||
display: flex !important;
|
||||
align-items: stretch !important;
|
||||
gap: 0.85rem !important;
|
||||
margin-bottom: 0.75rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form__field {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
flex: 1 1 auto !important;
|
||||
min-height: 3.15rem !important;
|
||||
padding: 0 1rem !important;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%) !important;
|
||||
border: 1px solid #d0d7de !important;
|
||||
border-radius: 16px !important;
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85), 0 8px 20px rgba(31, 35, 40, 0.06) !important;
|
||||
transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form__field:focus-within {
|
||||
border-color: #0969da !important;
|
||||
box-shadow: 0 0 0 4px rgba(9, 105, 218, 0.12), 0 12px 28px rgba(31, 35, 40, 0.1) !important;
|
||||
transform: translateY(-1px) !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form__icon {
|
||||
flex: 0 0 auto !important;
|
||||
margin-right: 0.7rem !important;
|
||||
color: #57606a !important;
|
||||
font-size: 1.15rem !important;
|
||||
line-height: 1 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form input[name="q"] {
|
||||
flex: 1 1 auto !important;
|
||||
width: 100% !important;
|
||||
min-width: 0 !important;
|
||||
padding: 0 !important;
|
||||
border: 0 !important;
|
||||
background: transparent !important;
|
||||
color: #1f2328 !important;
|
||||
font-size: 1rem !important;
|
||||
line-height: 1.5 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form input[name="q"]::placeholder {
|
||||
color: #8c959f !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form input[name="q"]:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form__submit {
|
||||
flex: 0 0 auto !important;
|
||||
min-width: 7rem !important;
|
||||
padding: 0 1.35rem !important;
|
||||
border: 0 !important;
|
||||
border-radius: 16px !important;
|
||||
background: linear-gradient(135deg, #0969da 0%, #1f6feb 100%) !important;
|
||||
color: #ffffff !important;
|
||||
font-size: 0.98rem !important;
|
||||
font-weight: 700 !important;
|
||||
letter-spacing: 0.01em !important;
|
||||
box-shadow: 0 12px 28px rgba(9, 105, 218, 0.22) !important;
|
||||
cursor: pointer !important;
|
||||
transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form__submit:hover {
|
||||
transform: translateY(-1px) !important;
|
||||
box-shadow: 0 16px 32px rgba(9, 105, 218, 0.28) !important;
|
||||
filter: brightness(1.02) !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form__submit:focus {
|
||||
outline: 3px solid rgba(9, 105, 218, 0.18) !important;
|
||||
outline-offset: 2px !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history {
|
||||
margin-bottom: 0.8rem !important;
|
||||
padding: 0.9rem 1rem 1rem !important;
|
||||
background: #ffffff !important;
|
||||
border: 1px solid #d8dee4 !important;
|
||||
border-radius: 16px !important;
|
||||
box-shadow: 0 10px 24px rgba(31, 35, 40, 0.08) !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history__header {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: space-between !important;
|
||||
gap: 0.75rem !important;
|
||||
margin-bottom: 0.8rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history__title {
|
||||
color: #57606a !important;
|
||||
font-size: 0.9rem !important;
|
||||
font-weight: 700 !important;
|
||||
letter-spacing: 0.01em !important;
|
||||
text-transform: uppercase !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history__clear {
|
||||
padding: 0 !important;
|
||||
border: 0 !important;
|
||||
background: transparent !important;
|
||||
color: #0969da !important;
|
||||
font-size: 0.92rem !important;
|
||||
font-weight: 600 !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history__clear:hover {
|
||||
color: #0550ae !important;
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history__list {
|
||||
display: flex !important;
|
||||
flex-wrap: wrap !important;
|
||||
gap: 0.65rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history__item,
|
||||
.wy-nav-content .rst-content .section-search-history__empty {
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
min-height: 2.2rem !important;
|
||||
padding: 0.4rem 0.8rem !important;
|
||||
border-radius: 999px !important;
|
||||
font-size: 0.95rem !important;
|
||||
line-height: 1.3 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history__item {
|
||||
color: #1f2328 !important;
|
||||
background: #f6f8fa !important;
|
||||
border: 1px solid #d0d7de !important;
|
||||
text-decoration: none !important;
|
||||
transition: border-color 0.18s ease, background 0.18s ease, color 0.18s ease, transform 0.18s ease !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history__item:hover {
|
||||
color: #0550ae !important;
|
||||
background: #edf4ff !important;
|
||||
border-color: #9ec1ff !important;
|
||||
transform: translateY(-1px) !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history__item[aria-current="true"] {
|
||||
color: #0550ae !important;
|
||||
background: #eaf2ff !important;
|
||||
border-color: #7aa7ff !important;
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history__empty {
|
||||
color: #57606a !important;
|
||||
background: #f6f8fa !important;
|
||||
border: 1px dashed #d0d7de !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content #section-search-results .search {
|
||||
list-style: none !important;
|
||||
padding-left: 0 !important;
|
||||
margin: 1.2rem 0 0 !important;
|
||||
display: grid !important;
|
||||
gap: 0.95rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content #section-search-results .search li.section-search-result {
|
||||
margin: 0 !important;
|
||||
padding: 1rem 1.1rem 1.05rem !important;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #fbfdff 100%) !important;
|
||||
border: 1px solid #d8dee4 !important;
|
||||
border-radius: 14px !important;
|
||||
box-shadow: 0 1px 2px rgba(31, 35, 40, 0.06) !important;
|
||||
transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content #section-search-results .search li.section-search-result:hover {
|
||||
border-color: #b6c2cf !important;
|
||||
box-shadow: 0 10px 24px rgba(31, 35, 40, 0.08) !important;
|
||||
transform: translateY(-1px) !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-result__header {
|
||||
margin-bottom: 0.35rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-result__title {
|
||||
display: block !important;
|
||||
font-size: 1.08rem !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.45 !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-result__meta {
|
||||
display: inline-block !important;
|
||||
margin-bottom: 0.6rem !important;
|
||||
padding: 0.18rem 0.55rem !important;
|
||||
font-size: 0.86rem !important;
|
||||
line-height: 1.4 !important;
|
||||
color: #57606a !important;
|
||||
background: #f6f8fa !important;
|
||||
border: 1px solid #d8dee4 !important;
|
||||
border-radius: 999px !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-result__snippet {
|
||||
margin: 0 !important;
|
||||
color: #24292f !important;
|
||||
line-height: 1.7 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content code,
|
||||
.wy-nav-content .rst-content tt,
|
||||
.wy-nav-content .rst-content .literal {
|
||||
color: #cf222e !important;
|
||||
background: #f6f8fa !important;
|
||||
border: 1px solid #d0d7de !important;
|
||||
border-radius: 6px !important;
|
||||
padding: 0.12em 0.38em !important;
|
||||
font-size: 0.92em !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content div[class^="highlight-"] {
|
||||
background: #f6f8fa !important;
|
||||
border: 1px solid #d8dee4 !important;
|
||||
border-radius: 10px !important;
|
||||
overflow: hidden !important;
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5) !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content div[class^="highlight-"] > .highlight {
|
||||
position: relative !important;
|
||||
border: 0 !important;
|
||||
border-radius: inherit !important;
|
||||
background: transparent !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content pre,
|
||||
.wy-nav-content .rst-content div[class^="highlight"] pre {
|
||||
background: transparent !important;
|
||||
border: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
padding: 16px 18px !important;
|
||||
line-height: 1.55 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content pre code,
|
||||
.wy-nav-content .rst-content div[class^="highlight"] pre code {
|
||||
background: transparent !important;
|
||||
border: 0 !important;
|
||||
padding: 0 !important;
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .highlight,
|
||||
.wy-nav-content div[class^="highlight"] {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .copybtn,
|
||||
.wy-nav-content button.copybtn {
|
||||
position: absolute !important;
|
||||
top: 12px !important;
|
||||
right: 12px !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
width: 2.25rem !important;
|
||||
height: 2.25rem !important;
|
||||
min-width: 2.25rem !important;
|
||||
padding: 0 !important;
|
||||
border: 1px solid #d0d7de !important;
|
||||
border-radius: 8px !important;
|
||||
background: rgba(255, 255, 255, 0.94) !important;
|
||||
color: #57606a !important;
|
||||
box-shadow: 0 1px 2px rgba(31, 35, 40, 0.08) !important;
|
||||
box-sizing: border-box !important;
|
||||
line-height: 1 !important;
|
||||
opacity: 0.96 !important;
|
||||
transition: all 0.18s ease !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .copybtn svg,
|
||||
.wy-nav-content button.copybtn svg {
|
||||
width: 1rem !important;
|
||||
height: 1rem !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
flex: 0 0 auto !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .copybtn:hover,
|
||||
.wy-nav-content button.copybtn:hover {
|
||||
background: #ffffff !important;
|
||||
color: #1f2328 !important;
|
||||
border-color: #8c959f !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .copybtn:focus,
|
||||
.wy-nav-content button.copybtn:focus {
|
||||
outline: 2px solid rgba(9, 105, 218, 0.28) !important;
|
||||
outline-offset: 2px !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .copybtn[data-copied="true"],
|
||||
.wy-nav-content button.copybtn[data-copied="true"] {
|
||||
color: #1a7f37 !important;
|
||||
border-color: rgba(26, 127, 55, 0.32) !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content blockquote {
|
||||
color: #57606a !important;
|
||||
background: #f6f8fa !important;
|
||||
border-left: 4px solid #d0d7de !important;
|
||||
border-radius: 0 10px 10px 0 !important;
|
||||
padding: 0.35rem 1rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content blockquote p:last-child {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content table.docutils,
|
||||
.wy-nav-content .rst-content table.docutils td,
|
||||
.wy-nav-content .rst-content table.docutils th {
|
||||
border-color: #d0d7de !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content table.docutils {
|
||||
border-radius: 10px !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content thead th {
|
||||
background: #f6f8fa !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content img {
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 4px 18px rgba(31, 35, 40, 0.12) !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .wy-breadcrumbs {
|
||||
color: #57606a !important;
|
||||
margin-bottom: 1.2rem !important;
|
||||
padding-bottom: 0.85rem !important;
|
||||
border-bottom: 1px solid #d8dee4 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .wy-breadcrumbs a {
|
||||
color: #57606a !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .headerlink {
|
||||
opacity: 0.35 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .headerlink:hover {
|
||||
opacity: 0.9 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .admonition,
|
||||
.wy-nav-content .rst-content .note,
|
||||
.wy-nav-content .rst-content .warning,
|
||||
.wy-nav-content .rst-content .important,
|
||||
.wy-nav-content .rst-content .tip {
|
||||
background: #ffffff !important;
|
||||
border: 1px solid #d0d7de !important;
|
||||
border-left: 4px solid #0969da !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .warning,
|
||||
.wy-nav-content .rst-content .important {
|
||||
border-left-color: #bf8700 !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .admonition-title,
|
||||
.wy-nav-content .rst-content .note .admonition-title,
|
||||
.wy-nav-content .rst-content .warning .admonition-title,
|
||||
.wy-nav-content .rst-content .important .admonition-title,
|
||||
.wy-nav-content .rst-content .tip .admonition-title {
|
||||
background: transparent !important;
|
||||
color: #1f2328 !important;
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.wy-nav-content {
|
||||
margin: 0 !important;
|
||||
padding: 24px 18px 32px !important;
|
||||
border: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content h1 {
|
||||
font-size: 1.8rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content h2 {
|
||||
font-size: 1.45rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .wy-side-nav-search {
|
||||
padding: 0.9rem 0.8rem 1rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-side .sidebar-search-entry__shortcut {
|
||||
padding: 0.78rem 0.8rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form {
|
||||
flex-direction: column !important;
|
||||
gap: 0.7rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-form__submit {
|
||||
width: 100% !important;
|
||||
min-height: 3rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history {
|
||||
padding: 0.85rem 0.85rem 0.9rem !important;
|
||||
}
|
||||
|
||||
.wy-nav-content .rst-content .section-search-history__header {
|
||||
align-items: flex-start !important;
|
||||
flex-direction: column !important;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,611 @@
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
const INDEX_PATH = "_static/section-search-index.json";
|
||||
const INDEX_SCRIPT_PATH = "_static/section-search-index.js";
|
||||
const SEARCH_APP_ID = "section-search-app";
|
||||
const SEARCH_RESULTS_ID = "section-search-results";
|
||||
const SEARCH_STATUS_ID = "section-search-status";
|
||||
const SEARCH_HISTORY_ID = "section-search-history";
|
||||
const HIT_CLASS = "section-search-hit";
|
||||
const HISTORY_LIMIT = 8;
|
||||
|
||||
let searchIndexPromise = null;
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
initSearchPage();
|
||||
initContentHighlight();
|
||||
});
|
||||
|
||||
function initSearchPage() {
|
||||
const app = document.getElementById(SEARCH_APP_ID);
|
||||
if (!app) {
|
||||
return;
|
||||
}
|
||||
|
||||
const query = getQueryParam("q").trim();
|
||||
const form = app.querySelector("form");
|
||||
const input = form ? form.querySelector('input[name="q"]') : null;
|
||||
const resultsRoot = document.getElementById(SEARCH_RESULTS_ID);
|
||||
const statusRoot = document.getElementById(SEARCH_STATUS_ID);
|
||||
const historyRoot = document.getElementById(SEARCH_HISTORY_ID);
|
||||
|
||||
if (input) {
|
||||
input.value = query;
|
||||
}
|
||||
|
||||
initSearchHistory(app, form, input, historyRoot, query);
|
||||
|
||||
if (!query) {
|
||||
if (statusRoot) {
|
||||
statusRoot.textContent = app.dataset.emptyQuery || "";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (statusRoot) {
|
||||
statusRoot.textContent = app.dataset.loading || "";
|
||||
}
|
||||
|
||||
loadSearchIndex()
|
||||
.then((payload) => {
|
||||
const results = searchEntries(payload.entries || [], query);
|
||||
saveSearchHistory(query);
|
||||
renderSearchHistory(app, historyRoot, query, input ? input.value.trim() : "");
|
||||
renderResults(resultsRoot, statusRoot, app, query, results);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Failed to load section search index.", error);
|
||||
if (statusRoot) {
|
||||
statusRoot.textContent = app.dataset.loadError || "Search index failed to load.";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initContentHighlight() {
|
||||
const app = document.getElementById(SEARCH_APP_ID);
|
||||
if (app) {
|
||||
return;
|
||||
}
|
||||
|
||||
const query = getQueryParam("highlight").trim();
|
||||
if (!query) {
|
||||
return;
|
||||
}
|
||||
|
||||
const container = document.querySelector('[itemprop="articleBody"]');
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
const terms = buildHighlightTerms(query);
|
||||
if (!terms.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
highlightMatches(container, terms);
|
||||
scrollToClosestHit();
|
||||
}
|
||||
|
||||
function loadSearchIndex() {
|
||||
if (window.SECTION_SEARCH_INDEX) {
|
||||
return Promise.resolve(window.SECTION_SEARCH_INDEX);
|
||||
}
|
||||
|
||||
if (!searchIndexPromise) {
|
||||
searchIndexPromise = loadSearchIndexScript().catch(() => loadSearchIndexJson());
|
||||
}
|
||||
return searchIndexPromise;
|
||||
}
|
||||
|
||||
function loadSearchIndexScript() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (window.SECTION_SEARCH_INDEX) {
|
||||
resolve(window.SECTION_SEARCH_INDEX);
|
||||
return;
|
||||
}
|
||||
|
||||
const existing = document.querySelector('script[data-section-search-index="true"]');
|
||||
if (existing) {
|
||||
existing.addEventListener("load", () => resolve(window.SECTION_SEARCH_INDEX));
|
||||
existing.addEventListener("error", reject);
|
||||
return;
|
||||
}
|
||||
|
||||
const script = document.createElement("script");
|
||||
script.src = getUrlRoot() + INDEX_SCRIPT_PATH;
|
||||
script.async = true;
|
||||
script.dataset.sectionSearchIndex = "true";
|
||||
script.onload = () => {
|
||||
if (window.SECTION_SEARCH_INDEX) {
|
||||
resolve(window.SECTION_SEARCH_INDEX);
|
||||
} else {
|
||||
reject(new Error("Section search index script loaded without payload."));
|
||||
}
|
||||
};
|
||||
script.onerror = () => reject(new Error("Failed to load section search index script."));
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
function loadSearchIndexJson() {
|
||||
return fetch(getUrlRoot() + INDEX_PATH).then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("HTTP " + response.status);
|
||||
}
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
|
||||
function searchEntries(entries, rawQuery) {
|
||||
const query = normalizeText(rawQuery);
|
||||
const tokens = buildSearchTokens(rawQuery);
|
||||
|
||||
return entries
|
||||
.map((entry) => scoreEntry(entry, query, tokens))
|
||||
.filter(Boolean)
|
||||
.sort(compareResults)
|
||||
.slice(0, 80);
|
||||
}
|
||||
|
||||
function scoreEntry(entry, query, tokens) {
|
||||
const title = normalizeText((entry.title || "") + " " + (entry.page_title || ""));
|
||||
const text = normalizeText(entry.text || "");
|
||||
const combined = (title + "\n" + text).trim();
|
||||
|
||||
if (!combined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const phraseMatch = query && combined.includes(query);
|
||||
const matchedTokens = tokens.filter((token) => title.includes(token) || text.includes(token));
|
||||
|
||||
if (!phraseMatch && tokens.length && matchedTokens.length < tokens.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!phraseMatch && !matchedTokens.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let score = entry.kind === "section" ? 20 : 5;
|
||||
|
||||
if (query && title.includes(query)) {
|
||||
score += 160;
|
||||
}
|
||||
if (query && text.includes(query)) {
|
||||
score += 90;
|
||||
}
|
||||
|
||||
matchedTokens.forEach((token) => {
|
||||
if (title.includes(token)) {
|
||||
score += 45;
|
||||
} else {
|
||||
score += 18;
|
||||
}
|
||||
});
|
||||
|
||||
if (entry.page_title && entry.title && entry.page_title !== entry.title) {
|
||||
score += 10;
|
||||
}
|
||||
|
||||
return {
|
||||
entry,
|
||||
score,
|
||||
snippet: makeSnippet(entry.text || entry.page_title || entry.title || "", query, tokens),
|
||||
};
|
||||
}
|
||||
|
||||
function compareResults(left, right) {
|
||||
if (right.score !== left.score) {
|
||||
return right.score - left.score;
|
||||
}
|
||||
|
||||
const leftTitle = ((left.entry.title || "") + " " + (left.entry.page_title || "")).toLowerCase();
|
||||
const rightTitle = ((right.entry.title || "") + " " + (right.entry.page_title || "")).toLowerCase();
|
||||
return leftTitle.localeCompare(rightTitle);
|
||||
}
|
||||
|
||||
function renderResults(root, statusRoot, app, query, results) {
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
|
||||
const highlightTerms = buildHighlightTerms(query);
|
||||
root.replaceChildren();
|
||||
|
||||
if (!results.length) {
|
||||
if (statusRoot) {
|
||||
statusRoot.textContent = app.dataset.noResults || "";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (statusRoot) {
|
||||
statusRoot.textContent = formatCountMessage(app, results.length);
|
||||
}
|
||||
|
||||
const list = document.createElement("ul");
|
||||
list.className = "search";
|
||||
list.setAttribute("role", "list");
|
||||
|
||||
results.forEach((result) => {
|
||||
list.appendChild(renderResultItem(result, query, highlightTerms));
|
||||
});
|
||||
|
||||
root.appendChild(list);
|
||||
}
|
||||
|
||||
function initSearchHistory(app, form, input, historyRoot, query) {
|
||||
if (!form || !input || !historyRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
renderSearchHistory(app, historyRoot, query, input.value.trim());
|
||||
|
||||
form.addEventListener("submit", () => {
|
||||
saveSearchHistory(input.value);
|
||||
});
|
||||
|
||||
input.addEventListener("focus", () => {
|
||||
renderSearchHistory(app, historyRoot, query, input.value.trim());
|
||||
toggleHistoryVisibility(historyRoot, true);
|
||||
});
|
||||
|
||||
input.addEventListener("input", () => {
|
||||
renderSearchHistory(app, historyRoot, query, input.value.trim());
|
||||
toggleHistoryVisibility(historyRoot, true);
|
||||
});
|
||||
|
||||
document.addEventListener("click", (event) => {
|
||||
if (!historyRoot.contains(event.target) && !form.contains(event.target)) {
|
||||
toggleHistoryVisibility(historyRoot, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderSearchHistory(app, historyRoot, currentQuery, draftQuery) {
|
||||
if (!historyRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
const history = getSearchHistory();
|
||||
const keyword = normalizeText(draftQuery || "");
|
||||
const filtered = keyword
|
||||
? history.filter((item) => normalizeText(item).includes(keyword))
|
||||
: history.slice();
|
||||
|
||||
historyRoot.replaceChildren();
|
||||
|
||||
const header = document.createElement("div");
|
||||
header.className = "section-search-history__header";
|
||||
|
||||
const title = document.createElement("div");
|
||||
title.className = "section-search-history__title";
|
||||
title.textContent = app.dataset.historyTitle || "Recent searches";
|
||||
header.appendChild(title);
|
||||
|
||||
if (history.length) {
|
||||
const clearButton = document.createElement("button");
|
||||
clearButton.type = "button";
|
||||
clearButton.className = "section-search-history__clear";
|
||||
clearButton.textContent = app.dataset.clearHistory || "Clear history";
|
||||
clearButton.addEventListener("click", () => {
|
||||
clearSearchHistory();
|
||||
renderSearchHistory(app, historyRoot, currentQuery, draftQuery);
|
||||
toggleHistoryVisibility(historyRoot, true);
|
||||
});
|
||||
header.appendChild(clearButton);
|
||||
}
|
||||
|
||||
historyRoot.appendChild(header);
|
||||
|
||||
const list = document.createElement("div");
|
||||
list.className = "section-search-history__list";
|
||||
|
||||
if (!filtered.length) {
|
||||
const empty = document.createElement("div");
|
||||
empty.className = "section-search-history__empty";
|
||||
empty.textContent = keyword ? app.dataset.noResults || "" : app.dataset.historyEmpty || "";
|
||||
list.appendChild(empty);
|
||||
} else {
|
||||
filtered.forEach((item) => {
|
||||
const link = document.createElement("a");
|
||||
link.className = "section-search-history__item";
|
||||
link.href = "?q=" + encodeURIComponent(item);
|
||||
link.textContent = item;
|
||||
if (normalizeText(item) === normalizeText(currentQuery)) {
|
||||
link.setAttribute("aria-current", "true");
|
||||
}
|
||||
list.appendChild(link);
|
||||
});
|
||||
}
|
||||
|
||||
historyRoot.appendChild(list);
|
||||
toggleHistoryVisibility(historyRoot, Boolean(history.length || keyword));
|
||||
}
|
||||
|
||||
function renderResultItem(result, query, highlightTerms) {
|
||||
const item = document.createElement("li");
|
||||
item.className = "kind-text section-search-result";
|
||||
|
||||
const header = document.createElement("div");
|
||||
header.className = "section-search-result__header";
|
||||
const link = document.createElement("a");
|
||||
link.className = "section-search-result__title";
|
||||
link.href = buildResultUrl(result.entry.url, query);
|
||||
appendHighlightedText(link, result.entry.title || result.entry.page_title || "", highlightTerms);
|
||||
header.appendChild(link);
|
||||
item.appendChild(header);
|
||||
|
||||
if (result.entry.page_title && result.entry.page_title !== result.entry.title) {
|
||||
const context = document.createElement("div");
|
||||
context.className = "section-search-result__meta";
|
||||
context.appendChild(createHighlightedFragment(result.entry.page_title, highlightTerms));
|
||||
item.appendChild(context);
|
||||
}
|
||||
|
||||
if (result.snippet) {
|
||||
const summary = document.createElement("p");
|
||||
summary.className = "search-snippet section-search-result__snippet";
|
||||
summary.appendChild(createHighlightedFragment(result.snippet, highlightTerms));
|
||||
item.appendChild(summary);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
function buildResultUrl(url, query) {
|
||||
const hashIndex = url.indexOf("#");
|
||||
const base = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
||||
const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
|
||||
const separator = base.includes("?") ? "&" : "?";
|
||||
return base + separator + "highlight=" + encodeURIComponent(query) + hash;
|
||||
}
|
||||
|
||||
function makeSnippet(text, query, tokens) {
|
||||
const source = collapseWhitespace(text);
|
||||
if (!source) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const candidates = [query].concat(tokens).filter(Boolean);
|
||||
let index = -1;
|
||||
|
||||
for (const term of candidates) {
|
||||
index = source.toLowerCase().indexOf(term.toLowerCase());
|
||||
if (index >= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < 0) {
|
||||
return source.slice(0, 180) + (source.length > 180 ? "..." : "");
|
||||
}
|
||||
|
||||
const start = Math.max(index - 70, 0);
|
||||
const end = Math.min(index + 110, source.length);
|
||||
const prefix = start > 0 ? "..." : "";
|
||||
const suffix = end < source.length ? "..." : "";
|
||||
return prefix + source.slice(start, end) + suffix;
|
||||
}
|
||||
|
||||
function buildSearchTokens(query) {
|
||||
const normalized = normalizeText(query);
|
||||
const latinTokens = normalized
|
||||
.split(/[^\p{Letter}\p{Number}_]+/u)
|
||||
.map((token) => token.trim())
|
||||
.filter(Boolean);
|
||||
const cjkTokens = normalized.match(/[\u3400-\u9fff]+/gu) || [];
|
||||
|
||||
return Array.from(new Set(latinTokens.concat(cjkTokens)));
|
||||
}
|
||||
|
||||
function buildHighlightTerms(query) {
|
||||
const normalized = normalizeText(query);
|
||||
const tokens = buildSearchTokens(query);
|
||||
const ordered = [normalized]
|
||||
.concat(tokens)
|
||||
.filter(Boolean)
|
||||
.sort((left, right) => right.length - left.length);
|
||||
|
||||
return Array.from(new Set(ordered));
|
||||
}
|
||||
|
||||
function highlightMatches(container, terms) {
|
||||
const matcher = new RegExp("(" + terms.map(escapeRegExp).join("|") + ")", "giu");
|
||||
const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, {
|
||||
acceptNode(node) {
|
||||
const parent = node.parentElement;
|
||||
if (!parent || !node.nodeValue || !node.nodeValue.trim()) {
|
||||
return NodeFilter.FILTER_REJECT;
|
||||
}
|
||||
if (parent.closest("script, style, noscript, mark, .headerlink")) {
|
||||
return NodeFilter.FILTER_REJECT;
|
||||
}
|
||||
return containsAny(node.nodeValue, terms) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
|
||||
},
|
||||
});
|
||||
|
||||
const textNodes = [];
|
||||
while (walker.nextNode()) {
|
||||
textNodes.push(walker.currentNode);
|
||||
}
|
||||
|
||||
textNodes.forEach((node) => {
|
||||
const value = node.nodeValue;
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
matcher.lastIndex = 0;
|
||||
let lastIndex = 0;
|
||||
let match = null;
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
while ((match = matcher.exec(value)) !== null) {
|
||||
if (match.index > lastIndex) {
|
||||
fragment.appendChild(document.createTextNode(value.slice(lastIndex, match.index)));
|
||||
}
|
||||
|
||||
const mark = document.createElement("mark");
|
||||
mark.className = HIT_CLASS;
|
||||
mark.textContent = match[0];
|
||||
fragment.appendChild(mark);
|
||||
lastIndex = match.index + match[0].length;
|
||||
}
|
||||
|
||||
if (lastIndex === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastIndex < value.length) {
|
||||
fragment.appendChild(document.createTextNode(value.slice(lastIndex)));
|
||||
}
|
||||
|
||||
node.parentNode.replaceChild(fragment, node);
|
||||
});
|
||||
}
|
||||
|
||||
function scrollToClosestHit() {
|
||||
const hash = decodeURIComponent(window.location.hash || "").replace(/^#/, "");
|
||||
let target = null;
|
||||
|
||||
if (hash) {
|
||||
const anchor = document.getElementById(hash);
|
||||
if (anchor) {
|
||||
const scope = anchor.closest("section") || anchor;
|
||||
target = scope.querySelector("." + HIT_CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
if (!target) {
|
||||
target = document.querySelector("." + HIT_CLASS);
|
||||
}
|
||||
|
||||
if (target) {
|
||||
window.requestAnimationFrame(() => {
|
||||
target.scrollIntoView({ block: "center" });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function formatCountMessage(app, count) {
|
||||
const template = count === 1 ? app.dataset.resultOne : app.dataset.resultMany;
|
||||
return (template || "").replace("{count}", String(count));
|
||||
}
|
||||
|
||||
function getQueryParam(name) {
|
||||
return new URLSearchParams(window.location.search).get(name) || "";
|
||||
}
|
||||
|
||||
function getSearchHistory() {
|
||||
try {
|
||||
const raw = window.localStorage.getItem(getHistoryStorageKey());
|
||||
const parsed = raw ? JSON.parse(raw) : [];
|
||||
return Array.isArray(parsed)
|
||||
? parsed.map((item) => collapseWhitespace(String(item))).filter(Boolean).slice(0, HISTORY_LIMIT)
|
||||
: [];
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function saveSearchHistory(query) {
|
||||
const normalized = collapseWhitespace(query);
|
||||
if (!normalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
const history = getSearchHistory().filter((item) => item !== normalized);
|
||||
history.unshift(normalized);
|
||||
|
||||
try {
|
||||
window.localStorage.setItem(getHistoryStorageKey(), JSON.stringify(history.slice(0, HISTORY_LIMIT)));
|
||||
} catch (error) {
|
||||
console.warn("Failed to save search history.", error);
|
||||
}
|
||||
}
|
||||
|
||||
function clearSearchHistory() {
|
||||
try {
|
||||
window.localStorage.removeItem(getHistoryStorageKey());
|
||||
} catch (error) {
|
||||
console.warn("Failed to clear search history.", error);
|
||||
}
|
||||
}
|
||||
|
||||
function getHistoryStorageKey() {
|
||||
const scope =
|
||||
window.location.pathname.replace(/search\.html$/i, "").replace(/index\.html$/i, "") ||
|
||||
getUrlRoot() ||
|
||||
"default";
|
||||
return "section_search_recent_queries::" + scope;
|
||||
}
|
||||
|
||||
function getUrlRoot() {
|
||||
return (window.DOCUMENTATION_OPTIONS && window.DOCUMENTATION_OPTIONS.URL_ROOT) || "";
|
||||
}
|
||||
|
||||
function toggleHistoryVisibility(historyRoot, visible) {
|
||||
if (!historyRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
historyRoot.hidden = !visible;
|
||||
}
|
||||
|
||||
function containsAny(text, terms) {
|
||||
const normalized = text.toLowerCase();
|
||||
return terms.some((term) => normalized.includes(term.toLowerCase()));
|
||||
}
|
||||
|
||||
function appendHighlightedText(target, text, terms) {
|
||||
target.appendChild(createHighlightedFragment(text, terms));
|
||||
}
|
||||
|
||||
function createHighlightedFragment(text, terms) {
|
||||
const fragment = document.createDocumentFragment();
|
||||
const source = text || "";
|
||||
const filteredTerms = (terms || []).filter(Boolean);
|
||||
|
||||
if (!source || !filteredTerms.length) {
|
||||
fragment.appendChild(document.createTextNode(source));
|
||||
return fragment;
|
||||
}
|
||||
|
||||
const matcher = new RegExp("(" + filteredTerms.map(escapeRegExp).join("|") + ")", "giu");
|
||||
let lastIndex = 0;
|
||||
let match = null;
|
||||
|
||||
while ((match = matcher.exec(source)) !== null) {
|
||||
if (match.index > lastIndex) {
|
||||
fragment.appendChild(document.createTextNode(source.slice(lastIndex, match.index)));
|
||||
}
|
||||
|
||||
const mark = document.createElement("mark");
|
||||
mark.className = "section-search-match";
|
||||
mark.textContent = match[0];
|
||||
fragment.appendChild(mark);
|
||||
lastIndex = match.index + match[0].length;
|
||||
}
|
||||
|
||||
if (lastIndex < source.length) {
|
||||
fragment.appendChild(document.createTextNode(source.slice(lastIndex)));
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
function normalizeText(text) {
|
||||
return collapseWhitespace(text).toLowerCase();
|
||||
}
|
||||
|
||||
function collapseWhitespace(text) {
|
||||
return (text || "").replace(/\s+/g, " ").trim();
|
||||
}
|
||||
|
||||
function escapeRegExp(text) {
|
||||
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user