Fixed some errors in generator-types (#6095)
Co-authored-by: starasov <starasov@sportmaster.ru>pull/6152/merge
							parent
							
								
									8a0c8a8fb1
								
							
						
					
					
						commit
						75c65e094f
					
				|  | @ -3,18 +3,21 @@ const pkg = require('../../package.json'); | |||
| const { parseAndWrite } = require('./lib/index.js'); | ||||
| const rootPath = path.resolve(__dirname, '../../'); | ||||
| 
 | ||||
| try { | ||||
|   parseAndWrite({ | ||||
|     version: pkg.version, | ||||
|     name: 'ant-design-vue', | ||||
|     path: path.resolve(rootPath, './components'), | ||||
|     // default match lang
 | ||||
|     test: /en-US\.md/, | ||||
|     outputDir: path.resolve(rootPath, './vetur'), | ||||
|     tagPrefix: 'a-', | ||||
| parseAndWrite({ | ||||
|   version: pkg.version, | ||||
|   name: 'ant-design-vue', | ||||
|   path: path.resolve(rootPath, './components'), | ||||
|   typingsPath: path.resolve(rootPath, './typings/global.d.ts'), | ||||
|   // default match lang
 | ||||
|   test: /en-US\.md/, | ||||
|   outputDir: path.resolve(rootPath, './vetur'), | ||||
|   tagPrefix: 'a-', | ||||
| }) | ||||
|   .then(result => { | ||||
|     // eslint-disable-next-line no-console
 | ||||
|     console.log(`generator types success: ${result} tags generated`); | ||||
|   }) | ||||
|   .catch(error => { | ||||
|     console.error('generator types error', error); | ||||
|     return Promise.reject(error); | ||||
|   }); | ||||
|   // eslint-disable-next-line no-console
 | ||||
|   console.log('generator types success'); | ||||
| } catch (e) { | ||||
|   console.error('generator types error', e); | ||||
| } | ||||
|  |  | |||
|  | @ -34,14 +34,19 @@ function parserProps(tag: VueTag, line: any) { | |||
|   }); | ||||
| } | ||||
| 
 | ||||
| export function formatter(articals: Articals, componentName: string, tagPrefix = '') { | ||||
| export function formatter( | ||||
|   articals: Articals, | ||||
|   componentName: string, | ||||
|   kebabComponentName: string, | ||||
|   tagPrefix = '', | ||||
| ) { | ||||
|   if (!articals.length) { | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   const tags: VueTag[] = []; | ||||
|   const tag: VueTag = { | ||||
|     name: getComponentName(componentName, tagPrefix), | ||||
|     name: kebabComponentName, | ||||
|     slots: [], | ||||
|     events: [], | ||||
|     attributes: [], | ||||
|  | @ -80,9 +85,13 @@ export function formatter(articals: Articals, componentName: string, tagPrefix = | |||
|     } | ||||
| 
 | ||||
|     // 额外的子组件
 | ||||
|     if (tableTitle.includes(componentName) && !tableTitle.includes('events')) { | ||||
|     if ( | ||||
|       tableTitle.includes(componentName) && | ||||
|       !tableTitle.includes('events') && | ||||
|       !tableTitle.includes('()') | ||||
|     ) { | ||||
|       const childTag: VueTag = { | ||||
|         name: getComponentName(tableTitle.replace('.', ''), tagPrefix), | ||||
|         name: getComponentName(tableTitle.replaceAll('.', '').replaceAll('/', ''), tagPrefix), | ||||
|         slots: [], | ||||
|         events: [], | ||||
|         attributes: [], | ||||
|  | @ -93,6 +102,7 @@ export function formatter(articals: Articals, componentName: string, tagPrefix = | |||
|       tags.push(childTag); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     // 额外的子组件事件
 | ||||
|     if (tableTitle.includes(componentName) && tableTitle.includes('events')) { | ||||
|       const childTagName = getComponentName( | ||||
|  |  | |||
|  | @ -1,52 +1,91 @@ | |||
| import glob from 'fast-glob'; | ||||
| import { join, dirname } from 'path'; | ||||
| import { dirname, join } from 'path'; | ||||
| import { mdParser } from './parser'; | ||||
| import { formatter } from './formatter'; | ||||
| import { genWebTypes } from './web-types'; | ||||
| import { readFileSync, outputFileSync } from 'fs-extra'; | ||||
| import { outputFileSync, readFileSync } from 'fs-extra'; | ||||
| import type { Options, VueTag } from './type'; | ||||
| import { normalizePath, getComponentName } from './utils'; | ||||
| import { genVeturTags, genVeturAttributes } from './vetur'; | ||||
| import { getComponentName, normalizePath, toKebabCase } from './utils'; | ||||
| import { genVeturAttributes, genVeturTags } from './vetur'; | ||||
| 
 | ||||
| async function readMarkdown(options: Options) { | ||||
|   // const mds = await glob(normalizePath(`${options.path}/**/*.md`))
 | ||||
|   const mds = await glob(normalizePath(`${options.path}/**/*.md`)); | ||||
|   return mds | ||||
| async function readMarkdown(options: Options): Promise<Map<String, VueTag>> { | ||||
|   const mdPaths = await glob(normalizePath(`${options.path}/**/*.md`)); | ||||
|   const data = mdPaths | ||||
|     .filter(md => options.test.test(md)) | ||||
|     .map(path => { | ||||
|       const docPath = dirname(path); | ||||
|       const componentName = docPath.substring(docPath.lastIndexOf('/') + 1); | ||||
|       return { | ||||
|         componentName: getComponentName(componentName || ''), | ||||
|         md: readFileSync(path, 'utf-8'), | ||||
|       }; | ||||
|     }); | ||||
|       const kebabComponentName = | ||||
|         options.tagPrefix + docPath.substring(docPath.lastIndexOf('/') + 1) || ''; | ||||
|       const componentName = getComponentName(docPath.substring(docPath.lastIndexOf('/') + 1) || ''); | ||||
|       const fileContent = readFileSync(path, 'utf-8'); | ||||
|       return formatter(mdParser(fileContent), componentName, kebabComponentName, options.tagPrefix); | ||||
|     }) | ||||
|     .filter(item => item) as VueTag[][]; | ||||
|   const tags: Map<String, VueTag> = new Map(); | ||||
|   data.flatMap(item => item).forEach(mergedTag => mergeTag(tags, mergedTag)); | ||||
|   return tags; | ||||
| } | ||||
| 
 | ||||
| export async function parseAndWrite(options: Options) { | ||||
| function readTypings(options: Options): Map<String, VueTag> { | ||||
|   const tags: Map<String, VueTag> = new Map(); | ||||
|   const fileContent = readFileSync(options.typingsPath, 'utf-8'); | ||||
|   fileContent | ||||
|     .split('\n') | ||||
|     .filter(line => line && line.includes('typeof')) | ||||
|     .map(line => { | ||||
|       const l = line.trim(); | ||||
|       return toKebabCase(l.substring(0, l.indexOf(':'))); | ||||
|     }) | ||||
|     .forEach(tagName => | ||||
|       tags.set(tagName, { | ||||
|         name: tagName, | ||||
|         slots: [], | ||||
|         events: [], | ||||
|         attributes: [], | ||||
|       }), | ||||
|     ); | ||||
|   return tags; | ||||
| } | ||||
| 
 | ||||
| function mergeTag(tags: Map<String, VueTag>, mergedTag: VueTag) { | ||||
|   const tagName = mergedTag.name; | ||||
|   const vueTag = tags.get(tagName); | ||||
|   if (vueTag) { | ||||
|     vueTag.slots = [...vueTag.slots, ...mergedTag.slots]; | ||||
|     vueTag.events = [...vueTag.events, ...mergedTag.events]; | ||||
|     vueTag.attributes = [...vueTag.attributes, ...mergedTag.attributes]; | ||||
|   } else { | ||||
|     tags.set(tagName, mergedTag); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function mergeTags(mergedTagsArr: Map<String, VueTag>[]): VueTag[] { | ||||
|   if (mergedTagsArr.length === 1) return [...mergedTagsArr[0].values()]; | ||||
|   const tags: Map<String, VueTag> = new Map(); | ||||
|   if (mergedTagsArr.length === 0) return []; | ||||
|   mergedTagsArr.forEach(mergedTags => { | ||||
|     mergedTags.forEach(mergedTag => mergeTag(tags, mergedTag)); | ||||
|   }); | ||||
|   return [...tags.values()]; | ||||
| } | ||||
| 
 | ||||
| export async function parseAndWrite(options: Options): Promise<Number> { | ||||
|   if (!options.outputDir) { | ||||
|     throw new Error('outputDir can not be empty.'); | ||||
|   } | ||||
| 
 | ||||
|   const docs = await readMarkdown(options); | ||||
|   const datas = docs | ||||
|     .map(doc => formatter(mdParser(doc.md), doc.componentName, options.tagPrefix)) | ||||
|     .filter(item => item) as VueTag[][]; | ||||
|   const tags: VueTag[] = []; | ||||
|   datas.forEach(arr => { | ||||
|     tags.push(...arr); | ||||
|   }); | ||||
| 
 | ||||
|   const tagsFromMarkdown = await readMarkdown(options); | ||||
|   const tagsFromTypings = await readTypings(options); | ||||
|   const tags = mergeTags([tagsFromMarkdown, tagsFromTypings]); | ||||
|   const webTypes = genWebTypes(tags, options); | ||||
|   const veturTags = genVeturTags(tags); | ||||
|   const veturAttributes = genVeturAttributes(tags); | ||||
| 
 | ||||
|   outputFileSync(join(options.outputDir, 'tags.json'), JSON.stringify(veturTags, null, 2)); | ||||
|   outputFileSync( | ||||
|     join(options.outputDir, 'attributes.json'), | ||||
|     JSON.stringify(veturAttributes, null, 2), | ||||
|   ); | ||||
|   outputFileSync(join(options.outputDir, 'web-types.json'), JSON.stringify(webTypes, null, 2)); | ||||
|   return tags.length; | ||||
| } | ||||
| 
 | ||||
| export default { parseAndWrite }; | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ function readLine(input: string) { | |||
| function splitTableLine(line: string) { | ||||
|   line = line.replace(/\\\|/g, 'JOIN'); | ||||
| 
 | ||||
|   const items = line.split('|').map(item => item.trim().replace('JOIN', '|')); | ||||
|   const items = line.split('|').map(item => item.trim().replaceAll('JOIN', '|')); | ||||
| 
 | ||||
|   // remove pipe character on both sides
 | ||||
|   items.pop(); | ||||
|  | @ -77,11 +77,6 @@ export function mdParser(input: string): Articals { | |||
|   const artical = []; | ||||
|   let start = 0; | ||||
|   const end = input.length; | ||||
|   // artical.push({
 | ||||
|   //   type: 'title',
 | ||||
|   //   content: title,
 | ||||
|   //   level: 0,
 | ||||
|   // });
 | ||||
| 
 | ||||
|   while (start < end) { | ||||
|     const target = input.substr(start); | ||||
|  | @ -108,6 +103,5 @@ export function mdParser(input: string): Articals { | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // artical[0].content = title
 | ||||
|   return artical; | ||||
| } | ||||
|  |  | |||
|  | @ -28,9 +28,9 @@ export type VueAttribute = { | |||
| 
 | ||||
| export type VueTag = { | ||||
|   name: string; | ||||
|   slots?: VueSlot[]; | ||||
|   events?: VueEvent[]; | ||||
|   attributes?: VueAttribute[]; | ||||
|   slots: VueSlot[]; | ||||
|   events: VueEvent[]; | ||||
|   attributes: VueAttribute[]; | ||||
|   description?: string; | ||||
| }; | ||||
| 
 | ||||
|  | @ -56,6 +56,7 @@ export type VeturResult = { | |||
| export type Options = { | ||||
|   name: string; | ||||
|   path: PathLike; | ||||
|   typingsPath: PathLike; | ||||
|   test: RegExp; | ||||
|   version: string; | ||||
|   outputDir?: string; | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| // myName -> my-name
 | ||||
| export function toKebabCase(input: string): string { | ||||
|   return input.replace(/[A-Z]/g, (val, index) => (index === 0 ? '' : '-') + val.toLowerCase()); | ||||
| export function toKebabCase(camel: string): string { | ||||
|   return camel.replace(/((?<=[a-z\d])[A-Z]|(?<=[A-Z\d])[A-Z](?=[a-z]))/g, '-$1').toLowerCase(); | ||||
| } | ||||
| 
 | ||||
| // name `v2.0.0` -> name
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 tarasovsn
						tarasovsn