2020-01-19 14:09:32 +08:00

141 lines
2.9 KiB
TypeScript

import { join } from 'path';
import { mdParser } from './md-parser';
import { codegen, Tag, Attribute } from './codegen';
import {
PathLike,
statSync,
mkdirSync,
existsSync,
readdirSync,
readFileSync,
writeFileSync,
} from 'fs';
export function parseText(input: string) {
const ast = mdParser(input);
return codegen(ast);
}
export type Options = {
// 需要解析的文件夹路径
path: PathLike;
// 文件匹配正则
test: RegExp;
// 输出目录
outputDir?: string;
// 递归的目录最大深度
maxDeep?: number;
// 解析出来的组件名前缀
tagPrefix?: string;
};
export type ParseResult = {
tags: Record<
string,
{
description: string;
attributes: string[];
}
>;
attributes: Record<string, Attribute>;
};
const defaultOptions = {
maxDeep: Infinity,
tagPrefix: '',
};
export function parse(options: Options) {
options = {
...defaultOptions,
...options,
};
const result: ParseResult = {
tags: {},
attributes: {},
};
function putResult(componentName: string, component: Tag) {
componentName = options.tagPrefix + componentName;
const attributes = Object.keys(component.attributes);
const tag = {
description: component.description,
attributes,
};
result.tags[componentName] = tag;
attributes.forEach(key => {
result.attributes[`${componentName}/${key}`] = component.attributes[key];
});
}
function recursiveParse(options: Options, deep: number) {
if (options.maxDeep && deep > options.maxDeep) {
return;
}
deep++;
const files = readdirSync(options.path);
files.forEach(item => {
const currentPath = join(options.path.toString(), item);
const stats = statSync(currentPath);
if (stats.isDirectory()) {
recursiveParse(
{
...options,
path: currentPath,
},
deep
);
} else if (stats.isFile() && options.test.test(item)) {
const file = readFileSync(currentPath);
const tags = parseText(file.toString());
if (tags.default) {
// one tag
putResult(currentPath.split('/').slice(-2)[0], tags.default);
} else {
Object.keys(tags).forEach(key => {
putResult(key, tags[key]);
});
}
}
});
}
recursiveParse(options, 0);
return result;
}
export function parseAndWrite(options: Options) {
const { tags, attributes } = parse(options);
if (!options.outputDir) {
return;
}
const isExist = existsSync(options.outputDir);
if (!isExist) {
mkdirSync(options.outputDir);
}
writeFileSync(
join(options.outputDir, 'tags.json'),
JSON.stringify(tags, null, 2)
);
writeFileSync(
join(options.outputDir, 'attributes.json'),
JSON.stringify(attributes, null, 2)
);
}
export default {
parse,
parseText,
parseAndWrite,
};