マーカーの形を成形

This commit is contained in:
tai-cha 2025-03-02 04:37:00 +00:00
parent f8282e8d1f
commit c34087b81a
2 changed files with 885 additions and 165 deletions

View File

@ -8,46 +8,234 @@ 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 のクォートを除去
// 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}`);
}
).replaceAll("\\'", "'");
return `bindProps: {${modifiedBlock}}`; //  置換後の block で bindProps: { ... } を再構成
}
);
return modifiedString;
}
// 子要素の処理(文字列から配列へ変換)
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 = [];
}
}
// 子マーカーの内部構造を適切に更新
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
@ -57,16 +245,29 @@ 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');
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);
}
@ -75,75 +276,136 @@ export type ComponentUsageInfo = AnalysisResults[number]['usage'][number];
function extractUsageInfoFromTemplateAst(
templateAst: any,
code: string,
): ComponentUsageInfo[] {
const usageInfoList: ComponentUsageInfo[] = [];
): SearchIndexItem[] {
// すべてのマーカー情報を保持するために、結果をトップレベルマーカー+すべての子マーカーを含む配列に変更
const allMarkers: SearchIndexItem[] = [];
// マーカーIDからオブジェクトへのマップ
const markerMap = new Map<string, SearchIndexItem>();
// 子マーカーIDを集約するためのセット
const childrenIds = new Set<string>();
if (!templateAst) {
return usageInfoList;
return allMarkers;
}
function traverse(node: any) {
// デバッグ情報
console.log('[create-search-index] Started extracting markers from AST');
// マーカーの基本情報を収集
function collectMarkers(node: any, parentId: string | null = null) {
// SearchMarkerコンポーネントの検出
if (node.type === 1 && node.tag === 'SearchMarker') {
// 元々の props を staticProps に全て展開する
const staticProps: Record<string, string> = {};
// マーカー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)}`;
console.log(`[create-search-index] Found SearchMarker with ID: ${markerId}`);
// マーカー基本情報
const markerInfo: SearchIndexItem = {
id: markerId,
children: [],
label: '',
keywords: [],
};
// 静的プロパティを抽出
if (node.props && Array.isArray(node.props)) {
node.props.forEach((prop: any) => {
if (prop.type === 6 && prop.name) {
staticProps[prop.name] = prop.value?.content || '';
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 || '';
console.log(`[create-search-index] Static prop ${prop.name}:`, prop.value?.content);
}
});
}
// markerId は __markerId または既存の props から取得
const markerId = node.__markerId || staticProps['markerId'];
if (markerId) {
staticProps['markerId'] = markerId;
}
const bindProps: Record<string, any> = {};
// 元々の 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 || '';
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 || '[]';
}
}
});
}
// __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);
// ラベルがない場合はデフォルト値を設定
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}`);
}
}
usageInfoList.push({
staticProps,
bindProps,
});
}
// 子ノードを処理(親は現在のノード)
if (node.children && Array.isArray(node.children)) {
node.children.forEach((child: any) => traverse(child));
}
node.children.forEach((child: any) => {
collectMarkers(child, markerId);
});
}
traverse(templateAst);
return usageInfoList;
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,22 +413,34 @@ 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}.`); // エラーログ
// ファイルを直接読み込む代替策を実行
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 { descriptor, errors } = vueSfcParse(code, {
}
try {
const { descriptor, errors } = vueSfcParse(options.transformedCodeCache[id], {
filename: filePath,
});
@ -175,18 +449,28 @@ export async function analyzeVueProps(options: {
continue; // エラーが発生したファイルはスキップ
}
const usageInfo = extractUsageInfoFromTemplateAst(descriptor.template?.ast, code);
if (!usageInfo) continue;
const fileMarkers = extractUsageInfoFromTemplateAst(descriptor.template?.ast, options.transformedCodeCache[id]);
if (usageInfo.length > 0) {
analysisResults.push({
filePath: filePath,
usage: usageInfo,
});
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}`);
}
}

View File

@ -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',
id: 'gAvOWkPnm',
label: i18n.ts._profile.description,
keywords: ['description','bio'],
},
bindProps: {},
{
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],
id: '46jUHufEx',
label: i18n.ts.makeFollowManuallyApprove,
keywords: ['follow', 'lock', i18n.ts.lockedAccountInfo],
},
},
],
{
id: 'yGVh4afrC',
label: i18n.ts.autoAcceptFollowed,
keywords: ['follow','auto','accept'],
},
{
filePath: 'src/pages/settings/mute-block.vue',
usage: [
{
staticProps: {
icon: 'ti ti-ban',
markerId: 'CVhDOYgMv',
id: 'vomfIAjG2',
label: i18n.ts.makeReactionsPublic,
keywords: ['reaction', 'public', i18n.ts.makeReactionsPublicDescription],
},
bindProps: {
locationLabel: [i18n.ts.muteAndBlock],
keywords: ['mute', i18n.ts.wordMute],
{
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: [
'kcHPXo5ZV',
],
},
{
id: '5V4EcXjrc',
label: i18n.ts._accountSettings.requireSigninToViewContents,
keywords: ['login', 'signin', i18n.ts._accountSettings.requireSigninToViewContentsDescription1, i18n.ts._accountSettings.requireSigninToViewContentsDescription2, i18n.ts._accountSettings.requireSigninToViewContentsDescription3],
},
{
staticProps: {
icon: 'ti ti-ban',
markerId: 'kcHPXo5ZV',
},
bindProps: {
locationLabel: [i18n.ts.muteAndBlock, i18n.ts.wordMute],
keywords: ['showMutedWord', i18n.ts.showMutedWord],
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',
},
{
id: 'rbnN7S4RC',
children: [
{
id: 'wAnn0Z9zp',
children: [
{
id: '5tIsotvIk',
label: i18n.ts.showMutedWord,
keywords: ['show'],
},
],
label: i18n.ts.wordMute,
keywords: ['note','word','soft','mute','hide'],
},
{
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 */