chore: simplify processing SearchLabel and SearchKeyword element

This commit is contained in:
anatawa12 2025-04-06 19:16:49 +09:00
parent 0367545183
commit bbe852da94
No known key found for this signature in database
GPG Key ID: 9CA909848B8E4EA6
1 changed files with 55 additions and 217 deletions

View File

@ -9,9 +9,9 @@ import { parse as vueSfcParse } from 'vue/compiler-sfc';
import {
createLogger,
EnvironmentModuleGraph,
normalizePath,
type LogErrorOptions,
type LogOptions,
normalizePath,
type Plugin,
type PluginOption
} from 'vite';
@ -22,13 +22,17 @@ import MagicString, { SourceMap } from 'magic-string';
import path from 'node:path'
import { hash, toBase62 } from '../vite.config';
import { minimatch } from 'minimatch';
import type {
AttributeNode, CompoundExpressionNode, DirectiveNode,
ElementNode,
RootNode, SimpleExpressionNode,
TemplateChildNode,
import {
type AttributeNode,
type CompoundExpressionNode,
type DirectiveNode,
type ElementNode,
ElementTypes,
NodeTypes,
type RootNode,
type SimpleExpressionNode,
type TemplateChildNode,
} from '@vue/compiler-core';
import { NodeTypes } from '@vue/compiler-core';
export interface SearchIndexItem {
id: string;
@ -60,7 +64,7 @@ interface MarkerRelation {
let logger = {
info: (msg: string, options?: LogOptions) => { },
warn: (msg: string, options?: LogOptions) => { },
error: (msg: string, options?: LogErrorOptions) => { },
error: (msg: string, options?: LogErrorOptions | unknown) => { },
};
let loggerInitialized = false;
@ -107,157 +111,55 @@ function customStringify(obj: unknown): string {
}
/**
*
*
*
*/
function extractElementText(node: TemplateChildNode): string | null {
if (!node) return null;
function extractElementText(node: ElementNode): string | null {
return extractElementTextChecked(node, node.tag);
}
function extractElementTextChecked(node: ElementNode, processingNodeName: string): string | null {
const result: string[] = [];
for (const child of node.children) {
const text = extractElementText2Inner(child, processingNodeName);
if (text == null) return null;
result.push(text);
}
return result.join('');
}
function extractElementText2Inner(node: TemplateChildNode, processingNodeName: string): string | null {
if (node.type === NodeTypes.COMPOUND_EXPRESSION) throw new Error("Unexpected COMPOUND_EXPRESSION");
logger.info(`Extracting text from node type=${node.type}, tag=${'tag' in node ? node.tag : 'unknown'}`);
// 1. 直接コンテンツの抽出を試行
const directContent = extractDirectContent(node);
if (directContent) return directContent;
// 子要素がない場合は終了
if (!('children' in node) || !Array.isArray(node.children)) {
switch (node.type) {
case NodeTypes.INTERPOLATION: {
const expr = node.content;
if (expr.type === NodeTypes.COMPOUND_EXPRESSION) throw new Error(`Unexpected COMPOUND_EXPRESSION`);
const exprResult = evalExpression(expr.content);
if (typeof exprResult !== 'string') {
logger.error(`Result of interpolation node is not string at line ${node.loc.start.line}`);
return null;
}
// 2. インターポレーションノードを検索
const interpolationContent = extractInterpolationContent(node.children);
if (interpolationContent) return interpolationContent;
// 3. 式ノードを検索
const expressionContent = extractExpressionContent(node.children);
if (expressionContent) return expressionContent;
// 5. 再帰的に子ノードを探索
return extractNestedContent(node.children);
}
/**
*
*/
function extractDirectContent(node: TemplateChildNode): string | null {
if (!('content' in node)) return null;
if (typeof node.content == 'object' && node.content.type === NodeTypes.COMPOUND_EXPRESSION) throw new Error("Unexpected COMPOUND_EXPRESSION");
const content = typeof node.content === 'string' ? node.content.trim()
: node.content.type !== NodeTypes.INTERPOLATION ? node.content.content.trim()
: null;
if (!content) return null;
logger.info(`Direct node content found: ${content}`);
// Mustache構文のチェック
const mustachePattern = /^\s*{{\s*(.*?)\s*}}\s*$/;
const mustacheMatch = content.match(mustachePattern);
if (mustacheMatch && mustacheMatch[1] && isI18nReference(mustacheMatch[1])) {
const extractedContent = mustacheMatch[1].trim();
logger.info(`Extracted i18n reference from mustache: ${extractedContent}`);
return extractedContent;
return exprResult;
}
// 直接i18n参照を含む場合
if (isI18nReference(content)) {
logger.info(`Direct i18n reference found: ${content}`);
return '$\{' + content + '}';
}
// その他のコンテンツ
return content;
}
/**
* Mustache
*/
function extractInterpolationContent(children: TemplateChildNode[]): string | null {
for (const child of children) {
if (child.type === NodeTypes.INTERPOLATION) {
logger.info(`Found interpolation node (Mustache): ${JSON.stringify(child.content).substring(0, 100)}...`);
if (child.content && child.content.type === 4 && child.content.content) {
const content = child.content.content.trim();
logger.info(`Interpolation content: ${content}`);
if (isI18nReference(content)) {
return '$\{' + content + '}';
}
} else if (child.content && typeof child.content === 'object') {
if (child.content.type == NodeTypes.COMPOUND_EXPRESSION) throw new Error("Unexpected COMPOUND_EXPRESSION");
// オブジェクト形式のcontentを探索
logger.info(`Complex interpolation node: ${JSON.stringify(child.content).substring(0, 100)}...`);
if (child.content.content) {
const content = child.content.content.trim();
if (isI18nReference(content)) {
logger.info(`Found i18n reference in complex interpolation: ${content}`);
return '$\{' + content + '}';
}
}
}
}
}
case NodeTypes.ELEMENT:
if (node.tagType === ElementTypes.ELEMENT) {
return extractElementTextChecked(node, processingNodeName);
} else {
logger.error(`Unexpected ${node.tag} extracting text of ${processingNodeName} ${node.loc.start.line}`);
return null;
}
/**
*
*/
function extractExpressionContent(children: TemplateChildNode[]): string | null {
// i18n.ts. 参照パターンを持つものを優先
for (const child of children) {
if (child.type === NodeTypes.TEXT && child.content) {
const expr = child.content.trim();
if (isI18nReference(expr)) {
logger.info(`Found i18n reference in expression node: ${expr}`);
return '$\{' + expr + '}';
}
}
}
// その他の式
for (const child of children) {
if (child.type === NodeTypes.TEXT && child.content) {
const expr = child.content.trim();
logger.info(`Found expression: ${expr}`);
return expr;
}
}
case NodeTypes.TEXT:
return node.content;
case NodeTypes.COMMENT:
// We skip comments
return '';
case NodeTypes.IF:
case NodeTypes.IF_BRANCH:
case NodeTypes.FOR:
case NodeTypes.TEXT_CALL:
logger.error(`Unexpected controlflow element extracting text of ${processingNodeName} ${node.loc.start.line}`);
return null;
}
/**
*
*/
function extractNestedContent(children: TemplateChildNode[]): string | null {
for (const child of children) {
if ('children' in child && Array.isArray(child.children) && child.children.length > 0) {
const nestedContent = extractElementText(child);
if (nestedContent) {
logger.info(`Found nested content: ${nestedContent}`);
return nestedContent;
}
} else if (child.type === NodeTypes.ELEMENT) {
// childrenがなくても内部を調査
const nestedContent = extractElementText(child);
if (nestedContent) {
logger.info(`Found content in childless element: ${nestedContent}`);
return nestedContent;
}
}
}
return null;
}
@ -286,92 +188,28 @@ function extractLabelsAndKeywords(nodes: TemplateChildNode[]): { label: string |
if (node.tag === 'SearchLabel') {
logger.info(`Found SearchLabel node, structure: ${JSON.stringify(node).substring(0, 200)}...`);
// まず完全なノード内容の抽出を試みる
const content = extractElementText(node);
if (content) {
label = content;
logger.info(`SearchLabel content extracted: ${content}`);
} else {
logger.info(`SearchLabel found but extraction failed, trying direct children inspection`);
// バックアップ: 子直接確認 - type=5のMustacheインターポレーションを重点的に確認
{
for (const child of node.children) {
// Mustacheインターポレーション
if (child.type === NodeTypes.INTERPOLATION && child.content) {
// content内の式を取り出す
if (child.content.type == NodeTypes.COMPOUND_EXPRESSION) throw new Error("unexpected COMPOUND_EXPRESSION");
const expression = child.content.content ||
(child.content.type === 4 ? child.content.content : null) ||
JSON.stringify(child.content);
logger.info(`Interpolation expression: ${expression}`);
if (typeof expression === 'string' && isI18nReference(expression)) {
label = expression.trim();
logger.info(`Found i18n in interpolation: ${label}`);
break;
}
}
// 式ノード
else if (child.type === NodeTypes.TEXT && child.content && isI18nReference(child.content)) {
label = child.content.trim();
logger.info(`Found i18n in expression: ${label}`);
break;
}
}
}
}
}
// SearchKeywordの処理
else if (node.tag === 'SearchKeyword') {
logger.info(`Found SearchKeyword node`);
// まず完全なノード内容の抽出を試みる
const content = extractElementText(node);
if (content) {
keywords.push(content);
logger.info(`SearchKeyword content extracted: ${content}`);
} else {
logger.info(`SearchKeyword found but extraction failed, trying direct children inspection`);
// バックアップ: 子直接確認 - type=5のMustacheインターポレーションを重点的に確認
{
for (const child of node.children) {
// Mustacheインターポレーション
if (child.type === NodeTypes.INTERPOLATION && child.content) {
// content内の式を取り出す
if (child.content.type == NodeTypes.COMPOUND_EXPRESSION) throw new Error("unexpected COMPOUND_EXPRESSION");
const expression = child.content.content ||
(child.content.type === 4 ? child.content.content : null) ||
JSON.stringify(child.content);
logger.info(`Keyword interpolation: ${expression}`);
if (typeof expression === 'string' && isI18nReference(expression)) {
const keyword = expression.trim();
keywords.push(keyword);
logger.info(`Found i18n keyword in interpolation: ${keyword}`);
break;
}
}
// 式ノード
else if (child.type === NodeTypes.TEXT && child.content && isI18nReference(child.content)) {
const keyword = child.content.trim();
keywords.push(keyword);
logger.info(`Found i18n keyword in expression: ${keyword}`);
break;
}
}
}
}
}
// 子要素を再帰的に調査ただしSearchMarkerは除外
if (node.children && Array.isArray(node.children)) {
findComponents(node.children);
}
}
}
}
findComponents(nodes);