chore: simplify processing SearchLabel and SearchKeyword element
This commit is contained in:
		
							parent
							
								
									0367545183
								
							
						
					
					
						commit
						bbe852da94
					
				|  | @ -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)) { | ||||
| 		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; | ||||
| 	} | ||||
| 
 | ||||
| 	// 直接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 + '}'; | ||||
| 					} | ||||
| 				} | ||||
| 	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; | ||||
| 			} | ||||
| 			return exprResult; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	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 + '}'; | ||||
| 		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; | ||||
| 			} | ||||
| 		} | ||||
| 		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; | ||||
| 	} | ||||
| 
 | ||||
| 	// その他の式
 | ||||
| 	for (const child of children) { | ||||
| 		if (child.type === NodeTypes.TEXT && child.content) { | ||||
| 			const expr = child.content.trim(); | ||||
| 			logger.info(`Found expression: ${expr}`); | ||||
| 			return expr; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	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,89 +188,25 @@ 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(node.children); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue