@patternfly/documentation-framework 2.0.0-alpha.6 → 2.0.0-alpha.60
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 +504 -0
- package/app.js +12 -12
- package/components/autoLinkHeader/autoLinkHeader.css +2 -2
- package/components/autoLinkHeader/autoLinkHeader.js +18 -13
- package/components/cssVariables/cssSearch.js +3 -4
- package/components/cssVariables/cssVariables.css +4 -4
- package/components/cssVariables/cssVariables.js +83 -84
- package/components/example/example.css +29 -29
- package/components/example/example.js +34 -6
- package/components/footer/footer.css +16 -16
- package/components/footer/footer.js +13 -13
- package/components/functionsTable/functionsTable.js +57 -0
- package/components/gdprBanner/gdprBanner.css +2 -2
- package/components/gdprBanner/gdprBanner.js +3 -3
- package/components/inlineAlert/inlineAlert.js +1 -1
- package/components/propsTable/propsTable.js +85 -79
- package/components/sectionGallery/TextSummary.js +31 -0
- package/components/sectionGallery/sectionDataListLayout.js +49 -0
- package/components/sectionGallery/sectionGallery.css +53 -0
- package/components/sectionGallery/sectionGallery.js +76 -0
- package/components/sectionGallery/sectionGalleryLayout.js +39 -0
- package/components/sectionGallery/sectionGalleryToolbar.js +38 -0
- package/components/sectionGallery/sectionGalleryWrapper.js +105 -0
- package/components/sideNav/sideNav.css +12 -12
- package/components/sideNav/sideNav.js +41 -13
- package/components/tableOfContents/tableOfContents.css +17 -17
- package/helpers/codesandbox.js +2 -2
- package/helpers/getTitle.js +2 -2
- package/layouts/sideNavLayout/sideNavLayout.css +7 -11
- package/layouts/sideNavLayout/sideNavLayout.js +57 -40
- package/package.json +28 -25
- package/pages/404/404.css +2 -2
- package/pages/404/index.js +1 -1
- package/pages/global-css-variables.md +16 -16
- package/routes.js +20 -8
- package/scripts/cli/build.js +6 -0
- package/scripts/cli/cli.js +2 -0
- package/scripts/cli/generate.js +2 -2
- package/scripts/cli/start.js +6 -8
- package/scripts/md/parseMD.js +46 -11
- package/scripts/md/styled-tags.js +8 -4
- package/scripts/tsDocgen.js +119 -91
- package/scripts/typeDocGen.js +209 -0
- package/scripts/webpack/webpack.base.config.js +34 -32
- package/scripts/webpack/webpack.client.config.js +11 -8
- package/scripts/webpack/webpack.server.config.js +8 -5
- package/scripts/writeScreenshots.js +3 -3
- package/templates/html.ejs +2 -4
- package/templates/mdx.css +156 -161
- package/templates/mdx.js +122 -51
- package/templates/patternfly-docs/content/extensions/extension/design-guidelines/design-guidelines.md +2 -0
- package/templates/patternfly-docs/content/extensions/extension/examples/basic.md +2 -0
- package/versions.json +29 -9
- package/components/topNav/topNav.css +0 -30
- package/pages/red-hat-font.md +0 -40
package/routes.js
CHANGED
|
@@ -9,6 +9,8 @@ const routes = {
|
|
|
9
9
|
...generatedRoutes
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
const defaultOrder = 50;
|
|
13
|
+
|
|
12
14
|
for (let route in routes) {
|
|
13
15
|
const pageData = routes[route];
|
|
14
16
|
if (pageData.SyncComponent) {
|
|
@@ -28,7 +30,7 @@ const isNull = o => o === null || o === undefined;
|
|
|
28
30
|
const groupedRoutes = Object.entries(routes)
|
|
29
31
|
.filter(([_slug, { id, section }]) => !isNull(id) && !isNull(section))
|
|
30
32
|
.reduce((accum, [slug, pageData]) => {
|
|
31
|
-
const { section, subsection = null, id, title, source,
|
|
33
|
+
const { section, subsection = null, id, title, source, hideNavItem, relPath, sortValue = null, subsectionSortValue = null } = pageData;
|
|
32
34
|
pageData.slug = slug;
|
|
33
35
|
// add section to groupedRoutes obj if not yet created
|
|
34
36
|
accum[section] = accum[section] || {};
|
|
@@ -40,9 +42,10 @@ const groupedRoutes = Object.entries(routes)
|
|
|
40
42
|
title,
|
|
41
43
|
slug: makeSlug(source, section, id, true, subsection),
|
|
42
44
|
sources: [],
|
|
43
|
-
katacodaLayout,
|
|
44
45
|
hideNavItem,
|
|
45
|
-
relPath
|
|
46
|
+
relPath,
|
|
47
|
+
...(sortValue && { sortValue }),
|
|
48
|
+
...(subsectionSortValue && { subsectionSortValue })
|
|
46
49
|
}
|
|
47
50
|
// add page to groupedRoutes obj section or subsection
|
|
48
51
|
if (subsection) {
|
|
@@ -52,10 +55,21 @@ const groupedRoutes = Object.entries(routes)
|
|
|
52
55
|
// add page to subsection
|
|
53
56
|
accum[section][subsection][id] = accum[section][subsection][id] || data;
|
|
54
57
|
accum[section][subsection][id].sources.push(pageData);
|
|
58
|
+
// nav item ordering
|
|
59
|
+
if (sortValue) {
|
|
60
|
+
accum[section][subsection].sortValue = sortValue;
|
|
61
|
+
}
|
|
62
|
+
if (subsectionSortValue) {
|
|
63
|
+
accum[section][subsection].subsectionSortValue = subsectionSortValue;
|
|
64
|
+
}
|
|
55
65
|
} else {
|
|
56
66
|
// add page to section
|
|
57
67
|
accum[section][id] = accum[section][id] || data;
|
|
58
68
|
accum[section][id].sources.push(pageData);
|
|
69
|
+
// nav item ordering
|
|
70
|
+
if (sortValue) {
|
|
71
|
+
accum[section][id].sortValue = sortValue;
|
|
72
|
+
}
|
|
59
73
|
}
|
|
60
74
|
|
|
61
75
|
return accum;
|
|
@@ -64,16 +78,13 @@ const groupedRoutes = Object.entries(routes)
|
|
|
64
78
|
const sourceOrder = {
|
|
65
79
|
react: 1,
|
|
66
80
|
'react-next': 1.1,
|
|
67
|
-
'react-composable': 1.2,
|
|
68
|
-
'react-deprecated': 1.3,
|
|
69
|
-
'react-legacy': 1.4,
|
|
70
81
|
'react-demos': 2,
|
|
82
|
+
'react-deprecated': 2.1,
|
|
71
83
|
html: 3,
|
|
72
84
|
'html-demos': 4,
|
|
73
85
|
'design-guidelines': 99,
|
|
74
86
|
'accessibility': 100
|
|
75
87
|
};
|
|
76
|
-
const defaultOrder = 50;
|
|
77
88
|
|
|
78
89
|
const sortSources = ({ source: s1 }, { source: s2 }) => {
|
|
79
90
|
const s1Index = sourceOrder[s1] || defaultOrder;
|
|
@@ -108,7 +119,8 @@ Object.entries(groupedRoutes)
|
|
|
108
119
|
// Loop through each page in expandable subsection
|
|
109
120
|
if (pageData.isSubsection) {
|
|
110
121
|
Object.entries(pageData).map(([section, ids]) => {
|
|
111
|
-
|
|
122
|
+
// only push nested page objects
|
|
123
|
+
if (ids && ids?.id) {
|
|
112
124
|
pageDataArr.push(ids);
|
|
113
125
|
}
|
|
114
126
|
})
|
package/scripts/cli/build.js
CHANGED
|
@@ -50,6 +50,11 @@ async function execFile(file, args) {
|
|
|
50
50
|
const child_execArgv = [
|
|
51
51
|
'--max-old-space-size=4096'
|
|
52
52
|
];
|
|
53
|
+
|
|
54
|
+
if (args.legacySSL) {
|
|
55
|
+
child_execArgv.push('--openssl-legacy-provider')
|
|
56
|
+
}
|
|
57
|
+
|
|
53
58
|
const child = fork(path.join(__dirname, file), child_argv, { execArgv: child_execArgv });
|
|
54
59
|
function errorHandler(err) {
|
|
55
60
|
console.error(err);
|
|
@@ -78,6 +83,7 @@ async function build(cmd, options) {
|
|
|
78
83
|
const config = getConfig(options);
|
|
79
84
|
config.analyze = options.analyze;
|
|
80
85
|
config.output = options.output;
|
|
86
|
+
config.legacySSL = options.legacySSL
|
|
81
87
|
|
|
82
88
|
// These get passed to `fork`ed builds
|
|
83
89
|
process.env.pathPrefix = config.pathPrefix;
|
package/scripts/cli/cli.js
CHANGED
|
@@ -26,6 +26,7 @@ program
|
|
|
26
26
|
.command('build <server|client|all>')
|
|
27
27
|
.option('-a, --analyze', 'use webpack-bundle-analyzer', false)
|
|
28
28
|
.option('-o, --output <folder>', 'output folder', 'public')
|
|
29
|
+
.option('--legacySSL', 'use legacy version of openssl, needed to support Node 18 until we upgrade webpack to v5', false)
|
|
29
30
|
.description('generates source files and runs webpack')
|
|
30
31
|
.action((cmd, options) => {
|
|
31
32
|
const { build } = require('./build');
|
|
@@ -44,6 +45,7 @@ program
|
|
|
44
45
|
program
|
|
45
46
|
.command('screenshots')
|
|
46
47
|
.option('-u, --urlPrefix <prefix>', 'where fullscreen pages are hosted', 'http://localhost:5000/v4')
|
|
48
|
+
.option('-a, --allRoutes', 'true if screenshots of all examples - not just full screen', false)
|
|
47
49
|
.description('updates screenshots for generated components')
|
|
48
50
|
.action(options => {
|
|
49
51
|
const { writeScreenshots } = require('../writeScreenshots');
|
package/scripts/cli/generate.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
-
const { sourceMD, sourceProps, writeIndex } = require('../md/parseMD');
|
|
2
|
+
const { sourceMD, sourceProps, sourceFunctionDocs, writeIndex } = require('../md/parseMD');
|
|
3
3
|
|
|
4
4
|
function getSource(options) {
|
|
5
5
|
return require(path.join(process.cwd(), options.parent.source));
|
|
@@ -9,7 +9,7 @@ function generate(options) {
|
|
|
9
9
|
const start = new Date();
|
|
10
10
|
console.log('write source files to patternfly-docs/generated');
|
|
11
11
|
const sourceMDWithOptions = (glob, source, ignore) => sourceMD(glob, source, ignore, options._name);
|
|
12
|
-
getSource(options)(sourceMDWithOptions, sourceProps);
|
|
12
|
+
getSource(options)(sourceMDWithOptions, sourceProps, sourceFunctionDocs);
|
|
13
13
|
const exitCode = writeIndex();
|
|
14
14
|
if (exitCode !== 0) {
|
|
15
15
|
process.exit(exitCode);
|
package/scripts/cli/start.js
CHANGED
|
@@ -6,17 +6,15 @@ const { getConfig } = require('./helpers');
|
|
|
6
6
|
const { watchMD } = require('../md/parseMD');
|
|
7
7
|
|
|
8
8
|
function startWebpackDevServer(webpackConfig) {
|
|
9
|
-
webpackConfig.devServer.
|
|
10
|
-
webpackConfig.devServer.publicPath = webpackConfig.output.publicPath;
|
|
9
|
+
webpackConfig.devServer.static = false;
|
|
11
10
|
const { port } = webpackConfig.devServer;
|
|
12
11
|
const compiler = webpack(webpackConfig);
|
|
13
|
-
const server = new WebpackDevServer(
|
|
12
|
+
const server = new WebpackDevServer(webpackConfig.devServer, compiler);
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
});
|
|
14
|
+
(async () => {
|
|
15
|
+
await server.start();
|
|
16
|
+
console.log(`Dev server is listening on port ${port}`);
|
|
17
|
+
})();
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
async function start(options) {
|
package/scripts/md/parseMD.js
CHANGED
|
@@ -12,10 +12,12 @@ const { typecheck } = require('./typecheck');
|
|
|
12
12
|
const { makeSlug } = require('../../helpers/slugger');
|
|
13
13
|
const { liveCodeTypes } = require('../../helpers/liveCodeTypes');
|
|
14
14
|
const { tsDocgen } = require('../tsDocgen');
|
|
15
|
+
const { getPackageFunctionDocumentation } = require("../typeDocGen");
|
|
15
16
|
|
|
16
17
|
let exitCode = 0;
|
|
17
18
|
const outputBase = path.join(process.cwd(), `patternfly-docs/generated`);
|
|
18
19
|
const tsDocs = {};
|
|
20
|
+
let functionDocs = {};
|
|
19
21
|
const routes = {};
|
|
20
22
|
const globs = {
|
|
21
23
|
props: [],
|
|
@@ -75,6 +77,24 @@ function toReactComponent(mdFilePath, source, buildMode) {
|
|
|
75
77
|
return acc;
|
|
76
78
|
}, []);
|
|
77
79
|
|
|
80
|
+
const functionDocumentation = Object.keys(
|
|
81
|
+
frontmatter.functions || {}
|
|
82
|
+
).reduce((acc, fileName) => {
|
|
83
|
+
const functionNames = frontmatter.functions[fileName];
|
|
84
|
+
|
|
85
|
+
functionNames.forEach((functionName) => {
|
|
86
|
+
if (functionDocs[fileName] && functionDocs[fileName][functionName]) {
|
|
87
|
+
const functionDescriptionWithName = { functionName, ...functionDocs[fileName][functionName]}
|
|
88
|
+
acc.push(functionDescriptionWithName);
|
|
89
|
+
} else {
|
|
90
|
+
file.message(
|
|
91
|
+
`function documentation for ${functionName} is missing from function docs generation`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return acc;
|
|
96
|
+
}, []);
|
|
97
|
+
|
|
78
98
|
const normalizedPath = relPath
|
|
79
99
|
.replace('node_modules/@patternfly/patternfly/docs', 'src/patternfly')
|
|
80
100
|
.replace(/node_modules\/@patternfly\/react-([\w-])/, (_, match) => `packages/react-${match}`)
|
|
@@ -84,7 +104,12 @@ function toReactComponent(mdFilePath, source, buildMode) {
|
|
|
84
104
|
id: frontmatter.id,
|
|
85
105
|
section: frontmatter.section || '',
|
|
86
106
|
subsection: frontmatter.subsection || '',
|
|
107
|
+
deprecated: frontmatter.deprecated || false,
|
|
108
|
+
beta: frontmatter.beta || false,
|
|
109
|
+
demo: frontmatter.demo || false,
|
|
110
|
+
newImplementationLink: frontmatter.newImplementationLink || false,
|
|
87
111
|
source,
|
|
112
|
+
tabName: frontmatter.tabName || null,
|
|
88
113
|
slug,
|
|
89
114
|
sourceLink: frontmatter.sourceLink || `https://github.com/patternfly/${
|
|
90
115
|
sourceRepo}/blob/main/${
|
|
@@ -106,26 +131,26 @@ function toReactComponent(mdFilePath, source, buildMode) {
|
|
|
106
131
|
if (propComponents.length > 0) {
|
|
107
132
|
pageData.propComponents = propComponents;
|
|
108
133
|
}
|
|
134
|
+
if (functionDocumentation.length > 0) {
|
|
135
|
+
pageData.functionDocumentation = functionDocumentation;
|
|
136
|
+
}
|
|
109
137
|
if (frontmatter.optIn) {
|
|
110
138
|
pageData.optIn = frontmatter.optIn;
|
|
111
139
|
}
|
|
112
|
-
if (frontmatter.beta) {
|
|
113
|
-
pageData.beta = frontmatter.beta;
|
|
114
|
-
}
|
|
115
140
|
if (frontmatter.cssPrefix) {
|
|
116
141
|
pageData.cssPrefix = Array.isArray(frontmatter.cssPrefix)
|
|
117
142
|
? frontmatter.cssPrefix
|
|
118
143
|
: [frontmatter.cssPrefix];
|
|
119
144
|
}
|
|
120
|
-
if (frontmatter.katacodaBroken) {
|
|
121
|
-
pageData.katacodaBroken = frontmatter.katacodaBroken;
|
|
122
|
-
}
|
|
123
|
-
if (frontmatter.katacodaLayout) {
|
|
124
|
-
pageData.katacodaLayout = frontmatter.katacodaLayout;
|
|
125
|
-
}
|
|
126
145
|
if (frontmatter.hideNavItem) {
|
|
127
146
|
pageData.hideNavItem = frontmatter.hideNavItem;
|
|
128
147
|
}
|
|
148
|
+
if (frontmatter.sortValue) {
|
|
149
|
+
pageData.sortValue = frontmatter.sortValue;
|
|
150
|
+
}
|
|
151
|
+
if (frontmatter.subsectionSortValue) {
|
|
152
|
+
pageData.subsectionSortValue = frontmatter.subsectionSortValue;
|
|
153
|
+
}
|
|
129
154
|
})
|
|
130
155
|
// Delete HTML comments
|
|
131
156
|
.use(require('./remove-comments'))
|
|
@@ -266,12 +291,21 @@ function sourceMDFile(file, source, buildMode) {
|
|
|
266
291
|
section: pageData.section,
|
|
267
292
|
subsection: pageData.subsection,
|
|
268
293
|
source: pageData.source,
|
|
269
|
-
|
|
270
|
-
...(pageData.hideNavItem && { hideNavItem: pageData.hideNavItem })
|
|
294
|
+
tabName: pageData.tabName,
|
|
295
|
+
...(pageData.hideNavItem && { hideNavItem: pageData.hideNavItem }),
|
|
296
|
+
...(pageData.beta && { beta: pageData.beta }),
|
|
297
|
+
...(pageData.deprecated && { deprecated: pageData.deprecated }),
|
|
298
|
+
...(pageData.demo && { demo: pageData.demo }),
|
|
299
|
+
...(pageData.sortValue && { sortValue: pageData.sortValue }),
|
|
300
|
+
...(pageData.subsectionSortValue && { subsectionSortValue: pageData.subsectionSortValue })
|
|
271
301
|
};
|
|
272
302
|
}
|
|
273
303
|
}
|
|
274
304
|
|
|
305
|
+
function sourceFunctionDocs(packageName) {
|
|
306
|
+
functionDocs = getPackageFunctionDocumentation(packageName);
|
|
307
|
+
}
|
|
308
|
+
|
|
275
309
|
function writeIndex() {
|
|
276
310
|
const stringifyRoute = ([route, pageData]) => `'${route}': {\n ${Object.entries(pageData)
|
|
277
311
|
.map(([key, val]) => `${key}: ${JSON.stringify(val)}`)
|
|
@@ -310,6 +344,7 @@ module.exports = {
|
|
|
310
344
|
globs.md.push({ glob, source, ignore });
|
|
311
345
|
sync(glob, { ignore }).forEach(file => sourceMDFile(file, source, buildMode));
|
|
312
346
|
},
|
|
347
|
+
sourceFunctionDocs,
|
|
313
348
|
writeIndex,
|
|
314
349
|
watchMD() {
|
|
315
350
|
globs.props.forEach(({ glob, ignore }) => {
|
|
@@ -24,22 +24,23 @@ function styledTags() {
|
|
|
24
24
|
node.properties.className = node.properties.className || '';
|
|
25
25
|
node.properties.className += node.properties.className ? ' ' : '';
|
|
26
26
|
node.properties.className += `ws-${node.tagName}`;
|
|
27
|
-
// Match pf-c-table implementation
|
|
27
|
+
// Match pf-v5-c-table implementation
|
|
28
28
|
// https://pf4.patternfly.org/components/table/html/basic-table/
|
|
29
29
|
if (node.tagName === 'table') {
|
|
30
|
-
node.properties.className += ' pf-c-table pf-m-grid-lg pf-m-compact';
|
|
30
|
+
node.properties.className += ' pf-v5-c-table pf-m-grid-lg pf-m-compact';
|
|
31
31
|
node.properties.role = 'grid';
|
|
32
32
|
let columnHeaders = [];
|
|
33
33
|
for (let child of node.children) {
|
|
34
34
|
if (child.tagName === 'thead') {
|
|
35
|
+
child.properties.className = 'pf-v5-c-table__thead';
|
|
35
36
|
// Find column headers
|
|
36
37
|
const tr = child.children.find(child => child.tagName === 'tr');
|
|
37
38
|
tr.properties.role = 'row';
|
|
39
|
+
tr.properties.className = 'pf-v5-c-table__tr';
|
|
38
40
|
tr.children
|
|
39
41
|
.filter(child => child.tagName === 'th')
|
|
40
42
|
.forEach(th => {
|
|
41
|
-
th.properties.className = th.properties.className
|
|
42
|
-
th.properties.className += ' pf-m-wrap';
|
|
43
|
+
th.properties.className = `${th.properties.className} pf-v5-c-table__th pf-m-wrap`;
|
|
43
44
|
th.properties.role = 'columnheader';
|
|
44
45
|
th.properties.scope = 'col';
|
|
45
46
|
let colName = '';
|
|
@@ -56,14 +57,17 @@ function styledTags() {
|
|
|
56
57
|
}
|
|
57
58
|
else if (child.tagName === 'tbody') {
|
|
58
59
|
child.properties.role = 'rowgroup';
|
|
60
|
+
child.properties.className = 'pf-v5-c-table__tbody';
|
|
59
61
|
child.children
|
|
60
62
|
.filter(tr => tr.tagName === 'tr')
|
|
61
63
|
.forEach(tr => {
|
|
62
64
|
tr.properties.role = 'row';
|
|
65
|
+
tr.properties.className = 'pf-v5-c-table__tr';
|
|
63
66
|
tr.children
|
|
64
67
|
.filter(td => td.tagName === 'td')
|
|
65
68
|
.forEach((td, i) => {
|
|
66
69
|
td.properties.role = 'cell';
|
|
70
|
+
td.properties.className = 'pf-v5-c-table__td';
|
|
67
71
|
if (columnHeaders[i]) {
|
|
68
72
|
td.properties['data-label'] = columnHeaders[i];
|
|
69
73
|
}
|
package/scripts/tsDocgen.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const reactDocgen = require(
|
|
3
|
-
const ts = require(
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const reactDocgen = require("react-docgen");
|
|
3
|
+
const ts = require("typescript");
|
|
4
4
|
|
|
5
5
|
const annotations = [
|
|
6
6
|
{
|
|
7
7
|
regex: /@deprecated/,
|
|
8
|
-
name:
|
|
9
|
-
type:
|
|
8
|
+
name: "deprecated",
|
|
9
|
+
type: "Boolean",
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
regex: /@hide/,
|
|
13
|
-
name:
|
|
14
|
-
type:
|
|
13
|
+
name: "hide",
|
|
14
|
+
type: "Boolean",
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
regex: /@beta/,
|
|
18
|
-
name:
|
|
19
|
-
type:
|
|
18
|
+
name: "beta",
|
|
19
|
+
type: "Boolean",
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
regex: /@propType\s+(.*)/,
|
|
23
|
-
name:
|
|
24
|
-
type:
|
|
25
|
-
}
|
|
23
|
+
name: "type",
|
|
24
|
+
type: "String",
|
|
25
|
+
},
|
|
26
26
|
];
|
|
27
27
|
|
|
28
28
|
function addAnnotations(prop) {
|
|
@@ -30,12 +30,12 @@ function addAnnotations(prop) {
|
|
|
30
30
|
annotations.forEach(({ regex, name }) => {
|
|
31
31
|
const match = prop.description.match(regex);
|
|
32
32
|
if (match) {
|
|
33
|
-
prop.description = prop.description.replace(regex,
|
|
33
|
+
prop.description = prop.description.replace(regex, "").trim();
|
|
34
34
|
if (name) {
|
|
35
35
|
prop[name] = match[2] || match[1] || true;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
})
|
|
38
|
+
});
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
return prop;
|
|
@@ -55,74 +55,101 @@ function getComponentMetadata(filename, sourceText) {
|
|
|
55
55
|
// console.warn(`No component found in ${filename}:`, err);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
return (parsedComponents || []).filter(
|
|
58
|
+
return (parsedComponents || []).filter(
|
|
59
|
+
(parsed) => parsed && parsed.displayName
|
|
60
|
+
);
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
const getNodeText = (node, sourceText) => {
|
|
64
|
+
if (!node || !node.pos || !node.end) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return sourceText.substring(node.pos, node.end).trim();
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const buildJsDocProps = (nodes, sourceText) =>
|
|
72
|
+
nodes?.reduce((acc, member) => {
|
|
73
|
+
const name =
|
|
74
|
+
(member.name && member.name.escapedText) ||
|
|
75
|
+
(member.parameters &&
|
|
76
|
+
`[${getNodeText(member.parameters[0], sourceText)}]`) ||
|
|
77
|
+
"Unknown";
|
|
78
|
+
acc[name] = {
|
|
79
|
+
description: member.jsDoc
|
|
80
|
+
? member.jsDoc.map((doc) => doc.comment).join("\n")
|
|
81
|
+
: null,
|
|
82
|
+
required: member.questionToken === undefined,
|
|
83
|
+
type: {
|
|
84
|
+
raw: getNodeText(member.type, sourceText).trim(),
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
return acc;
|
|
88
|
+
}, {});
|
|
89
|
+
|
|
90
|
+
const getSourceFileStatements = (filename, sourceText) => {
|
|
91
|
+
const { statements } = ts.createSourceFile(
|
|
63
92
|
filename,
|
|
64
93
|
sourceText,
|
|
65
94
|
ts.ScriptTarget.Latest // languageVersion
|
|
66
95
|
);
|
|
67
|
-
|
|
68
|
-
function getText(node) {
|
|
69
|
-
if (!node || !node.pos || !node.end) {
|
|
70
|
-
return undefined;
|
|
71
|
-
}
|
|
72
|
-
return sourceText.substring(node.pos, node.end).trim();
|
|
73
|
-
}
|
|
74
96
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
97
|
+
return statements;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const getInterfaceMetadata = (filename, sourceText) =>
|
|
101
|
+
getSourceFileStatements(filename, sourceText).reduce(
|
|
102
|
+
(metaDataAcc, statement) => {
|
|
103
|
+
if (statement.kind === ts.SyntaxKind.InterfaceDeclaration) {
|
|
104
|
+
metaDataAcc.push({
|
|
105
|
+
displayName: statement.name.escapedText,
|
|
106
|
+
description: statement.jsDoc?.map((doc) => doc.comment).join("\n"),
|
|
107
|
+
props: buildJsDocProps(statement.members, sourceText),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return metaDataAcc;
|
|
112
|
+
},
|
|
113
|
+
[]
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const getTypeAliasMetadata = (filename, sourceText) =>
|
|
117
|
+
getSourceFileStatements(filename, sourceText).reduce(
|
|
118
|
+
(metaDataAcc, statement) => {
|
|
119
|
+
if (statement.kind === ts.SyntaxKind.TypeAliasDeclaration) {
|
|
120
|
+
const props = statement.type.types?.reduce((propAcc, type) => {
|
|
121
|
+
if (type.members) {
|
|
122
|
+
propAcc.push(buildJsDocProps(type.members, sourceText));
|
|
91
123
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
124
|
+
|
|
125
|
+
return propAcc;
|
|
126
|
+
}, []);
|
|
127
|
+
|
|
128
|
+
metaDataAcc.push({
|
|
129
|
+
props,
|
|
130
|
+
displayName: statement.name.escapedText,
|
|
131
|
+
description: statement.jsDoc?.map((doc) => doc.comment).join("\n"),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return metaDataAcc;
|
|
136
|
+
},
|
|
137
|
+
[]
|
|
138
|
+
);
|
|
106
139
|
|
|
107
140
|
function normalizeProp([
|
|
108
141
|
name,
|
|
109
|
-
{
|
|
110
|
-
required,
|
|
111
|
-
annotatedType,
|
|
112
|
-
type,
|
|
113
|
-
tsType,
|
|
114
|
-
description,
|
|
115
|
-
defaultValue
|
|
116
|
-
}
|
|
142
|
+
{ required, annotatedType, type, tsType, description, defaultValue },
|
|
117
143
|
]) {
|
|
118
144
|
const res = {
|
|
119
145
|
name,
|
|
120
|
-
type:
|
|
121
|
-
||
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
||
|
|
125
|
-
|
|
146
|
+
type:
|
|
147
|
+
annotatedType ||
|
|
148
|
+
(type && type.name) ||
|
|
149
|
+
(type && (type.raw || type.name)) ||
|
|
150
|
+
(tsType && (tsType.raw || tsType.name)) ||
|
|
151
|
+
"No type info",
|
|
152
|
+
description,
|
|
126
153
|
};
|
|
127
154
|
if (required) {
|
|
128
155
|
res.required = true;
|
|
@@ -134,45 +161,46 @@ function normalizeProp([
|
|
|
134
161
|
return res;
|
|
135
162
|
}
|
|
136
163
|
|
|
137
|
-
function getDescription(parsed, ) {
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
164
|
function tsDocgen(file) {
|
|
142
|
-
const sourceText = fs.readFileSync(file,
|
|
165
|
+
const sourceText = fs.readFileSync(file, "utf8");
|
|
143
166
|
const componentMeta = getComponentMetadata(file, sourceText); // Array of components with props
|
|
144
167
|
const interfaceMeta = getInterfaceMetadata(file, sourceText); // Array of interfaces with props
|
|
145
|
-
const
|
|
146
|
-
|
|
168
|
+
const typeAliasMeta = getTypeAliasMetadata(file, sourceText); // Array of type aliases with props
|
|
169
|
+
const propsMetaMap = [...interfaceMeta, ...typeAliasMeta].reduce(function (
|
|
170
|
+
target,
|
|
171
|
+
interfaceOrTypeAlias
|
|
172
|
+
) {
|
|
173
|
+
target[interfaceOrTypeAlias.displayName] = interfaceOrTypeAlias;
|
|
147
174
|
return target;
|
|
148
|
-
},
|
|
175
|
+
},
|
|
176
|
+
{});
|
|
149
177
|
|
|
150
|
-
// Go through each component and check if they have an interface with a jsDoc description
|
|
178
|
+
// Go through each component and check if they have an interface or type alias with a jsDoc description
|
|
151
179
|
// If so copy it over (fix for https://github.com/patternfly/patternfly-react/issues/7612)
|
|
152
|
-
componentMeta.forEach(c => {
|
|
180
|
+
componentMeta.forEach((c) => {
|
|
153
181
|
if (c.description) {
|
|
154
182
|
return c;
|
|
155
183
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
184
|
+
|
|
185
|
+
const propsName = `${c.displayName}Props`;
|
|
186
|
+
if (propsMetaMap[propsName]?.description) {
|
|
187
|
+
c.description = propsMetaMap[propsName].description;
|
|
159
188
|
}
|
|
160
|
-
})
|
|
189
|
+
});
|
|
161
190
|
|
|
162
|
-
return componentMeta
|
|
163
|
-
|
|
164
|
-
.map(parsed => ({
|
|
191
|
+
return [...componentMeta, ...interfaceMeta, ...typeAliasMeta].map(
|
|
192
|
+
(parsed) => ({
|
|
165
193
|
name: parsed.displayName,
|
|
166
|
-
description: parsed.description ||
|
|
194
|
+
description: parsed.description || "",
|
|
167
195
|
props: Object.entries(parsed.props || {})
|
|
168
196
|
.map(normalizeProp)
|
|
169
197
|
.map(addAnnotations)
|
|
170
|
-
.filter(prop => !prop.hide)
|
|
171
|
-
.sort((p1, p2) => p1.name.localeCompare(p2.name))
|
|
172
|
-
})
|
|
198
|
+
.filter((prop) => !prop.hide)
|
|
199
|
+
.sort((p1, p2) => p1.name.localeCompare(p2.name)),
|
|
200
|
+
})
|
|
201
|
+
);
|
|
173
202
|
}
|
|
174
203
|
|
|
175
204
|
module.exports = {
|
|
176
|
-
tsDocgen
|
|
205
|
+
tsDocgen,
|
|
177
206
|
};
|
|
178
|
-
|