@patternfly/quickstarts 2.3.3 → 2.3.4

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.
Files changed (32) hide show
  1. package/dist/ConsoleInternal/components/markdown-view.d.ts +1 -1
  2. package/dist/ConsoleShared/src/components/markdown-extensions/accordion-extension.d.ts +7 -0
  3. package/dist/ConsoleShared/src/components/markdown-extensions/accordion-render-extension.d.ts +6 -0
  4. package/dist/ConsoleShared/src/components/markdown-extensions/const.d.ts +2 -0
  5. package/dist/ConsoleShared/src/components/markdown-extensions/index.d.ts +2 -0
  6. package/dist/index.es.js +101 -28
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/index.js +99 -26
  9. package/dist/index.js.map +1 -1
  10. package/dist/patternfly-docs/quick-starts/design-guidelines/design-guidelines.md +1 -1
  11. package/dist/patternfly-docs/quick-starts/examples/about.md +28 -21
  12. package/dist/patternfly-docs/quick-starts/examples/basic.md +7 -5
  13. package/dist/patternfly-docs/quick-starts/examples/help-topics.md +8 -5
  14. package/dist/patternfly-nested.css +209 -1
  15. package/dist/quickstarts-base.css +49 -49
  16. package/dist/quickstarts-full.es.js +2928 -4373
  17. package/dist/quickstarts-full.es.js.map +1 -1
  18. package/dist/quickstarts-standalone.css +6 -0
  19. package/dist/quickstarts-standalone.min.css +2 -2
  20. package/dist/quickstarts.css +49 -49
  21. package/dist/quickstarts.min.css +1 -1
  22. package/package.json +8 -5
  23. package/src/ConsoleInternal/components/markdown-view.tsx +34 -50
  24. package/src/ConsoleShared/src/components/markdown-extensions/accordion-extension.tsx +52 -0
  25. package/src/ConsoleShared/src/components/markdown-extensions/accordion-render-extension.tsx +60 -0
  26. package/src/ConsoleShared/src/components/markdown-extensions/const.ts +2 -0
  27. package/src/ConsoleShared/src/components/markdown-extensions/index.ts +2 -0
  28. package/src/HelpTopicPanelContent.tsx +1 -1
  29. package/src/QuickStartMarkdownView.tsx +5 -0
  30. package/src/QuickStartPanelContent.tsx +11 -2
  31. package/src/controller/QuickStartTaskHeader.tsx +12 -1
  32. package/src/declaration.d.ts +1 -0
@@ -5,7 +5,7 @@ declare type ShowdownExtension = {
5
5
  regex?: RegExp;
6
6
  replace?: (...args: any[]) => string;
7
7
  };
8
- export declare const markdownConvert: (markdown: any, extensions?: ShowdownExtension[]) => any;
8
+ export declare const markdownConvert: (markdown: string, extensions?: ShowdownExtension[]) => Promise<any>;
9
9
  declare type SyncMarkdownProps = {
10
10
  content?: string;
11
11
  emptyMsg?: string;
@@ -0,0 +1,7 @@
1
+ import './showdown-extension.scss';
2
+ declare const useAccordionShowdownExtension: () => {
3
+ type: string;
4
+ regex: RegExp;
5
+ replace: (_text: string, accordionContent: string, _command: string, accordionHeading: string) => string;
6
+ };
7
+ export default useAccordionShowdownExtension;
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ declare type accordionRenderExtensionProps = {
3
+ docContext: HTMLDocument;
4
+ };
5
+ declare const AccordionRenderExtension: React.FC<accordionRenderExtensionProps>;
6
+ export default AccordionRenderExtension;
@@ -1,3 +1,5 @@
1
1
  export declare const MARKDOWN_COPY_BUTTON_ID = "data-copy-for";
2
2
  export declare const MARKDOWN_EXECUTE_BUTTON_ID = "data-execute-for";
3
3
  export declare const MARKDOWN_SNIPPET_ID = "data-snippet-id";
4
+ export declare const ACCORDION_MARKDOWN_BUTTON_ID = "accordion-markdown-button-id";
5
+ export declare const ACCORDION_MARKDOWN_CONTENT_ID = "accordion-markdown-content-id";
@@ -3,3 +3,5 @@ export { default as useInlineCopyClipboardShowdownExtension } from './inline-cli
3
3
  export { default as useMultilineCopyClipboardShowdownExtension } from './multiline-clipboard-extension';
4
4
  export { default as useAdmonitionShowdownExtension } from './admonition-extension';
5
5
  export { default as useCodeShowdownExtension } from './code-extension';
6
+ export { default as useAccordionShowdownExtension } from './accordion-extension';
7
+ export { default as AccordionRenderExtension } from './accordion-render-extension';
package/dist/index.es.js CHANGED
@@ -1,16 +1,16 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { createContext, useCallback, useEffect, useState } from 'react';
3
- import { Card, CardHeader, CardActions, CardTitle, CardBody, CardFooter, Modal as Modal$1, Tooltip, Alert, CodeBlock, Popover, PopoverPosition, Button, Text, TextVariants, TextList, TextListItem, Flex, FlexItem, Title, Label, Gallery, GalleryItem, ToolbarItem, SearchInput, Select, SelectVariant, SelectOption, Toolbar, ToolbarContent, EmptyState, EmptyStateIcon, EmptyStateBody, EmptyStatePrimary, Divider, ModalVariant, WizardNavItem, List, ExpandableSection, ListItem, Radio, DrawerPanelContent, DrawerHead, DrawerActions, DrawerCloseButton, DrawerPanelBody, Drawer, DrawerContent, DrawerContentBody, OptionsMenuItem, Stack, StackItem, OptionsMenu, OptionsMenuToggle } from '@patternfly/react-core';
3
+ import { Card, CardHeader, CardActions, CardTitle, CardBody, CardFooter, Modal as Modal$1, Tooltip, Alert, CodeBlock, Accordion, AccordionItem, AccordionToggle, AccordionContent, Popover, PopoverPosition, Button, Text, TextVariants, TextList, TextListItem, Flex, FlexItem, Title, Label, Gallery, GalleryItem, ToolbarItem, SearchInput, Select, SelectVariant, SelectOption, Toolbar, ToolbarContent, EmptyState, EmptyStateIcon, EmptyStateBody, EmptyStatePrimary, Divider, ModalVariant, WizardNavItem, List, ExpandableSection, ListItem, Radio, DrawerPanelContent, DrawerHead, DrawerActions, DrawerCloseButton, DrawerPanelBody, Drawer, DrawerContent, DrawerContentBody, OptionsMenuItem, Stack, StackItem, OptionsMenu, OptionsMenuToggle } from '@patternfly/react-core';
4
4
  import SearchIcon from '@patternfly/react-icons/dist/js/icons/search-icon';
5
5
  import { css } from '@patternfly/react-styles';
6
6
  import RocketIcon from '@patternfly/react-icons/dist/js/icons/rocket-icon';
7
- import { __rest } from 'tslib';
7
+ import { __rest, __awaiter } from 'tslib';
8
8
  import * as ReactDOM from 'react-dom';
9
9
  import { renderToStaticMarkup } from 'react-dom/server';
10
10
  import CopyIcon from '@patternfly/react-icons/dist/js/icons/copy-icon';
11
11
  import LightbulbIcon from '@patternfly/react-icons/dist/js/icons/lightbulb-icon';
12
12
  import FireIcon from '@patternfly/react-icons/dist/js/icons/fire-icon';
13
- import { Converter } from 'showdown';
13
+ import { marked } from 'marked';
14
14
  import SyncAltIcon from '@patternfly/react-icons/dist/js/icons/sync-alt-icon';
15
15
  import CheckCircleIcon from '@patternfly/react-icons/dist/js/icons/check-circle-icon';
16
16
  import ExclamationCircleIcon from '@patternfly/react-icons/dist/js/icons/exclamation-circle-icon';
@@ -1195,7 +1195,9 @@ const MarkdownHighlightExtension = ({ docContext, rootSelector, }) => {
1195
1195
  };
1196
1196
 
1197
1197
  const MARKDOWN_COPY_BUTTON_ID = 'data-copy-for';
1198
- const MARKDOWN_SNIPPET_ID = 'data-snippet-id';
1198
+ const MARKDOWN_SNIPPET_ID = 'data-snippet-id';
1199
+ const ACCORDION_MARKDOWN_BUTTON_ID = `accordion-markdown-button-id`;
1200
+ const ACCORDION_MARKDOWN_CONTENT_ID = `accordion-markdown-content-id`;
1199
1201
 
1200
1202
  const CopyClipboard = ({ element, rootSelector, docContext, }) => {
1201
1203
  const { getResource } = React.useContext(QuickStartContext);
@@ -1285,16 +1287,7 @@ const useMultilineCopyClipboardShowdownExtension = () => {
1285
1287
 
1286
1288
  // eslint-disable-next-line @typescript-eslint/no-require-imports
1287
1289
  const DOMPurify = require('dompurify');
1288
- const markdownConvert = (markdown, extensions) => {
1289
- const converter = new Converter({
1290
- tables: true,
1291
- openLinksInNewWindow: true,
1292
- strikethrough: true,
1293
- emoji: false,
1294
- });
1295
- if (extensions) {
1296
- converter.addExtension(extensions);
1297
- }
1290
+ const markdownConvert = (markdown, extensions) => __awaiter(void 0, void 0, void 0, function* () {
1298
1291
  DOMPurify.addHook('beforeSanitizeElements', function (node) {
1299
1292
  // nodeType 1 = element type
1300
1293
  // transform anchor tags
@@ -1321,20 +1314,38 @@ const markdownConvert = (markdown, extensions) => {
1321
1314
  node.setAttribute('xlink:show', 'new');
1322
1315
  }
1323
1316
  });
1324
- return DOMPurify.sanitize(converter.makeHtml(markdown), {
1325
- USE_PROFILES: {
1326
- html: true,
1327
- svg: true,
1328
- },
1329
- });
1330
- };
1317
+ // Replace code fences with non markdown formatting relates tokens so that marked doesn't try to parse them as code spans
1318
+ const markdownWithSubstitutedCodeFences = markdown.replace(/```/g, '@@@');
1319
+ const parsedMarkdown = yield marked.parse(markdownWithSubstitutedCodeFences);
1320
+ // Swap the temporary tokens back to code fences before we run the extensions
1321
+ let md = parsedMarkdown.replace(/@@@/g, '```');
1322
+ if (extensions) {
1323
+ // Convert code spans back to md format before we run the custom extension regexes
1324
+ md = md.replace(/<code>(.*)<\/code>/g, '`$1`');
1325
+ extensions.forEach(({ regex, replace }) => {
1326
+ if (regex) {
1327
+ md = md.replace(regex, replace);
1328
+ }
1329
+ });
1330
+ // Convert any remaining backticks back into code spans
1331
+ md = md.replace(/`(.*)`/g, '<code>$1</code>');
1332
+ }
1333
+ return DOMPurify.sanitize(md);
1334
+ });
1331
1335
  const SyncMarkdownView = ({
1332
1336
  // truncateContent,
1333
1337
  content, emptyMsg, extensions, renderExtension, exactHeight, inline, className, }) => {
1334
1338
  const { getResource } = React.useContext(QuickStartContext);
1335
- const markup = React.useMemo(() => {
1336
- return markdownConvert(content || emptyMsg || getResource('Not available'), extensions);
1337
- }, [content, emptyMsg, extensions, getResource]);
1339
+ const [markup, setMarkup] = React.useState('');
1340
+ React.useEffect(() => {
1341
+ function getMd() {
1342
+ return __awaiter(this, void 0, void 0, function* () {
1343
+ const md = yield markdownConvert(content || emptyMsg || getResource('Not available'), extensions);
1344
+ setMarkup(md);
1345
+ });
1346
+ }
1347
+ getMd();
1348
+ }, [content, emptyMsg, getResource, extensions]);
1338
1349
  const innerProps = {
1339
1350
  renderExtension: (extensions === null || extensions === void 0 ? void 0 : extensions.length) > 0 ? renderExtension : undefined,
1340
1351
  exactHeight,
@@ -1459,6 +1470,7 @@ const QuickStartMarkdownView = ({ content, exactHeight, className, }) => {
1459
1470
  const multilineCopyClipboardShowdownExtension = useMultilineCopyClipboardShowdownExtension();
1460
1471
  const admonitionShowdownExtension = useAdmonitionShowdownExtension();
1461
1472
  const codeShowdownExtension = useCodeShowdownExtension();
1473
+ const accordionShowdownExtension = useAccordionShowdownExtension();
1462
1474
  return (React.createElement(SyncMarkdownView, { inline: true, content: content, exactHeight: exactHeight, extensions: [
1463
1475
  {
1464
1476
  type: 'lang',
@@ -1482,8 +1494,10 @@ const QuickStartMarkdownView = ({ content, exactHeight, className, }) => {
1482
1494
  multilineCopyClipboardShowdownExtension,
1483
1495
  admonitionShowdownExtension,
1484
1496
  codeShowdownExtension,
1497
+ accordionShowdownExtension,
1485
1498
  ...(markdown ? markdown.extensions : []),
1486
1499
  ], renderExtension: (docContext, rootSelector) => (React.createElement(React.Fragment, null,
1500
+ React.createElement(AccordionRenderExtension, { docContext: docContext }),
1487
1501
  React.createElement(MarkdownHighlightExtension, { docContext: docContext, rootSelector: rootSelector }),
1488
1502
  React.createElement(MarkdownCopyClipboard, { docContext: docContext, rootSelector: rootSelector }),
1489
1503
  markdown &&
@@ -1539,6 +1553,45 @@ const useCodeShowdownExtension = () => {
1539
1553
  }), []);
1540
1554
  };
1541
1555
 
1556
+ const useAccordionShowdownExtension = () => {
1557
+ return React.useMemo(() => ({
1558
+ type: 'lang',
1559
+ regex: /\[(.+)]{{(accordion) ("(.*?)")}}/g,
1560
+ replace: (_text, accordionContent, _command, accordionHeading) => {
1561
+ const accordionId = new String(accordionHeading).replace(/\s/g, '-');
1562
+ return removeTemplateWhitespace(renderToStaticMarkup(React.createElement(Accordion, { asDefinitionList: true },
1563
+ React.createElement(AccordionItem, null,
1564
+ React.createElement(AccordionToggle, { isExpanded: false, id: `${ACCORDION_MARKDOWN_BUTTON_ID}-${accordionId}` }, accordionHeading),
1565
+ React.createElement(AccordionContent, { id: `${ACCORDION_MARKDOWN_CONTENT_ID}-${accordionId}`, isHidden: !false }, accordionContent)))));
1566
+ },
1567
+ }), []);
1568
+ };
1569
+
1570
+ const AccordionShowdownHandler = ({ buttonElement, contentElement, }) => {
1571
+ const [expanded, setExpanded] = React.useState(false);
1572
+ const handleClick = () => {
1573
+ const expandedModifier = 'pf-m-expanded';
1574
+ buttonElement.className = `pf-c-accordion__toggle ${!expanded ? expandedModifier : ''}`;
1575
+ contentElement.hidden = expanded;
1576
+ contentElement.className = `pf-c-accordion__expanded-content ${!expanded ? expandedModifier : ''}`;
1577
+ setExpanded(!expanded);
1578
+ };
1579
+ useEventListener(buttonElement, 'click', handleClick);
1580
+ return React.createElement(React.Fragment, null);
1581
+ };
1582
+ const AccordionRenderExtension = ({ docContext }) => {
1583
+ const buttonElements = docContext.querySelectorAll(`[id ^= ${ACCORDION_MARKDOWN_BUTTON_ID}]`);
1584
+ const contentElements = docContext.querySelectorAll(`[id ^= ${ACCORDION_MARKDOWN_CONTENT_ID}]`);
1585
+ return buttonElements.length > 0 ? (React.createElement(React.Fragment, null, Array.from(buttonElements).map((elm) => {
1586
+ const content = Array.from(contentElements).find((elm2) => {
1587
+ const elmId = elm.id.split(ACCORDION_MARKDOWN_BUTTON_ID)[1];
1588
+ const elm2Id = elm2.id.split(ACCORDION_MARKDOWN_CONTENT_ID)[1];
1589
+ return elmId === elm2Id;
1590
+ });
1591
+ return (React.createElement(AccordionShowdownHandler, { key: elm.id.split(ACCORDION_MARKDOWN_BUTTON_ID)[1], buttonElement: elm, contentElement: content }));
1592
+ }))) : null;
1593
+ };
1594
+
1542
1595
  const FallbackImg = ({ src, alt, className, fallback }) => {
1543
1596
  const [isSrcValid, setIsSrcValid] = React.useState(true);
1544
1597
  if (src && isSrcValid) {
@@ -1959,12 +2012,22 @@ const TaskIcon = ({ taskIndex, taskStatus }) => {
1959
2012
  };
1960
2013
  const QuickStartTaskHeader = ({ title, taskIndex, subtitle, taskStatus, size, isActiveTask, onTaskSelect, children, }) => {
1961
2014
  const titleRef = React.useRef(null);
2015
+ const [parsedTitle, setParsedTitle] = React.useState('');
1962
2016
  React.useEffect(() => {
1963
2017
  if (isActiveTask) {
1964
2018
  // Focus the WizardNavItem button element that contains the title
1965
2019
  titleRef.current.parentNode.focus();
1966
2020
  }
1967
2021
  }, [isActiveTask]);
2022
+ React.useEffect(() => {
2023
+ function getParsedTitle() {
2024
+ return __awaiter(this, void 0, void 0, function* () {
2025
+ const convertedMdTitle = yield markdownConvert(title);
2026
+ setParsedTitle(removeParagraphWrap(convertedMdTitle));
2027
+ });
2028
+ }
2029
+ getParsedTitle();
2030
+ }, [title]);
1968
2031
  const classNames = css('pfext-quick-start-task-header__title', {
1969
2032
  'pfext-quick-start-task-header__title-success': taskStatus === QuickStartTaskStatus.SUCCESS,
1970
2033
  'pfext-quick-start-task-header__title-failed': taskStatus === (QuickStartTaskStatus.FAILED || QuickStartTaskStatus.VISITED),
@@ -1980,7 +2043,7 @@ const QuickStartTaskHeader = ({ title, taskIndex, subtitle, taskStatus, size, is
1980
2043
  const content = (React.createElement("div", { className: "pfext-quick-start-task-header", ref: titleRef },
1981
2044
  React.createElement(TaskIcon, { taskIndex: taskIndex, taskStatus: taskStatus }),
1982
2045
  React.createElement(Title, { headingLevel: "h3", size: size, className: classNames },
1983
- React.createElement("span", { dangerouslySetInnerHTML: { __html: removeParagraphWrap(markdownConvert(title)) } }),
2046
+ React.createElement("span", { dangerouslySetInnerHTML: { __html: parsedTitle } }),
1984
2047
  isActiveTask && subtitle && (React.createElement("span", { className: "pfext-quick-start-task-header__subtitle", "data-test-id": "quick-start-task-subtitle" },
1985
2048
  ' ',
1986
2049
  subtitle))),
@@ -2187,6 +2250,7 @@ const QuickStartPanelContent = (_a) => {
2187
2250
  const titleRef = React.useRef(null);
2188
2251
  const { getResource, activeQuickStartState } = React.useContext(QuickStartContext);
2189
2252
  const [contentRef, setContentRef] = React.useState();
2253
+ const [displayName, setDisplayName] = React.useState('');
2190
2254
  const shadows = useScrollShadows(contentRef);
2191
2255
  const quickStart = quickStarts.find((qs) => qs.metadata.name === activeQuickStartID);
2192
2256
  const taskNumber = activeQuickStartState === null || activeQuickStartState === void 0 ? void 0 : activeQuickStartState.taskNumber;
@@ -2214,13 +2278,22 @@ const QuickStartPanelContent = (_a) => {
2214
2278
  titleRef.current.focus();
2215
2279
  }
2216
2280
  }, [quickStart]);
2281
+ React.useEffect(() => {
2282
+ function getDisplayName() {
2283
+ return __awaiter(this, void 0, void 0, function* () {
2284
+ const convertedMdDisplayName = yield markdownConvert(quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.displayName);
2285
+ setDisplayName(removeParagraphWrap(convertedMdDisplayName));
2286
+ });
2287
+ }
2288
+ getDisplayName();
2289
+ }, [quickStart]);
2217
2290
  const content = quickStart ? (React.createElement(DrawerPanelContent, Object.assign({ isResizable: isResizable, className: "pfext-quick-start__base", "data-testid": `qs-drawer-${camelize(quickStart.spec.displayName)}`, "data-qs": `qs-step-${getStep()}`, "data-test": "quickstart drawer" }, props),
2218
2291
  React.createElement("div", { className: headerClasses },
2219
2292
  React.createElement(DrawerHead, null,
2220
2293
  React.createElement("div", { className: "pfext-quick-start-panel-content__title", tabIndex: -1, ref: titleRef },
2221
- React.createElement(Title, { headingLevel: "h1", size: "xl", className: "pfext-quick-start-panel-content__name", style: { marginRight: 'var(--pf-global--spacer--md)' } },
2294
+ React.createElement(Title, { headingLevel: "h2", size: "xl", className: "pfext-quick-start-panel-content__name", style: { marginRight: 'var(--pf-global--spacer--md)' } },
2222
2295
  React.createElement("span", { dangerouslySetInnerHTML: {
2223
- __html: removeParagraphWrap(markdownConvert(quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.displayName)),
2296
+ __html: displayName,
2224
2297
  } }),
2225
2298
  ' ',
2226
2299
  React.createElement("small", { className: "pfext-quick-start-panel-content__duration" }, (quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.durationMinutes) ? getResource('{{type}} • {{duration, number}} minutes', quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.durationMinutes)
@@ -2387,7 +2460,7 @@ const HelpTopicPanelContent = (_a) => {
2387
2460
  setActiveHelpTopicByName(topicName);
2388
2461
  toggleHelpTopicMenu();
2389
2462
  };
2390
- const menuItems = filteredHelpTopics.length > 0 &&
2463
+ const menuItems = filteredHelpTopics.length > 1 &&
2391
2464
  filteredHelpTopics.map((topic) => {
2392
2465
  return (React.createElement(OptionsMenuItem, { key: topic.name, onSelect: onSelectHelpTopic, id: topic.name }, topic.title));
2393
2466
  });