mirror of
https://kevinblog.sytes.net/Code/Jibo-Revival-Group/JiboViteDocs.git
synced 2026-06-16 16:16:13 +00:00
Initalize
This commit is contained in:
169
node_modules/vitepress/dist/client/theme-default/support/docsearch.js
generated
vendored
Normal file
169
node_modules/vitepress/dist/client/theme-default/support/docsearch.js
generated
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
import { isObject } from '../../shared';
|
||||
/**
|
||||
* Resolves the effective mode based on config and available features.
|
||||
*
|
||||
* - 'auto': infer hybrid vs sidePanel-only from provided config
|
||||
* - 'sidePanel': force sidePanel-only even if keyword search is configured
|
||||
* - 'hybrid': force hybrid (error if keyword search is not configured)
|
||||
* - 'modal': force modal even if sidePanel is configured
|
||||
*/
|
||||
export function resolveMode(options) {
|
||||
const mode = options.mode ?? 'auto';
|
||||
const hasKeyword = hasKeywordSearch(options);
|
||||
const askAi = options.askAi;
|
||||
const hasSidePanelConfig = Boolean(askAi && typeof askAi === 'object' && askAi.sidePanel);
|
||||
switch (mode) {
|
||||
case 'sidePanel':
|
||||
// Force sidePanel-only - hide keyword search
|
||||
return {
|
||||
mode,
|
||||
showKeywordSearch: false,
|
||||
useSidePanel: true
|
||||
};
|
||||
case 'hybrid':
|
||||
// Force hybrid - keyword search must be configured
|
||||
if (!hasKeyword) {
|
||||
console.error('[vitepress] mode: "hybrid" requires keyword search credentials (appId, apiKey, indexName).');
|
||||
}
|
||||
return {
|
||||
mode,
|
||||
showKeywordSearch: hasKeyword,
|
||||
useSidePanel: true
|
||||
};
|
||||
case 'modal':
|
||||
// Force modal - don't use sidepanel for askai, even if configured
|
||||
return {
|
||||
mode,
|
||||
showKeywordSearch: hasKeyword,
|
||||
useSidePanel: false
|
||||
};
|
||||
case 'auto':
|
||||
default:
|
||||
// Auto-detect based on config
|
||||
return {
|
||||
mode: 'auto',
|
||||
showKeywordSearch: hasKeyword,
|
||||
useSidePanel: hasSidePanelConfig
|
||||
};
|
||||
}
|
||||
}
|
||||
export function hasKeywordSearch(options) {
|
||||
return Boolean(options.appId && options.apiKey && options.indexName);
|
||||
}
|
||||
export function hasAskAi(askAi) {
|
||||
if (!askAi)
|
||||
return false;
|
||||
if (typeof askAi === 'string')
|
||||
return askAi.length > 0;
|
||||
return Boolean(askAi.assistantId);
|
||||
}
|
||||
/**
|
||||
* Removes existing `lang:` filters and appends `lang:${lang}`.
|
||||
* Handles both flat arrays and nested arrays (for OR conditions).
|
||||
*/
|
||||
export function mergeLangFacetFilters(rawFacetFilters, lang) {
|
||||
const input = Array.isArray(rawFacetFilters)
|
||||
? rawFacetFilters
|
||||
: rawFacetFilters
|
||||
? [rawFacetFilters]
|
||||
: [];
|
||||
const filtered = input
|
||||
.map((filter) => {
|
||||
if (Array.isArray(filter)) {
|
||||
// Handle nested arrays (OR conditions)
|
||||
return filter.filter((f) => typeof f === 'string' && !f.startsWith('lang:'));
|
||||
}
|
||||
return filter;
|
||||
})
|
||||
.filter((filter) => {
|
||||
if (typeof filter === 'string') {
|
||||
return !filter.startsWith('lang:');
|
||||
}
|
||||
// Keep nested arrays with remaining filters
|
||||
return Array.isArray(filter) && filter.length > 0;
|
||||
});
|
||||
return [...filtered, `lang:${lang}`];
|
||||
}
|
||||
/**
|
||||
* Validates that required Algolia credentials are present.
|
||||
*/
|
||||
export function validateCredentials(options) {
|
||||
const appId = options.appId;
|
||||
const apiKey = options.apiKey;
|
||||
const indexName = options.indexName;
|
||||
return {
|
||||
valid: Boolean(appId && apiKey && indexName),
|
||||
appId,
|
||||
apiKey,
|
||||
indexName
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Builds Ask AI configuration from various input formats.
|
||||
*/
|
||||
export function buildAskAiConfig(askAiProp, options, lang) {
|
||||
const isAskAiString = typeof askAiProp === 'string';
|
||||
const askAiSearchParameters = !isAskAiString && askAiProp.searchParameters
|
||||
? { ...askAiProp.searchParameters }
|
||||
: undefined;
|
||||
// If Ask AI defines its own facetFilters, merge lang filtering into those.
|
||||
// Otherwise, reuse the keyword search facetFilters so Ask AI follows the
|
||||
// same language filtering behavior by default.
|
||||
const askAiFacetFiltersSource = askAiSearchParameters?.facetFilters ??
|
||||
options.searchParameters?.facetFilters;
|
||||
const askAiFacetFilters = mergeLangFacetFilters(askAiFacetFiltersSource, lang);
|
||||
const mergedAskAiSearchParameters = {
|
||||
...askAiSearchParameters,
|
||||
facetFilters: askAiFacetFilters.length ? askAiFacetFilters : undefined
|
||||
};
|
||||
const result = {
|
||||
...(isAskAiString ? {} : askAiProp),
|
||||
indexName: isAskAiString ? options.indexName : askAiProp.indexName,
|
||||
apiKey: isAskAiString ? options.apiKey : askAiProp.apiKey,
|
||||
appId: isAskAiString ? options.appId : askAiProp.appId,
|
||||
assistantId: isAskAiString ? askAiProp : askAiProp.assistantId
|
||||
};
|
||||
// Keep `searchParameters` undefined unless it has at least one key.
|
||||
if (Object.values(mergedAskAiSearchParameters).some((v) => v != null)) {
|
||||
result.searchParameters = mergedAskAiSearchParameters;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Resolves Algolia search options for the given language,
|
||||
* merging in locale-specific overrides and language facet filters.
|
||||
*/
|
||||
export function resolveOptionsForLanguage(options, localeIndex, lang) {
|
||||
options = deepMerge(options, options.locales?.[localeIndex] || {});
|
||||
const facetFilters = mergeLangFacetFilters(options.searchParameters?.facetFilters, lang);
|
||||
const askAi = options.askAi
|
||||
? buildAskAiConfig(options.askAi, options, lang)
|
||||
: undefined;
|
||||
return {
|
||||
...options,
|
||||
searchParameters: { ...options.searchParameters, facetFilters },
|
||||
askAi
|
||||
};
|
||||
}
|
||||
function deepMerge(target, source) {
|
||||
const result = { ...target };
|
||||
for (const key in source) {
|
||||
const value = source[key];
|
||||
if (value === undefined)
|
||||
continue;
|
||||
// special case: replace entirely
|
||||
if (key === 'searchParameters') {
|
||||
result[key] = value;
|
||||
continue;
|
||||
}
|
||||
// deep-merge only plain objects; arrays are replaced entirely
|
||||
if (isObject(value) && isObject(result[key])) {
|
||||
result[key] = deepMerge(result[key], value);
|
||||
}
|
||||
else {
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
delete result.locales;
|
||||
return result;
|
||||
}
|
||||
33
node_modules/vitepress/dist/client/theme-default/support/lru.js
generated
vendored
Normal file
33
node_modules/vitepress/dist/client/theme-default/support/lru.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// adapted from https://stackoverflow.com/a/46432113/11613622
|
||||
export class LRUCache {
|
||||
max;
|
||||
cache;
|
||||
constructor(max = 10) {
|
||||
this.max = max;
|
||||
this.cache = new Map();
|
||||
}
|
||||
get(key) {
|
||||
let item = this.cache.get(key);
|
||||
if (item !== undefined) {
|
||||
// refresh key
|
||||
this.cache.delete(key);
|
||||
this.cache.set(key, item);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
set(key, val) {
|
||||
// refresh key
|
||||
if (this.cache.has(key))
|
||||
this.cache.delete(key);
|
||||
// evict oldest
|
||||
else if (this.cache.size === this.max)
|
||||
this.cache.delete(this.first());
|
||||
this.cache.set(key, val);
|
||||
}
|
||||
first() {
|
||||
return this.cache.keys().next().value;
|
||||
}
|
||||
clear() {
|
||||
this.cache.clear();
|
||||
}
|
||||
}
|
||||
9
node_modules/vitepress/dist/client/theme-default/support/reactivity.js
generated
vendored
Normal file
9
node_modules/vitepress/dist/client/theme-default/support/reactivity.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { computed } from 'vue';
|
||||
export function smartComputed(getter, comparator = (oldValue, newValue) => JSON.stringify(oldValue) === JSON.stringify(newValue)) {
|
||||
return computed((oldValue) => {
|
||||
const newValue = getter();
|
||||
return oldValue === undefined || !comparator(oldValue, newValue)
|
||||
? newValue
|
||||
: oldValue;
|
||||
});
|
||||
}
|
||||
89
node_modules/vitepress/dist/client/theme-default/support/sidebar.js
generated
vendored
Normal file
89
node_modules/vitepress/dist/client/theme-default/support/sidebar.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
import { isActive } from '../../shared';
|
||||
import { ensureStartingSlash } from './utils';
|
||||
/**
|
||||
* Get the `Sidebar` from sidebar option. This method will ensure to get correct
|
||||
* sidebar config from `MultiSideBarConfig` with various path combinations such
|
||||
* as matching `guide/` and `/guide/`. If no matching config was found, it will
|
||||
* return empty array.
|
||||
*/
|
||||
export function getSidebar(_sidebar, path) {
|
||||
if (Array.isArray(_sidebar))
|
||||
return addBase(_sidebar);
|
||||
if (_sidebar == null)
|
||||
return [];
|
||||
path = ensureStartingSlash(path);
|
||||
const dir = Object.keys(_sidebar)
|
||||
.sort((a, b) => {
|
||||
return b.split('/').length - a.split('/').length;
|
||||
})
|
||||
.find((dir) => {
|
||||
// make sure the multi sidebar key starts with slash too
|
||||
return path.startsWith(ensureStartingSlash(dir));
|
||||
});
|
||||
const sidebar = dir ? _sidebar[dir] : [];
|
||||
return Array.isArray(sidebar)
|
||||
? addBase(sidebar)
|
||||
: addBase(sidebar.items, sidebar.base);
|
||||
}
|
||||
/**
|
||||
* Get or generate sidebar group from the given sidebar items.
|
||||
*/
|
||||
export function getSidebarGroups(sidebar) {
|
||||
const groups = [];
|
||||
let lastGroupIndex = 0;
|
||||
for (const index in sidebar) {
|
||||
const item = sidebar[index];
|
||||
if (item.items) {
|
||||
lastGroupIndex = groups.push(item);
|
||||
continue;
|
||||
}
|
||||
if (!groups[lastGroupIndex]) {
|
||||
groups.push({ items: [] });
|
||||
}
|
||||
groups[lastGroupIndex].items.push(item);
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
export function getFlatSideBarLinks(sidebar) {
|
||||
const links = [];
|
||||
function recursivelyExtractLinks(items) {
|
||||
for (const item of items) {
|
||||
if (item.text && item.link) {
|
||||
links.push({
|
||||
text: item.text,
|
||||
link: item.link,
|
||||
docFooterText: item.docFooterText
|
||||
});
|
||||
}
|
||||
if (item.items) {
|
||||
recursivelyExtractLinks(item.items);
|
||||
}
|
||||
}
|
||||
}
|
||||
recursivelyExtractLinks(sidebar);
|
||||
return links;
|
||||
}
|
||||
/**
|
||||
* Check if the given sidebar item contains any active link.
|
||||
*/
|
||||
export function hasActiveLink(path, items) {
|
||||
if (Array.isArray(items)) {
|
||||
return items.some((item) => hasActiveLink(path, item));
|
||||
}
|
||||
return isActive(path, items.link)
|
||||
? true
|
||||
: items.items
|
||||
? hasActiveLink(path, items.items)
|
||||
: false;
|
||||
}
|
||||
function addBase(items, _base) {
|
||||
return [...items].map((_item) => {
|
||||
const item = { ..._item };
|
||||
const base = item.base || _base;
|
||||
if (base && item.link)
|
||||
item.link = base + item.link.replace(/^\//, base.endsWith('/') ? '' : '/');
|
||||
if (item.items)
|
||||
item.items = addBase(item.items, base);
|
||||
return item;
|
||||
});
|
||||
}
|
||||
49
node_modules/vitepress/dist/client/theme-default/support/translation.js
generated
vendored
Normal file
49
node_modules/vitepress/dist/client/theme-default/support/translation.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import { useData } from '../composables/data';
|
||||
/**
|
||||
* @param themeObject Can be an object with `translations` and `locales` properties
|
||||
*/
|
||||
export function createSearchTranslate(defaultTranslations) {
|
||||
const { localeIndex, theme } = useData();
|
||||
function translate(key) {
|
||||
const keyPath = key.split('.');
|
||||
const themeObject = theme.value.search?.options;
|
||||
const isObject = themeObject && typeof themeObject === 'object';
|
||||
const locales = (isObject && themeObject.locales?.[localeIndex.value]?.translations) ||
|
||||
null;
|
||||
const translations = (isObject && themeObject.translations) || null;
|
||||
let localeResult = locales;
|
||||
let translationResult = translations;
|
||||
let defaultResult = defaultTranslations;
|
||||
const lastKey = keyPath.pop();
|
||||
for (const k of keyPath) {
|
||||
let fallbackResult = null;
|
||||
const foundInFallback = defaultResult?.[k];
|
||||
if (foundInFallback) {
|
||||
fallbackResult = defaultResult = foundInFallback;
|
||||
}
|
||||
const foundInTranslation = translationResult?.[k];
|
||||
if (foundInTranslation) {
|
||||
fallbackResult = translationResult = foundInTranslation;
|
||||
}
|
||||
const foundInLocale = localeResult?.[k];
|
||||
if (foundInLocale) {
|
||||
fallbackResult = localeResult = foundInLocale;
|
||||
}
|
||||
// Put fallback into unresolved results
|
||||
if (!foundInFallback) {
|
||||
defaultResult = fallbackResult;
|
||||
}
|
||||
if (!foundInTranslation) {
|
||||
translationResult = fallbackResult;
|
||||
}
|
||||
if (!foundInLocale) {
|
||||
localeResult = fallbackResult;
|
||||
}
|
||||
}
|
||||
return (localeResult?.[lastKey] ??
|
||||
translationResult?.[lastKey] ??
|
||||
defaultResult?.[lastKey] ??
|
||||
'');
|
||||
}
|
||||
return translate;
|
||||
}
|
||||
33
node_modules/vitepress/dist/client/theme-default/support/utils.js
generated
vendored
Normal file
33
node_modules/vitepress/dist/client/theme-default/support/utils.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { withBase } from 'vitepress';
|
||||
import { isExternal, treatAsHtml } from '../../shared';
|
||||
import { useData } from '../composables/data';
|
||||
export function throttleAndDebounce(fn, delay) {
|
||||
let timeoutId;
|
||||
let called = false;
|
||||
return () => {
|
||||
if (timeoutId)
|
||||
clearTimeout(timeoutId);
|
||||
if (!called) {
|
||||
fn();
|
||||
(called = true) && setTimeout(() => (called = false), delay);
|
||||
}
|
||||
else
|
||||
timeoutId = setTimeout(fn, delay);
|
||||
};
|
||||
}
|
||||
export function ensureStartingSlash(path) {
|
||||
return path.startsWith('/') ? path : `/${path}`;
|
||||
}
|
||||
export function normalizeLink(url) {
|
||||
const { pathname, search, hash, protocol } = new URL(url, 'http://a.com');
|
||||
if (isExternal(url) ||
|
||||
url.startsWith('#') ||
|
||||
!protocol.startsWith('http') ||
|
||||
!treatAsHtml(pathname))
|
||||
return url;
|
||||
const { site } = useData();
|
||||
const normalizedPath = pathname.endsWith('/') || pathname.endsWith('.html')
|
||||
? url
|
||||
: url.replace(/(?:(^\.+)\/)?.*$/, `$1${pathname.replace(/(\.md)?$/, site.value.cleanUrls ? '' : '.html')}${search}${hash}`);
|
||||
return withBase(normalizedPath);
|
||||
}
|
||||
Reference in New Issue
Block a user