handoff-app 1.0.6 → 1.1.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Changelog.md +2 -0
- package/dist/config.js +4 -0
- package/dist/transformers/docgen/index.d.ts +13 -6
- package/dist/transformers/docgen/index.js +207 -34
- package/dist/transformers/plugins/ssr-render.js +7 -1
- package/dist/transformers/preview/component/css.d.ts +1 -0
- package/dist/transformers/preview/component.d.ts +6 -0
- package/dist/transformers/preview/types.d.ts +2 -0
- package/dist/transformers/types.d.ts +0 -18
- package/dist/transformers/utils/schema-loader.js +2 -2
- package/dist/transformers/utils/schema.d.ts +2 -2
- package/dist/transformers/utils/schema.js +2 -2
- package/dist/types/config.d.ts +15 -0
- package/dist/types.d.ts +2 -0
- package/package.json +2 -1
- package/src/app/components/Component/Preview.tsx +324 -200
- package/src/app/components/Foundations/RulesSheet.tsx +10 -4
- package/src/app/pages/system/component/[component]/index.tsx +24 -10
- package/src/config.ts +4 -0
- package/src/transformers/README.md +3 -3
- package/src/transformers/docgen/index.ts +257 -42
- package/src/transformers/plugins/ssr-render.ts +14 -2
- package/src/transformers/preview/component.ts +6 -0
- package/src/transformers/preview/types.ts +2 -0
- package/src/transformers/types.ts +0 -18
- package/src/transformers/utils/schema-loader.ts +2 -2
- package/src/transformers/utils/schema.ts +2 -2
- package/src/types/config.ts +15 -0
- package/src/types.ts +2 -0
- package/templates/default/handoff.config.js.tpl +6 -0
- package/templates/default/handoff.config.with-examples.js.tpl +6 -0
package/Changelog.md
CHANGED
|
@@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
6
6
|
and this project adheres to
|
|
7
7
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
8
|
|
|
9
|
+
## \[1.1.0]
|
|
10
|
+
|
|
9
11
|
## \[1.0.6] - 2026-02-24
|
|
10
12
|
|
|
11
13
|
Version 1.0.4 fixed an issue when running Handoff in subpaths (eg.
|
package/dist/config.js
CHANGED
|
@@ -9,6 +9,10 @@ const defaultConfig = () => {
|
|
|
9
9
|
exportsOutputDirectory: (_c = process.env.HANDOFF_OUTPUT_DIR) !== null && _c !== void 0 ? _c : 'exported',
|
|
10
10
|
sitesOutputDirectory: (_d = process.env.HANDOFF_SITES_DIR) !== null && _d !== void 0 ? _d : 'out',
|
|
11
11
|
useVariables: (_e = Boolean(process.env.HANDOFF_USE_VARIABLES)) !== null && _e !== void 0 ? _e : false,
|
|
12
|
+
reactDocgen: {
|
|
13
|
+
maxDepth: 7,
|
|
14
|
+
excludeDirectories: ['dist', 'build', '.next'],
|
|
15
|
+
},
|
|
12
16
|
app: {
|
|
13
17
|
theme: 'default',
|
|
14
18
|
title: 'Convertiv Design System',
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { type GeneratedDocs } from 'handoff-docgen';
|
|
2
|
+
import { SlotMetadata } from '../preview/component';
|
|
3
|
+
export declare const getPropertiesFromGeneratedDocs: (generatedDocs: GeneratedDocs, entry: string, handoff: any) => {
|
|
4
|
+
[key: string]: SlotMetadata;
|
|
5
|
+
} | null;
|
|
6
|
+
export declare const enrichPropertiesWithDocgen: (properties: {
|
|
7
|
+
[key: string]: SlotMetadata;
|
|
8
|
+
} | null | undefined, docgenProperties: {
|
|
9
|
+
[key: string]: SlotMetadata;
|
|
10
|
+
} | null | undefined) => {
|
|
11
|
+
[key: string]: SlotMetadata;
|
|
12
|
+
} | null;
|
|
13
|
+
export declare const generateDocsArtifact: (entry: string, handoff: any) => Promise<GeneratedDocs | null>;
|
|
7
14
|
export declare const generatePropertiesFromDocgen: (entry: string, handoff: any) => Promise<{
|
|
8
15
|
[key: string]: any;
|
|
9
16
|
} | null>;
|
|
@@ -12,50 +12,223 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.generatePropertiesFromDocgen = void 0;
|
|
15
|
+
exports.generatePropertiesFromDocgen = exports.generateDocsArtifact = exports.enrichPropertiesWithDocgen = exports.getPropertiesFromGeneratedDocs = void 0;
|
|
16
16
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
17
17
|
const path_1 = __importDefault(require("path"));
|
|
18
|
-
const
|
|
18
|
+
const handoff_docgen_1 = require("handoff-docgen");
|
|
19
19
|
const logger_1 = require("../../utils/logger");
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
const component_1 = require("../preview/component");
|
|
21
|
+
const DEFAULT_DOCGEN_MAX_DEPTH = 7;
|
|
22
|
+
const DEFAULT_DOCGEN_EXCLUDE_DIRECTORIES = ['dist', 'build', '.next'];
|
|
23
|
+
const generatorCache = new Map();
|
|
24
|
+
const normalizePathForCompare = (filePath) => filePath.replace(/\\/g, '/');
|
|
25
|
+
const mapDocgenTypeToSlotType = (typeName) => {
|
|
26
|
+
const normalizedType = typeName === null || typeName === void 0 ? void 0 : typeName.trim().toLowerCase();
|
|
27
|
+
switch (normalizedType) {
|
|
28
|
+
case 'boolean':
|
|
29
|
+
return component_1.SlotType.BOOLEAN;
|
|
30
|
+
case 'number':
|
|
31
|
+
return component_1.SlotType.NUMBER;
|
|
32
|
+
case 'string':
|
|
33
|
+
return component_1.SlotType.TEXT;
|
|
34
|
+
case 'array':
|
|
35
|
+
return component_1.SlotType.ARRAY;
|
|
36
|
+
case 'object':
|
|
37
|
+
return component_1.SlotType.OBJECT;
|
|
38
|
+
case 'function':
|
|
39
|
+
return component_1.SlotType.FUNCTION;
|
|
40
|
+
case 'enum':
|
|
41
|
+
return component_1.SlotType.ENUM;
|
|
42
|
+
case 'any':
|
|
43
|
+
case 'unknown':
|
|
44
|
+
return component_1.SlotType.ANY;
|
|
45
|
+
default:
|
|
46
|
+
if (normalizedType === null || normalizedType === void 0 ? void 0 : normalizedType.includes('=>')) {
|
|
47
|
+
return component_1.SlotType.FUNCTION;
|
|
48
|
+
}
|
|
49
|
+
return component_1.SlotType.TEXT;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const getDocgenConfig = (handoff) => {
|
|
53
|
+
var _a, _b, _c;
|
|
54
|
+
const reactDocgenConfig = (_b = (_a = handoff === null || handoff === void 0 ? void 0 : handoff.config) === null || _a === void 0 ? void 0 : _a.reactDocgen) !== null && _b !== void 0 ? _b : (_c = handoff === null || handoff === void 0 ? void 0 : handoff.config) === null || _c === void 0 ? void 0 : _c.docgen;
|
|
55
|
+
const configuredMaxDepth = reactDocgenConfig === null || reactDocgenConfig === void 0 ? void 0 : reactDocgenConfig.maxDepth;
|
|
56
|
+
const configuredExcludeDirectories = reactDocgenConfig === null || reactDocgenConfig === void 0 ? void 0 : reactDocgenConfig.excludeDirectories;
|
|
57
|
+
const maxDepth = typeof configuredMaxDepth === 'number' && Number.isFinite(configuredMaxDepth) && configuredMaxDepth > 0
|
|
58
|
+
? Math.floor(configuredMaxDepth)
|
|
59
|
+
: DEFAULT_DOCGEN_MAX_DEPTH;
|
|
60
|
+
const excludeDirectories = Array.isArray(configuredExcludeDirectories)
|
|
61
|
+
? configuredExcludeDirectories
|
|
62
|
+
.map((entry) => String(entry).trim())
|
|
63
|
+
.filter((entry) => entry.length > 0)
|
|
64
|
+
: DEFAULT_DOCGEN_EXCLUDE_DIRECTORIES;
|
|
65
|
+
return {
|
|
66
|
+
maxDepth,
|
|
67
|
+
excludeDirectories: excludeDirectories.length > 0 ? excludeDirectories : DEFAULT_DOCGEN_EXCLUDE_DIRECTORIES,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
const getGenerator = (componentDirectory, tsconfigPath, maxDepth, excludeDirectories) => {
|
|
71
|
+
const cacheKey = `${componentDirectory}::${tsconfigPath}::${maxDepth}::${excludeDirectories.join('|')}`;
|
|
72
|
+
const cached = generatorCache.get(cacheKey);
|
|
73
|
+
if (cached) {
|
|
74
|
+
return cached;
|
|
75
|
+
}
|
|
76
|
+
const generator = (0, handoff_docgen_1.createGenerator)({
|
|
77
|
+
componentDirectory,
|
|
78
|
+
tsconfigPath,
|
|
79
|
+
maxDepth,
|
|
80
|
+
pathMode: 'relative',
|
|
81
|
+
excludeDirectories,
|
|
82
|
+
});
|
|
83
|
+
generatorCache.set(cacheKey, generator);
|
|
84
|
+
return generator;
|
|
85
|
+
};
|
|
86
|
+
const findComponentDocForEntry = (generatedDocs, entry, handoff) => {
|
|
87
|
+
const normalizedEntryAbsolute = normalizePathForCompare(path_1.default.resolve(entry));
|
|
88
|
+
const normalizedEntryRelative = normalizePathForCompare(path_1.default.relative(handoff.workingPath, normalizedEntryAbsolute));
|
|
89
|
+
const entryBasename = path_1.default.basename(normalizedEntryAbsolute, path_1.default.extname(normalizedEntryAbsolute));
|
|
90
|
+
const matchesByFile = generatedDocs.components.filter((component) => {
|
|
91
|
+
const source = normalizePathForCompare(component.sourceFile);
|
|
92
|
+
return source === normalizedEntryAbsolute || source === normalizedEntryRelative || source.endsWith(`/${normalizedEntryRelative}`);
|
|
93
|
+
});
|
|
94
|
+
if (matchesByFile.length > 0) {
|
|
95
|
+
return matchesByFile[0];
|
|
96
|
+
}
|
|
97
|
+
const matchesByName = generatedDocs.components.filter((component) => component.name === entryBasename);
|
|
98
|
+
if (matchesByName.length > 0) {
|
|
99
|
+
return matchesByName[0];
|
|
100
|
+
}
|
|
101
|
+
return generatedDocs.components[0];
|
|
102
|
+
};
|
|
103
|
+
const toSlotMetadata = (prop) => {
|
|
104
|
+
var _a, _b;
|
|
105
|
+
const slotType = mapDocgenTypeToSlotType(prop.docgenType || ((_a = prop.deepType) === null || _a === void 0 ? void 0 : _a.kind) || 'any');
|
|
106
|
+
const deepType = prop.deepType;
|
|
107
|
+
const metadata = {
|
|
108
|
+
id: prop.name,
|
|
109
|
+
name: prop.name,
|
|
110
|
+
description: prop.description || '',
|
|
111
|
+
generic: (deepType === null || deepType === void 0 ? void 0 : deepType.display) || prop.docgenType || '',
|
|
112
|
+
default: prop.defaultValue,
|
|
113
|
+
type: slotType,
|
|
114
|
+
rules: {
|
|
115
|
+
required: !!prop.required,
|
|
116
|
+
},
|
|
117
|
+
docgenType: prop.docgenType,
|
|
118
|
+
deepType: prop.deepType,
|
|
119
|
+
typeRefs: prop.typeRefs,
|
|
120
|
+
warnings: prop.warnings,
|
|
121
|
+
annotations: prop.annotations,
|
|
122
|
+
};
|
|
123
|
+
if ((deepType === null || deepType === void 0 ? void 0 : deepType.kind) === 'object' && ((_b = deepType.properties) === null || _b === void 0 ? void 0 : _b.length)) {
|
|
124
|
+
metadata.type = component_1.SlotType.OBJECT;
|
|
125
|
+
metadata.properties = Object.fromEntries(deepType.properties.map((property) => {
|
|
126
|
+
var _a, _b;
|
|
127
|
+
return [
|
|
128
|
+
property.name,
|
|
129
|
+
toSlotMetadata({
|
|
130
|
+
name: property.name,
|
|
131
|
+
required: !property.optional,
|
|
132
|
+
description: property.description,
|
|
133
|
+
docgenType: ((_a = property.type) === null || _a === void 0 ? void 0 : _a.display) || ((_b = property.type) === null || _b === void 0 ? void 0 : _b.kind) || 'unknown',
|
|
134
|
+
deepType: property.type,
|
|
135
|
+
annotations: property.annotations,
|
|
136
|
+
}),
|
|
137
|
+
];
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
else if ((deepType === null || deepType === void 0 ? void 0 : deepType.kind) === 'array' && deepType.elementType) {
|
|
141
|
+
metadata.type = component_1.SlotType.ARRAY;
|
|
142
|
+
metadata.items = {
|
|
143
|
+
type: mapDocgenTypeToSlotType(deepType.elementType.display || deepType.elementType.kind),
|
|
144
|
+
properties: deepType.elementType.kind === 'object' && deepType.elementType.properties
|
|
145
|
+
? Object.fromEntries(deepType.elementType.properties.map((property) => {
|
|
146
|
+
var _a, _b;
|
|
147
|
+
return [
|
|
148
|
+
property.name,
|
|
149
|
+
toSlotMetadata({
|
|
150
|
+
name: property.name,
|
|
151
|
+
required: !property.optional,
|
|
152
|
+
description: property.description,
|
|
153
|
+
docgenType: ((_a = property.type) === null || _a === void 0 ? void 0 : _a.display) || ((_b = property.type) === null || _b === void 0 ? void 0 : _b.kind) || 'unknown',
|
|
154
|
+
deepType: property.type,
|
|
155
|
+
annotations: property.annotations,
|
|
156
|
+
}),
|
|
157
|
+
];
|
|
158
|
+
}))
|
|
159
|
+
: undefined,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
return metadata;
|
|
163
|
+
};
|
|
164
|
+
const toPropertiesMap = (generatedDocs, entry, handoff) => {
|
|
165
|
+
var _a;
|
|
166
|
+
if (!generatedDocs.components.length) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const componentDoc = findComponentDocForEntry(generatedDocs, entry, handoff);
|
|
170
|
+
if (!componentDoc || !((_a = componentDoc.props) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
const properties = {};
|
|
174
|
+
for (const prop of componentDoc.props) {
|
|
175
|
+
properties[prop.name] = toSlotMetadata(prop);
|
|
176
|
+
}
|
|
177
|
+
return properties;
|
|
178
|
+
};
|
|
179
|
+
const getPropertiesFromGeneratedDocs = (generatedDocs, entry, handoff) => toPropertiesMap(generatedDocs, entry, handoff);
|
|
180
|
+
exports.getPropertiesFromGeneratedDocs = getPropertiesFromGeneratedDocs;
|
|
181
|
+
const enrichPropertiesWithDocgen = (properties, docgenProperties) => {
|
|
182
|
+
if (!properties && !docgenProperties) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
if (!properties) {
|
|
186
|
+
return docgenProperties || null;
|
|
187
|
+
}
|
|
188
|
+
if (!docgenProperties) {
|
|
189
|
+
return properties;
|
|
190
|
+
}
|
|
191
|
+
const merged = Object.assign({}, properties);
|
|
192
|
+
const docgenEntries = Object.entries(docgenProperties);
|
|
193
|
+
for (const [propName, docgenProp] of docgenEntries) {
|
|
194
|
+
const existing = merged[propName];
|
|
195
|
+
if (!existing) {
|
|
196
|
+
merged[propName] = docgenProp;
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
merged[propName] = Object.assign(Object.assign({}, existing), { generic: existing.generic || docgenProp.generic, default: existing.default || docgenProp.default, docgenType: docgenProp.docgenType, deepType: docgenProp.deepType, typeRefs: docgenProp.typeRefs, warnings: docgenProp.warnings, annotations: docgenProp.annotations });
|
|
200
|
+
}
|
|
201
|
+
return merged;
|
|
202
|
+
};
|
|
203
|
+
exports.enrichPropertiesWithDocgen = enrichPropertiesWithDocgen;
|
|
204
|
+
const generateDocsArtifact = (entry, handoff) => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
205
|
try {
|
|
29
|
-
// Use root project's tsconfig.json
|
|
30
206
|
const tsconfigPath = path_1.default.resolve(handoff.workingPath, 'tsconfig.json');
|
|
31
|
-
// Check if tsconfig exists
|
|
32
207
|
if (!fs_extra_1.default.existsSync(tsconfigPath)) {
|
|
33
|
-
logger_1.Logger.warn(`TypeScript config not found at ${tsconfigPath}, using default
|
|
208
|
+
logger_1.Logger.warn(`TypeScript config not found at ${tsconfigPath}, using default resolution`);
|
|
34
209
|
}
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
};
|
|
46
|
-
const parser = (0, react_docgen_typescript_1.withCustomConfig)(tsconfigPath, parserConfig);
|
|
47
|
-
const docgenResults = parser.parse(entry);
|
|
48
|
-
if (docgenResults.length > 0) {
|
|
49
|
-
const componentDoc = docgenResults[0];
|
|
50
|
-
if (componentDoc.props && Object.keys(componentDoc.props).length > 0) {
|
|
51
|
-
return (0, schema_1.convertDocgenToProperties)(Object.values(componentDoc.props));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
210
|
+
const componentDirectory = path_1.default.dirname(path_1.default.resolve(entry));
|
|
211
|
+
const { maxDepth, excludeDirectories } = getDocgenConfig(handoff);
|
|
212
|
+
const generator = getGenerator(componentDirectory, tsconfigPath, maxDepth, excludeDirectories);
|
|
213
|
+
return yield generator.generate({
|
|
214
|
+
componentDirectory,
|
|
215
|
+
tsconfigPath,
|
|
216
|
+
maxDepth,
|
|
217
|
+
pathMode: 'relative',
|
|
218
|
+
excludeDirectories,
|
|
219
|
+
});
|
|
55
220
|
}
|
|
56
221
|
catch (error) {
|
|
57
|
-
logger_1.Logger.warn(`Failed to generate docs with
|
|
222
|
+
logger_1.Logger.warn(`Failed to generate docs with handoff-docgen for ${entry}: ${error}`);
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
exports.generateDocsArtifact = generateDocsArtifact;
|
|
227
|
+
const generatePropertiesFromDocgen = (entry, handoff) => __awaiter(void 0, void 0, void 0, function* () {
|
|
228
|
+
const generatedDocs = yield (0, exports.generateDocsArtifact)(entry, handoff);
|
|
229
|
+
if (!generatedDocs) {
|
|
58
230
|
return null;
|
|
59
231
|
}
|
|
232
|
+
return (0, exports.getPropertiesFromGeneratedDocs)(generatedDocs, entry, handoff);
|
|
60
233
|
});
|
|
61
234
|
exports.generatePropertiesFromDocgen = generatePropertiesFromDocgen;
|
|
@@ -62,7 +62,7 @@ function loadComponentSchemaAndModule(componentData, componentPath, handoff) {
|
|
|
62
62
|
component = moduleExports.exports.default;
|
|
63
63
|
// Try to load schema from component exports
|
|
64
64
|
properties = yield (0, schema_loader_1.loadSchemaFromComponent)(moduleExports.exports, handoff);
|
|
65
|
-
// If no schema found, use
|
|
65
|
+
// If no schema found, use shared docgen fallback
|
|
66
66
|
if (!properties) {
|
|
67
67
|
properties = yield (0, docgen_1.generatePropertiesFromDocgen)(componentPath, handoff);
|
|
68
68
|
}
|
|
@@ -169,6 +169,7 @@ function ssrRenderPlugin(componentData, documentationComponents, handoff) {
|
|
|
169
169
|
const componentSourceCode = fs_extra_1.default.readFileSync(componentPath, 'utf8');
|
|
170
170
|
// Load component schema and module
|
|
171
171
|
const [schemaProperties, ReactComponent] = yield loadComponentSchemaAndModule(componentData, componentPath, handoff);
|
|
172
|
+
const generatedDocs = yield (0, docgen_1.generateDocsArtifact)(componentPath, handoff);
|
|
172
173
|
if (!ReactComponent) {
|
|
173
174
|
logger_1.Logger.error(`Failed to load React component for ${componentId}`);
|
|
174
175
|
return;
|
|
@@ -177,6 +178,11 @@ function ssrRenderPlugin(componentData, documentationComponents, handoff) {
|
|
|
177
178
|
if (schemaProperties) {
|
|
178
179
|
componentData.properties = schemaProperties;
|
|
179
180
|
}
|
|
181
|
+
if (generatedDocs) {
|
|
182
|
+
const docgenProperties = (0, docgen_1.getPropertiesFromGeneratedDocs)(generatedDocs, componentPath, handoff);
|
|
183
|
+
componentData.properties = (0, docgen_1.enrichPropertiesWithDocgen)(componentData.properties, docgenProperties) || {};
|
|
184
|
+
componentData.docgen = generatedDocs;
|
|
185
|
+
}
|
|
180
186
|
// Ensure components object exists
|
|
181
187
|
if (!documentationComponents) {
|
|
182
188
|
documentationComponents = {};
|
|
@@ -41,6 +41,7 @@ declare const buildComponentCss: (data: TransformComponentTokensResult, handoff:
|
|
|
41
41
|
};
|
|
42
42
|
validations?: Record<string, import("../../../types").ValidationResult>;
|
|
43
43
|
page?: import("../types").ComponentPageDefinition;
|
|
44
|
+
docgen?: import("handoff-docgen").GeneratedDocs;
|
|
44
45
|
}>;
|
|
45
46
|
/**
|
|
46
47
|
* Build the main CSS file using Vite
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DocAnnotation, TypeNode } from 'handoff-docgen';
|
|
1
2
|
import Handoff from '../../index';
|
|
2
3
|
export interface ComponentMetadata {
|
|
3
4
|
title: string;
|
|
@@ -38,6 +39,11 @@ export interface SlotMetadata {
|
|
|
38
39
|
};
|
|
39
40
|
key?: string;
|
|
40
41
|
rules?: RuleObject;
|
|
42
|
+
docgenType?: string;
|
|
43
|
+
deepType?: TypeNode;
|
|
44
|
+
typeRefs?: string[];
|
|
45
|
+
warnings?: string[];
|
|
46
|
+
annotations?: DocAnnotation[];
|
|
41
47
|
}
|
|
42
48
|
export type RuleObject = {
|
|
43
49
|
required?: boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Card } from '../../app/components/Component/Cards';
|
|
2
|
+
import type { GeneratedDocs } from 'handoff-docgen';
|
|
2
3
|
import { ValidationResult } from '../../types';
|
|
3
4
|
import { Filter } from '../../utils/filter';
|
|
4
5
|
import { SlotMetadata } from './component';
|
|
@@ -159,6 +160,7 @@ export type TransformComponentTokensResult = {
|
|
|
159
160
|
};
|
|
160
161
|
validations?: Record<string, ValidationResult>;
|
|
161
162
|
page?: ComponentPageDefinition;
|
|
163
|
+
docgen?: GeneratedDocs;
|
|
162
164
|
} | null;
|
|
163
165
|
export type OptionalPreviewRender = {
|
|
164
166
|
title: string;
|
|
@@ -2,24 +2,6 @@ import { Types as CoreTypes } from 'handoff-core';
|
|
|
2
2
|
import { Plugin } from 'vite';
|
|
3
3
|
import { SlotMetadata } from './preview/component';
|
|
4
4
|
import { TransformComponentTokensResult } from './preview/types';
|
|
5
|
-
/**
|
|
6
|
-
* Configuration for react-docgen-typescript parser
|
|
7
|
-
*/
|
|
8
|
-
export interface DocgenParserConfig {
|
|
9
|
-
savePropValueAsString: boolean;
|
|
10
|
-
shouldExtractLiteralValuesFromEnum: boolean;
|
|
11
|
-
shouldRemoveUndefinedFromOptional: boolean;
|
|
12
|
-
propFilter: (prop: any) => boolean;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Result from react-docgen-typescript parsing
|
|
16
|
-
*/
|
|
17
|
-
export interface DocgenResult {
|
|
18
|
-
props: {
|
|
19
|
-
[key: string]: any;
|
|
20
|
-
};
|
|
21
|
-
[key: string]: any;
|
|
22
|
-
}
|
|
23
5
|
/**
|
|
24
6
|
* Module evaluation result
|
|
25
7
|
*/
|
|
@@ -43,7 +43,7 @@ const loadSchemaFromFile = (schemaPath, handoff) => __awaiter(void 0, void 0, vo
|
|
|
43
43
|
}
|
|
44
44
|
else if (schema) {
|
|
45
45
|
// Schema exists but is not a valid schema object (e.g., type/interface)
|
|
46
|
-
// Use
|
|
46
|
+
// Use handoff-docgen to document the schema file
|
|
47
47
|
return yield (0, docgen_1.generatePropertiesFromDocgen)(schemaPath, handoff);
|
|
48
48
|
}
|
|
49
49
|
return null;
|
|
@@ -72,7 +72,7 @@ const loadSchemaFromComponent = (componentExports, handoff) => __awaiter(void 0,
|
|
|
72
72
|
}
|
|
73
73
|
else if (schema) {
|
|
74
74
|
// Schema exists but is not a valid schema object (e.g., type/interface)
|
|
75
|
-
// Use
|
|
75
|
+
// Use handoff-docgen to document the schema
|
|
76
76
|
return yield (0, docgen_1.generatePropertiesFromDocgen)(componentExports.__filename || '', handoff);
|
|
77
77
|
}
|
|
78
78
|
return null;
|
|
@@ -10,8 +10,8 @@ export declare const ensureIds: (properties: {
|
|
|
10
10
|
[key: string]: SlotMetadata;
|
|
11
11
|
};
|
|
12
12
|
/**
|
|
13
|
-
* Converts
|
|
14
|
-
* @param docgenProps - Array of props from
|
|
13
|
+
* Converts baseline docgen props to our SlotMetadata format
|
|
14
|
+
* @param docgenProps - Array of props from a docgen parser
|
|
15
15
|
* @returns Converted properties object
|
|
16
16
|
*/
|
|
17
17
|
export declare const convertDocgenToProperties: (docgenProps: any[]) => {
|
|
@@ -470,8 +470,8 @@ const ensureNestedParsing = (metadata) => {
|
|
|
470
470
|
return metadata;
|
|
471
471
|
};
|
|
472
472
|
/**
|
|
473
|
-
* Converts
|
|
474
|
-
* @param docgenProps - Array of props from
|
|
473
|
+
* Converts baseline docgen props to our SlotMetadata format
|
|
474
|
+
* @param docgenProps - Array of props from a docgen parser
|
|
475
475
|
* @returns Converted properties object
|
|
476
476
|
*/
|
|
477
477
|
const convertDocgenToProperties = (docgenProps) => {
|
package/dist/types/config.d.ts
CHANGED
|
@@ -74,6 +74,21 @@ export interface Config {
|
|
|
74
74
|
exportsOutputDirectory?: string;
|
|
75
75
|
sitesOutputDirectory?: string;
|
|
76
76
|
useVariables?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Configuration for React component docs generation (handoff-docgen).
|
|
79
|
+
*/
|
|
80
|
+
reactDocgen?: {
|
|
81
|
+
/**
|
|
82
|
+
* Maximum recursion depth for nested type traversal.
|
|
83
|
+
* @default 7
|
|
84
|
+
*/
|
|
85
|
+
maxDepth?: number;
|
|
86
|
+
/**
|
|
87
|
+
* Directory names to exclude while scanning for components.
|
|
88
|
+
* @default ["dist", "build", ".next"]
|
|
89
|
+
*/
|
|
90
|
+
excludeDirectories?: string[];
|
|
91
|
+
};
|
|
77
92
|
app?: NextAppConfig;
|
|
78
93
|
/**
|
|
79
94
|
* Configuration for the build pipeline
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Types as CoreTypes } from 'handoff-core';
|
|
2
|
+
import type { GeneratedDocs } from 'handoff-docgen';
|
|
2
3
|
import { SlotMetadata } from './transformers/preview/component';
|
|
3
4
|
import { ComponentPageDefinition } from './transformers/preview/types';
|
|
4
5
|
import { type Filter } from './utils/filter';
|
|
@@ -74,6 +75,7 @@ export interface PreviewObject {
|
|
|
74
75
|
*/
|
|
75
76
|
validations?: Record<string, ValidationResult>;
|
|
76
77
|
page?: ComponentPageDefinition;
|
|
78
|
+
docgen?: GeneratedDocs;
|
|
77
79
|
}
|
|
78
80
|
export type PreviewJson = {
|
|
79
81
|
components: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "handoff-app",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.1.0-canary.1",
|
|
4
4
|
"description": "Automated documentation toolchain for building client side documentation from figma",
|
|
5
5
|
"author ": {
|
|
6
6
|
"name": "Convertiv",
|
|
@@ -100,6 +100,7 @@
|
|
|
100
100
|
"gray-matter": "^4.0.3",
|
|
101
101
|
"handlebars": "^4.7.8",
|
|
102
102
|
"handoff-core": "^0.2.0",
|
|
103
|
+
"handoff-docgen": "^0.1.0",
|
|
103
104
|
"html-react-parser": "^5.2.5",
|
|
104
105
|
"jquery": "^3.6.1",
|
|
105
106
|
"lodash": "^4.17.21",
|