Skip to content

Commit

Permalink
Merge branch 'apiDocs' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
matto49 committed Aug 10, 2023
2 parents 64a839c + ceea53f commit ee16670
Show file tree
Hide file tree
Showing 28 changed files with 2,489 additions and 137 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"private": true,
"scripts": {
"preinstall": "npx only-allow pnpm",
"start": "npm run build:props && npm run build:catalog && cd packages/demo && npm run start",
"start": "npm run build:catalog && cd packages/demo && npm run start",
"start:loader": "pnpm --filter demo start:loader",
"build:props": "node ./scripts/build_props.mjs",
"build:catalog": "node ./scripts/build_catalog.mjs"
},
Expand All @@ -25,4 +26,4 @@
"core-js": "^3.25.1",
"gsap": "^3.12.2"
}
}
}
1 change: 1 addition & 0 deletions packages/demo/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './index.scss';
96 changes: 96 additions & 0 deletions packages/demo/loaders/api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const parser_1 = require("@babel/parser");
const core_1 = require("@babel/core");
const path_1 = require("path");
// const curDir = path.dirname(fileURLToPath(import.meta.url));
const curDir = __dirname;
function getPivotDesignProps() {
return getProps((0, path_1.resolve)(curDir, '../../../design-props/components/index.ts'));
}
function parseComment(commentStr) {
let props = {};
if (!commentStr) {
return props;
}
const COMMENT_REG = /@(\w+)\s+(.+)/g;
for (const prop of commentStr.matchAll(COMMENT_REG)) {
const [, key, val] = prop;
props[key] = val;
}
return props;
}
function getProps(path) {
if (!(0, fs_1.existsSync)(path)) {
throw `<API />设置的props所在路径${path}不存在`;
}
const sourceCode = (0, fs_1.readFileSync)(path, { encoding: 'utf-8' });
const ast = (0, parser_1.parse)(sourceCode, {
// 不确定是module还是es6写法
sourceType: 'unambiguous',
plugins: ['typescript'],
});
let returnProps = new Map();
// 该函数返回值是代码,所以只好在plugin的post部分修改了props值
(0, core_1.traverse)(ast, {
TSInterfaceDeclaration: (path) => {
const { name } = path.node.id;
const extendsVal = path.node.extends;
if (!returnProps.has(name)) {
returnProps.set(name, []);
}
extendsVal?.forEach((item) => {
if (item.expression.name === 'PivotDesignProps') {
const props = getPivotDesignProps().get('PivotDesignProps');
returnProps.set(name, props);
}
});
path.traverse({
TSPropertySignature: (p) => {
if (p.parentKey === 'members')
return;
// "'--button-background-color'"的特殊处理
const key = p.get('key').toString().replaceAll(/['"]/g, '');
const value = p.get('typeAnnotation').toString().slice(1);
const optional = p.get('optional').node;
const commentStr = p.get('leadingComments').length > 0 && p.get('leadingComments')[0].node.value;
const comments = parseComment(commentStr);
let props = returnProps.get(name);
const newProps = { key, value, optional, ...comments };
props.push(newProps);
returnProps.set(name, props);
},
});
},
});
return returnProps;
}
function getPropsNode(props) {
let node = '';
for (const key of props.keys()) {
const val = props.get(key);
node += `export const ${key}Props = ${JSON.stringify(val)}\n
<ApiTable name='${key}' params={${key}Props}></ApiTable>\n`;
}
return node;
}
function loader(source) {
let sourceCode = source.trim();
const apiBlockReg = /<Api\s+path=(["'])([^"']+)\1(><\/Api>|\s+\/>)/g;
const matchValArr = sourceCode.matchAll(apiBlockReg);
const arr = Array.from(matchValArr);
if (arr.length) {
for (let matchVal of arr) {
let [initialVal, , pathVal] = matchVal;
pathVal = (0, path_1.join)(curDir, '../../../design-props', pathVal);
const props = getProps(pathVal);
const propsNode = getPropsNode(props);
sourceCode = sourceCode.replace(initialVal, propsNode);
}
// 添加ApiTable的import\
sourceCode = 'import ApiTable from "../../ApiTable.tsx";\n\n' + sourceCode;
}
return sourceCode;
}
exports.default = loader;
105 changes: 105 additions & 0 deletions packages/demo/loaders/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { existsSync, readFileSync } from 'fs';
import { parse } from '@babel/parser';
import { declare } from '@babel/helper-plugin-utils';
import { transformFromAstSync, traverse } from '@babel/core';
import { ParamsMap } from './type';
import { join, resolve } from 'path';

// const curDir = path.dirname(fileURLToPath(import.meta.url));
const curDir = __dirname;

function getPivotDesignProps() {
return getProps(resolve(curDir, '../../../design-props/components/index.ts'));
}

function parseComment(commentStr: string) {
let props = {};
if (!commentStr) {
return props;
}
const COMMENT_REG = /@(\w+)\s+(.+)/g;
for (const prop of commentStr.matchAll(COMMENT_REG)) {
const [, key, val] = prop;
props[key] = val;
}
return props;
}

function getProps(path: string) {
if (!existsSync(path)) {
throw `<API />设置的props所在路径${path}不存在`;
}
const sourceCode = readFileSync(path, { encoding: 'utf-8' });
const ast = parse(sourceCode, {
// 不确定是module还是es6写法
sourceType: 'unambiguous',
plugins: ['typescript'],
});
let returnProps = new Map();
// 该函数返回值是代码,所以只好在plugin的post部分修改了props值
traverse(ast, {
TSInterfaceDeclaration: (path) => {
const { name } = path.node.id;
const extendsVal = path.node.extends;
if (!returnProps.has(name)) {
returnProps.set(name, []);
}
extendsVal?.forEach((item) => {
if (item.expression.name === 'PivotDesignProps') {
const props = getPivotDesignProps().get('PivotDesignProps');
returnProps.set(name, props);
}
});
path.traverse({
TSPropertySignature: (p) => {
if (p.parentKey === 'members') return;
// "'--button-background-color'"的特殊处理
const key = p.get('key').toString().replaceAll(/['"]/g, '');
const value = p.get('typeAnnotation').toString().slice(1);
const optional = p.get('optional').node;
const commentStr = p.get('leadingComments').length > 0 && p.get('leadingComments')[0].node.value;
const comments = parseComment(commentStr);
let props = returnProps.get(name);
const newProps = { key, value, optional, ...comments };
props.push(newProps);
returnProps.set(name, props);
},
});
},
});
return returnProps;
}

function getPropsNode(props: ParamsMap) {
let node = '';
for (const key of props.keys()) {
const val = props.get(key);
node += `export const ${key}Props = ${JSON.stringify(val)}\n
<ApiTable name='${key}' params={${key}Props}></ApiTable>\n`;
}
return node;
}

function loader(source: string) {
let sourceCode = source.trim();

const apiBlockReg = /<Api\s+path=(["'])([^"']+)\1(><\/Api>|\s+\/>)/g;

const matchValArr = sourceCode.matchAll(apiBlockReg);
const arr = Array.from(matchValArr);
if (arr.length) {
for (let matchVal of arr) {
let [initialVal, , pathVal] = matchVal;
pathVal = join(curDir, '../../../design-props', pathVal);
const props = getProps(pathVal);
const propsNode = getPropsNode(props);
sourceCode = sourceCode.replace(initialVal, propsNode);
}
// 添加ApiTable的import\
sourceCode = 'import ApiTable from "../../ApiTable.tsx";\n\n' + sourceCode;
}

return sourceCode;
}

export default loader;
2 changes: 2 additions & 0 deletions packages/demo/loaders/api/type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
12 changes: 12 additions & 0 deletions packages/demo/loaders/api/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface Param {
key: string;
value: string;
optional: boolean;
version: string;
description: string;
default: string;
}

export type Params = Param[];

export type ParamsMap = Map<string, Params>;
6 changes: 3 additions & 3 deletions packages/demo/loaders/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ module.exports = function loader(source) {
// 如 <demo />
const importName = isImport
? m[2]
.match(/<([\s\S]*?)\/>/g)[0]
.slice(1, -2)
.trim()
.match(/<([\s\S]*?)\/>/g)[0]
.slice(1, -2)
.trim()
: null;

if (isImport) {
Expand Down
12 changes: 12 additions & 0 deletions packages/demo/loaders/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
},
"target": "ESNext",
"module": "CommonJS",
"noEmitOnError": false,
"allowSyntheticDefaultImports": true
},
}
15 changes: 13 additions & 2 deletions packages/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,30 @@
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack serve --mode development --open --hot",
"start": "webpack serve --mode development --hot",
"start:loader": "concurrently \"pnpm start\" \"pnpm loader:dev\"",
"loader:dev": "cd ./loaders && tsc -w",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.19.1",
"@babel/core": "^7.19.3",
"@babel/parser": "^7.22.7",
"@babel/plugin-transform-react-jsx": "^7.22.5",
"@babel/preset-env": "^7.19.1",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
"@types/babel__core": "^7.20.1",
"@types/babel__helper-plugin-utils": "^7.10.0",
"@types/babel__parser": "^7.1.1",
"@types/node": "^18.7.18",
"@types/prismjs": "^1.26.0",
"@types/react": "^18.0.20",
"@types/react-dom": "^18.0.6",
"babel-loader": "^8.2.5",
"concurrently": "^8.2.0",
"core-js": "^3.25.1",
"css-loader": "^6.7.1",
"eslint": "^8.28.0",
Expand All @@ -36,8 +44,11 @@
"webpack-dev-server": "^4.11.0"
},
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
"@mdx-js/loader": "^2.1.5",
"@mdx-js/react": "^2.3.0",
"@types/babel-core": "^6.25.7",
"babel": "^6.23.0",
"babel-plugin-prismjs": "^2.1.0",
"gsap": "^3.11.5",
"pivot-design": "workspace:*",
Expand Down
45 changes: 45 additions & 0 deletions packages/demo/src/ApiTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Params } from '../loaders/api/type';
import React from 'react';
import './index.scss';

interface ITableProps {
name: string;
params: Params;
}

const ApiTable: React.FC<ITableProps> = ({ name, params }) => {
// console.log(params, name);
return (
<>
<h3 className="pivot-props-apiTitle">{name}</h3>
<table className="pivot-props-table">
<thead>
<tr>
<th>参数名称</th>
<th>说明</th>
<th>参数类型</th>
<th>默认值</th>
<th>版本支持</th>
</tr>
</thead>
<tbody>
{params.map((param) => {
return (
<tr>
<td style={{ width: '15%' }}>{param.key}</td>
<td style={{ width: '40%' }}>{param.description}</td>
<td style={{ width: '20%' }}>{param.value}</td>
<td style={{ width: '15%' }}>
{param.default && param.default.length && param.default !== 'undefined' ? param.default : '—'}
</td>
<td style={{ width: '10%' }}>{param.version}</td>
</tr>
);
})}
</tbody>
</table>
</>
);
};

export default ApiTable;
3 changes: 2 additions & 1 deletion packages/demo/src/components/Button/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ import Props from './props.mdx';
<Loading />
</CodeBlock>

<Props />
{/* 导入的是design-props下路径的文件 */}
<Api path="/components/button.ts" />
6 changes: 3 additions & 3 deletions packages/demo/src/components/Card/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ import Props from './props.mdx';
## 加载中

<CodeBlock line={'5-7'}>
<Loading />
<Loading/>
</CodeBlock>

<Props />
{/* 导入的是design-props下路径的文件 */}
<Api path="/components/card.ts" />
3 changes: 2 additions & 1 deletion packages/demo/src/components/Draggable/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,5 @@ import Props from './props.mdx';
<MultipleContainer />
</CodeBlock>

<Props />
{/* 导入的是design-props下路径的文件 */}
<Api path="/components/draggable.ts" />
Loading

0 comments on commit ee16670

Please sign in to comment.