/
extractArgTypes.ts
115 lines (103 loc) · 2.71 KB
/
extractArgTypes.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { ArgTypes } from '@storybook/api';
import { logger } from '@storybook/client-logger';
import type {
SvelteComponentDoc,
JSDocType,
JSDocKeyword,
JSDocTypeConst,
} from 'sveltedoc-parser/typings';
import { ArgTypesExtractor } from '../../lib/docgen';
type ComponentWithDocgen = {
__docgen: SvelteComponentDoc;
};
function hasKeyword(keyword: string, keywords: JSDocKeyword[]): boolean {
return keywords ? keywords.find((k) => k.name === keyword) != null : false;
}
export const extractArgTypes: ArgTypesExtractor = (component: ComponentWithDocgen) => {
try {
// eslint-disable-next-line no-underscore-dangle
const docgen = component.__docgen;
if (docgen) {
return createArgTypes(docgen);
}
} catch (err) {
logger.log(`Error extracting argTypes: ${err}`);
}
return {};
};
export const createArgTypes = (docgen: SvelteComponentDoc) => {
const results: ArgTypes = {};
docgen.data.forEach((item) => {
results[item.name] = {
control: parseTypeToControl(item.type),
name: item.name,
description: item.description,
type: {
required: hasKeyword('required', item.keywords),
name: item.type?.text,
},
table: {
type: {
summary: item.type?.text,
},
defaultValue: {
summary: item.defaultValue,
},
category: 'properties',
},
};
});
docgen.events.forEach((item) => {
results[`event_${item.name}`] = {
name: item.name,
description: item.description,
type: { name: 'void' },
table: {
category: 'events',
},
};
});
docgen.slots.forEach((item) => {
results[`slot_${item.name}`] = {
name: item.name,
description: [item.description, item.params?.map((p) => `\`${p.name}\``).join(' ')]
.filter((p) => p)
.join('\n\n'),
type: { name: 'void' },
table: {
category: 'slots',
},
};
});
return results;
};
/**
* Function to convert the type from sveltedoc-parser to a storybook type
* @param typeName
* @returns string
*/
const parseTypeToControl = (type: JSDocType): any => {
if (!type) {
return null;
}
if (type.kind === 'type') {
switch (type.type) {
case 'string':
return { type: 'text' };
case 'enum':
return { type: 'radio' };
case 'any':
return { type: 'object' };
default:
return { type: type.type };
}
} else if (type.kind === 'union') {
if (Array.isArray(type.type) && !type.type.find((t) => t.type !== 'string')) {
return {
type: 'radio',
options: type.type.filter((t) => t.kind === 'const').map((t: JSDocTypeConst) => t.value),
};
}
}
return null;
};