* feat(spatial): 添加空间查询包 - ISpatialQuery: 空间查询接口 - findInRadius, findInRect, findNearest, findKNearest - raycast, raycastFirst - IBounds, IRaycastHit, SpatialFilter 类型 - ISpatialIndex: 空间索引接口 - insert, remove, update, clear, getAll - GridSpatialIndex: 网格空间索引实现 - 基于均匀网格的空间划分 - 支持所有 ISpatialQuery 操作 - 工具函数 - createBounds, isPointInBounds, boundsIntersect - distanceSquared, distance * feat(spatial): 添加空间查询蓝图节点 - 添加 FindInRadius/FindInRect/FindNearest/FindKNearest 节点 - 添加 Raycast/RaycastFirst 射线检测节点 - 每个节点包含模板和执行器 - 使用 menuPath: ['Spatial', ...] 组织节点菜单
152 lines
4.7 KiB
JavaScript
152 lines
4.7 KiB
JavaScript
/**
|
||
* TypeDoc Plugin for Bilingual Documentation
|
||
* TypeDoc 双语文档插件
|
||
*
|
||
* Supports @zh and @en tags for bilingual documentation generation.
|
||
* 支持 @zh 和 @en 标签来生成双语文档。
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* /**
|
||
* * @zh 组件基类,所有组件都应继承此类
|
||
* * @en Base class for all components
|
||
* *\/
|
||
* export class Component { }
|
||
* ```
|
||
*/
|
||
|
||
import { Application, Converter, ReflectionKind, Comment, CommentTag } from 'typedoc';
|
||
|
||
/**
|
||
* @zh TypeDoc 双语插件入口
|
||
* @en TypeDoc bilingual plugin entry
|
||
* @param {Application} app - TypeDoc 应用实例 | TypeDoc application instance
|
||
*/
|
||
export function load(app) {
|
||
// 注册自定义标签 | Register custom tags
|
||
app.options.addReader({
|
||
name: 'bilingual-tags',
|
||
order: 0,
|
||
supportsPackages: false,
|
||
read(container) {
|
||
// 添加 @zh 和 @en 作为已知标签
|
||
// Add @zh and @en as known tags
|
||
const knownTags = container.getValue('blockTags') || [];
|
||
if (!knownTags.includes('@zh')) {
|
||
knownTags.push('@zh');
|
||
}
|
||
if (!knownTags.includes('@en')) {
|
||
knownTags.push('@en');
|
||
}
|
||
container.setValue('blockTags', knownTags);
|
||
}
|
||
});
|
||
|
||
// 监听解析完成事件 | Listen for conversion completion
|
||
app.converter.on(Converter.EVENT_RESOLVE_BEGIN, (context) => {
|
||
processReflections(context.project);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* @zh 处理所有反射对象的注释
|
||
* @en Process comments for all reflections
|
||
* @param {import('typedoc').ProjectReflection} project
|
||
*/
|
||
function processReflections(project) {
|
||
for (const reflection of project.getReflectionsByKind(ReflectionKind.All)) {
|
||
if (reflection.comment) {
|
||
processBilingualComment(reflection.comment);
|
||
}
|
||
|
||
// 处理签名注释 | Process signature comments
|
||
if ('signatures' in reflection && reflection.signatures) {
|
||
for (const sig of reflection.signatures) {
|
||
if (sig.comment) {
|
||
processBilingualComment(sig.comment);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @zh 处理单个注释的双语标签
|
||
* @en Process bilingual tags in a single comment
|
||
* @param {Comment} comment
|
||
*/
|
||
function processBilingualComment(comment) {
|
||
const zhTags = comment.blockTags?.filter(tag => tag.tag === '@zh') || [];
|
||
const enTags = comment.blockTags?.filter(tag => tag.tag === '@en') || [];
|
||
|
||
if (zhTags.length === 0 && enTags.length === 0) {
|
||
return;
|
||
}
|
||
|
||
// 构建双语摘要 | Build bilingual summary
|
||
const parts = [];
|
||
|
||
// 添加中文部分 | Add Chinese part
|
||
if (zhTags.length > 0) {
|
||
const zhText = zhTags.map(tag => tagContentToString(tag)).join('\n');
|
||
parts.push(zhText);
|
||
}
|
||
|
||
// 添加英文部分 | Add English part
|
||
if (enTags.length > 0) {
|
||
const enText = enTags.map(tag => tagContentToString(tag)).join('\n');
|
||
if (parts.length > 0) {
|
||
parts.push(''); // 空行分隔 | Empty line separator
|
||
}
|
||
parts.push(enText);
|
||
}
|
||
|
||
// 如果有双语内容,更新摘要 | Update summary if bilingual content exists
|
||
if (parts.length > 0) {
|
||
// 保留原有摘要(如果不是来自 @zh/@en)| Keep original summary if not from @zh/@en
|
||
const originalSummary = comment.summary?.map(part => {
|
||
if (typeof part === 'string') return part;
|
||
if (part.kind === 'text') return part.text;
|
||
return '';
|
||
}).join('') || '';
|
||
|
||
// 如果原有摘要不是空的且不是重复的,保留它
|
||
// Keep original summary if not empty and not duplicate
|
||
const bilingualText = parts.join('\n');
|
||
if (originalSummary && !bilingualText.includes(originalSummary.trim())) {
|
||
comment.summary = [
|
||
{ kind: 'text', text: originalSummary + '\n\n' + bilingualText }
|
||
];
|
||
} else {
|
||
comment.summary = [
|
||
{ kind: 'text', text: bilingualText }
|
||
];
|
||
}
|
||
}
|
||
|
||
// 移除已处理的 @zh/@en 标签,避免重复显示
|
||
// Remove processed @zh/@en tags to avoid duplicate display
|
||
comment.blockTags = comment.blockTags?.filter(
|
||
tag => tag.tag !== '@zh' && tag.tag !== '@en'
|
||
);
|
||
}
|
||
|
||
/**
|
||
* @zh 将标签内容转换为字符串
|
||
* @en Convert tag content to string
|
||
* @param {CommentTag} tag
|
||
* @returns {string}
|
||
*/
|
||
function tagContentToString(tag) {
|
||
if (!tag.content) return '';
|
||
|
||
return tag.content.map(part => {
|
||
if (typeof part === 'string') return part;
|
||
if (part.kind === 'text') return part.text;
|
||
if (part.kind === 'code') return '`' + part.text + '`';
|
||
return '';
|
||
}).join('');
|
||
}
|
||
|
||
export default { load };
|