mirror of
https://github.com/XeroAlpha/sapi-typedoc.git
synced 2024-11-22 17:48:50 +00:00
引入ESLint与Prettier
This commit is contained in:
parent
f7e29dc285
commit
040f0f3f5c
2741
package-lock.json
generated
2741
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,12 +4,19 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "node ./script/build.js",
|
||||
"update": "node ./script/update.js"
|
||||
"update": "node ./script/update.js",
|
||||
"lint-script": "eslint --fix script"
|
||||
},
|
||||
"dependencies": {
|
||||
"ts-morph": "^20.0.0",
|
||||
"typedoc": "^0.25.1",
|
||||
"typedoc-plugin-mdn-links": "^3.1.0",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.52.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"prettier": "^3.0.3"
|
||||
}
|
||||
}
|
||||
|
16
script/.eslintrc.js
Normal file
16
script/.eslintrc.js
Normal file
@ -0,0 +1,16 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
plugins: ['prettier'],
|
||||
extends: ['eslint:recommended', 'prettier'],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest'
|
||||
},
|
||||
env: {
|
||||
commonjs: true,
|
||||
es2021: true,
|
||||
node: true
|
||||
},
|
||||
rules: {
|
||||
'prettier/prettier': 'error'
|
||||
}
|
||||
};
|
7
script/.prettierrc
Normal file
7
script/.prettierrc
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/prettierrc",
|
||||
"printWidth": 120,
|
||||
"tabWidth": 4,
|
||||
"trailingComma": "none",
|
||||
"singleQuote": true
|
||||
}
|
107
script/build.js
107
script/build.js
@ -1,33 +1,33 @@
|
||||
const TypeDoc = require("typedoc");
|
||||
const { Project } = require("ts-morph");
|
||||
const { createRequire } = require("module");
|
||||
const { resolve: resolvePath, relative: relativePath } = require("path");
|
||||
const { existsSync, readFileSync, readdirSync, mkdirSync, writeFileSync } = require("fs");
|
||||
const { split } = require("./split");
|
||||
const { execSync } = require("child_process");
|
||||
const TypeDoc = require('typedoc');
|
||||
const { Project } = require('ts-morph');
|
||||
const { createRequire } = require('module');
|
||||
const { resolve: resolvePath, relative: relativePath } = require('path');
|
||||
const { existsSync, readFileSync, readdirSync, mkdirSync, writeFileSync } = require('fs');
|
||||
const { split } = require('./split');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
const basePath = resolvePath(__dirname, "..");
|
||||
const originalPath = resolvePath(basePath, "original");
|
||||
const translatedPath = resolvePath(basePath, "translated");
|
||||
const distPath = resolvePath(basePath, "dist");
|
||||
const hookPath = resolvePath(__dirname, "hooks");
|
||||
const basePath = resolvePath(__dirname, '..');
|
||||
const originalPath = resolvePath(basePath, 'original');
|
||||
const translatedPath = resolvePath(basePath, 'translated');
|
||||
const distPath = resolvePath(basePath, 'dist');
|
||||
const hookPath = resolvePath(__dirname, 'hooks');
|
||||
|
||||
const namespacePrefix = "@minecraft/";
|
||||
const botModules = [
|
||||
"@minecraft/vanilla-data"
|
||||
];
|
||||
const namespacePrefix = '@minecraft/';
|
||||
const botModules = ['@minecraft/vanilla-data'];
|
||||
|
||||
function readPackageInfo(modulePath) {
|
||||
const packageInfoPath = resolvePath(modulePath, "package.json");
|
||||
const packageInfoPath = resolvePath(modulePath, 'package.json');
|
||||
if (existsSync(packageInfoPath)) {
|
||||
try {
|
||||
return JSON.parse(readFileSync(packageInfoPath, "utf-8"));
|
||||
} catch(e) { /* ignore */ }
|
||||
return JSON.parse(readFileSync(packageInfoPath, 'utf-8'));
|
||||
} catch (e) {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function findModule(moduleName, root) {
|
||||
const localRequire = createRequire(resolvePath(root, "node_modules"));
|
||||
const localRequire = createRequire(resolvePath(root, 'node_modules'));
|
||||
const searchPaths = localRequire.resolve.paths(moduleName);
|
||||
for (const searchPath of searchPaths) {
|
||||
const modulePath = resolvePath(searchPath, moduleName);
|
||||
@ -57,14 +57,13 @@ function getCommonStringFromStart(a, b) {
|
||||
return a.slice(0, len);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
|
||||
async function build(translated) {
|
||||
// 加载钩子
|
||||
mkdirSync(hookPath, { recursive: true });
|
||||
const hookScripts = readdirSync(hookPath)
|
||||
.filter((name) => /\.(cjs|js)$/i.test(name));
|
||||
const hookScripts = readdirSync(hookPath).filter((name) => /\.(cjs|js)$/i.test(name));
|
||||
hookScripts.sort();
|
||||
const scriptRequire = createRequire(hookPath);
|
||||
const scriptHooks = hookScripts.map((name) => scriptRequire(resolvePath(hookPath, name)));
|
||||
@ -73,7 +72,7 @@ async function build(translated) {
|
||||
const scriptHook = scriptHooks[i];
|
||||
const logName = `[${event}] ${hookScripts[i]}`;
|
||||
let hookFunc;
|
||||
if (typeof scriptHooks === "function") {
|
||||
if (typeof scriptHooks === 'function') {
|
||||
hookFunc = scriptHook.bind(null, event);
|
||||
} else {
|
||||
hookFunc = scriptHook[event];
|
||||
@ -85,28 +84,28 @@ async function build(translated) {
|
||||
console.timeEnd(logName);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 尝试加载翻译文件对应版本的 package.json
|
||||
console.time('[restoreDependencies] Total');
|
||||
const originalPackageJsonPath = resolvePath(originalPath, "package.json");
|
||||
const cachedPackageJsonPath = resolvePath(translatedPath, "package.json");
|
||||
const originalPackageJsonPath = resolvePath(originalPath, 'package.json');
|
||||
const cachedPackageJsonPath = resolvePath(translatedPath, 'package.json');
|
||||
const originalPackageJsonData = readFileSync(originalPackageJsonPath);
|
||||
if (existsSync(cachedPackageJsonPath)) {
|
||||
writeFileSync(originalPackageJsonPath, readFileSync(cachedPackageJsonPath));
|
||||
}
|
||||
|
||||
// 使依赖与 package.json 同步
|
||||
execSync("npm install", {
|
||||
execSync('npm install', {
|
||||
cwd: originalPath,
|
||||
stdio: "inherit"
|
||||
stdio: 'inherit'
|
||||
});
|
||||
console.timeEnd('[restoreDependencies] Total');
|
||||
|
||||
// 从依赖中构建用于生成文档的项目
|
||||
console.time('[loadOriginal] Total');
|
||||
await runHooks("beforeLoad", {});
|
||||
const tsConfigFilePath = resolvePath(translatedPath, "tsconfig.json");
|
||||
await runHooks('beforeLoad', {});
|
||||
const tsConfigFilePath = resolvePath(translatedPath, 'tsconfig.json');
|
||||
const project = new Project({
|
||||
tsConfigFilePath,
|
||||
skipAddingFilesFromTsConfig: true
|
||||
@ -123,9 +122,9 @@ async function build(translated) {
|
||||
console.log(`Loading d.ts for ${moduleName}@${version}`);
|
||||
const dtsFiles = [];
|
||||
walkFiles(modulePath, (dir, file, path) => {
|
||||
if (file && file.endsWith(".d.ts")) {
|
||||
if (file && file.endsWith('.d.ts')) {
|
||||
const relPath = relativePath(modulePath, path);
|
||||
if (!relPath.includes("node_modules")) {
|
||||
if (!relPath.includes('node_modules')) {
|
||||
dtsFiles.push(path);
|
||||
}
|
||||
}
|
||||
@ -136,24 +135,25 @@ async function build(translated) {
|
||||
if (dtsFiles.length === 1) {
|
||||
const sourceFile = project.createSourceFile(
|
||||
resolvePath(translatedPath, `${pureModuleName}.d.ts`),
|
||||
readFileSync(dtsFiles[0], "utf-8").replace(/\r\n|\r/g, '\n'),
|
||||
readFileSync(dtsFiles[0], 'utf-8').replace(/\r\n|\r/g, '\n'),
|
||||
{ overwrite: true }
|
||||
);
|
||||
if (!botModules.includes(moduleName)) sourceFiles.push(sourceFile);
|
||||
} else {
|
||||
const typeEntry = resolvePath(modulePath, packageInfo.types).replace(/\.d\.ts$/i, "");
|
||||
const commonParent = dtsFiles.map((path) => resolvePath(path, ".."))
|
||||
const typeEntry = resolvePath(modulePath, packageInfo.types).replace(/\.d\.ts$/i, '');
|
||||
const commonParent = dtsFiles
|
||||
.map((path) => resolvePath(path, '..'))
|
||||
.reduce((common, parent) => getCommonStringFromStart(common, parent));
|
||||
const moduleRoot = resolvePath(translatedPath, pureModuleName);
|
||||
const moduleEntry = resolvePath(moduleRoot, relativePath(commonParent, typeEntry));
|
||||
const moduleEntryRelative = `./${relativePath(translatedPath, moduleEntry).replace(/\\/g, "/")}`;
|
||||
const moduleEntryRelative = `./${relativePath(translatedPath, moduleEntry).replace(/\\/g, '/')}`;
|
||||
const exportStatement = `export * from ${JSON.stringify(moduleEntryRelative)};`;
|
||||
dtsFiles.forEach((file) => {
|
||||
const target = resolvePath(moduleRoot, relativePath(commonParent, file));
|
||||
mkdirSync(resolvePath(target, ".."), { recursive: true });
|
||||
mkdirSync(resolvePath(target, '..'), { recursive: true });
|
||||
const sourceFile = project.createSourceFile(
|
||||
target,
|
||||
readFileSync(file, "utf-8").replace(/\r\n|\r/g, '\n'),
|
||||
readFileSync(file, 'utf-8').replace(/\r\n|\r/g, '\n'),
|
||||
{ overwrite: true }
|
||||
);
|
||||
if (!botModules.includes(moduleName)) sourceFiles.push(sourceFile);
|
||||
@ -169,9 +169,9 @@ async function build(translated) {
|
||||
}
|
||||
});
|
||||
writeFileSync(originalPackageJsonPath, originalPackageJsonData);
|
||||
await runHooks("afterLoad", { project, sourceFiles, dependencies });
|
||||
await runHooks('afterLoad', { project, sourceFiles, dependencies });
|
||||
console.timeEnd('[loadOriginal] Total');
|
||||
|
||||
|
||||
if (translated) {
|
||||
// 将顶层成员替换为带翻译的版本
|
||||
console.time('[translate] Total');
|
||||
@ -182,7 +182,7 @@ async function build(translated) {
|
||||
pieces.sort((a, b) => b.start - a.start);
|
||||
pieces.forEach((piece) => {
|
||||
if (!existsSync(piece.path)) return;
|
||||
const text = readFileSync(piece.path, "utf-8");
|
||||
const text = readFileSync(piece.path, 'utf-8');
|
||||
sourceFileText = `${sourceFileText.slice(0, piece.start)}${text}${sourceFileText.slice(piece.end)}`;
|
||||
writtenCount++;
|
||||
});
|
||||
@ -190,29 +190,32 @@ async function build(translated) {
|
||||
sourceFile.replaceWithText(sourceFileText);
|
||||
}
|
||||
});
|
||||
await runHooks("afterTranslate", { project, sourceFiles, dependencies });
|
||||
await runHooks('afterTranslate', { project, sourceFiles, dependencies });
|
||||
console.timeEnd('[translate] Total');
|
||||
}
|
||||
|
||||
// 生成 TypeDoc 页面
|
||||
console.time('[analyze] Total');
|
||||
project.saveSync();
|
||||
const tsdocApplication = await TypeDoc.Application.bootstrapWithPlugins({
|
||||
tsconfig: tsConfigFilePath,
|
||||
githubPages: false
|
||||
}, [new TypeDoc.TSConfigReader()]);
|
||||
await runHooks("beforeConvert", { project, sourceFiles, dependencies, tsdocApplication });
|
||||
const tsdocApplication = await TypeDoc.Application.bootstrapWithPlugins(
|
||||
{
|
||||
tsconfig: tsConfigFilePath,
|
||||
githubPages: false
|
||||
},
|
||||
[new TypeDoc.TSConfigReader()]
|
||||
);
|
||||
await runHooks('beforeConvert', { project, sourceFiles, dependencies, tsdocApplication });
|
||||
const tsdocProject = await tsdocApplication.convert();
|
||||
console.timeEnd('[analyze] Total');
|
||||
if (tsdocProject) {
|
||||
console.time('[emit] Total');
|
||||
await runHooks("afterConvert", { project, sourceFiles, dependencies, tsdocApplication, tsdocProject });
|
||||
await runHooks('afterConvert', { project, sourceFiles, dependencies, tsdocApplication, tsdocProject });
|
||||
await tsdocApplication.generateDocs(tsdocProject, distPath);
|
||||
await tsdocApplication.generateJson(tsdocProject, resolvePath(distPath, 'index.json'));
|
||||
await runHooks("afterEmit", { project, sourceFiles, dependencies, tsdocApplication, tsdocProject });
|
||||
await runHooks('afterEmit', { project, sourceFiles, dependencies, tsdocApplication, tsdocProject });
|
||||
console.timeEnd('[emit] Total');
|
||||
} else {
|
||||
throw new Error("Convert failed");
|
||||
throw new Error('Convert failed');
|
||||
}
|
||||
return { project, sourceFiles, dependencies, tsdocProject };
|
||||
}
|
||||
@ -225,4 +228,4 @@ if (require.main === module) {
|
||||
build(true).catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,19 @@
|
||||
const TypeDoc = require("typedoc");
|
||||
const TypeDoc = require('typedoc');
|
||||
|
||||
/** @type {import('./hook').Hook} */
|
||||
module.exports = {
|
||||
afterConvert({ tsdocProject }) {
|
||||
const reflectionEntries = Object.entries(tsdocProject.reflections)
|
||||
.filter(([id, refl]) => !refl.kindOf([
|
||||
TypeDoc.ReflectionKind.ConstructorSignature,
|
||||
TypeDoc.ReflectionKind.CallSignature,
|
||||
TypeDoc.ReflectionKind.GetSignature,
|
||||
TypeDoc.ReflectionKind.SetSignature
|
||||
]))
|
||||
.map(([id, refl]) => [refl.getFriendlyFullName(), refl]);
|
||||
const reflectionEntries = Object.values(tsdocProject.reflections)
|
||||
.filter(
|
||||
(refl) =>
|
||||
!refl.kindOf([
|
||||
TypeDoc.ReflectionKind.ConstructorSignature,
|
||||
TypeDoc.ReflectionKind.CallSignature,
|
||||
TypeDoc.ReflectionKind.GetSignature,
|
||||
TypeDoc.ReflectionKind.SetSignature
|
||||
])
|
||||
)
|
||||
.map((refl) => [refl.getFriendlyFullName(), refl]);
|
||||
const visitCommentPart = (/** @type {TypeDoc.CommentDisplayPart} */ part) => {
|
||||
if (part.kind === 'inline-tag' && part.tag === '@link') {
|
||||
if (typeof part.target === 'string') {
|
||||
@ -19,26 +22,30 @@ module.exports = {
|
||||
if (typeof part.target === 'object' && part.target.name === part.text) {
|
||||
return;
|
||||
}
|
||||
const segments = part.text.split(/[\./]/);
|
||||
const segments = part.text.split(/[./]/);
|
||||
const probablySymbolNames = segments.map((_, i) => segments.slice(i).join('.'));
|
||||
const foundReflections = reflectionEntries.map(([friendlyFullName, refl]) => [
|
||||
probablySymbolNames.findIndex((symbolName) => friendlyFullName === symbolName || friendlyFullName.endsWith(`.${symbolName}`)),
|
||||
refl,
|
||||
friendlyFullName
|
||||
]).filter(([rank, refl]) => rank >= 0);
|
||||
const foundReflections = reflectionEntries
|
||||
.map(([friendlyFullName, refl]) => [
|
||||
probablySymbolNames.findIndex(
|
||||
(symbolName) =>
|
||||
friendlyFullName === symbolName || friendlyFullName.endsWith(`.${symbolName}`)
|
||||
),
|
||||
refl,
|
||||
friendlyFullName
|
||||
])
|
||||
.filter(([rank]) => rank >= 0);
|
||||
if (foundReflections.length === 0) {
|
||||
return;
|
||||
}
|
||||
const bestMatchReflection = foundReflections
|
||||
.reduce((best, e) => e[0] < best[0] ? e : best);
|
||||
const bestMatchReflection = foundReflections.reduce((best, e) => (e[0] < best[0] ? e : best));
|
||||
const bestMatchReflections = foundReflections.filter((e) => e[0] <= bestMatchReflection[0]);
|
||||
if (bestMatchReflections.length >= 2) {
|
||||
console.warn(`Multiple resolutions of link: ${part.text}`);
|
||||
}
|
||||
part.target = bestMatchReflection[1];
|
||||
}
|
||||
}
|
||||
Object.entries(tsdocProject.reflections).forEach(([id, reflection]) => {
|
||||
};
|
||||
Object.values(tsdocProject.reflections).forEach((reflection) => {
|
||||
if (reflection.comment) {
|
||||
reflection.comment.summary.forEach(visitCommentPart);
|
||||
reflection.comment.blockTags.forEach((tag) => {
|
||||
|
@ -1,10 +1,10 @@
|
||||
/** @type {import('./hook').Hook} */
|
||||
module.exports = {
|
||||
afterConvert({ tsdocProject }) {
|
||||
Object.entries(tsdocProject.reflections).forEach(([id, reflection]) => {
|
||||
Object.values(tsdocProject.reflections).forEach((reflection) => {
|
||||
if (reflection.sources) {
|
||||
reflection.sources.forEach((source) => {
|
||||
source.fileName = source.fileName.replace("translated", tsdocProject.name);
|
||||
source.fileName = source.fileName.replace('translated', tsdocProject.name);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
6
script/hooks/hook.d.ts
vendored
6
script/hooks/hook.d.ts
vendored
@ -1,5 +1,5 @@
|
||||
import { Project, SourceFile } from "ts-morph";
|
||||
import { Application, ProjectReflection } from "typedoc";
|
||||
import { Project, SourceFile } from 'ts-morph';
|
||||
import { Application, ProjectReflection } from 'typedoc';
|
||||
|
||||
declare type HookFunction<Context> = (context: Context) => void | Promise<void>;
|
||||
|
||||
@ -23,5 +23,5 @@ declare interface Hook {
|
||||
afterTranslate?: HookFunction<TranslateHookContext>;
|
||||
beforeConvert?: HookFunction<BeforeConvertHookContext>;
|
||||
afterConvert?: HookFunction<AfterConvertHookContext>;
|
||||
afterConvert?: HookFunction<AfterConvertHookContext>;
|
||||
afterEmit?: HookFunction<AfterConvertHookContext>;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
const { SyntaxKind, SourceFile } = require("ts-morph");
|
||||
const { resolve: resolvePath, relative: relativePath } = require("path");
|
||||
const { SyntaxKind } = require('ts-morph');
|
||||
const { resolve: resolvePath, relative: relativePath } = require('path');
|
||||
|
||||
const basePath = resolvePath(__dirname, "..");
|
||||
const translatingPath = resolvePath(basePath, "translate-pieces");
|
||||
const translatedPath = resolvePath(basePath, "translated");
|
||||
const basePath = resolvePath(__dirname, '..');
|
||||
const translatingPath = resolvePath(basePath, 'translate-pieces');
|
||||
const translatedPath = resolvePath(basePath, 'translated');
|
||||
|
||||
const SkippedTopLevelSyntaxKinds = [
|
||||
SyntaxKind.EndOfFileToken,
|
||||
@ -12,14 +12,14 @@ const SkippedTopLevelSyntaxKinds = [
|
||||
];
|
||||
|
||||
const SyntaxKindToCategory = new Map([
|
||||
[SyntaxKind.EnumDeclaration, "enums"],
|
||||
[SyntaxKind.ClassDeclaration, "classes"],
|
||||
[SyntaxKind.FunctionDeclaration, "functions"],
|
||||
[SyntaxKind.InterfaceDeclaration, "interfaces"],
|
||||
[SyntaxKind.ModuleDeclaration, "modules"],
|
||||
[SyntaxKind.TypeAliasDeclaration, "types"],
|
||||
[SyntaxKind.VariableStatement, "variables"],
|
||||
[SyntaxKind.ExportDeclaration, "types"]
|
||||
[SyntaxKind.EnumDeclaration, 'enums'],
|
||||
[SyntaxKind.ClassDeclaration, 'classes'],
|
||||
[SyntaxKind.FunctionDeclaration, 'functions'],
|
||||
[SyntaxKind.InterfaceDeclaration, 'interfaces'],
|
||||
[SyntaxKind.ModuleDeclaration, 'modules'],
|
||||
[SyntaxKind.TypeAliasDeclaration, 'types'],
|
||||
[SyntaxKind.VariableStatement, 'variables'],
|
||||
[SyntaxKind.ExportDeclaration, 'types']
|
||||
]);
|
||||
|
||||
/**
|
||||
@ -33,7 +33,8 @@ function split(sourceFile) {
|
||||
);
|
||||
const piecePathList = [];
|
||||
const pieces = [];
|
||||
const packageDocumentationJSDoc = sourceFile.getDescendantsOfKind(SyntaxKind.JSDoc)
|
||||
const packageDocumentationJSDoc = sourceFile
|
||||
.getDescendantsOfKind(SyntaxKind.JSDoc)
|
||||
.find((jsdoc) => jsdoc.getTags().some((tag) => tag.getTagName() === 'packageDocumentation'));
|
||||
if (packageDocumentationJSDoc) {
|
||||
pieces.push({
|
||||
@ -44,7 +45,8 @@ function split(sourceFile) {
|
||||
}
|
||||
sourceFile.forEachChild((node) => {
|
||||
if (SkippedTopLevelSyntaxKinds.includes(node.getKind())) return;
|
||||
const includedSymbols = node.getDescendants()
|
||||
const includedSymbols = node
|
||||
.getDescendants()
|
||||
.map((e) => e.getSymbol())
|
||||
.filter((e) => e);
|
||||
let symbol = node.getSymbol();
|
||||
@ -67,7 +69,8 @@ function split(sourceFile) {
|
||||
pieceIndex++;
|
||||
}
|
||||
piecePathList.push(piecePath.toLowerCase());
|
||||
const jsdocList = node.getChildrenOfKind(SyntaxKind.JSDoc)
|
||||
const jsdocList = node
|
||||
.getChildrenOfKind(SyntaxKind.JSDoc)
|
||||
.filter((jsdoc) => jsdoc.getStart() !== packageDocumentationJSDoc.getStart());
|
||||
let pieceStart = node.getStart(false);
|
||||
if (jsdocList.length > 0) {
|
||||
@ -82,4 +85,4 @@ function split(sourceFile) {
|
||||
return pieces;
|
||||
}
|
||||
|
||||
module.exports = { split };
|
||||
module.exports = { split };
|
||||
|
150
script/update.js
150
script/update.js
@ -1,20 +1,18 @@
|
||||
const { execSync } = require("child_process");
|
||||
const { readFileSync, writeFileSync, rmSync, mkdirSync, existsSync } = require("fs");
|
||||
const { resolve: resolvePath } = require("path");
|
||||
const { URL } = require("url");
|
||||
const { build } = require("./build.js");
|
||||
const { split } = require("./split.js");
|
||||
const { execSync } = require('child_process');
|
||||
const { readFileSync, writeFileSync, rmSync, mkdirSync, existsSync } = require('fs');
|
||||
const { resolve: resolvePath } = require('path');
|
||||
const { URL } = require('url');
|
||||
const { build } = require('./build.js');
|
||||
const { split } = require('./split.js');
|
||||
|
||||
const basePath = resolvePath(__dirname, "..");
|
||||
const originalPath = resolvePath(basePath, "original");
|
||||
const translatingPath = resolvePath(basePath, "translate-pieces");
|
||||
const translatedPath = resolvePath(basePath, "translated");
|
||||
const basePath = resolvePath(__dirname, '..');
|
||||
const originalPath = resolvePath(basePath, 'original');
|
||||
const translatingPath = resolvePath(basePath, 'translate-pieces');
|
||||
const translatedPath = resolvePath(basePath, 'translated');
|
||||
|
||||
const namespacePrefix = "@minecraft/";
|
||||
const baseURL = "https://projectxero.top/sapi/";
|
||||
const botModules = [
|
||||
"@minecraft/vanilla-data"
|
||||
];
|
||||
const namespacePrefix = '@minecraft/';
|
||||
const baseURL = 'https://projectxero.top/sapi/';
|
||||
const botModules = ['@minecraft/vanilla-data'];
|
||||
|
||||
function extractVersionInfo(versionString) {
|
||||
const match = /^([\d.]+-\w+)\.([\d.]+)-(\w+)(\.\d+)?$/.exec(versionString);
|
||||
@ -28,29 +26,29 @@ function extractVersionInfo(versionString) {
|
||||
}
|
||||
|
||||
const KindString = [
|
||||
"项目", // Project = 0x1,
|
||||
"模块", // Module = 0x2,
|
||||
"命名空间", // Namespace = 0x4,
|
||||
"枚举", // Enum = 0x8,
|
||||
"枚举成员", // EnumMember = 0x10,
|
||||
"变量", // Variable = 0x20,
|
||||
"函数", // Function = 0x40,
|
||||
"类", // Class = 0x80,
|
||||
"接口", // Interface = 0x100,
|
||||
"构造器", // Constructor = 0x200,
|
||||
"属性", // Property = 0x400,
|
||||
"方法", // Method = 0x800,
|
||||
"调用签名", // CallSignature = 0x1000,
|
||||
"索引签名", // IndexSignature = 0x2000,
|
||||
"构造器签名", // ConstructorSignature = 0x4000,
|
||||
"参数", // Parameter = 0x8000,
|
||||
"类型字面量", // TypeLiteral = 0x10000,
|
||||
"类型参数", // TypeParameter = 0x20000,
|
||||
"访问器", // Accessor = 0x40000,
|
||||
"Getter 签名", // GetSignature = 0x80000,
|
||||
"Setter 签名", // SetSignature = 0x100000,
|
||||
"类型别名", // TypeAlias = 0x200000,
|
||||
"引用" // Reference = 0x400000
|
||||
'项目', // Project = 0x1,
|
||||
'模块', // Module = 0x2,
|
||||
'命名空间', // Namespace = 0x4,
|
||||
'枚举', // Enum = 0x8,
|
||||
'枚举成员', // EnumMember = 0x10,
|
||||
'变量', // Variable = 0x20,
|
||||
'函数', // Function = 0x40,
|
||||
'类', // Class = 0x80,
|
||||
'接口', // Interface = 0x100,
|
||||
'构造器', // Constructor = 0x200,
|
||||
'属性', // Property = 0x400,
|
||||
'方法', // Method = 0x800,
|
||||
'调用签名', // CallSignature = 0x1000,
|
||||
'索引签名', // IndexSignature = 0x2000,
|
||||
'构造器签名', // ConstructorSignature = 0x4000,
|
||||
'参数', // Parameter = 0x8000,
|
||||
'类型字面量', // TypeLiteral = 0x10000,
|
||||
'类型参数', // TypeParameter = 0x20000,
|
||||
'访问器', // Accessor = 0x40000,
|
||||
'Getter 签名', // GetSignature = 0x80000,
|
||||
'Setter 签名', // SetSignature = 0x100000,
|
||||
'类型别名', // TypeAlias = 0x200000,
|
||||
'引用' // Reference = 0x400000
|
||||
];
|
||||
function kindToString(kind) {
|
||||
const result = [];
|
||||
@ -59,28 +57,30 @@ function kindToString(kind) {
|
||||
result.push(KindString[i]);
|
||||
}
|
||||
}
|
||||
return result.join("/");
|
||||
return result.join('/');
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// 强制检出 original 分支
|
||||
const head = execSync("git rev-parse --abbrev-ref HEAD", {
|
||||
const head = execSync('git rev-parse --abbrev-ref HEAD', {
|
||||
cwd: basePath
|
||||
}).toString("utf-8").trim();
|
||||
if (head !== "original" && head !== "HEAD") {
|
||||
execSync("git checkout original", {
|
||||
})
|
||||
.toString('utf-8')
|
||||
.trim();
|
||||
if (head !== 'original' && head !== 'HEAD') {
|
||||
execSync('git checkout original', {
|
||||
cwd: basePath,
|
||||
stdio: "inherit"
|
||||
stdio: 'inherit'
|
||||
});
|
||||
}
|
||||
|
||||
// 清除 node_modules 与缓存的 package.json
|
||||
const packageInfoPath = resolvePath(originalPath, "package.json");
|
||||
const packageSnapshotPath = resolvePath(translatedPath, "package.json");
|
||||
const packageInfoPath = resolvePath(originalPath, 'package.json');
|
||||
const packageSnapshotPath = resolvePath(translatedPath, 'package.json');
|
||||
if (existsSync(packageSnapshotPath)) {
|
||||
rmSync(packageSnapshotPath);
|
||||
}
|
||||
const originalNodeModulesDir = resolvePath(originalPath, "node_modules");
|
||||
const originalNodeModulesDir = resolvePath(originalPath, 'node_modules');
|
||||
if (existsSync(originalNodeModulesDir)) {
|
||||
rmSync(originalNodeModulesDir, { recursive: true, force: true });
|
||||
}
|
||||
@ -94,32 +94,21 @@ async function main() {
|
||||
const pieces = split(sourceFile);
|
||||
const sourceFileText = sourceFile.getFullText();
|
||||
pieces.forEach((piece) => {
|
||||
mkdirSync(resolvePath(piece.path, ".."), { recursive: true });
|
||||
mkdirSync(resolvePath(piece.path, '..'), { recursive: true });
|
||||
writeFileSync(piece.path, sourceFileText.slice(piece.start, piece.end));
|
||||
});
|
||||
});
|
||||
|
||||
// 生成 README.md
|
||||
const readMePath = resolvePath(translatedPath, "README.md");
|
||||
const readMe = readFileSync(readMePath, "utf-8");
|
||||
const readMePath = resolvePath(translatedPath, 'README.md');
|
||||
const readMe = readFileSync(readMePath, 'utf-8');
|
||||
|
||||
const summaryLines = [
|
||||
"<!-- summary start -->",
|
||||
"",
|
||||
"模块:",
|
||||
""
|
||||
];
|
||||
const summaryLines = ['<!-- summary start -->', '', '模块:', ''];
|
||||
tsdocProject.children.forEach((moduleRef) => {
|
||||
const docURL = new URL(moduleRef.url || '', baseURL);
|
||||
summaryLines.push(`- [${namespacePrefix}${moduleRef.name}](${docURL})`);
|
||||
});
|
||||
summaryLines.push([
|
||||
"",
|
||||
"NPM 包:",
|
||||
"",
|
||||
"|包名|版本|",
|
||||
"| - | - |"
|
||||
]);
|
||||
summaryLines.push(['', 'NPM 包:', '', '|包名|版本|', '| - | - |']);
|
||||
let gameVersion;
|
||||
Object.entries(dependencies).forEach(([moduleName, version]) => {
|
||||
let versionString = version;
|
||||
@ -131,32 +120,16 @@ async function main() {
|
||||
const npmURL = `https://www.npmjs.com/package/${moduleName}`;
|
||||
summaryLines.push(`|[${moduleName}](${npmURL})|\`${versionString}\`|`);
|
||||
});
|
||||
summaryLines.push([
|
||||
"",
|
||||
`游戏版本号:\`${gameVersion}\``,
|
||||
"",
|
||||
"<!-- summary end -->"
|
||||
]);
|
||||
summaryLines.push(['', `游戏版本号:\`${gameVersion}\``, '', '<!-- summary end -->']);
|
||||
|
||||
const statusHeadLines = [
|
||||
"<!-- status start -->",
|
||||
"",
|
||||
"|模块|进度|",
|
||||
"| - | - |"
|
||||
];
|
||||
const statusHeadLines = ['<!-- status start -->', '', '|模块|进度|', '| - | - |'];
|
||||
const statusLines = [];
|
||||
tsdocProject.children.forEach((moduleRef) => {
|
||||
const moduleFullName = namespacePrefix + moduleRef.name;
|
||||
if (botModules.includes(moduleFullName)) return;
|
||||
const linkHref = moduleFullName.replace(/[@\/]/g, "");
|
||||
const linkHref = moduleFullName.replace(/[@/]/g, '');
|
||||
statusHeadLines.push(`|[${moduleFullName}](#${linkHref})|0/${moduleRef.children.length}|`);
|
||||
statusLines.push([
|
||||
"",
|
||||
`### ${moduleFullName}`,
|
||||
"",
|
||||
"|名称|类型|状态|",
|
||||
"| - | - | - |"
|
||||
]);
|
||||
statusLines.push(['', `### ${moduleFullName}`, '', '|名称|类型|状态|', '| - | - | - |']);
|
||||
moduleRef.children.forEach((member) => {
|
||||
const kindStr = kindToString(member.kind);
|
||||
const url = new URL(member.url, baseURL);
|
||||
@ -164,18 +137,15 @@ async function main() {
|
||||
});
|
||||
});
|
||||
statusLines.unshift(statusHeadLines);
|
||||
statusLines.push([
|
||||
"",
|
||||
"<!-- status end -->"
|
||||
]);
|
||||
statusLines.push(['', '<!-- status end -->']);
|
||||
|
||||
const newReadMe = readMe
|
||||
.replace(/<!-- summary start -->\n\n[^]+\n\n<!-- summary end -->/, summaryLines.flat().join("\n"))
|
||||
.replace(/<!-- status start -->\n\n[^]+\n\n<!-- status end -->/, statusLines.flat().join("\n"));
|
||||
.replace(/<!-- summary start -->\n\n[^]+\n\n<!-- summary end -->/, summaryLines.flat().join('\n'))
|
||||
.replace(/<!-- status start -->\n\n[^]+\n\n<!-- status end -->/, statusLines.flat().join('\n'));
|
||||
writeFileSync(readMePath, newReadMe);
|
||||
|
||||
// 生成 package.json 快照
|
||||
const packageInfo = JSON.parse(readFileSync(packageInfoPath, "utf-8"));
|
||||
const packageInfo = JSON.parse(readFileSync(packageInfoPath, 'utf-8'));
|
||||
writeFileSync(packageSnapshotPath, JSON.stringify({ ...packageInfo, dependencies }, null, 2));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user