UNPKG

@awesome-fe/translate

Version:
129 lines 5.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JsdocTranslator = void 0; const abstract_translator_1 = require("./abstract-translator"); const ts_morph_1 = require("ts-morph"); const util_1 = require("util"); const markdown_translator_1 = require("./markdown-translator"); const lodash_1 = require("lodash"); const delay_1 = require("../dom/delay"); function getTagsWithAncestors(node) { if (!node) { return []; } // 如果不是,就跳过这一层,直接返回父级的结果 if (!ts_morph_1.Node.isJSDocable(node)) { return getTagsWithAncestors(node.getParent()); } // 取当前节点的所有标记 const tags = node.getJsDocs().map(it => it.getTags()).flat(); // 合并当前节点的标记和父级节点的标记 return [...tags, ...getTagsWithAncestors(node.getParent())]; } function shouldTranslate(node, options) { if (!ts_morph_1.Node.isJSDocable(node)) { return false; } if (ts_morph_1.Node.isModifierable(node)) { if (node.hasModifier(ts_morph_1.SyntaxKind.PrivateKeyword)) { return false; } } const tags = getTagsWithAncestors(node).map(it => it.getTagName()); return (!options.mustIncludesTags || (0, lodash_1.intersection)(tags, options.mustIncludesTags).length > 0) && (!options.mustExcludesTags || (0, lodash_1.intersection)(tags, options.mustExcludesTags).length === 0); } function preprocess(text) { return text.replace(/(```\w*\n)(.*?)(```\n)/gs, (_, leading, body, tailing) => { return `${leading}${body.replace(/@/g, '@')}${tailing}`; }); } function postprocess(text) { return text.replace(/@/g, '@'); } class JsdocTranslator extends abstract_translator_1.AbstractTranslator { markdownTranslator = new markdown_translator_1.MarkdownTranslator(this.engine); parse(text) { const project = new ts_morph_1.Project({ manipulationSettings: { indentationText: ts_morph_1.IndentationText.TwoSpaces } }); return project.createSourceFile('placeholder.ts', preprocess(text)); } serialize(doc) { return postprocess(doc.getFullText()); } async flush() { return super.flush() // 需要等待一小段时间才能确保已经写回,目前原因不详 .then(() => (0, delay_1.delay)(500)); } translateMarkdown(sentence, options) { return this.markdownTranslator.translateContentAndFlush(sentence, options).then((result) => result); } translateDoc(doc, options) { this.translateNode(doc, options).then(it => it); return doc; } async translateNode(node, options) { if (ts_morph_1.Node.isJSDocable(node) && shouldTranslate(node, options)) { const docs = node.getJsDocs(); for (const doc of docs) { const structure = doc.getStructure(); const tagTasks = structure.tags.map(tag => this.translateTag(tag, options)); const origin = structure.description.trim(); const descriptionTask = this.translateMarkdown(origin, options).then(translation => { if (translation.trim() !== origin.trim()) { structure.description = removeExtraBlankLines(translation); } }); Promise.all([...tagTasks, descriptionTask].filter(it => !!it)).then(() => { if (!(0, util_1.isDeepStrictEqual)(structure, doc.getStructure())) { doc.set(structure); } }); } } const children = Array.from(node.getChildren()); children.forEach((subNode) => { this.translateNode(subNode, options); }); return node; } translateTag(tag, options) { const text = tag.text; if (isBinaryTag(tag)) { const [, name, description] = (text ?? '').match(/^((?:{.*?}\s*)?(?:[\w.\[\]]+|\[.*?])\s+)([\s\S]*)$/) ?? []; if (description?.trim()) { return this.translateMarkdown(description, options).then(translation => { if (translation.trim() !== description.trim()) { tag.text = (name ?? '') + removeExtraBlankLines(translation); } }); } } else if (isUnaryTag(tag)) { const [, prefix, description] = (text ?? '').match(/^({.*?}\s*)?([\s\S]*)$/); if (description?.trim()) { return this.translateMarkdown(description, options).then(translation => { if (translation.trim() !== description.trim()) { const leadingLines = ['publicApi', 'returns', 'codeGenApi', 'ngModule'].includes(tag.tagName) ? '\n\n' : ''; const tailingLines = ['usageNotes', 'description', 'deprecated'].includes(tag.tagName) ? '\n\n' : ''; tag.text = leadingLines + (prefix ?? '') + tailingLines + removeExtraBlankLines(translation); } }); } } } } exports.JsdocTranslator = JsdocTranslator; // 有两个参数且需要翻译的标记,如 @param a Some value function isBinaryTag(tag) { return ['param', 'arg', 'argument', 'property', 'prop', 'yields', 'yield', 'template', 'breaking-change'].includes(tag.tagName); } // 有一个参数且需要翻译的标记,如 @returns Some value function isUnaryTag(tag) { return ['returns', 'return', 'classdesc', 'description', 'desc', 'summary', 'throws', 'deprecated', 'usageNotes', 'see'].includes(tag.tagName); } function removeExtraBlankLines(translation) { return translation.replace(/\n$/s, '') + '\n'; } //# sourceMappingURL=jsdoc-translator.js.map