1 | import isNumber from './prop-is-number.js'
|
2 |
|
3 | const isActionable = item =>
|
4 |
|
5 |
|
6 |
|
7 | item.name !== 'onWhen' && /^on[A-Z]/.test(item.name)
|
8 |
|
9 | const extractPropsAndItems = item => {
|
10 | const props = []
|
11 | const regex = /(props|item)\.([a-zA-Z][a-zA-Z0-9.]*[a-zA-Z0-9]+)(.)?/g
|
12 |
|
13 | let matches = regex.exec(item.value)
|
14 | while (matches !== null) {
|
15 |
|
16 | if (matches.index === regex.lastIndex) {
|
17 | regex.lastIndex++
|
18 | }
|
19 |
|
20 | const isExplicitFunctionCall = matches[3] === '('
|
21 | props.push({
|
22 | isItem: matches[1] === 'item',
|
23 | path: matches[2],
|
24 | type:
|
25 | isActionable(item) || isExplicitFunctionCall
|
26 | ? 'function'
|
27 | : isNumber[item.name] ? 'number' : 'string',
|
28 | })
|
29 | matches = regex.exec(item.value)
|
30 | }
|
31 | return props
|
32 | }
|
33 |
|
34 | const isList = item => item.type === 'List'
|
35 | const isListFrom = item => item.name === 'from' && isList(item)
|
36 |
|
37 | export default list => {
|
38 | const flatProps = {}
|
39 |
|
40 | let listFromPath
|
41 | list.forEach((item, index) => {
|
42 | extractPropsAndItems(item).forEach(propOrItem => {
|
43 | if (isListFrom(item)) {
|
44 |
|
45 | listFromPath = propOrItem.path
|
46 | } else if (isList(item) && propOrItem.path.endsWith('.length')) {
|
47 |
|
48 | return
|
49 | }
|
50 |
|
51 | if (propOrItem.isItem) {
|
52 |
|
53 | if (!listFromPath) return
|
54 |
|
55 | propOrItem.path = `${listFromPath}.${propOrItem.path}`
|
56 | }
|
57 |
|
58 | flatProps[propOrItem.path] = propOrItem
|
59 | })
|
60 | })
|
61 |
|
62 | const props = {}
|
63 |
|
64 | Object.keys(flatProps)
|
65 | .sort()
|
66 | .forEach(key => {
|
67 | const prop = flatProps[key]
|
68 |
|
69 | if (key.includes('.')) {
|
70 | const [main, ...rest] = key.split('.')
|
71 | let ref = props[main]
|
72 | if (!ref || typeof ref === 'string') {
|
73 | ref = props[main] = {
|
74 | type: prop.isItem ? 'array' : 'object',
|
75 | shape: {},
|
76 | }
|
77 | }
|
78 |
|
79 |
|
80 | rest.forEach(part => {
|
81 | ref.shape[part] = prop.type
|
82 | })
|
83 | } else {
|
84 | props[key] = prop.type
|
85 | }
|
86 | })
|
87 |
|
88 | return props
|
89 | }
|