マーカーの形を成形
This commit is contained in:
parent
f8282e8d1f
commit
c34087b81a
|
@ -8,47 +8,235 @@ import type { Plugin } from 'vite';
|
|||
import fs from 'node:fs';
|
||||
import { glob } from 'glob';
|
||||
import JSON5 from 'json5';
|
||||
import { randomUUID } from 'crypto';
|
||||
import MagicString from 'magic-string';
|
||||
import path from 'node:path'
|
||||
import { hash, toBase62 } from '../vite.config';
|
||||
|
||||
export interface AnalysisResult {
|
||||
export type AnalysisResult = {
|
||||
filePath: string;
|
||||
usage: ComponentUsageInfo[];
|
||||
usage: SearchIndexItem[];
|
||||
}
|
||||
|
||||
export interface ComponentUsageInfo {
|
||||
staticProps: Record<string, string>;
|
||||
bindProps: Record<string, string>;
|
||||
export type SearchIndexItem = {
|
||||
id: string;
|
||||
path?: string;
|
||||
label: string;
|
||||
keywords: string | string[];
|
||||
icon?: string;
|
||||
children?: (SearchIndexItem[] | string);
|
||||
}
|
||||
|
||||
function outputAnalysisResultAsTS(outputPath: string, analysisResults: AnalysisResult[]): void {
|
||||
// (outputAnalysisResultAsTS 関数の実装は前回と同様)
|
||||
const varName = 'searchIndexes'; // 変数名
|
||||
console.log(`[create-search-index] Processing ${analysisResults.length} files for output`);
|
||||
|
||||
const jsonString = JSON5.stringify(analysisResults, { space: "\t", quote: "'" }); // JSON.stringify で JSON 文字列を生成
|
||||
// 新しいツリー構造を構築
|
||||
const allMarkers = new Map<string, SearchIndexItem>();
|
||||
|
||||
// bindProps の値を文字列置換で修正する関数
|
||||
function modifyBindPropsInString(jsonString: string): string {
|
||||
const modifiedString = jsonString.replace(
|
||||
/bindProps:\s*\{([^}]*)\}/g, // bindProps: { ... } にマッチ (g フラグで複数箇所を置換)
|
||||
(match, bindPropsBlock) => {
|
||||
// bindPropsBlock ( { ... } 内) の各プロパティをさらに置換
|
||||
const modifiedBlock = bindPropsBlock.replace(
|
||||
/(.*):\s*\'(.*)\'/g, // propName: 'propValue' にマッチ
|
||||
(propMatch, propName, propValue) => {
|
||||
return `${propName}: ${propValue}`; // propValue のクォートを除去
|
||||
}
|
||||
).replaceAll("\\'", "'");
|
||||
return `bindProps: {${modifiedBlock}}`; // 置換後の block で bindProps: { ... } を再構成
|
||||
}
|
||||
);
|
||||
return modifiedString;
|
||||
}
|
||||
// 1. すべてのマーカーを一旦フラットに収集
|
||||
for (const file of analysisResults) {
|
||||
console.log(`[create-search-index] Processing file: ${file.filePath} with ${file.usage.length} markers`);
|
||||
for (const marker of file.usage) {
|
||||
if (marker.id) {
|
||||
// キーワードの処理(文字列から配列へ変換)
|
||||
let keywords = marker.keywords;
|
||||
if (typeof keywords === 'string' && keywords.startsWith('[') && keywords.endsWith(']')) {
|
||||
try {
|
||||
// JSON5解析を試みる(ただしi18n参照などがある場合は例外発生)
|
||||
keywords = JSON5.parse(keywords.replace(/'/g, '"'));
|
||||
} catch (e) {
|
||||
// 解析に失敗した場合は文字列のままにする
|
||||
console.log(`[create-search-index] Keeping keywords as string expression: ${keywords}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 子要素の処理(文字列から配列へ変換)
|
||||
let children = marker.children || [];
|
||||
if (typeof children === 'string' && children.startsWith('[') && children.endsWith(']')) {
|
||||
try {
|
||||
// JSON5解析を試みる
|
||||
children = JSON5.parse(children.replace(/'/g, '"'));
|
||||
} catch (e) {
|
||||
// 解析に失敗した場合は空配列に
|
||||
console.log(`[create-search-index] Could not parse children: ${children}, using empty array`);
|
||||
children = [];
|
||||
}
|
||||
}
|
||||
|
||||
const tsOutput = `
|
||||
// 子マーカーの内部構造を適切に更新
|
||||
if (Array.isArray(children) && children.length > 0) {
|
||||
console.log(`[create-search-index] Marker ${marker.id} has ${children.length} children: ${JSON.stringify(children)}`);
|
||||
}
|
||||
|
||||
allMarkers.set(marker.id, {
|
||||
...marker,
|
||||
keywords,
|
||||
children: Array.isArray(children) ? children : []
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[create-search-index] Collected total ${allMarkers.size} unique markers`);
|
||||
|
||||
// 2. 子マーカーIDの収集
|
||||
const childIds = new Set<string>();
|
||||
|
||||
allMarkers.forEach((marker, id) => {
|
||||
const children = marker.children;
|
||||
if (Array.isArray(children)) {
|
||||
children.forEach(childId => {
|
||||
if (typeof childId === 'string') {
|
||||
if (!allMarkers.has(childId)) {
|
||||
console.warn(`[create-search-index] Warning: Child marker ID ${childId} referenced but not found`);
|
||||
} else {
|
||||
childIds.add(childId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`[create-search-index] Found ${childIds.size} child markers`);
|
||||
|
||||
// 3. ルートマーカーの特定(他の誰かの子でないマーカー)
|
||||
const rootMarkers: SearchIndexItem[] = [];
|
||||
|
||||
allMarkers.forEach((marker, id) => {
|
||||
if (!childIds.has(id)) {
|
||||
// このマーカーはルート(他の誰の子でもない)
|
||||
rootMarkers.push(marker);
|
||||
console.log(`[create-search-index] Added root marker to output: ${id} with label ${marker.label}`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`[create-search-index] Found ${rootMarkers.length} root markers`);
|
||||
|
||||
// 4. 子マーカーの参照を解決(IDから実際のオブジェクトに)
|
||||
function resolveChildrenReferences(marker: SearchIndexItem): SearchIndexItem {
|
||||
// マーカーのディープコピーを作成
|
||||
const resolvedMarker = { ...marker };
|
||||
|
||||
// 子リファレンスを解決
|
||||
if (Array.isArray(marker.children)) {
|
||||
const children: SearchIndexItem[] = [];
|
||||
|
||||
for (const childId of marker.children) {
|
||||
if (typeof childId === 'string') {
|
||||
const childMarker = allMarkers.get(childId);
|
||||
|
||||
if (childMarker) {
|
||||
// 子マーカーの子も再帰的に解決
|
||||
const resolvedChild = resolveChildrenReferences(childMarker);
|
||||
children.push(resolvedChild);
|
||||
console.log(`[create-search-index] Resolved child ${childId} for parent ${marker.id}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 子が存在する場合のみchildrenプロパティを設定
|
||||
if (children.length > 0) {
|
||||
resolvedMarker.children = children;
|
||||
} else {
|
||||
// 子がない場合はchildrenプロパティを削除
|
||||
delete resolvedMarker.children;
|
||||
}
|
||||
}
|
||||
|
||||
return resolvedMarker;
|
||||
}
|
||||
|
||||
// すべてのルートマーカーに対して子の参照を解決
|
||||
const resolvedRootMarkers = rootMarkers.map(marker => {
|
||||
return resolveChildrenReferences(marker);
|
||||
});
|
||||
|
||||
// 特殊なプロパティ変換用の関数
|
||||
function formatSpecialProperty(key: string, value: any): string {
|
||||
// 値がundefinedの場合は空文字列を返す
|
||||
if (value === undefined) {
|
||||
return '""';
|
||||
}
|
||||
|
||||
// childrenが配列の場合は特別に処理
|
||||
if (key === 'children' && Array.isArray(value)) {
|
||||
return customStringify(value);
|
||||
}
|
||||
|
||||
// 文字列でない場合はJSON5で文字列化
|
||||
if (typeof value !== 'string') {
|
||||
return JSON5.stringify(value);
|
||||
}
|
||||
|
||||
// i18n.ts 参照を含む場合
|
||||
if (value.includes('i18n.ts.')) {
|
||||
return value; // クォートなしで直接返す
|
||||
}
|
||||
|
||||
// keywords が配列リテラルの形式の場合
|
||||
if (key === 'keywords' && value.startsWith('[') && value.endsWith(']')) {
|
||||
return value; // クォートなしで直接返す
|
||||
}
|
||||
|
||||
// 上記以外は通常の JSON5 文字列として返す
|
||||
return JSON5.stringify(value);
|
||||
}
|
||||
|
||||
// オブジェクトをカスタム形式に変換する関数
|
||||
function customStringify(obj: any, depth = 0): string {
|
||||
const INDENT_STR = '\t';
|
||||
if (Array.isArray(obj)) {
|
||||
if (obj.length === 0) return '[]';
|
||||
const indent = INDENT_STR.repeat(depth);
|
||||
const childIndent = INDENT_STR.repeat(depth + 1);
|
||||
const items = obj.map(item => `${childIndent}${customStringify(item, depth + 1)}`).join(',\n');
|
||||
return `[\n${items},\n${indent}]`;
|
||||
}
|
||||
|
||||
if (obj === null || typeof obj !== 'object') {
|
||||
return JSON5.stringify(obj);
|
||||
}
|
||||
|
||||
const indent = INDENT_STR.repeat(depth);
|
||||
const childIndent = INDENT_STR.repeat(depth + 1);
|
||||
const entries = Object.entries(obj)
|
||||
.filter(([key, value]) => {
|
||||
// valueがundefinedの場合は出力しない
|
||||
if (value === undefined) return false;
|
||||
// childrenが空配列の場合は出力しない
|
||||
if (key === 'children' && Array.isArray(value) && value.length === 0) return false;
|
||||
return true;
|
||||
})
|
||||
.map(([key, value]) => {
|
||||
// childrenが配列の場合で要素がある場合のみ特別処理
|
||||
if (key === 'children' && Array.isArray(value) && value.length > 0) {
|
||||
return `${childIndent}${key}: ${customStringify(value, depth + 1)}`;
|
||||
}
|
||||
return `${childIndent}${key}: ${formatSpecialProperty(key, value)}`;
|
||||
});
|
||||
|
||||
if (entries.length === 0) return '{}';
|
||||
return `{\n${entries.join(',\n')},\n${indent}}`;
|
||||
}
|
||||
|
||||
// 最終出力用のデバッグ情報を生成
|
||||
let totalMarkers = resolvedRootMarkers.length;
|
||||
let totalChildren = 0;
|
||||
|
||||
function countNestedMarkers(markers: SearchIndexItem[]): void {
|
||||
for (const marker of markers) {
|
||||
if (marker.children && Array.isArray(marker.children)) {
|
||||
totalChildren += marker.children.length;
|
||||
totalMarkers += marker.children.length;
|
||||
countNestedMarkers(marker.children as SearchIndexItem[]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
countNestedMarkers(resolvedRootMarkers);
|
||||
console.log(`[create-search-index] Total markers in tree: ${totalMarkers} (${resolvedRootMarkers.length} roots + ${totalChildren} nested children)`);
|
||||
|
||||
// 結果をTS形式で出力
|
||||
const tsOutput = `
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
@ -57,93 +245,167 @@ function outputAnalysisResultAsTS(outputPath: string, analysisResults: AnalysisR
|
|||
// This file was automatically generated by create-search-index.
|
||||
// Do not edit this file.
|
||||
|
||||
/* eslint-disable @stylistic/comma-spacing */
|
||||
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
export const ${varName} = ${modifyBindPropsInString(jsonString)} as const;
|
||||
export type SearchIndexItem = {
|
||||
id: string;
|
||||
path?: string;
|
||||
label: string;
|
||||
keywords: string | string[];
|
||||
icon?: string;
|
||||
children?: (SearchIndexItem[] | string);
|
||||
};
|
||||
|
||||
export type AnalysisResults = typeof ${varName};
|
||||
export type ComponentUsageInfo = AnalysisResults[number]['usage'][number];
|
||||
export const searchIndexes:SearchIndexItem[] = ${customStringify(resolvedRootMarkers)} as const;
|
||||
|
||||
export type SearchIndex = typeof searchIndexes;
|
||||
|
||||
/* eslint-enable @stylistic/comma-spacing */
|
||||
`;
|
||||
|
||||
try {
|
||||
fs.writeFileSync(outputPath, tsOutput, 'utf-8');
|
||||
} catch (error) {
|
||||
console.error('[create-search-index]: error: ', error);
|
||||
}
|
||||
try {
|
||||
fs.writeFileSync(outputPath, tsOutput, 'utf-8');
|
||||
console.log(`[create-search-index] Successfully wrote search index to ${outputPath} with ${resolvedRootMarkers.length} root entries and ${totalChildren} nested children`);
|
||||
} catch (error) {
|
||||
console.error('[create-search-index]: error: ', error);
|
||||
}
|
||||
}
|
||||
|
||||
function extractUsageInfoFromTemplateAst(
|
||||
templateAst: any,
|
||||
code: string,
|
||||
): ComponentUsageInfo[] {
|
||||
const usageInfoList: ComponentUsageInfo[] = [];
|
||||
templateAst: any,
|
||||
code: string,
|
||||
): SearchIndexItem[] {
|
||||
// すべてのマーカー情報を保持するために、結果をトップレベルマーカー+すべての子マーカーを含む配列に変更
|
||||
const allMarkers: SearchIndexItem[] = [];
|
||||
// マーカーIDからオブジェクトへのマップ
|
||||
const markerMap = new Map<string, SearchIndexItem>();
|
||||
// 子マーカーIDを集約するためのセット
|
||||
const childrenIds = new Set<string>();
|
||||
|
||||
if (!templateAst) {
|
||||
return usageInfoList;
|
||||
}
|
||||
if (!templateAst) {
|
||||
return allMarkers;
|
||||
}
|
||||
|
||||
function traverse(node: any) {
|
||||
if (node.type === 1 && node.tag === 'SearchMarker') {
|
||||
// 元々の props を staticProps に全て展開する
|
||||
const staticProps: Record<string, string> = {};
|
||||
if (node.props && Array.isArray(node.props)) {
|
||||
node.props.forEach((prop: any) => {
|
||||
if (prop.type === 6 && prop.name) {
|
||||
staticProps[prop.name] = prop.value?.content || '';
|
||||
}
|
||||
});
|
||||
}
|
||||
// markerId は __markerId または既存の props から取得
|
||||
const markerId = node.__markerId || staticProps['markerId'];
|
||||
if (markerId) {
|
||||
staticProps['markerId'] = markerId;
|
||||
}
|
||||
// デバッグ情報
|
||||
console.log('[create-search-index] Started extracting markers from AST');
|
||||
|
||||
const bindProps: Record<string, any> = {};
|
||||
// マーカーの基本情報を収集
|
||||
function collectMarkers(node: any, parentId: string | null = null) {
|
||||
// SearchMarkerコンポーネントの検出
|
||||
if (node.type === 1 && node.tag === 'SearchMarker') {
|
||||
// マーカーID生成 (markerId属性またはDOM内に記録されているものを使用)
|
||||
const markerIdProp = node.props?.find((p: any) => p.name === 'markerId');
|
||||
const markerId = markerIdProp?.value?.content ||
|
||||
node.__markerId ||
|
||||
`marker-${Math.random().toString(36).substring(2, 10)}`;
|
||||
|
||||
// 元々の props から bindProps を抽出
|
||||
if (node.props && Array.isArray(node.props)) {
|
||||
node.props.forEach((prop: any) => {
|
||||
if (prop.type === 7 && prop.name === 'bind' && prop.arg.content) {
|
||||
bindProps[prop.arg.content] = prop.exp?.content || '';
|
||||
}
|
||||
});
|
||||
}
|
||||
console.log(`[create-search-index] Found SearchMarker with ID: ${markerId}`);
|
||||
|
||||
// __children がある場合、bindProps に children を追加
|
||||
if (node.__children) {
|
||||
bindProps['children'] = node.__children;
|
||||
} else if (node.props && Array.isArray(node.props)) {
|
||||
const childrenProp = node.props.find(
|
||||
(prop: any) =>
|
||||
prop.type === 7 &&
|
||||
prop.name === 'bind' &&
|
||||
prop.arg?.content === 'children'
|
||||
);
|
||||
if (childrenProp && childrenProp.exp) {
|
||||
try {
|
||||
bindProps['children'] = JSON5.parse(
|
||||
code.slice(childrenProp.exp.loc.start.offset, childrenProp.exp.loc.end.offset).replace(/'/g, '"')
|
||||
);
|
||||
} catch (e) {
|
||||
console.error('Error parsing :children attribute', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
// マーカー基本情報
|
||||
const markerInfo: SearchIndexItem = {
|
||||
id: markerId,
|
||||
children: [],
|
||||
label: '',
|
||||
keywords: [],
|
||||
};
|
||||
|
||||
usageInfoList.push({
|
||||
staticProps,
|
||||
bindProps,
|
||||
});
|
||||
}
|
||||
// 静的プロパティを抽出
|
||||
if (node.props && Array.isArray(node.props)) {
|
||||
node.props.forEach((prop: any) => {
|
||||
if (prop.type === 6 && prop.name && prop.name !== 'markerId') {
|
||||
// 静的プロパティの抽出
|
||||
if (prop.name === 'path') markerInfo.path = prop.value?.content || '';
|
||||
else if (prop.name === 'icon') markerInfo.icon = prop.value?.content || '';
|
||||
else if (prop.name === 'label') markerInfo.label = prop.value?.content || '';
|
||||
|
||||
if (node.children && Array.isArray(node.children)) {
|
||||
node.children.forEach((child: any) => traverse(child));
|
||||
}
|
||||
}
|
||||
console.log(`[create-search-index] Static prop ${prop.name}:`, prop.value?.content);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
traverse(templateAst);
|
||||
return usageInfoList;
|
||||
// バインドプロパティを抽出
|
||||
if (node.props && Array.isArray(node.props)) {
|
||||
node.props.forEach((prop: any) => {
|
||||
if (prop.type === 7 && prop.name === 'bind' && prop.arg?.content) {
|
||||
const propName = prop.arg.content;
|
||||
const propValue = prop.exp?.content || '';
|
||||
|
||||
console.log(`[create-search-index] Bind prop ${propName}:`, propValue);
|
||||
|
||||
if (propName === 'label') {
|
||||
markerInfo.label = propValue;
|
||||
} else if (propName === 'path') {
|
||||
markerInfo.path = propValue;
|
||||
} else if (propName === 'icon') {
|
||||
markerInfo.icon = propValue;
|
||||
} else if (propName === 'keywords') {
|
||||
markerInfo.keywords = propValue || '[]';
|
||||
} else if (propName === 'children') {
|
||||
markerInfo.children = propValue || '[]';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ラベルがない場合はデフォルト値を設定
|
||||
if (!markerInfo.label) {
|
||||
markerInfo.label = 'Unnamed marker';
|
||||
}
|
||||
|
||||
// キーワードがない場合はデフォルト値を設定
|
||||
if (!markerInfo.keywords || (Array.isArray(markerInfo.keywords) && markerInfo.keywords.length === 0)) {
|
||||
markerInfo.keywords = '[]';
|
||||
}
|
||||
|
||||
// マーカーをマップに保存し、すべてのマーカーリストにも追加
|
||||
markerMap.set(markerId, markerInfo);
|
||||
allMarkers.push(markerInfo); // すべてのマーカーを保持
|
||||
|
||||
// 親子関係を記録
|
||||
if (parentId) {
|
||||
const parent = markerMap.get(parentId);
|
||||
if (parent) {
|
||||
if (!parent.children) parent.children = [];
|
||||
if (Array.isArray(parent.children)) {
|
||||
parent.children.push(markerId);
|
||||
} else {
|
||||
parent.children = [markerId];
|
||||
}
|
||||
childrenIds.add(markerId);
|
||||
console.log(`[create-search-index] Added ${markerId} as child of ${parentId}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 子ノードを処理(親は現在のノード)
|
||||
if (node.children && Array.isArray(node.children)) {
|
||||
node.children.forEach((child: any) => {
|
||||
collectMarkers(child, markerId);
|
||||
});
|
||||
}
|
||||
|
||||
return markerId;
|
||||
}
|
||||
|
||||
// SearchMarkerでない場合は、子ノードを同じ親コンテキストで処理
|
||||
if (node.children && Array.isArray(node.children)) {
|
||||
node.children.forEach((child: any) => {
|
||||
collectMarkers(child, parentId);
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// AST解析を開始
|
||||
collectMarkers(templateAst);
|
||||
|
||||
// デバッグ情報
|
||||
console.log(`[create-search-index] Found ${markerMap.size} markers, ${childrenIds.size} children`);
|
||||
|
||||
// 重要: すべてのマーカー情報を返す
|
||||
return allMarkers;
|
||||
}
|
||||
|
||||
export async function analyzeVueProps(options: {
|
||||
|
@ -151,42 +413,64 @@ export async function analyzeVueProps(options: {
|
|||
exportFilePath: string,
|
||||
transformedCodeCache: Record<string, string>
|
||||
}): Promise<void> {
|
||||
const analysisResults: AnalysisResult[] = [];
|
||||
const allMarkers: SearchIndexItem[] = [];
|
||||
|
||||
// 対象ファイルパスを glob で展開
|
||||
// 対象ファイルパスを glob で展開
|
||||
const filePaths = options.targetFilePaths.reduce<string[]>((acc, filePathPattern) => {
|
||||
const matchedFiles = glob.sync(filePathPattern);
|
||||
return [...acc, ...matchedFiles];
|
||||
}, []);
|
||||
|
||||
console.log(`[create-search-index] Found ${filePaths.length} matching files to analyze`);
|
||||
|
||||
for (const filePath of filePaths) {
|
||||
const code = options.transformedCodeCache[path.resolve(filePath)]; // options 経由でキャッシュ参照
|
||||
const id = path.resolve(filePath); // 絶対パスに変換
|
||||
const code = options.transformedCodeCache[id]; // options 経由でキャッシュ参照
|
||||
if (!code) { // キャッシュミスの場合
|
||||
console.error(`[create-search-index] Error: No cached code found for: ${filePath}.`); // エラーログ
|
||||
continue;
|
||||
}
|
||||
const { descriptor, errors } = vueSfcParse(code, {
|
||||
filename: filePath,
|
||||
});
|
||||
|
||||
if (errors.length) {
|
||||
console.error(`[create-search-index] Compile Error: ${filePath}`, errors);
|
||||
continue; // エラーが発生したファイルはスキップ
|
||||
// ファイルを直接読み込む代替策を実行
|
||||
try {
|
||||
const directCode = fs.readFileSync(filePath, 'utf-8');
|
||||
options.transformedCodeCache[id] = directCode;
|
||||
console.log(`[create-search-index] Loaded file directly instead: ${filePath}`);
|
||||
} catch (err) {
|
||||
console.error(`[create-search-index] Failed to load file directly: ${filePath}`, err);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const usageInfo = extractUsageInfoFromTemplateAst(descriptor.template?.ast, code);
|
||||
if (!usageInfo) continue;
|
||||
|
||||
if (usageInfo.length > 0) {
|
||||
analysisResults.push({
|
||||
filePath: filePath,
|
||||
usage: usageInfo,
|
||||
try {
|
||||
const { descriptor, errors } = vueSfcParse(options.transformedCodeCache[id], {
|
||||
filename: filePath,
|
||||
});
|
||||
|
||||
if (errors.length) {
|
||||
console.error(`[create-search-index] Compile Error: ${filePath}`, errors);
|
||||
continue; // エラーが発生したファイルはスキップ
|
||||
}
|
||||
|
||||
const fileMarkers = extractUsageInfoFromTemplateAst(descriptor.template?.ast, options.transformedCodeCache[id]);
|
||||
|
||||
if (fileMarkers && fileMarkers.length > 0) {
|
||||
allMarkers.push(...fileMarkers); // すべてのマーカーを収集
|
||||
console.log(`[create-search-index] Successfully extracted ${fileMarkers.length} markers from ${filePath}`);
|
||||
} else {
|
||||
console.log(`[create-search-index] No markers found in ${filePath}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[create-search-index] Error analyzing file ${filePath}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
outputAnalysisResultAsTS(options.exportFilePath, analysisResults); // outputAnalysisResultAsTS を呼び出す
|
||||
// 収集したすべてのマーカー情報を使用
|
||||
const analysisResult: AnalysisResult[] = [
|
||||
{
|
||||
filePath: "combined-markers", // すべてのファイルのマーカーを1つのエントリとして扱う
|
||||
usage: allMarkers,
|
||||
}
|
||||
];
|
||||
|
||||
outputAnalysisResultAsTS(options.exportFilePath, analysisResult); // すべてのマーカー情報を渡す
|
||||
}
|
||||
|
||||
interface MarkerRelation {
|
||||
|
@ -333,7 +617,7 @@ async function processVueFile(
|
|||
const newIds = childIds.filter(id => !childrenArray.includes(id));
|
||||
if (newIds.length > 0) {
|
||||
childrenArray = [...childrenArray, ...newIds];
|
||||
const updatedChildrenArrayStr = JSON.stringify(childrenArray).replace(/"/g, "'");
|
||||
const updatedChildrenArrayStr = JSON5.stringify(childrenArray).replace(/"/g, "'");
|
||||
s.overwrite(childrenStart, childrenEnd + 1, updatedChildrenArrayStr);
|
||||
console.log(`[create-search-index] Added ${newIds.length} child markerIds to existing :children in ${id}`);
|
||||
}
|
||||
|
@ -366,7 +650,7 @@ async function processVueFile(
|
|||
if (attrValueStart > -1 && attrValueEnd > -1) {
|
||||
const absoluteStart = parentNodeStart + attrValueStart;
|
||||
const absoluteEnd = parentNodeStart + attrValueEnd;
|
||||
const updatedArrayStr = JSON.stringify(childrenArray).replace(/"/g, "'");
|
||||
const updatedArrayStr = JSON5.stringify(childrenArray).replace(/"/g, "'");
|
||||
s.overwrite(absoluteStart, absoluteEnd, updatedArrayStr);
|
||||
console.log(`[create-search-index] Updated existing :children in tag text for ${id}`);
|
||||
}
|
||||
|
@ -377,7 +661,7 @@ async function processVueFile(
|
|||
}
|
||||
} else {
|
||||
// :children 属性がまだない場合、新規作成
|
||||
s.appendRight(endOfParentStartTag, ` :children="${JSON.stringify(childIds).replace(/"/g, "'")}"`);
|
||||
s.appendRight(endOfParentStartTag, ` :children="${JSON5.stringify(childIds).replace(/"/g, "'")}"`);
|
||||
console.log(`[create-search-index] Created new :children attribute with ${childIds.length} markerIds in ${id}`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,70 +7,506 @@
|
|||
// This file was automatically generated by create-search-index.
|
||||
// Do not edit this file.
|
||||
|
||||
/* eslint-disable @stylistic/comma-spacing */
|
||||
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
export const searchIndexes = [
|
||||
export type SearchIndexItem = {
|
||||
id: string;
|
||||
path?: string;
|
||||
label: string;
|
||||
keywords: string | string[];
|
||||
icon?: string;
|
||||
children?: (SearchIndexItem[] | string);
|
||||
};
|
||||
|
||||
export const searchIndexes:SearchIndexItem[] = [
|
||||
{
|
||||
filePath: 'src/pages/settings/profile.vue',
|
||||
usage: [
|
||||
id: 'EfN1JU93S',
|
||||
children: [
|
||||
{
|
||||
staticProps: {
|
||||
markerId: '4mWPWOqkN',
|
||||
},
|
||||
bindProps: {},
|
||||
id: 'uHreVVQIS',
|
||||
label: i18n.ts._profile.name,
|
||||
keywords: ['name'],
|
||||
},
|
||||
{
|
||||
staticProps: {
|
||||
markerId: 'gw1zundQ3',
|
||||
},
|
||||
bindProps: {},
|
||||
id: 'gAvOWkPnm',
|
||||
label: i18n.ts._profile.description,
|
||||
keywords: ['description','bio'],
|
||||
},
|
||||
{
|
||||
id: 'jDQ9ug9JI',
|
||||
label: i18n.ts.location,
|
||||
keywords: ['location','locale'],
|
||||
},
|
||||
{
|
||||
id: '4IINpCs7w',
|
||||
label: i18n.ts.birthday,
|
||||
keywords: ['birthday','birthdate','age'],
|
||||
},
|
||||
{
|
||||
id: 'nrKSnXwYN',
|
||||
label: i18n.ts.language,
|
||||
keywords: ['language','locale'],
|
||||
},
|
||||
{
|
||||
id: 'xpFKUEupm',
|
||||
label: i18n.ts._profile.metadataEdit,
|
||||
keywords: ['metadata'],
|
||||
},
|
||||
{
|
||||
id: 'EAdtWppOM',
|
||||
label: i18n.ts._profile.followedMessage,
|
||||
keywords: ['follow', 'message', i18n.ts._profile.followedMessageDescription],
|
||||
},
|
||||
{
|
||||
id: 'agaHOwYSm',
|
||||
label: i18n.ts.reactionAcceptance,
|
||||
keywords: ['reaction'],
|
||||
},
|
||||
{
|
||||
id: 'E3EMH8zsB',
|
||||
children: [
|
||||
{
|
||||
id: 'xYknyiCsI',
|
||||
label: i18n.ts.flagAsCat,
|
||||
keywords: ['cat', i18n.ts.flagAsCatDescription],
|
||||
},
|
||||
{
|
||||
id: '2yIzPU9hg',
|
||||
label: i18n.ts.flagAsBot,
|
||||
keywords: ['bot', i18n.ts.flagAsBotDescription],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.advancedSettings,
|
||||
keywords: [],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.profile,
|
||||
keywords: ['profile'],
|
||||
path: '/settings/profile',
|
||||
icon: 'ti ti-user',
|
||||
},
|
||||
{
|
||||
filePath: 'src/pages/settings/privacy.vue',
|
||||
usage: [
|
||||
id: 'zUK4HIXfh',
|
||||
children: [
|
||||
{
|
||||
staticProps: {
|
||||
icon: 'ti ti-lock-open',
|
||||
markerId: 'ssTCH2oBL',
|
||||
},
|
||||
bindProps: {
|
||||
locationLabel: [i18n.ts.privacy, i18n.ts.makeFollowManuallyApprove],
|
||||
keywords: ['follow', 'lock', i18n.ts.lockedAccountInfo],
|
||||
},
|
||||
id: '46jUHufEx',
|
||||
label: i18n.ts.makeFollowManuallyApprove,
|
||||
keywords: ['follow', 'lock', i18n.ts.lockedAccountInfo],
|
||||
},
|
||||
{
|
||||
id: 'yGVh4afrC',
|
||||
label: i18n.ts.autoAcceptFollowed,
|
||||
keywords: ['follow','auto','accept'],
|
||||
},
|
||||
{
|
||||
id: 'vomfIAjG2',
|
||||
label: i18n.ts.makeReactionsPublic,
|
||||
keywords: ['reaction', 'public', i18n.ts.makeReactionsPublicDescription],
|
||||
},
|
||||
{
|
||||
id: 'BakhCOlGl',
|
||||
label: i18n.ts.followingVisibility,
|
||||
keywords: ['following','visibility'],
|
||||
},
|
||||
{
|
||||
id: 'nALctPZes',
|
||||
label: i18n.ts.followersVisibility,
|
||||
keywords: ['follower','visibility'],
|
||||
},
|
||||
{
|
||||
id: 'g39hgvANq',
|
||||
label: i18n.ts.hideOnlineStatus,
|
||||
keywords: ['online', 'status', i18n.ts.hideOnlineStatusDescription],
|
||||
},
|
||||
{
|
||||
id: 'jFd8aByjS',
|
||||
label: i18n.ts.noCrawle,
|
||||
keywords: ['crawle', 'index', 'search', i18n.ts.noCrawleDescription],
|
||||
},
|
||||
{
|
||||
id: 'qlcVI7TvT',
|
||||
label: i18n.ts.preventAiLearning,
|
||||
keywords: ['crawle', 'ai', i18n.ts.preventAiLearningDescription],
|
||||
},
|
||||
{
|
||||
id: 'nGm8gxxph',
|
||||
label: i18n.ts.makeExplorable,
|
||||
keywords: ['explore', i18n.ts.makeExplorableDescription],
|
||||
},
|
||||
{
|
||||
id: 'o8bJdIWBc',
|
||||
children: [
|
||||
{
|
||||
id: '5V4EcXjrc',
|
||||
label: i18n.ts._accountSettings.requireSigninToViewContents,
|
||||
keywords: ['login', 'signin', i18n.ts._accountSettings.requireSigninToViewContentsDescription1, i18n.ts._accountSettings.requireSigninToViewContentsDescription2, i18n.ts._accountSettings.requireSigninToViewContentsDescription3],
|
||||
},
|
||||
{
|
||||
id: 'huYLq7zx9',
|
||||
label: i18n.ts._accountSettings.makeNotesFollowersOnlyBefore,
|
||||
keywords: ['follower', i18n.ts._accountSettings.makeNotesFollowersOnlyBeforeDescription],
|
||||
},
|
||||
{
|
||||
id: '4HRzEG7td',
|
||||
label: i18n.ts._accountSettings.makeNotesHiddenBefore,
|
||||
keywords: ['hidden', i18n.ts._accountSettings.makeNotesHiddenBeforeDescription],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.lockdown,
|
||||
keywords: ['lockdown'],
|
||||
},
|
||||
{
|
||||
id: '6AAT3LUIL',
|
||||
label: i18n.ts.rememberNoteVisibility,
|
||||
keywords: ['remember','keep','note','visibility'],
|
||||
},
|
||||
{
|
||||
id: '8d0FCNIgm',
|
||||
label: i18n.ts.defaultNoteVisibility,
|
||||
keywords: ['default','note','visibility'],
|
||||
},
|
||||
{
|
||||
id: 'o3hisYwlV',
|
||||
label: i18n.ts.keepCw,
|
||||
keywords: ['remember','keep','note','cw'],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.privacy,
|
||||
keywords: ['privacy'],
|
||||
path: '/settings/privacy',
|
||||
icon: 'ti ti-lock-open',
|
||||
},
|
||||
{
|
||||
filePath: 'src/pages/settings/mute-block.vue',
|
||||
usage: [
|
||||
id: 'rbnN7S4RC',
|
||||
children: [
|
||||
{
|
||||
staticProps: {
|
||||
icon: 'ti ti-ban',
|
||||
markerId: 'CVhDOYgMv',
|
||||
},
|
||||
bindProps: {
|
||||
locationLabel: [i18n.ts.muteAndBlock],
|
||||
keywords: ['mute', i18n.ts.wordMute],
|
||||
children: [
|
||||
'kcHPXo5ZV',
|
||||
],
|
||||
},
|
||||
id: 'wAnn0Z9zp',
|
||||
children: [
|
||||
{
|
||||
id: '5tIsotvIk',
|
||||
label: i18n.ts.showMutedWord,
|
||||
keywords: ['show'],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.wordMute,
|
||||
keywords: ['note','word','soft','mute','hide'],
|
||||
},
|
||||
{
|
||||
staticProps: {
|
||||
icon: 'ti ti-ban',
|
||||
markerId: 'kcHPXo5ZV',
|
||||
},
|
||||
bindProps: {
|
||||
locationLabel: [i18n.ts.muteAndBlock, i18n.ts.wordMute],
|
||||
keywords: ['showMutedWord', i18n.ts.showMutedWord],
|
||||
},
|
||||
id: 'evlmsuKtu',
|
||||
label: i18n.ts.hardWordMute,
|
||||
keywords: ['note','word','hard','mute','hide'],
|
||||
},
|
||||
{
|
||||
id: 'zLHWO9mBm',
|
||||
label: i18n.ts.instanceMute,
|
||||
keywords: ['note','server','instance','host','federation','mute','hide'],
|
||||
},
|
||||
{
|
||||
id: 's3IxYcSKj',
|
||||
label: `${i18n.ts.mutedUsers} (${ i18n.ts.renote })`,
|
||||
keywords: ['renote','mute','hide','user'],
|
||||
},
|
||||
{
|
||||
id: 'iBnGIbcys',
|
||||
label: i18n.ts.mutedUsers,
|
||||
keywords: ['note','mute','hide','user'],
|
||||
},
|
||||
{
|
||||
id: 'g6aGcN8X5',
|
||||
label: i18n.ts.blockedUsers,
|
||||
keywords: ['block','user'],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.muteAndBlock,
|
||||
keywords: ['mute','block'],
|
||||
path: '/settings/mute-block',
|
||||
icon: 'ti ti-ban',
|
||||
},
|
||||
{
|
||||
id: 'qZGmAjsxj',
|
||||
children: [
|
||||
{
|
||||
id: 'ln8mPGca4',
|
||||
label: i18n.ts.uiLanguage,
|
||||
keywords: ['language'],
|
||||
},
|
||||
{
|
||||
id: '3zpvHzV5g',
|
||||
label: i18n.ts.overridedDeviceKind,
|
||||
keywords: ['device','type','kind','smartphone','tablet','desktop'],
|
||||
},
|
||||
{
|
||||
id: '1QvSeZtNe',
|
||||
label: i18n.ts.showFixedPostForm,
|
||||
keywords: ['post','form','timeline'],
|
||||
},
|
||||
{
|
||||
id: 'oVjAZ97m1',
|
||||
label: i18n.ts.showFixedPostFormInChannel,
|
||||
keywords: ['post','form','timeline','channel'],
|
||||
},
|
||||
{
|
||||
id: '6sIzeMWoB',
|
||||
label: i18n.ts.pinnedList,
|
||||
keywords: ['pinned','list'],
|
||||
},
|
||||
{
|
||||
id: '6HbFzMsfZ',
|
||||
children: [
|
||||
{
|
||||
id: 'pQO0HwBg5',
|
||||
label: i18n.ts.collapseRenotes,
|
||||
keywords: ['renote', i18n.ts.collapseRenotesDescription],
|
||||
},
|
||||
{
|
||||
id: 'r8RoaDGyB',
|
||||
label: i18n.ts.showNoteActionsOnlyHover,
|
||||
keywords: ['hover','show','footer','action'],
|
||||
},
|
||||
{
|
||||
id: 'dhe5ltCVy',
|
||||
label: i18n.ts.showClipButtonInNoteFooter,
|
||||
keywords: ['footer','action','clip','show'],
|
||||
},
|
||||
{
|
||||
id: 'lJijzarvh',
|
||||
label: i18n.ts.enableAdvancedMfm,
|
||||
keywords: ['mfm','enable','show','advanced'],
|
||||
},
|
||||
{
|
||||
id: 'plFY7Zr0Y',
|
||||
label: i18n.ts.enableAnimatedMfm,
|
||||
keywords: ['mfm','enable','show','animated'],
|
||||
},
|
||||
{
|
||||
id: 'uCWeJdWGo',
|
||||
label: i18n.ts.enableQuickAddMfmFunction,
|
||||
keywords: ['mfm','enable','show','advanced','picker','form','function','fn'],
|
||||
},
|
||||
{
|
||||
id: 'jojGm1s0T',
|
||||
label: i18n.ts.showReactionsCount,
|
||||
keywords: ['reaction','count','show'],
|
||||
},
|
||||
{
|
||||
id: 'gob3LGyDO',
|
||||
label: i18n.ts.showGapBetweenNotesInTimeline,
|
||||
keywords: ['note','timeline','gap'],
|
||||
},
|
||||
{
|
||||
id: 'v5IaTjjUK',
|
||||
label: i18n.ts.loadRawImages,
|
||||
keywords: ['image','photo','picture','media','thumbnail','quality','raw','attachment'],
|
||||
},
|
||||
{
|
||||
id: '9rlymuz2e',
|
||||
label: i18n.ts.reactionsDisplaySize,
|
||||
keywords: ['reaction','size','scale','display'],
|
||||
},
|
||||
{
|
||||
id: 'a6JkO6iHN',
|
||||
label: i18n.ts.limitWidthOfReaction,
|
||||
keywords: ['reaction','size','scale','display','width','limit'],
|
||||
},
|
||||
{
|
||||
id: 'B2C8Chpn3',
|
||||
label: i18n.ts.instanceTicker,
|
||||
keywords: ['ticker','information','label','instance','server','host','federation'],
|
||||
},
|
||||
{
|
||||
id: 'lXGQcJA0m',
|
||||
label: i18n.ts.displayOfSensitiveMedia,
|
||||
keywords: ['attachment','image','photo','picture','media','thumbnail','nsfw','sensitive','display','show','hide','visibility'],
|
||||
},
|
||||
{
|
||||
id: 'fI9unfBG9',
|
||||
label: i18n.ts.mediaListWithOneImageAppearance,
|
||||
keywords: ['attachment','image','photo','picture','media','thumbnail','list','size','height'],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.displayOfNote,
|
||||
keywords: ['note','display'],
|
||||
},
|
||||
{
|
||||
id: 'ksPnvPfsq',
|
||||
children: [
|
||||
{
|
||||
id: 'rlKh8qQSy',
|
||||
label: i18n.ts.useGroupedNotifications,
|
||||
keywords: ['group'],
|
||||
},
|
||||
{
|
||||
id: 'mZoLcRxn9',
|
||||
label: i18n.ts.position,
|
||||
keywords: ['position'],
|
||||
},
|
||||
{
|
||||
id: 'mu8Fghr9P',
|
||||
label: i18n.ts.stackAxis,
|
||||
keywords: ['stack','axis','direction'],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.notificationDisplay,
|
||||
keywords: ['notification','display'],
|
||||
},
|
||||
{
|
||||
id: 'sUAe1tYeV',
|
||||
children: [
|
||||
{
|
||||
id: 'pXk2Bq5c7',
|
||||
label: i18n.ts.reduceUiAnimation,
|
||||
keywords: ['animation','motion','reduce'],
|
||||
},
|
||||
{
|
||||
id: 'l92lxxESG',
|
||||
label: i18n.ts.useBlurEffect,
|
||||
keywords: ['blur'],
|
||||
},
|
||||
{
|
||||
id: '5fw6zkK39',
|
||||
label: i18n.ts.useBlurEffectForModal,
|
||||
keywords: ['blur','modal'],
|
||||
},
|
||||
{
|
||||
id: 'm3kpvUE3f',
|
||||
label: i18n.ts.disableShowingAnimatedImages,
|
||||
keywords: ['disable','animation','image','photo','picture','media','thumbnail','gif'],
|
||||
},
|
||||
{
|
||||
id: 'EEHGMwhkC',
|
||||
label: i18n.ts.highlightSensitiveMedia,
|
||||
keywords: ['highlight','sensitive','nsfw','image','photo','picture','media','thumbnail'],
|
||||
},
|
||||
{
|
||||
id: 'hBnm0B8aI',
|
||||
label: i18n.ts.squareAvatars,
|
||||
keywords: ['avatar','icon','square'],
|
||||
},
|
||||
{
|
||||
id: 'm9Q5z11L8',
|
||||
label: i18n.ts.showAvatarDecorations,
|
||||
keywords: ['avatar','icon','decoration','show'],
|
||||
},
|
||||
{
|
||||
id: 'pHvwcwF4c',
|
||||
label: i18n.ts.useSystemFont,
|
||||
keywords: ['font','system','native'],
|
||||
},
|
||||
{
|
||||
id: '3lcbrBHYZ',
|
||||
label: i18n.ts.forceShowAds,
|
||||
keywords: ['ad','show'],
|
||||
},
|
||||
{
|
||||
id: '523Bx87JU',
|
||||
label: i18n.ts.seasonalScreenEffect,
|
||||
keywords: ['effect','show'],
|
||||
},
|
||||
{
|
||||
id: '7dFSaWz4u',
|
||||
label: i18n.ts.useNativeUIForVideoAudioPlayer,
|
||||
keywords: ['native','system','video','audio','player','media'],
|
||||
},
|
||||
{
|
||||
id: 'q3Vv5zIZu',
|
||||
label: i18n.ts.menuStyle,
|
||||
keywords: ['menu','style','popup','drawer'],
|
||||
},
|
||||
{
|
||||
id: 'd1Gno6GaT',
|
||||
label: i18n.ts.emojiStyle,
|
||||
keywords: ['emoji','style','native','system','fluent','twemoji'],
|
||||
},
|
||||
{
|
||||
id: '3sV67CRuN',
|
||||
label: i18n.ts.fontSize,
|
||||
keywords: ['font','size'],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.appearance,
|
||||
keywords: ['appearance'],
|
||||
},
|
||||
{
|
||||
id: 'AOASYDlhv',
|
||||
children: [
|
||||
{
|
||||
id: 'rwvOv068t',
|
||||
label: i18n.ts.openImageInNewTab,
|
||||
keywords: ['image','photo','picture','media','thumbnail','new','tab'],
|
||||
},
|
||||
{
|
||||
id: '1XB7XWwbI',
|
||||
label: i18n.ts.useReactionPickerForContextMenu,
|
||||
keywords: ['reaction','picker','contextmenu','open'],
|
||||
},
|
||||
{
|
||||
id: '4fjitJYAl',
|
||||
label: i18n.ts.enableInfiniteScroll,
|
||||
keywords: ['load','auto','more'],
|
||||
},
|
||||
{
|
||||
id: 'f2Nk4GdTa',
|
||||
label: i18n.ts.keepScreenOn,
|
||||
keywords: ['keep','screen','display','on'],
|
||||
},
|
||||
{
|
||||
id: '3D54jQsGn',
|
||||
label: i18n.ts.disableStreamingTimeline,
|
||||
keywords: ['disable','streaming','timeline'],
|
||||
},
|
||||
{
|
||||
id: '6MKp7i7iH',
|
||||
label: i18n.ts.enableHorizontalSwipe,
|
||||
keywords: ['swipe','horizontal','tab'],
|
||||
},
|
||||
{
|
||||
id: 'eSvGS9DsY',
|
||||
label: i18n.ts.alwaysConfirmFollow,
|
||||
keywords: ['follow','confirm','always'],
|
||||
},
|
||||
{
|
||||
id: 'kGYY8LCdK',
|
||||
label: i18n.ts.confirmWhenRevealingSensitiveMedia,
|
||||
keywords: ['sensitive','nsfw','media','image','photo','picture','attachment','confirm'],
|
||||
},
|
||||
{
|
||||
id: 'fdOu3BDKL',
|
||||
label: i18n.ts.confirmOnReact,
|
||||
keywords: ['reaction','confirm'],
|
||||
},
|
||||
{
|
||||
id: 'isbDLeTjm',
|
||||
label: i18n.ts.whenServerDisconnected,
|
||||
keywords: ['server','disconnect','reconnect','reload','streaming'],
|
||||
},
|
||||
{
|
||||
id: 'F5werzQkF',
|
||||
label: i18n.ts._contextMenu.title,
|
||||
keywords: ['contextmenu','system','native'],
|
||||
},
|
||||
{
|
||||
id: 'CPNGOZAoV',
|
||||
label: i18n.ts.numberOfPageCache,
|
||||
keywords: ['cache','page'],
|
||||
},
|
||||
{
|
||||
id: '5XHiLyaol',
|
||||
label: i18n.ts.dataSaver,
|
||||
keywords: ['datasaver'],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.behavior,
|
||||
keywords: ['behavior'],
|
||||
},
|
||||
],
|
||||
label: i18n.ts.general,
|
||||
keywords: ['general'],
|
||||
icon: 'ti ti-adjustments',
|
||||
},
|
||||
] as const;
|
||||
|
||||
export type AnalysisResults = typeof searchIndexes;
|
||||
export type ComponentUsageInfo = AnalysisResults[number]['usage'][number];
|
||||
export type SearchIndex = typeof searchIndexes;
|
||||
|
||||
/* eslint-enable @stylistic/comma-spacing */
|
||||
|
|
Loading…
Reference in New Issue