From 3a8d015194e13224edc37650665c71e2087698b3 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Mon, 7 Apr 2025 17:03:43 +0900 Subject: [PATCH] enhance(frontend): improve search index --- .../lib/vite-plugin-create-search-index.ts | 31 ++++++++++++++++--- .../src/components/global/SearchIcon.vue | 14 +++++++++ packages/frontend/src/components/index.ts | 3 ++ .../frontend/src/pages/settings/other.vue | 12 +++---- .../src/pages/settings/preferences.vue | 18 +++++------ 5 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 packages/frontend/src/components/global/SearchIcon.vue diff --git a/packages/frontend/lib/vite-plugin-create-search-index.ts b/packages/frontend/lib/vite-plugin-create-search-index.ts index a0a98b2d3e..a1093cacb5 100644 --- a/packages/frontend/lib/vite-plugin-create-search-index.ts +++ b/packages/frontend/lib/vite-plugin-create-search-index.ts @@ -227,10 +227,11 @@ function extractElementText2Inner(node: TemplateChildNode, processingNodeName: s // region extractUsageInfoFromTemplateAst /** - * SearchLabelとSearchKeywordを探して抽出する関数 + * SearchLabel/SearchKeyword/SearchIconを探して抽出する関数 */ -function extractLabelsAndKeywords(nodes: TemplateChildNode[]): { label: string | null, keywords: string[] } { +function extractSugarTags(nodes: TemplateChildNode[]): { label: string | null, keywords: string[], icon: string | null } { let label: string | null | undefined = undefined; + let icon: string | null | undefined = undefined; const keywords: string[] = []; logger.info(`Extracting labels and keywords from ${nodes.length} nodes`); @@ -253,14 +254,32 @@ function extractLabelsAndKeywords(nodes: TemplateChildNode[]): { label: string | keywords.push(content); } return; + case 'SearchIcon': + if (icon !== undefined) { + logger.warn(`Duplicate SearchIcon found, ignoring the second one at ${node.loc.start.line}`); + break; // 2つ目のSearchIconは無視 + } + + if (node.children.length !== 1) { + logger.error(`SearchIcon must have exactly one child at ${node.loc.start.line}`); + return; + } + + const iconNode = node.children[0]; + if (iconNode.type !== NodeTypes.ELEMENT) { + logger.error(`SearchIcon must have a child element at ${node.loc.start.line}`); + return; + } + icon = getStringProp(findAttribute(iconNode.props, 'class')); + return; } return; }); // デバッグ情報 - logger.info(`Extraction completed: label=${label}, keywords=[${keywords.join(', ')}]`); - return { label: label ?? null, keywords }; + logger.info(`Extraction completed: label=${label}, keywords=[${keywords.join(', ')}, icon=${icon}]`); + return { label: label ?? null, keywords, icon: icon ?? null }; } function getStringProp(attr: AttributeNode | DirectiveNode | null): string | null { @@ -354,10 +373,12 @@ function extractUsageInfoFromTemplateAst( // SearchLabelとSearchKeywordを抽出 (AST全体を探索) { - const extracted = extractLabelsAndKeywords(node.children); + const extracted = extractSugarTags(node.children); if (extracted.label && markerInfo.label) logger.warn(`Duplicate label found for ${markerId} at ${id}:${node.loc.start.line}`); + if (extracted.icon && markerInfo.icon) logger.warn(`Duplicate icon found for ${markerId} at ${id}:${node.loc.start.line}`); markerInfo.label = extracted.label ?? markerInfo.label ?? ''; markerInfo.keywords = [...extracted.keywords, ...markerInfo.keywords]; + markerInfo.icon = extracted.icon ?? markerInfo.icon ?? undefined; } if (!markerInfo.label) { diff --git a/packages/frontend/src/components/global/SearchIcon.vue b/packages/frontend/src/components/global/SearchIcon.vue new file mode 100644 index 0000000000..27a284faf0 --- /dev/null +++ b/packages/frontend/src/components/global/SearchIcon.vue @@ -0,0 +1,14 @@ + + + + + + + diff --git a/packages/frontend/src/components/index.ts b/packages/frontend/src/components/index.ts index 6c6903c3a4..34cf598b84 100644 --- a/packages/frontend/src/components/index.ts +++ b/packages/frontend/src/components/index.ts @@ -30,6 +30,7 @@ import PageWithAnimBg from './global/PageWithAnimBg.vue'; import SearchMarker from './global/SearchMarker.vue'; import SearchLabel from './global/SearchLabel.vue'; import SearchKeyword from './global/SearchKeyword.vue'; +import SearchIcon from './global/SearchIcon.vue'; import type { App } from 'vue'; @@ -67,6 +68,7 @@ export const components = { SearchMarker: SearchMarker, SearchLabel: SearchLabel, SearchKeyword: SearchKeyword, + SearchIcon: SearchIcon, }; declare module '@vue/runtime-core' { @@ -98,5 +100,6 @@ declare module '@vue/runtime-core' { SearchMarker: typeof SearchMarker; SearchLabel: typeof SearchLabel; SearchKeyword: typeof SearchKeyword; + SearchIcon: typeof SearchIcon; } } diff --git a/packages/frontend/src/pages/settings/other.vue b/packages/frontend/src/pages/settings/other.vue index 58fcb0c5e0..d97ea6e459 100644 --- a/packages/frontend/src/pages/settings/other.vue +++ b/packages/frontend/src/pages/settings/other.vue @@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +
@@ -49,7 +49,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -58,7 +58,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -67,7 +67,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -81,7 +81,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -100,7 +100,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
diff --git a/packages/frontend/src/pages/settings/preferences.vue b/packages/frontend/src/pages/settings/preferences.vue index 86ae8af213..647fed10e3 100644 --- a/packages/frontend/src/pages/settings/preferences.vue +++ b/packages/frontend/src/pages/settings/preferences.vue @@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -111,7 +111,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -279,7 +279,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -341,7 +341,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -382,7 +382,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -421,7 +421,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -531,7 +531,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -567,7 +567,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
{{ i18n.ts.reloadRequiredToApplySettings }} @@ -601,7 +601,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +