Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"generate:themes-dev": "node scripts/generate-themes-dev.js",
"generate:file:taro": "node scripts/taro/generate-nutui-taro.js",
"generate:file:taro:pages": "node scripts/taro/generate-taro-pages.js",
"generate:props_json": "PROPS_JSON=true node scripts/build-comments-to-dts.mjs",
"lint": "eslint ./src/packages/*/",
"lint:fix": "eslint --fix ./src/packages",
"prepare": "husky && npm run generate:file && npm run generate:file:taro && npm run generate:file:taro:pages",
Expand Down
146 changes: 72 additions & 74 deletions scripts/build-comments-to-dts.mjs
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
/**
* 向生成的组件类型文件中注入注释
* 通过在其他脚本 import codeShift 方法,可以向生成的组件类型文件中增加 JSDoc
* 通过npm scripts 触发,可在 src/types 下生成 props.json 文件
*/
import * as path from 'path'
import { dirname } from 'path'
import fse from 'fs-extra'
import j from 'jscodeshift'
import markdownit from 'markdown-it'
import { fileURLToPath } from 'url'
import { dirname } from 'path'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const dist = 'release/h5/dist'

const PROPS_JSON = process.env.PROPS_JSON

/**
* 通过 cofnig.json 获取所有组件的数据
*/
function readAllComponents() {
const config = JSON.parse(fse.readFileSync(path.join(__dirname, '../src/config.json')).toString())
const components = config.nav.reduce(function (accumulator, currentValue) {
const components = config.nav.reduce(function(accumulator, currentValue) {
currentValue.packages.forEach((pkg) => {
if (pkg.exclude || pkg.version !== '2.0.0') {
if (pkg.exclude) {
return
}
accumulator.push(pkg)
Expand Down Expand Up @@ -52,7 +54,7 @@ function extractPropsTable(doc) {
token.type == 'heading_open' &&
token.tag == 'h3' &&
sources[index + 1].type == 'inline' &&
sources[index + 1].content === 'Props'
sources[index + 1].content.toLowerCase() == 'props'
) {
const componentName = sources[index - 2].content
let startIndex = index + 3
Expand Down Expand Up @@ -99,95 +101,91 @@ function markdownTable2Json(table) {
return rows
}

function addComments(dtsPath, propsTable, componentName) {
const source = fse.readFileSync(dtsPath).toString()

function findInTable(identifierName) {
const [info] = propsTable.filter(
(t) => t[0].replace(/'/g, '') === identifierName
)
return info
}

const transform = (file, api) => {
const j = api.jscodeshift.withParser('ts')
return j(file.source)
.find(j.TSInterfaceDeclaration, {
id: {
name: componentName + 'Props',
type: 'Identifier',
},
})
.forEach((path) => {
path.value?.body?.body?.forEach((item) => {
if (!item.key) return
const info = findInTable(item.key.name)
if (!info) return
item['comments'] = [
j.commentBlock(`*\n* ${info[1]}\n* @default ${info[3]}\n`),
]
})
})
.toSource()
}
const result = transform({ source }, { jscodeshift: j })
if (result) {
fse.writeFileSync(dtsPath, result)
}
}

function getDtsPath(key, outDir) {
// Tabs.Tabpane -> tabpane
let name
if (key === 'Tabs.Tabpane') {
name = 'tabpane'
} else {
name = key.toLowerCase().replace('.', '')
}
const file = path.join(__dirname, `../${outDir}/es/packages`, name, name + '.d.ts')
return file
}

function getComponentName(key) {
// Tabs.Tabpane -> tabpane
let name = key
if (key === 'Tabs.Tabpane') {
name = 'TabPane'
}
return name.replace('.', '')
}

/**
* step 1: 从 config.json 中读取组件列表,迭代
* step a: 读取组件的 doc.md 或 doc.taro.md
* step b: 提取文档中的 Props 相关的表格,并转换为 JSON 数据
* step c: 添加注释
*/
export function codeShift(env) {
export function codeShift(platform) {
const components = readAllComponents()
const componentsProps = {}
components.forEach((component) => {
const { name } = component
const componentDocumentPath = path.join(
__dirname,
'../src/packages',
name.toLowerCase(),
env === 'taro' ? 'doc.taro.md' : 'doc.md'
platform === 'taro' ? 'doc.taro.md' : 'doc.md',
)
if (fse.pathExistsSync(componentDocumentPath)) {
const tables = extractPropsTable(
readComponentDocument(componentDocumentPath)
readComponentDocument(componentDocumentPath),
)
Object.keys(tables).forEach((key) => {
const dtsPath = getDtsPath(key, env !== 'taro' ? dist : dist.replace('h5', env))
if (fse.pathExistsSync(dtsPath)) {
const table = markdownTable2Json(tables[key])
addComments(dtsPath, table, getComponentName(key))
} else {
console.warn(name + ' dts file does not exist')
}
const table = markdownTable2Json(tables[key])
componentsProps[key.toLowerCase()] = table.reduce((acc, [key, desc, types, defaultValue]) => {
acc[key] = {
desc: desc,
types: types,
defaultValue: defaultValue,
}
return acc
}, {})
})
} else {
// console.warn(name + ' document file does not exist')
}
if (!PROPS_JSON) {
if (!component.exportEmpty) addJSDoc(componentsProps, name, platform)
}
})
if (PROPS_JSON) {
const jsonContent = JSON.stringify(componentsProps, ' ', 2)
fse.writeFileSync(path.join(__dirname, '../src/types', `props.json`), jsonContent)
}
}

function addJSDoc(propsJson, componentName, platform) {
const transform = (file, api) => {
const j = api.jscodeshift.withParser('ts')
const ast = j(file.source)
function addComment(item) {
if (!item.key) return
const description = propsJson[componentName.toLowerCase()][item.key.name]
if (!description) return
item['comments'] = [
j.commentBlock(`*\n* ${description['desc']}\n`),
]
}
ast
.find(j.TSTypeAliasDeclaration).forEach((path) => {
const annotationTypes = path.value.typeAnnotation.types
if (!annotationTypes) return
const typeLiteral = annotationTypes[annotationTypes.length - 1]
if (!typeLiteral.members) return
typeLiteral.members.forEach((item) => {
addComment(item)
})
})
ast.find(j.TSInterfaceDeclaration, {
id: {
name: `Base${componentName}`,
type: 'Identifier',
},
})
.forEach((path) => {
path.value?.body?.body?.forEach((item) => {
addComment(item)
})
})

return ast.toSource()
}
const baseType = path.join(__dirname, `../release/${platform || 'h5'}/dist/es/types/spec/${componentName.toLowerCase()}/base.d.ts`)
const source = fse.readFileSync(baseType, { encoding: 'utf8' })
const result = transform({ source }, { jscodeshift: j })
fse.writeFileSync(baseType, result)
}

PROPS_JSON && codeShift('h5')
1 change: 0 additions & 1 deletion scripts/build-taro.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ const transform = (file, api, replace) => {
return
}
const dir = join(__dirname, alias.replace('@/', '../src/'))
console.log(alias, file)
if (file.path) {
path.node.source.value = relativePath(dir, file.path)?.replace(
'.taro',
Expand Down
1 change: 1 addition & 0 deletions src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@
"show": false,
"taro": true,
"author": "Alex.hxy",
"exportEmpty": true,
"dd": true
},
{
Expand Down
2 changes: 1 addition & 1 deletion src/packages/datepickerview/doc.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { DatePickerView } from '@nutui/nutui'

:::

## DatePicker
## DatePickerView

### Props

Expand Down
2 changes: 1 addition & 1 deletion src/packages/datepickerview/doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { DatePickerView } from '@nutui/nutui'

:::

## DatePicker
## DatePickerView

### Props

Expand Down
2 changes: 1 addition & 1 deletion src/packages/datepickerview/doc.taro.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { DatePickerView } from '@nutui/nutui-taro'

:::

## DatePicker
## DatePickerView

### Props

Expand Down
2 changes: 1 addition & 1 deletion src/packages/datepickerview/doc.zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { DatePickerView } from '@nutui/nutui'

:::

## DatePicker
## DatePickerView

### Props

Expand Down
2 changes: 1 addition & 1 deletion src/packages/rate/doc.taro.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ import { Rate } from '@nutui/nutui-react-taro'

## Rate

## Props
### Props

| 属性 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
Expand Down
10 changes: 7 additions & 3 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ export * from './spec/picker/base'
export * from './spec/picker/h5'
export * from './spec/picker/taro'

export * from './spec/pickerview/base'
export * from './spec/pickerview/h5'
export * from './spec/pickerview/taro'

export * from './spec/noticebar/base'
export * from './spec/noticebar/h5'
export * from './spec/noticebar/taro'
Expand Down Expand Up @@ -344,6 +348,6 @@ export * from './spec/audio/base'
export * from './spec/audio/h5'
export * from './spec/audio/taro'

export * from './spec/step/base'
export * from './spec/step/h5'
export * from './spec/step/taro'
export * from './spec/steps/base'
export * from './spec/steps/h5'
export * from './spec/steps/taro'
11 changes: 0 additions & 11 deletions src/types/spec/picker/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,3 @@ export interface BasePicker<POPUP_PROPS = any> extends BaseProps {
onChange?: (args0: PickerOnChangeCallbackParameter) => void
children?: any
}

export interface BasePickerView extends BaseProps {
setRefs?: (ref: any) => any
options: PickerOptions[]
value?: PickerValue[]
defaultValue?: PickerValue[]
threeDimensional?: boolean
duration?: number | string
renderLabel: (item: PickerOption) => React.ReactNode
onChange?: (arg0: PickerOnChangeCallbackParameter) => void
}
4 changes: 2 additions & 2 deletions src/types/spec/picker/h5.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BasePicker, BasePickerView, BasePickerRoller } from './base'
import { BasePicker, BasePickerRoller } from './base'
import { WebPopupProps } from '../popup/h5'

export interface WebPickerProps extends BasePicker<WebPopupProps> {}
export interface WebPickerViewProps extends BasePickerView {}

export interface WebPickerRollerProps extends BasePickerRoller {}
3 changes: 1 addition & 2 deletions src/types/spec/picker/taro.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { BasePicker, BasePickerRoller, BasePickerView } from './base'
import { BasePicker, BasePickerRoller } from './base'
import { TaroPopupProps } from '../popup/taro'

export interface TaroPickerProps extends BasePicker<TaroPopupProps> {}
export interface TaroPickerViewProps extends BasePickerView {}
export interface TaroPickerRollerProps extends BasePickerRoller {}
18 changes: 18 additions & 0 deletions src/types/spec/pickerview/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { BaseProps } from '../../base/props'
import {
PickerOnChangeCallbackParameter,
PickerOption,
PickerOptions,
PickerValue,
} from '../picker/base'

export interface BasePickerView extends BaseProps {
setRefs?: (ref: any) => any
options: PickerOptions[]
value?: PickerValue[]
defaultValue?: PickerValue[]
threeDimensional?: boolean
duration?: number | string
renderLabel: (item: PickerOption) => React.ReactNode
onChange?: (arg0: PickerOnChangeCallbackParameter) => void
}
3 changes: 3 additions & 0 deletions src/types/spec/pickerview/h5.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { BasePickerView } from './base'

export interface WebPickerViewProps extends BasePickerView {}
3 changes: 3 additions & 0 deletions src/types/spec/pickerview/taro.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { BasePickerView } from './base'

export interface TaroPickerViewProps extends BasePickerView {}
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading