Skip to content

Commit

Permalink
ci: auto generate comment
Browse files Browse the repository at this point in the history
  • Loading branch information
guoxianzhe committed Jul 4, 2023
1 parent 5d45a14 commit db25bba
Show file tree
Hide file tree
Showing 7 changed files with 302 additions and 1 deletion.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"husky": "^8.0.3",
"jsdom": "^21.1.0",
"lint-staged": "^13.2.1",
"markdown-it": "^13.0.1",
"minimist": "^1.2.8",
"prettier": "^2.8.4",
"release-it": "^15.10.3",
Expand Down
3 changes: 2 additions & 1 deletion packages/agora-rtc-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
"test:watch": "vitest --ui",
"gene-stories": "esbuild-dev ../../scripts/generate-storybook-mdx.ts",
"gene-md": "esbuild-dev ../../scripts/generate-docs.ts",
"gene-docs": "pnpm run gene-md && pnpm run gene-stories"
"gene-comment": "esbuild-dev ../../scripts/api.ts && esbuild-dev ../../scripts/component.ts",
"gene-docs": "pnpm run gene-md && pnpm run gene-stories && pnpm run gene-comment"
},
"peerDependencies": {
"agora-rtc-sdk-ng": ">=4.18.0",
Expand Down
36 changes: 36 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions scripts/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ export const languagesFormat = [".zh-CN", ".en-US"];
export const packagePath = path.join(__dirname, "..", "packages", "agora-rtc-react");
export const docsPath = path.join(packagePath, "docs");
export const storiesPath = path.join(packagePath, "src", "stories");
export const hooksPath = path.join(packagePath, "src", "hooks");
export const componentsPath = path.join(packagePath, "src", "components");
129 changes: 129 additions & 0 deletions scripts/docs/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import fs from "node:fs";
import path from "node:path";

import jsdom from "jsdom";
import MarkdownIt from "markdown-it";

import { docsPath, hooksPath, languagesFormat } from "../const";

import { readDirRecursively, tableToJson } from "./utils";

const md = new MarkdownIt();

async function writeComment(markdownPath) {
const markdown = fs.readFileSync(markdownPath, "utf-8");
const result = md.render(markdown, "utf-8");
const dom: HTMLElement = new jsdom.JSDOM(result).window.document;

const target = dom.querySelector("h3")?.textContent;
const targetDescription = dom.querySelectorAll("p")[0]?.textContent;
const targetRequireParameterList = tableToJson(dom.querySelectorAll("table")[0]);
const targetRequireParameterInsertList: string[] = [];
for (const row of targetRequireParameterList) {
let targetRequireParameterContent = " * @param";
for (let i = 0; i < row.length; i++) {
if ((i == 0 || i == 3) && row[i]?.textContent) {
const replacedStr = row[i].innerHTML
.replace(/<a href="(.*)">(.*)<\/a>/, "[$2]($1)")
.replace(/<code>(.*?)<\/code>/g, "`$1`");
targetRequireParameterContent = targetRequireParameterContent + " " + replacedStr;
}
if (i == 1 && row[i]?.textContent) {
targetRequireParameterContent =
targetRequireParameterContent + " " + "{" + row[i].textContent + "}";
}
}
targetRequireParameterInsertList.push(targetRequireParameterContent);
}
const targetReturnParameterList = tableToJson(dom.querySelectorAll("table")[1]);
const targetReturnParameterInsertList: string[] = [];
for (const row of targetReturnParameterList) {
let targetReturnParameterContent = " * @return";
for (let i = 0; i < row.length; i++) {
if ((i == 0 || i == 1) && row[i]?.textContent) {
targetReturnParameterContent = targetReturnParameterContent + " " + row[i].textContent;
}
}
targetReturnParameterInsertList.push(targetReturnParameterContent);
}

const files = fs.readdirSync(hooksPath);
files.forEach(file => {
const filePath = path.join(hooksPath, file);

let content = fs.readFileSync(filePath, "utf-8");

if (content.includes(`export function ${target}`)) {
let comment = `
/**
* ${targetDescription}
*
`;
if (targetRequireParameterInsertList.length > 0) {
comment = comment.concat(targetRequireParameterInsertList.join("\n"));
}
if (targetReturnParameterInsertList.length > 0) {
comment = comment.concat(`\n`);
comment = comment.concat(targetReturnParameterInsertList.join("\n"));
}
comment = comment.concat(`\n */`);
const position = content.indexOf(`export function ${target}`);
content = content.slice(0, position - 1) + comment + content.slice(position - 1);
fs.writeFileSync(filePath, content);
}
});
}

async function cleanComment(filePath) {
let content = fs.readFileSync(filePath, "utf-8");
const regex = /\/\*(.*?)\*\//gs;

content = content.replace(regex, (match, group) => {
if (group.includes("@ignore")) {
return match;
} else if (group.includes("@__PURE__")) {
return match;
} else {
return "";
}
});
fs.writeFileSync(filePath, content);
}

//hooks clean
await readDirRecursively(`${hooksPath}`, async (filePath: string) => {
if (
filePath.includes("client.ts") ||
filePath.includes("context.ts") ||
filePath.includes("tracks.ts") ||
filePath.includes("users.ts")
) {
await cleanComment(filePath);
}
});

//hooks inject
await readDirRecursively(`${docsPath}/hooks`, async (filePath: string) => {
if (filePath.includes(languagesFormat[1])) {
await writeComment(filePath);
}
});

//interfaces clean
await readDirRecursively(`${hooksPath}`, async (filePath: string) => {
if (
filePath.includes("client.ts") ||
filePath.includes("context.ts") ||
filePath.includes("tracks.ts") ||
filePath.includes("users.ts")
) {
await cleanComment(filePath);
}
});

//interfaces inject
await readDirRecursively(`${docsPath}/hooks`, async (filePath: string) => {
if (filePath.includes(languagesFormat[1])) {
await writeComment(filePath);
}
});
99 changes: 99 additions & 0 deletions scripts/docs/component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import fs from "node:fs";
import path from "node:path";

import jsdom from "jsdom";
import MarkdownIt from "markdown-it";

import { componentsPath, docsPath, languagesFormat } from "../const";

import { readDirRecursively, tableToJson } from "./utils";

const md = new MarkdownIt();

async function writeComment(markdownPath) {
const markdown = fs.readFileSync(markdownPath, "utf-8");
const result = md.render(markdown, "utf-8");
const dom: HTMLElement = new jsdom.JSDOM(result).window.document;

const target = dom.querySelector("h3")?.textContent;
const targetDescription = dom.querySelectorAll("p")[0]?.textContent;
const targetRequireParameterList = tableToJson(dom.querySelectorAll("table")[0]);

const files = fs.readdirSync(componentsPath);
files.forEach(file => {
const filePath = path.join(componentsPath, file);

let content = fs.readFileSync(filePath, "utf-8");

if (content.includes(`export function ${target}`)) {
let comment = `
/**
* ${targetDescription}
`;
comment = comment.concat(`\n */`);
const position = content.indexOf(`export function ${target}`);
content = content.slice(0, position - 1) + comment + content.slice(position - 1);

for (const row of targetRequireParameterList) {
let interfaceName = "";
let replacedStr = "";
if (row[0]?.textContent) {
interfaceName = row[0].textContent;
}
if (row[3]?.innerHTML) {
replacedStr = row[3]?.innerHTML
.replace(/<a href="(.*)">(.*)<\/a>/, "[$2]($1)")
.replace(/&lt;li&gt;(.*?)&lt;\/li&gt;/g, "$1")
.replace(/<code>(.*?)<\/code>/g, "`$1`");
}
const interfaceComment = `
/**
* ${replacedStr}
*/\n`;
if (content.includes(`readonly ${interfaceName}`)) {
const interfacePosition = content.indexOf(`readonly ${interfaceName}`);
content =
content.slice(0, interfacePosition - 1) +
interfaceComment +
content.slice(interfacePosition - 1);
}
}
fs.writeFileSync(filePath, content);
}
});
}

async function cleanComment(filePath) {
let content = fs.readFileSync(filePath, "utf-8");
const regex = /\/\*(.*?)\*\//gs;

content = content.replace(regex, (match, group) => {
if (group.includes("@ignore")) {
return match;
} else if (group.includes("@__PURE__")) {
return match;
} else {
return "";
}
});
fs.writeFileSync(filePath, content);
}

//components clean
await readDirRecursively(`${componentsPath}`, async (filePath: string) => {
if (
!filePath.includes(".stories.tsx") &&
!filePath.includes("styles.ts") &&
!filePath.includes("TrackBoundary.tsx") &&
!filePath.includes("UserCover.tsx")
) {
await cleanComment(filePath);
}
});

// components inject
await readDirRecursively(`${docsPath}/components`, async (filePath: string) => {
if (filePath.includes(languagesFormat[1])) {
await writeComment(filePath);
}
});
32 changes: 32 additions & 0 deletions scripts/docs/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import fs from "node:fs";
import path from "node:path";

export function tableToJson(table) {
if (!table) {
return [];
}
const data: HTMLTableCellElement[][] = [];
for (let i = 1; i < table.rows.length; i++) {
const tableRow: HTMLTableRowElement = table.rows[i];
const rowData: HTMLTableCellElement[] = [];
for (let j = 0; j < tableRow.cells.length; j++) {
rowData.push(tableRow.cells[j]);
}
data.push(rowData);
}
return data;
}

export async function readDirRecursively(dir, handler) {
const files = fs.readdirSync(dir);
files.forEach(async file => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);

if (stat.isDirectory()) {
readDirRecursively(filePath, handler);
} else {
handler && handler(filePath);
}
});
}

0 comments on commit db25bba

Please sign in to comment.