@patternfly/documentation-framework 1.0.0
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 +3964 -0
- package/README.md +92 -0
- package/app.js +118 -0
- package/assets/android-chrome-36x36.png +0 -0
- package/assets/android-chrome-48x48.png +0 -0
- package/assets/android-chrome-96x96.png +0 -0
- package/assets/favicon-16x16.png +0 -0
- package/assets/favicon-32x32.png +0 -0
- package/assets/favicon-48x48.png +0 -0
- package/assets/favicon.ico +0 -0
- package/assets/manifest.json +29 -0
- package/components/autoLinkHeader/autoLinkHeader.css +22 -0
- package/components/autoLinkHeader/autoLinkHeader.js +41 -0
- package/components/cssVariables/cssSearch.js +32 -0
- package/components/cssVariables/cssVariables.css +15 -0
- package/components/cssVariables/cssVariables.js +233 -0
- package/components/example/example.css +106 -0
- package/components/example/example.js +196 -0
- package/components/example/exampleToolbar.js +208 -0
- package/components/example/missing-thumbnail.jpg +0 -0
- package/components/footer/RHLogo.png +0 -0
- package/components/footer/footer.css +114 -0
- package/components/footer/footer.js +262 -0
- package/components/gdprBanner/gdprBanner.css +14 -0
- package/components/gdprBanner/gdprBanner.js +31 -0
- package/components/index.js +12 -0
- package/components/inlineAlert/inlineAlert.js +19 -0
- package/components/link/link.js +68 -0
- package/components/propsTable/propTypeWithLinks.js +33 -0
- package/components/propsTable/propsTable.js +82 -0
- package/components/sideNav/sideNav.css +17 -0
- package/components/sideNav/sideNav.js +95 -0
- package/components/tableOfContents/tableOfContents.css +77 -0
- package/components/tableOfContents/tableOfContents.js +89 -0
- package/components/topNav/topNav.css +30 -0
- package/components/topNav/topNav.js +24 -0
- package/global.css +7 -0
- package/helpers/asyncComponentFactory.js +41 -0
- package/helpers/capitalize.js +7 -0
- package/helpers/codeTitleTransformer.js +40 -0
- package/helpers/codesandbox.js +204 -0
- package/helpers/copy.js +19 -0
- package/helpers/createHandlebars.js +26 -0
- package/helpers/d3-timer.js +7 -0
- package/helpers/extractExampleHelpers.js +24 -0
- package/helpers/fonts.js +164 -0
- package/helpers/getId.js +6 -0
- package/helpers/getTitle.js +5 -0
- package/helpers/index.js +9 -0
- package/helpers/liveCodeTypes.js +4 -0
- package/helpers/slugger.js +35 -0
- package/helpers/trackEvent.js +17 -0
- package/helpers/xterm-addon-fit.js +3 -0
- package/helpers/xterm.js +8 -0
- package/images/patternfly-logo.svg +14 -0
- package/images/patternfly-orb.svg +28 -0
- package/layouts/index.js +1 -0
- package/layouts/logo.svg +33 -0
- package/layouts/sideNavLayout/sideNavLayout.css +104 -0
- package/layouts/sideNavLayout/sideNavLayout.js +237 -0
- package/package.json +87 -0
- package/pages/404/404.css +16 -0
- package/pages/404/404.svg +26 -0
- package/pages/404/chart.svg +24 -0
- package/pages/404/components.svg +1 -0
- package/pages/404/guidelines.svg +1 -0
- package/pages/404/index.js +136 -0
- package/pages/404/patternfly-flat.svg +1 -0
- package/pages/global-css-variables.md +108 -0
- package/pages/img/component-variable-mapping.png +0 -0
- package/pages/red-hat-font.md +40 -0
- package/routes-client.js +1 -0
- package/routes-generated.js +1 -0
- package/routes.js +155 -0
- package/scripts/cli/build.js +95 -0
- package/scripts/cli/buildClient.js +23 -0
- package/scripts/cli/buildServer.js +24 -0
- package/scripts/cli/cli.js +63 -0
- package/scripts/cli/generate.js +23 -0
- package/scripts/cli/helpers.js +9 -0
- package/scripts/cli/init.js +68 -0
- package/scripts/cli/serve.js +13 -0
- package/scripts/cli/start.js +32 -0
- package/scripts/md/anchor-header.js +69 -0
- package/scripts/md/auto-link-url.js +33 -0
- package/scripts/md/example-captions.js +67 -0
- package/scripts/md/jsxAttributes.js +20 -0
- package/scripts/md/mdx-ast-to-mdx-hast.js +210 -0
- package/scripts/md/mdx-hast-to-jsx.js +233 -0
- package/scripts/md/parseMD.js +308 -0
- package/scripts/md/remove-comments.js +21 -0
- package/scripts/md/styled-tags.js +87 -0
- package/scripts/md/typecheck.js +133 -0
- package/scripts/tsDocgen.js +155 -0
- package/scripts/webpack/getHtmlWebpackPlugins.js +78 -0
- package/scripts/webpack/prerender.js +59 -0
- package/scripts/webpack/webpack.base.config.js +159 -0
- package/scripts/webpack/webpack.client.config.js +146 -0
- package/scripts/webpack/webpack.server.config.js +55 -0
- package/scripts/writeScreenshots.js +66 -0
- package/templates/design-guidelines.js +13 -0
- package/templates/html.ejs +52 -0
- package/templates/mdx.css +308 -0
- package/templates/mdx.js +185 -0
- package/templates/patternfly-docs/content/extensions/extension/design-guidelines/design-guidelines.md +25 -0
- package/templates/patternfly-docs/content/extensions/extension/design-guidelines/img/card-elements.png +0 -0
- package/templates/patternfly-docs/content/extensions/extension/examples/Basic.jsx +4 -0
- package/templates/patternfly-docs/content/extensions/extension/examples/basic.md +25 -0
- package/templates/patternfly-docs/pages/index.js +27 -0
- package/templates/patternfly-docs/patternfly-docs.config.js +6 -0
- package/templates/patternfly-docs/patternfly-docs.css.js +8 -0
- package/templates/patternfly-docs/patternfly-docs.routes.js +12 -0
- package/templates/patternfly-docs/patternfly-docs.source.js +24 -0
- package/templates/sitemap.ejs +10 -0
- package/versions.json +870 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
.ws-toc {
|
|
2
|
+
top: 0;
|
|
3
|
+
align-self: flex-start;
|
|
4
|
+
position: sticky;
|
|
5
|
+
width: calc(100% + var(--pf-c-page__main-section--PaddingLeft) + var(--pf-c-page__main-section--PaddingRight));
|
|
6
|
+
background-color: var(--pf-global--BackgroundColor--200);
|
|
7
|
+
z-index: 501;
|
|
8
|
+
margin: calc(var(--pf-c-page__main-section--PaddingTop) * -1) calc(var(--pf-c-page__main-section--PaddingRight) * -2) var(--pf-global--spacer--md) calc(var(--pf-c-page__main-section--PaddingLeft) * -1);
|
|
9
|
+
padding: var(--pf-global--spacer--md) 0 var(--pf-global--spacer--md) var(--pf-global--spacer--md);
|
|
10
|
+
box-shadow: var(--pf-global--BoxShadow--lg-bottom);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.ws-toc.pf-m-expanded {
|
|
14
|
+
box-shadow: var(--pf-global--BoxShadow--sm-bottom)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Mobile jumplinks */
|
|
18
|
+
@media (max-width: 1450px) {
|
|
19
|
+
.ws-toc.pf-m-expanded .pf-c-jump-links__main {
|
|
20
|
+
max-height: 65vh;
|
|
21
|
+
overflow: auto;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ws-toc .pf-c-jump-links__header {
|
|
25
|
+
position: sticky;
|
|
26
|
+
top: 0;
|
|
27
|
+
background-color: var(--pf-global--BackgroundColor--200);
|
|
28
|
+
z-index: 2;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.ws-toc .pf-c-jump-links__main {
|
|
33
|
+
scrollbar-width: none;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Hide TOC scrollbar Chrome, Safari & Opera */
|
|
37
|
+
.ws-toc .pf-c-jump-links__main::-webkit-scrollbar {
|
|
38
|
+
display: none;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@media (min-width: 1451px) {
|
|
42
|
+
.ws-toc {
|
|
43
|
+
width: 280px;
|
|
44
|
+
max-height: calc(100vh - 76px);
|
|
45
|
+
overflow-y: auto;
|
|
46
|
+
/* Hide TOC scrollbar IE, Edge & Firefox */
|
|
47
|
+
-ms-overflow-style: none;
|
|
48
|
+
scrollbar-width: none;
|
|
49
|
+
order: 1;
|
|
50
|
+
padding: 0 var(--pf-global--spacer--lg) var(--pf-global--spacer--lg) var(--pf-global--spacer--2xl);
|
|
51
|
+
flex-grow: 1;
|
|
52
|
+
background: none;
|
|
53
|
+
margin: 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.ws-toc,
|
|
57
|
+
.ws-toc.pf-m-expanded {
|
|
58
|
+
box-shadow: none;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* .ws-toc-link { */
|
|
63
|
+
.ws-toc-item .pf-c-jump-links__link {
|
|
64
|
+
position: relative;
|
|
65
|
+
display: block;
|
|
66
|
+
color: var(--ws-toc-link--Color, var(--pf-global--Color--300));
|
|
67
|
+
font-size: var(--pf-global--FontSize--sm);
|
|
68
|
+
margin: -4px 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.ws-toc-sublist > .ws-toc-item:first-child .pf-c-jump-links__link {
|
|
72
|
+
margin-top: 0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.ws-toc-item.pf-m-current .pf-c-jump-links__link::before {
|
|
76
|
+
z-index: 1;
|
|
77
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { JumpLinks, JumpLinksItem, JumpLinksList } from '@patternfly/react-core';
|
|
3
|
+
import { trackEvent } from '../../helpers';
|
|
4
|
+
|
|
5
|
+
export const TableOfContents = ({ items }) => {
|
|
6
|
+
// Used to recalculate JumpLinks offset if screen size changes
|
|
7
|
+
const [width, setWidth] = React.useState(window.innerWidth);
|
|
8
|
+
const updateWidth = () => {
|
|
9
|
+
const { innerWidth } = window;
|
|
10
|
+
innerWidth !== width && setWidth(innerWidth);
|
|
11
|
+
}
|
|
12
|
+
let jumpLinksItems = [];
|
|
13
|
+
let wasSublistRendered = false;
|
|
14
|
+
|
|
15
|
+
const renderSublist = (item, nextItemArr) => {
|
|
16
|
+
wasSublistRendered = true;
|
|
17
|
+
return (
|
|
18
|
+
<>
|
|
19
|
+
{item.text}
|
|
20
|
+
<JumpLinksList>
|
|
21
|
+
{nextItemArr.map(curItem => (
|
|
22
|
+
<JumpLinksItem
|
|
23
|
+
key={curItem.id}
|
|
24
|
+
href={`#${curItem.id}`}
|
|
25
|
+
className="ws-toc-item"
|
|
26
|
+
onKeyDown={updateWidth}
|
|
27
|
+
onMouseDown={updateWidth}
|
|
28
|
+
onClick={() => trackEvent('jump_link_click', 'click_event', curItem.id.toUpperCase())}
|
|
29
|
+
>
|
|
30
|
+
{curItem.text}
|
|
31
|
+
</JumpLinksItem>
|
|
32
|
+
))}
|
|
33
|
+
</JumpLinksList>
|
|
34
|
+
</>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const renderJumpLinksItems = () => {
|
|
39
|
+
items.forEach((item, index) => {
|
|
40
|
+
let nextItem = items[index + 1];
|
|
41
|
+
// Don't render empty <JumpLinksItem> for an array of sublist items
|
|
42
|
+
if (wasSublistRendered) {
|
|
43
|
+
wasSublistRendered = false;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (!Array.isArray(nextItem) && Array.isArray(item)) {
|
|
47
|
+
{item.map(curItem => jumpLinksItems.push(
|
|
48
|
+
<JumpLinksItem
|
|
49
|
+
key={curItem.id}
|
|
50
|
+
href={`#${curItem.id}`}
|
|
51
|
+
className="ws-toc-item"
|
|
52
|
+
onKeyDown={updateWidth}
|
|
53
|
+
onMouseDown={updateWidth}
|
|
54
|
+
onClick={() => trackEvent('jump_link_click', 'click_event', curItem.id.toUpperCase())}
|
|
55
|
+
>
|
|
56
|
+
{curItem.text}
|
|
57
|
+
</JumpLinksItem>
|
|
58
|
+
))}
|
|
59
|
+
} else {
|
|
60
|
+
jumpLinksItems.push(
|
|
61
|
+
<JumpLinksItem
|
|
62
|
+
key={item.id}
|
|
63
|
+
href={`#${item.id}`}
|
|
64
|
+
className="ws-toc-item"
|
|
65
|
+
onKeyDown={updateWidth}
|
|
66
|
+
onMouseDown={updateWidth}
|
|
67
|
+
onClick={() => trackEvent('jump_link_click', 'click_event', item.id.toUpperCase())}
|
|
68
|
+
>
|
|
69
|
+
{ Array.isArray(nextItem) ? renderSublist(item, nextItem) : item.text }
|
|
70
|
+
</JumpLinksItem>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
return jumpLinksItems;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<JumpLinks
|
|
79
|
+
label="Table of contents"
|
|
80
|
+
isVertical
|
|
81
|
+
scrollableSelector="#ws-page-main"
|
|
82
|
+
className="ws-toc"
|
|
83
|
+
offset={width > 1450 ? 92 : 148}
|
|
84
|
+
expandable={{ default: 'expandable', '2xl': 'nonExpandable' }}
|
|
85
|
+
>
|
|
86
|
+
{ renderJumpLinksItems() }
|
|
87
|
+
</JumpLinks>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* Don't bother with specifity war */
|
|
2
|
+
.ws-top-nav-link.pf-c-nav__link {
|
|
3
|
+
color: var(--pf-global--BackgroundColor--light-100);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.ws-top-nav-link.pf-c-nav__link:active,
|
|
7
|
+
.ws-top-nav-link.pf-c-nav__link:hover,
|
|
8
|
+
.ws-top-nav-link.pf-c-nav__link.pf-m-current {
|
|
9
|
+
color: var(--pf-global--BackgroundColor--dark-100);
|
|
10
|
+
background-color: var(--pf-global--BackgroundColor--light-100);
|
|
11
|
+
transition: .5s;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* Don't bother with specifity war */
|
|
15
|
+
.ws-top-nav-link.pf-c-nav__link::before {
|
|
16
|
+
top: 0 !important;
|
|
17
|
+
bottom: auto !important;
|
|
18
|
+
right: 0 !important;
|
|
19
|
+
left: 0 !important;
|
|
20
|
+
border-color: var(--pf-global--link--Color--light--hover) !important;
|
|
21
|
+
transform: scaleX(0);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Animate bar growing outwards */
|
|
25
|
+
.ws-top-nav-link.pf-c-nav__link:active::before,
|
|
26
|
+
.ws-top-nav-link.pf-c-nav__link:hover::before,
|
|
27
|
+
.ws-top-nav-link.pf-c-nav__link.pf-m-current::before {
|
|
28
|
+
transition: transform .5s;
|
|
29
|
+
transform: scaleX(1);
|
|
30
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Link } from '@patternfly/documentation-framework/components';
|
|
3
|
+
import { Nav, NavList, NavItem } from '@patternfly/react-core';
|
|
4
|
+
import { Location } from '@reach/router';
|
|
5
|
+
|
|
6
|
+
export const TopNav = ({ navItems }) => (
|
|
7
|
+
<Location>
|
|
8
|
+
{({ location }) =>
|
|
9
|
+
<Nav aria-label="Patternfly top nav" variant="horizontal">
|
|
10
|
+
<NavList>
|
|
11
|
+
{navItems.map(({ path, text }) => (
|
|
12
|
+
<NavItem
|
|
13
|
+
key={path}
|
|
14
|
+
isActive={location.pathname.includes(path)}
|
|
15
|
+
>
|
|
16
|
+
<Link className="ws-top-nav-link" to={path}>{text}</Link>
|
|
17
|
+
</NavItem>
|
|
18
|
+
))}
|
|
19
|
+
</NavList>
|
|
20
|
+
</Nav>
|
|
21
|
+
}
|
|
22
|
+
</Location>
|
|
23
|
+
);
|
|
24
|
+
|
package/global.css
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const React = require('react');
|
|
2
|
+
|
|
3
|
+
const cache = {};
|
|
4
|
+
|
|
5
|
+
function asyncComponentFactory(route, pageData) {
|
|
6
|
+
const { Component } = pageData;
|
|
7
|
+
|
|
8
|
+
class AsyncComponent extends React.Component {
|
|
9
|
+
state = {
|
|
10
|
+
isLoaded: false
|
|
11
|
+
};
|
|
12
|
+
static preload() {
|
|
13
|
+
return Component().then(res => {
|
|
14
|
+
cache[route] = res.default;
|
|
15
|
+
return res.default;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
static getPageData() {
|
|
19
|
+
return cache[route] ? cache[route].pageData : {};
|
|
20
|
+
}
|
|
21
|
+
render() {
|
|
22
|
+
if (cache[route]) {
|
|
23
|
+
return React.createElement(cache[route]);
|
|
24
|
+
}
|
|
25
|
+
AsyncComponent.preload().then(() => this.setState({ isLoaded: true }));
|
|
26
|
+
|
|
27
|
+
// Simple loading state
|
|
28
|
+
return React.createElement('div',
|
|
29
|
+
{ style: { height: '100vh' } },
|
|
30
|
+
'Loading...'
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
AsyncComponent.displayName = route.replace(/\//g, '.');
|
|
35
|
+
|
|
36
|
+
return AsyncComponent;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = {
|
|
40
|
+
asyncComponentFactory
|
|
41
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const visit = require('unist-util-visit');
|
|
2
|
+
|
|
3
|
+
function exampleCaptions() {
|
|
4
|
+
return tree => {
|
|
5
|
+
visit(tree, 'element', (node, _index, parent) => {
|
|
6
|
+
if (node.tagName !== 'pre') {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const codeNode = node.children[0];
|
|
10
|
+
if (codeNode.tagName !== 'code' || codeNode.properties.title) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
let title = 'Untitled example';
|
|
14
|
+
|
|
15
|
+
// Starting from node, look up for h3s
|
|
16
|
+
let startLooking = false;
|
|
17
|
+
for(let i = parent.children.length - 1; i > 0; i--) {
|
|
18
|
+
const child = parent.children[i];
|
|
19
|
+
if (child === node) {
|
|
20
|
+
startLooking = true;
|
|
21
|
+
}
|
|
22
|
+
else if (startLooking) {
|
|
23
|
+
if (
|
|
24
|
+
child.tagName === 'h3' &&
|
|
25
|
+
child.children &&
|
|
26
|
+
child.children[0].value
|
|
27
|
+
) {
|
|
28
|
+
title = child.children[0].value;
|
|
29
|
+
parent.children.splice(i, 1);
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
codeNode.properties.title = title;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = exampleCaptions;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
const { parse } = require('@patternfly/ast-helpers');
|
|
2
|
+
const versions = require('../versions.json');
|
|
3
|
+
const overpass = require('./fonts');
|
|
4
|
+
const { capitalize } = require('./capitalize');
|
|
5
|
+
|
|
6
|
+
const getStaticParams = (title, html) => {
|
|
7
|
+
const imgAssetRegex = /['"](\/assets\/images\/.*)['"]/g;
|
|
8
|
+
let imgAsset;
|
|
9
|
+
while ((imgAsset = imgAssetRegex.exec(html))) {
|
|
10
|
+
const imgName = imgAsset[1];
|
|
11
|
+
html = html.replace(imgName, `https://www.patternfly.org/v4${imgName}`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
files: {
|
|
16
|
+
'index.html': {
|
|
17
|
+
content: `
|
|
18
|
+
<!DOCTYPE html>
|
|
19
|
+
<html lang="en" class="pf-m-redhat-font">
|
|
20
|
+
<head>
|
|
21
|
+
<meta charset="utf-8" />
|
|
22
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
23
|
+
<link rel="stylesheet" href="fonts.css" />
|
|
24
|
+
<!-- Include latest PatternFly CSS via CDN -->
|
|
25
|
+
<link
|
|
26
|
+
rel="stylesheet"
|
|
27
|
+
href="https://unpkg.com/@patternfly/patternfly/patternfly.css"
|
|
28
|
+
crossorigin="anonymous"
|
|
29
|
+
>
|
|
30
|
+
<link rel="stylesheet" href="style.css" />
|
|
31
|
+
<title>PatternFly ${title} CodeSandbox Example</title>
|
|
32
|
+
</head>
|
|
33
|
+
<body>
|
|
34
|
+
${html}
|
|
35
|
+
</body>
|
|
36
|
+
</html>
|
|
37
|
+
`,
|
|
38
|
+
},
|
|
39
|
+
'package.json': {
|
|
40
|
+
content: {},
|
|
41
|
+
},
|
|
42
|
+
'style.css': {
|
|
43
|
+
content: ''
|
|
44
|
+
},
|
|
45
|
+
'fonts.css': {
|
|
46
|
+
content: overpass
|
|
47
|
+
},
|
|
48
|
+
'sandbox.config.json': {
|
|
49
|
+
content: { template: 'static' }
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
template: 'static',
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Allow 4 formats for example identifiers
|
|
57
|
+
// 1. Example = () => { return <jsx />; }
|
|
58
|
+
// 2. class Example {}
|
|
59
|
+
// 3. function Example() { return <jsx />; }
|
|
60
|
+
// 4. const Example = () => { return <jsx />; }
|
|
61
|
+
const allowedIdentifiers = [
|
|
62
|
+
'ClassDeclaration',
|
|
63
|
+
'FunctionDeclaration',
|
|
64
|
+
'ExpressionStatement',
|
|
65
|
+
'VariableDeclaration'
|
|
66
|
+
];
|
|
67
|
+
function getExampleDeclaration(code) {
|
|
68
|
+
code = code
|
|
69
|
+
.replace(/export\s+default\s+/g, '')
|
|
70
|
+
.replace(/export\s+/g, '');
|
|
71
|
+
|
|
72
|
+
const { body } = parse(code);
|
|
73
|
+
const lastParsed = body[body.length - 1];
|
|
74
|
+
if (allowedIdentifiers.includes(lastParsed.type)) {
|
|
75
|
+
return lastParsed;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function getIdentifier(title) {
|
|
80
|
+
return capitalize(
|
|
81
|
+
title
|
|
82
|
+
.replace(/^[^A-Za-z]/, '')
|
|
83
|
+
.replace(/\s+([a-z])?/g, (_, match) => match ? capitalize(match) : '')
|
|
84
|
+
.replace(/[^A-Za-z0-9_]/g, '')
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function prettyExampleCode(title, code, declaration, identifier) {
|
|
89
|
+
// Create identifier from title
|
|
90
|
+
const ident = identifier || getIdentifier(title);
|
|
91
|
+
const jsxBlock = code.substring(declaration.start, declaration.end);
|
|
92
|
+
if (identifier) {
|
|
93
|
+
return code.replace(jsxBlock, `const ${jsxBlock}`);
|
|
94
|
+
}
|
|
95
|
+
if (jsxBlock.includes('\n')) {
|
|
96
|
+
// Make pretty
|
|
97
|
+
return code.replace(jsxBlock, `const ${ident} = () => (\n ${
|
|
98
|
+
jsxBlock
|
|
99
|
+
.replace(/\n/g, '\n ')
|
|
100
|
+
.replace(/;[ \t]*$/, '')
|
|
101
|
+
}\n)`);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
return code.replace(jsxBlock, `const ${ident} = () => ${jsxBlock}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// TODO: Make React examples work and use a template that has our assets.
|
|
109
|
+
function getReactParams(title, code, scope, lang) {
|
|
110
|
+
let toRender = null;
|
|
111
|
+
try {
|
|
112
|
+
let declaration = getExampleDeclaration(code);
|
|
113
|
+
if (declaration.type === 'ExpressionStatement') {
|
|
114
|
+
if (!declaration.expression.left) {
|
|
115
|
+
// () => <jsx />
|
|
116
|
+
code = prettyExampleCode(title, code, declaration);
|
|
117
|
+
toRender = getIdentifier(title);
|
|
118
|
+
} else if (declaration.expression.type === 'AssignmentExpression') {
|
|
119
|
+
// Basic = () => <jsx />
|
|
120
|
+
code = prettyExampleCode(title, code, declaration, declaration.expression.left.name);
|
|
121
|
+
toRender = declaration.expression.left.name;
|
|
122
|
+
}
|
|
123
|
+
} else if (declaration.type === 'VariableDeclaration') {
|
|
124
|
+
toRender = declaration.declarations[0].id.name;
|
|
125
|
+
} else if (declaration.id) {
|
|
126
|
+
toRender = declaration.id.name;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
// Ignore
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const imgImportRegex = /import\s*(\w*).*['"](.*)(\.(png|jpe?g|webp|gif|svg))['"]/g;
|
|
134
|
+
let imgImportMatch;
|
|
135
|
+
while ((imgImportMatch = imgImportRegex.exec(code))) {
|
|
136
|
+
const imgName = imgImportMatch[1];
|
|
137
|
+
code = code.replace(imgImportMatch[0], `const ${imgName} = "https://www.patternfly.org/v4${scope[imgName]}"`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const dependencies = {
|
|
141
|
+
'@patternfly/react-core': versions.Releases[0].versions['@patternfly/react-core']
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
if (lang === 'ts') {
|
|
145
|
+
dependencies['@babel/runtime'] = 'latest';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
Object.entries(versions.Releases[0].versions)
|
|
149
|
+
.filter(([pkg]) => code.includes(pkg))
|
|
150
|
+
.forEach(([pkg, version]) => dependencies[pkg] = version);
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
files: {
|
|
154
|
+
'index.html': {
|
|
155
|
+
content: `<!DOCTYPE html>
|
|
156
|
+
<html lang="en" class="pf-m-redhat-font">
|
|
157
|
+
<head>
|
|
158
|
+
<meta charset="utf-8" />
|
|
159
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
160
|
+
<title>PatternFly-React ${title} CodeSandbox Example</title>
|
|
161
|
+
</head>
|
|
162
|
+
<body>
|
|
163
|
+
<noscript>
|
|
164
|
+
You need to enable JavaScript to run this app.
|
|
165
|
+
</noscript>
|
|
166
|
+
<div id="root" style="height:100%"></div>
|
|
167
|
+
</body>
|
|
168
|
+
</html>`,
|
|
169
|
+
},
|
|
170
|
+
[lang === 'ts' ? 'index.tsx' : 'index.js']: {
|
|
171
|
+
content: `import ReactDOM from 'react-dom';
|
|
172
|
+
import "@patternfly/react-core/dist/styles/base.css";
|
|
173
|
+
import './fonts.css';
|
|
174
|
+
|
|
175
|
+
${code}
|
|
176
|
+
|
|
177
|
+
const rootElement = document.getElementById("root");
|
|
178
|
+
ReactDOM.render(<${toRender} />, rootElement);`
|
|
179
|
+
},
|
|
180
|
+
'fonts.css': {
|
|
181
|
+
content: overpass
|
|
182
|
+
},
|
|
183
|
+
'package.json': {
|
|
184
|
+
content: {
|
|
185
|
+
dependencies: {
|
|
186
|
+
...dependencies,
|
|
187
|
+
'react': '^16.8.0',
|
|
188
|
+
'react-dom': '^16.8.0'
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
'sandbox.config.json': {
|
|
193
|
+
content: { template: lang === 'ts' ? 'create-react-app-typescript' : 'create-react-app' }
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
module.exports = {
|
|
200
|
+
getReactParams,
|
|
201
|
+
getStaticParams,
|
|
202
|
+
getExampleDeclaration,
|
|
203
|
+
prettyExampleCode
|
|
204
|
+
};
|
package/helpers/copy.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const copy = textToCopy => {
|
|
2
|
+
let el = document.createElement('textarea');
|
|
3
|
+
// Set value (string to be copied)
|
|
4
|
+
el.value = textToCopy;
|
|
5
|
+
// Set non-editable to avoid focus and move outside of view
|
|
6
|
+
el.setAttribute('readonly', '');
|
|
7
|
+
el.style = {
|
|
8
|
+
display: 'none',
|
|
9
|
+
position: 'absolute',
|
|
10
|
+
left: '-9999px'
|
|
11
|
+
};
|
|
12
|
+
document.body.appendChild(el);
|
|
13
|
+
// Select text inside element
|
|
14
|
+
el.select();
|
|
15
|
+
// Copy text to clipboard
|
|
16
|
+
document.execCommand('copy');
|
|
17
|
+
// Remove temporary element
|
|
18
|
+
document.body.removeChild(el);
|
|
19
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const Handlebars = require('handlebars');
|
|
2
|
+
|
|
3
|
+
const createHandlebars = nodes => {
|
|
4
|
+
const instance = Handlebars.create();
|
|
5
|
+
|
|
6
|
+
// Add helpers
|
|
7
|
+
instance.registerHelper('concat', (...params) => {
|
|
8
|
+
// Ignore the object appended by handlebars.
|
|
9
|
+
if (typeof params[params.length - 1] === 'object') {
|
|
10
|
+
params.pop();
|
|
11
|
+
}
|
|
12
|
+
return params.join('');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// Add partials
|
|
16
|
+
nodes.forEach(({ fields }) => instance.registerPartial(
|
|
17
|
+
fields.name, // Partial name
|
|
18
|
+
fields.partial // Partial template
|
|
19
|
+
));
|
|
20
|
+
|
|
21
|
+
return instance;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
createHandlebars
|
|
26
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// react-charts depends on victory-core which uses d3-timer to create an
|
|
2
|
+
// animation event loop using setInterval. This event loop will cause Node.js
|
|
3
|
+
// to hang if we prerender charts pages, so just replace with calls that resolve instantly.
|
|
4
|
+
module.exports = {
|
|
5
|
+
timer: () => {},
|
|
6
|
+
now: () => {}
|
|
7
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const { slugger } = require('./slugger');
|
|
2
|
+
|
|
3
|
+
// Used in core's dev:lite
|
|
4
|
+
function getExampleClassName(source, componentType, componentName) {
|
|
5
|
+
// Compatibility with old gatsby workspace
|
|
6
|
+
if (source === 'html') {
|
|
7
|
+
source = 'core';
|
|
8
|
+
}
|
|
9
|
+
return slugger(`ws-${source}-${componentType}-${componentName}`);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Used in core's dev:lite
|
|
13
|
+
function getExampleId(source, componentType, componentName, exampleTitle) {
|
|
14
|
+
// Compatibility with old gatsby workspace
|
|
15
|
+
if (source === 'html') {
|
|
16
|
+
source = 'core';
|
|
17
|
+
}
|
|
18
|
+
return slugger(`ws-${source}-${componentType}-${componentName}-${exampleTitle}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = {
|
|
22
|
+
getExampleClassName,
|
|
23
|
+
getExampleId
|
|
24
|
+
};
|