@patternfly/quickstarts 6.3.0-prerelease.5 → 6.3.0-prerelease.7

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.
@@ -163,6 +163,10 @@
163
163
  border: var(--pf-v6-c-card--BorderColor) var(--pf-v6-c-card--BorderStyle) var(--pf-v6-c-card--BorderWidth);
164
164
  }
165
165
 
166
+ .pfext-quick-start-footer {
167
+ padding-top: var(--pf-t--global--spacer--md);
168
+ }
169
+
166
170
  .pfext-quick-start-task {
167
171
  flex: 1 1 0;
168
172
  overflow: auto;
@@ -174,10 +178,6 @@
174
178
  height: initial;
175
179
  }
176
180
 
177
- .pfext-quick-start-footer {
178
- padding-top: var(--pf-t--global--spacer--md);
179
- }
180
-
181
181
  .pfext-quick-start-task-header button.pf-v6-c-wizard__nav-link {
182
182
  margin-bottom: var(--pf-t--global--spacer--md);
183
183
  }
@@ -1 +1 @@
1
- .pfext-quick-start-panel{--pf-v6-c-drawer__panel--PaddingBlockStart:0}.pfext-popover__base ul{list-style-type:var(--pf-t--global--list-style)}.pfext-markdown-view .h1,.pfext-markdown-view .h2,.pfext-markdown-view .h3,.pfext-markdown-view .h4,.pfext-markdown-view .h5,.pfext-markdown-view .h6,.pfext-markdown-view h1,.pfext-markdown-view h2,.pfext-markdown-view h3,.pfext-markdown-view h4,.pfext-markdown-view h5,.pfext-markdown-view h6{font-family:var(--pf-t--global--font--family--heading);font-weight:var(--pf-t--global--font--weight--heading);line-height:1.1;color:inherit}.pfext-markdown-view .h1,.pfext-markdown-view .h2,.pfext-markdown-view .h3,.pfext-markdown-view h1,.pfext-markdown-view h2,.pfext-markdown-view h3{margin-top:23px;margin-bottom:11.5px}.pfext-markdown-view .h4,.pfext-markdown-view .h5,.pfext-markdown-view .h6,.pfext-markdown-view h4,.pfext-markdown-view h5,.pfext-markdown-view h6{margin-top:11.5px;margin-bottom:11.5px}.pfext-markdown-view .h1,.pfext-markdown-view h1{font-size:var(--pf-t--global--font--size--heading--h1)}.pfext-markdown-view .h2,.pfext-markdown-view h2{font-size:var(--pf-t--global--font--size--heading--h2)}.pfext-markdown-view .h3,.pfext-markdown-view h3{font-size:var(--pf-t--global--font--size--heading--h3)}.pfext-markdown-view .h4,.pfext-markdown-view h4{font-size:var(--pf-t--global--font--size--heading--h4)}.pfext-markdown-view .h5,.pfext-markdown-view h5{font-size:var(--pf-t--global--font--size--heading--h5)}.pfext-markdown-view .h6,.pfext-markdown-view h6{font-size:var(--pf-t--global--font--size--heading--h6)}.pfext-markdown-view p{margin:0 0 11.5px}.pfext-markdown-view ol,.pfext-markdown-view ul{margin-top:0;margin-bottom:11.5px}.pfext-markdown-view ol ol,.pfext-markdown-view ol ul,.pfext-markdown-view ul ol,.pfext-markdown-view ul ul{margin-bottom:0}.pfext-markdown-view dl{margin-top:0;margin-bottom:23px}.pfext-markdown-view dd,.pfext-markdown-view dt{line-height:1.66666667}.pfext-markdown-view dt{font-weight:700}.pfext-markdown-view dd{margin-left:0}.pfext-markdown-view blockquote{padding:11.5px 23px;margin:0 0 23px;font-size:17.5px;border-left:5px solid #f1f1f1}.pfext-markdown-view blockquote ol:last-child,.pfext-markdown-view blockquote p:last-child,.pfext-markdown-view blockquote ul:last-child{margin-bottom:0}.pfext-markdown-view code,.pfext-markdown-view pre{font-family:Menlo,Monaco,Consolas,monospace}.pfext-markdown-view code{padding:2px 4px;font-size:90%;color:#004368;background-color:#def3ff;border-radius:1px}.pfext-markdown-view pre{display:block;padding:11px;margin:0 0 11.5px;font-size:13px;line-height:1.66666667;color:#363636;word-break:break-all;word-wrap:break-word;background-color:#fafafa;border:1px solid #ccc;border-radius:1px}.pfext-markdown-view pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pfext-markdown-view table{background-color:transparent}.pfext-markdown-view table col[class*=col-]{position:static;display:table-column;float:none}.pfext-markdown-view table td[class*=col-],.pfext-markdown-view table th[class*=col-]{position:static;display:table-cell;float:none}.pfext-markdown-view caption{padding-top:10px;padding-bottom:10px;color:#9c9c9c;text-align:left}.pfext-markdown-view th{text-align:left}.pfext-quick-start-panel-content{background-color:var(--pf-t--global--color--brand--default);color:var(--pf-t--global--text--color--inverse);padding:var(--pf-t--global--spacer--md) var(--pf-t--global--spacer--lg)}.pfext-quick-start-panel-content__body{display:flex;flex-direction:column}.pfext-quick-start-panel-content span.pf-v6-c-button__icon{color:var(--pf-t--global--text--color--inverse)}.pf-v6-theme-dark .pfext-catalog-item-icon__img{filter:brightness(1.5) invert(1) hue-rotate(180deg) saturate(4)}.pfext-catalog-item .pf-v6-c-card__header-main .pf-v6-c-icon__content{display:contents}.pfext-catalog-item.pf-v6-c-card.pf-m-clickable::before,.pfext-catalog-item.pf-v6-c-card.pf-m-selectable::before{border:var(--pf-v6-c-card--BorderColor) var(--pf-v6-c-card--BorderStyle) var(--pf-v6-c-card--BorderWidth)}.pfext-quick-start-task{flex:1 1 0;overflow:auto}.pfext-quick-start-task .pf-v6-c-accordion,.pfext-quick-start-task .pf-v6-c-alert,.pfext-quick-start-task .pf-v6-c-code-block{margin-block-end:var(--pf-v6-c-content--MarginBlockEnd)}.pfext-quick-start-task .pf-v6-c-wizard{height:initial}.pfext-quick-start-footer{padding-top:var(--pf-t--global--spacer--md)}.pfext-quick-start-task-header button.pf-v6-c-wizard__nav-link{margin-bottom:var(--pf-t--global--spacer--md)}.pfext-quick-start-task-header button.pf-v6-c-wizard__nav-link.pf-m-current{--pf-v6-c-wizard__nav-link-main--BackgroundColor:transparent}.pfext-quick-start-task-header button.pf-v6-c-wizard__nav-link::before{background-color:var(--pf-v6-c-wizard__nav-link--m-current--before--BackgroundColor);color:var(--pf-v6-c-wizard__nav-link--m-current--before--Color);min-width:var(--pf-v6-c-wizard__nav-link--before--Width)}.pfext-quick-start-task-header__title{font-family:var(--pf-t--global--font--family--body);font-weight:var(---pf-t--global--font--weight--body--bold);font-size:var(--pf-t--global--font--size--body--lg)}.pfext-quick-start-task-header__subtitle{font-size:var(--pf-t--global--font--size--body--default);color:var(--pf-t--global--text--color--subtle);font-weight:var(--pf-t--global--font--weight--body)}.pfext-quick-start-task-header__tryagain{display:block;font-size:var(--pf-t--global--font--size--body--default);color:var(--pf-t--global--text--color--subtle);font-weight:var(--pf-t--global--font--weight--body)}@keyframes pfext-spotlight-expand{0%{outline-offset:-4px;outline-width:4px;opacity:1}100%{outline-offset:21px;outline-width:12px;opacity:0}}@keyframes pfext-spotlight-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes pfext-spotlight-fade-out{0%{opacity:1}100%{opacity:0}}.pfext-spotlight{pointer-events:none;position:absolute}.pfext-spotlight__with-backdrop{mix-blend-mode:hard-light}.pfext-spotlight__element-highlight-noanimate{border:var(--pf-t--global--border--width--strong) solid var(--pf-t--global--border--color--brand--default);background-color:var(--pf-t--color--gray--40);z-index:9999}.pfext-spotlight__element-highlight-animate{pointer-events:none;position:absolute;box-shadow:inset 0 0 0 4px var(--pf-t--global--color--brand--default);opacity:0;animation:.4s pfext-spotlight-fade-in 0s ease-in-out,5s pfext-spotlight-fade-out 12.8s ease-in-out;animation-fill-mode:forwards}.pfext-spotlight__element-highlight-animate::after{content:"";position:absolute;left:0;right:0;top:0;bottom:0;animation:1.2s pfext-spotlight-expand 1.6s ease-out;animation-fill-mode:forwards;outline:4px solid var(--pf-t--global--color--brand--default);outline-offset:-4px}.pf-v6-c-clipboard-copy{--pf-v6-c-clipboard-copy__toggle-icon--Transition:.2s ease-in 0s;--pf-v6-c-clipboard-copy--m-expanded__toggle-icon--Rotate:90deg;--pf-v6-c-clipboard-copy__expandable-content--MarginBlockStart:var(--pf-t--global--spacer--xs);--pf-v6-c-clipboard-copy__expandable-content--PaddingBlockStart:var(--pf-t--global--spacer--md);--pf-v6-c-clipboard-copy__expandable-content--PaddingInlineEnd:var(--pf-t--global--spacer--md);--pf-v6-c-clipboard-copy__expandable-content--PaddingBlockEnd:var(--pf-t--global--spacer--md);--pf-v6-c-clipboard-copy__expandable-content--PaddingInlineStart:var(--pf-t--global--spacer--md);--pf-v6-c-clipboard-copy__expandable-content--BackgroundColor:var(--pf-t--global--background--color--primary--default);--pf-v6-c-clipboard-copy__expandable-content--BorderBlockStartWidth:var(--pf-t--global--border--width--control--default);--pf-v6-c-clipboard-copy__expandable-content--BorderInlineEndWidth:var(--pf-t--global--border--width--control--default);--pf-v6-c-clipboard-copy__expandable-content--BorderBlockEndWidth:var(--pf-t--global--border--width--control--default);--pf-v6-c-clipboard-copy__expandable-content--BorderInlineStartWidth:var(--pf-t--global--border--width--control--default);--pf-v6-c-clipboard-copy__expandable-content--BorderColor:var(--pf-t--global--border--color--default);--pf-v6-c-clipboard-copy__expandable-content--BorderRadius:var(--pf-t--global--border--radius--small);--pf-v6-c-clipboard-copy__expandable-content--OutlineOffset:var(--pf-t--global--spacer--xs);--pf-v6-c-clipboard-copy__group--Gap:var(--pf-t--global--spacer--gap--control-to-control--default);--pf-v6-c-clipboard-copy--m-inline--PaddingInlineStart:var(--pf-t--global--spacer--xs);--pf-v6-c-clipboard-copy--m-inline--PaddingInlineEnd:var(--pf-t--global--spacer--xs);--pf-v6-c-clipboard-copy--m-inline--BackgroundColor:var(--pf-t--global--background--color--secondary--default);--pf-v6-c-clipboard-copy__actions--Gap:var(--pf-t--global--spacer--gap--action-to-action--plain);--pf-v6-c-clipboard-copy__actions--MarginInlineStart:var(--pf-t--global--spacer--gap--text-to-element--compact);--pf-v6-c-clipboard-copy__actions-item--button--Color:var(--pf-t--global--icon--color--subtle);--pf-v6-c-clipboard-copy__actions-item--button--hover--Color:var(--pf-t--global--icon--color--regular);--pf-v6-c-clipboard-copy__text--m-code--FontFamily:var(--pf-t--global--font--family--mono);--pf-v6-c-clipboard-copy__text--m-code--FontSize:var(--pf-t--global--font--size--body--default)}.pf-v6-c-clipboard-copy.pf-m-inline{display:inline;padding-inline-start:var(--pf-v6-c-clipboard-copy--m-inline--PaddingInlineStart);padding-inline-end:var(--pf-v6-c-clipboard-copy--m-inline--PaddingInlineEnd);white-space:nowrap;background-color:var(--pf-v6-c-clipboard-copy--m-inline--BackgroundColor)}.pf-v6-c-clipboard-copy.pf-m-inline.pf-m-block{display:block}.pf-v6-c-clipboard-copy__text{word-break:break-word;white-space:normal}.pf-v6-c-clipboard-copy__actions{display:inline-flex;gap:var(--pf-v6-c-clipboard-copy__actions--Gap);margin-inline-start:var(--pf-v6-c-clipboard-copy__actions--MarginInlineStart)}.pf-v6-c-clipboard-copy__actions-item .pf-v6-c-button.pf-m-plain{--pf-v6-c-button--m-plain__icon--Color:var(--pf-v6-c-clipboard-copy__actions-item--button--Color);--pf-v6-c-button--m-plain--hover__icon--Color:var(--pf-v6-c-clipboard-copy__actions-item--button--hover--Color)}.pf-v6-c-code-block{--pf-v6-c-code-block--BackgroundColor:var(--pf-t--global--background--color--secondary--default);--pf-v6-c-code-block--BorderRadius:var(--pf-t--global--border--radius--medium);--pf-v6-c-code-block__header--BorderBlockEndWidth:var(--pf-t--global--border--width--divider--default);--pf-v6-c-code-block__header--BorderBlockEndColor:var(--pf-t--global--border--color--default);--pf-v6-c-code-block__header--PaddingBlockStart:var(--pf-t--global--spacer--xs);--pf-v6-c-code-block__header--PaddingBlockEnd:var(--pf-t--global--spacer--xs);--pf-v6-c-code-block__header--PaddingInlineEnd:var(--pf-t--global--spacer--sm);--pf-v6-c-code-block__header--PaddingInlineStart:var(--pf-t--global--spacer--sm);--pf-v6-c-code-block__content--PaddingBlockStart:var(--pf-t--global--spacer--md);--pf-v6-c-code-block__content--PaddingInlineEnd:var(--pf-t--global--spacer--md);--pf-v6-c-code-block__content--PaddingBlockEnd:var(--pf-t--global--spacer--md);--pf-v6-c-code-block__content--PaddingInlineStart:var(--pf-t--global--spacer--md);--pf-v6-c-code-block__pre--FontFamily:var(--pf-t--global--font--family--mono);--pf-v6-c-code-block__pre--FontSize:var(--pf-t--global--font--size--xs)}.pf-v6-c-code-block{background-color:var(--pf-v6-c-code-block--BackgroundColor);border-radius:var(--pf-v6-c-code-block--BorderRadius)}.pf-v6-c-code-block__header{display:flex;padding-block-start:var(--pf-v6-c-code-block__header--PaddingBlockStart);padding-block-end:var(--pf-v6-c-code-block__header--PaddingBlockEnd);padding-inline-start:var(--pf-v6-c-code-block__header--PaddingInlineStart);padding-inline-end:var(--pf-v6-c-code-block__header--PaddingInlineEnd);border-block-end:var(--pf-v6-c-code-block__header--BorderBlockEndWidth) solid var(--pf-v6-c-code-block__header--BorderBlockEndColor)}.pf-v6-c-code-block__actions{display:flex;margin-inline-start:auto}.pf-v6-c-code-block__content{padding-block-start:var(--pf-v6-c-code-block__content--PaddingBlockStart);padding-block-end:var(--pf-v6-c-code-block__content--PaddingBlockEnd);padding-inline-start:var(--pf-v6-c-code-block__content--PaddingInlineStart);padding-inline-end:var(--pf-v6-c-code-block__content--PaddingInlineEnd)}.pf-v6-c-code-block__pre{font-family:var(--pf-v6-c-code-block__pre--FontFamily);font-size:var(--pf-v6-c-code-block__pre--FontSize);overflow-wrap:break-word;white-space:pre-wrap}.pf-v6-c-code-block__code{font-family:var(--pf-v6-c-code-block__code--FontFamily,inherit)}
1
+ .pfext-quick-start-panel{--pf-v6-c-drawer__panel--PaddingBlockStart:0}.pfext-popover__base ul{list-style-type:var(--pf-t--global--list-style)}.pfext-markdown-view .h1,.pfext-markdown-view .h2,.pfext-markdown-view .h3,.pfext-markdown-view .h4,.pfext-markdown-view .h5,.pfext-markdown-view .h6,.pfext-markdown-view h1,.pfext-markdown-view h2,.pfext-markdown-view h3,.pfext-markdown-view h4,.pfext-markdown-view h5,.pfext-markdown-view h6{font-family:var(--pf-t--global--font--family--heading);font-weight:var(--pf-t--global--font--weight--heading);line-height:1.1;color:inherit}.pfext-markdown-view .h1,.pfext-markdown-view .h2,.pfext-markdown-view .h3,.pfext-markdown-view h1,.pfext-markdown-view h2,.pfext-markdown-view h3{margin-top:23px;margin-bottom:11.5px}.pfext-markdown-view .h4,.pfext-markdown-view .h5,.pfext-markdown-view .h6,.pfext-markdown-view h4,.pfext-markdown-view h5,.pfext-markdown-view h6{margin-top:11.5px;margin-bottom:11.5px}.pfext-markdown-view .h1,.pfext-markdown-view h1{font-size:var(--pf-t--global--font--size--heading--h1)}.pfext-markdown-view .h2,.pfext-markdown-view h2{font-size:var(--pf-t--global--font--size--heading--h2)}.pfext-markdown-view .h3,.pfext-markdown-view h3{font-size:var(--pf-t--global--font--size--heading--h3)}.pfext-markdown-view .h4,.pfext-markdown-view h4{font-size:var(--pf-t--global--font--size--heading--h4)}.pfext-markdown-view .h5,.pfext-markdown-view h5{font-size:var(--pf-t--global--font--size--heading--h5)}.pfext-markdown-view .h6,.pfext-markdown-view h6{font-size:var(--pf-t--global--font--size--heading--h6)}.pfext-markdown-view p{margin:0 0 11.5px}.pfext-markdown-view ol,.pfext-markdown-view ul{margin-top:0;margin-bottom:11.5px}.pfext-markdown-view ol ol,.pfext-markdown-view ol ul,.pfext-markdown-view ul ol,.pfext-markdown-view ul ul{margin-bottom:0}.pfext-markdown-view dl{margin-top:0;margin-bottom:23px}.pfext-markdown-view dd,.pfext-markdown-view dt{line-height:1.66666667}.pfext-markdown-view dt{font-weight:700}.pfext-markdown-view dd{margin-left:0}.pfext-markdown-view blockquote{padding:11.5px 23px;margin:0 0 23px;font-size:17.5px;border-left:5px solid #f1f1f1}.pfext-markdown-view blockquote ol:last-child,.pfext-markdown-view blockquote p:last-child,.pfext-markdown-view blockquote ul:last-child{margin-bottom:0}.pfext-markdown-view code,.pfext-markdown-view pre{font-family:Menlo,Monaco,Consolas,monospace}.pfext-markdown-view code{padding:2px 4px;font-size:90%;color:#004368;background-color:#def3ff;border-radius:1px}.pfext-markdown-view pre{display:block;padding:11px;margin:0 0 11.5px;font-size:13px;line-height:1.66666667;color:#363636;word-break:break-all;word-wrap:break-word;background-color:#fafafa;border:1px solid #ccc;border-radius:1px}.pfext-markdown-view pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pfext-markdown-view table{background-color:transparent}.pfext-markdown-view table col[class*=col-]{position:static;display:table-column;float:none}.pfext-markdown-view table td[class*=col-],.pfext-markdown-view table th[class*=col-]{position:static;display:table-cell;float:none}.pfext-markdown-view caption{padding-top:10px;padding-bottom:10px;color:#9c9c9c;text-align:left}.pfext-markdown-view th{text-align:left}.pfext-quick-start-panel-content{background-color:var(--pf-t--global--color--brand--default);color:var(--pf-t--global--text--color--inverse);padding:var(--pf-t--global--spacer--md) var(--pf-t--global--spacer--lg)}.pfext-quick-start-panel-content__body{display:flex;flex-direction:column}.pfext-quick-start-panel-content span.pf-v6-c-button__icon{color:var(--pf-t--global--text--color--inverse)}.pf-v6-theme-dark .pfext-catalog-item-icon__img{filter:brightness(1.5) invert(1) hue-rotate(180deg) saturate(4)}.pfext-catalog-item .pf-v6-c-card__header-main .pf-v6-c-icon__content{display:contents}.pfext-catalog-item.pf-v6-c-card.pf-m-clickable::before,.pfext-catalog-item.pf-v6-c-card.pf-m-selectable::before{border:var(--pf-v6-c-card--BorderColor) var(--pf-v6-c-card--BorderStyle) var(--pf-v6-c-card--BorderWidth)}.pfext-quick-start-footer{padding-top:var(--pf-t--global--spacer--md)}.pfext-quick-start-task{flex:1 1 0;overflow:auto}.pfext-quick-start-task .pf-v6-c-accordion,.pfext-quick-start-task .pf-v6-c-alert,.pfext-quick-start-task .pf-v6-c-code-block{margin-block-end:var(--pf-v6-c-content--MarginBlockEnd)}.pfext-quick-start-task .pf-v6-c-wizard{height:initial}.pfext-quick-start-task-header button.pf-v6-c-wizard__nav-link{margin-bottom:var(--pf-t--global--spacer--md)}.pfext-quick-start-task-header button.pf-v6-c-wizard__nav-link.pf-m-current{--pf-v6-c-wizard__nav-link-main--BackgroundColor:transparent}.pfext-quick-start-task-header button.pf-v6-c-wizard__nav-link::before{background-color:var(--pf-v6-c-wizard__nav-link--m-current--before--BackgroundColor);color:var(--pf-v6-c-wizard__nav-link--m-current--before--Color);min-width:var(--pf-v6-c-wizard__nav-link--before--Width)}.pfext-quick-start-task-header__title{font-family:var(--pf-t--global--font--family--body);font-weight:var(---pf-t--global--font--weight--body--bold);font-size:var(--pf-t--global--font--size--body--lg)}.pfext-quick-start-task-header__subtitle{font-size:var(--pf-t--global--font--size--body--default);color:var(--pf-t--global--text--color--subtle);font-weight:var(--pf-t--global--font--weight--body)}.pfext-quick-start-task-header__tryagain{display:block;font-size:var(--pf-t--global--font--size--body--default);color:var(--pf-t--global--text--color--subtle);font-weight:var(--pf-t--global--font--weight--body)}@keyframes pfext-spotlight-expand{0%{outline-offset:-4px;outline-width:4px;opacity:1}100%{outline-offset:21px;outline-width:12px;opacity:0}}@keyframes pfext-spotlight-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes pfext-spotlight-fade-out{0%{opacity:1}100%{opacity:0}}.pfext-spotlight{pointer-events:none;position:absolute}.pfext-spotlight__with-backdrop{mix-blend-mode:hard-light}.pfext-spotlight__element-highlight-noanimate{border:var(--pf-t--global--border--width--strong) solid var(--pf-t--global--border--color--brand--default);background-color:var(--pf-t--color--gray--40);z-index:9999}.pfext-spotlight__element-highlight-animate{pointer-events:none;position:absolute;box-shadow:inset 0 0 0 4px var(--pf-t--global--color--brand--default);opacity:0;animation:.4s pfext-spotlight-fade-in 0s ease-in-out,5s pfext-spotlight-fade-out 12.8s ease-in-out;animation-fill-mode:forwards}.pfext-spotlight__element-highlight-animate::after{content:"";position:absolute;left:0;right:0;top:0;bottom:0;animation:1.2s pfext-spotlight-expand 1.6s ease-out;animation-fill-mode:forwards;outline:4px solid var(--pf-t--global--color--brand--default);outline-offset:-4px}.pf-v6-c-clipboard-copy{--pf-v6-c-clipboard-copy__toggle-icon--Transition:.2s ease-in 0s;--pf-v6-c-clipboard-copy--m-expanded__toggle-icon--Rotate:90deg;--pf-v6-c-clipboard-copy__expandable-content--MarginBlockStart:var(--pf-t--global--spacer--xs);--pf-v6-c-clipboard-copy__expandable-content--PaddingBlockStart:var(--pf-t--global--spacer--md);--pf-v6-c-clipboard-copy__expandable-content--PaddingInlineEnd:var(--pf-t--global--spacer--md);--pf-v6-c-clipboard-copy__expandable-content--PaddingBlockEnd:var(--pf-t--global--spacer--md);--pf-v6-c-clipboard-copy__expandable-content--PaddingInlineStart:var(--pf-t--global--spacer--md);--pf-v6-c-clipboard-copy__expandable-content--BackgroundColor:var(--pf-t--global--background--color--primary--default);--pf-v6-c-clipboard-copy__expandable-content--BorderBlockStartWidth:var(--pf-t--global--border--width--control--default);--pf-v6-c-clipboard-copy__expandable-content--BorderInlineEndWidth:var(--pf-t--global--border--width--control--default);--pf-v6-c-clipboard-copy__expandable-content--BorderBlockEndWidth:var(--pf-t--global--border--width--control--default);--pf-v6-c-clipboard-copy__expandable-content--BorderInlineStartWidth:var(--pf-t--global--border--width--control--default);--pf-v6-c-clipboard-copy__expandable-content--BorderColor:var(--pf-t--global--border--color--default);--pf-v6-c-clipboard-copy__expandable-content--BorderRadius:var(--pf-t--global--border--radius--small);--pf-v6-c-clipboard-copy__expandable-content--OutlineOffset:var(--pf-t--global--spacer--xs);--pf-v6-c-clipboard-copy__group--Gap:var(--pf-t--global--spacer--gap--control-to-control--default);--pf-v6-c-clipboard-copy--m-inline--PaddingInlineStart:var(--pf-t--global--spacer--xs);--pf-v6-c-clipboard-copy--m-inline--PaddingInlineEnd:var(--pf-t--global--spacer--xs);--pf-v6-c-clipboard-copy--m-inline--BackgroundColor:var(--pf-t--global--background--color--secondary--default);--pf-v6-c-clipboard-copy__actions--Gap:var(--pf-t--global--spacer--gap--action-to-action--plain);--pf-v6-c-clipboard-copy__actions--MarginInlineStart:var(--pf-t--global--spacer--gap--text-to-element--compact);--pf-v6-c-clipboard-copy__actions-item--button--Color:var(--pf-t--global--icon--color--subtle);--pf-v6-c-clipboard-copy__actions-item--button--hover--Color:var(--pf-t--global--icon--color--regular);--pf-v6-c-clipboard-copy__text--m-code--FontFamily:var(--pf-t--global--font--family--mono);--pf-v6-c-clipboard-copy__text--m-code--FontSize:var(--pf-t--global--font--size--body--default)}.pf-v6-c-clipboard-copy.pf-m-inline{display:inline;padding-inline-start:var(--pf-v6-c-clipboard-copy--m-inline--PaddingInlineStart);padding-inline-end:var(--pf-v6-c-clipboard-copy--m-inline--PaddingInlineEnd);white-space:nowrap;background-color:var(--pf-v6-c-clipboard-copy--m-inline--BackgroundColor)}.pf-v6-c-clipboard-copy.pf-m-inline.pf-m-block{display:block}.pf-v6-c-clipboard-copy__text{word-break:break-word;white-space:normal}.pf-v6-c-clipboard-copy__actions{display:inline-flex;gap:var(--pf-v6-c-clipboard-copy__actions--Gap);margin-inline-start:var(--pf-v6-c-clipboard-copy__actions--MarginInlineStart)}.pf-v6-c-clipboard-copy__actions-item .pf-v6-c-button.pf-m-plain{--pf-v6-c-button--m-plain__icon--Color:var(--pf-v6-c-clipboard-copy__actions-item--button--Color);--pf-v6-c-button--m-plain--hover__icon--Color:var(--pf-v6-c-clipboard-copy__actions-item--button--hover--Color)}.pf-v6-c-code-block{--pf-v6-c-code-block--BackgroundColor:var(--pf-t--global--background--color--secondary--default);--pf-v6-c-code-block--BorderRadius:var(--pf-t--global--border--radius--medium);--pf-v6-c-code-block__header--BorderBlockEndWidth:var(--pf-t--global--border--width--divider--default);--pf-v6-c-code-block__header--BorderBlockEndColor:var(--pf-t--global--border--color--default);--pf-v6-c-code-block__header--PaddingBlockStart:var(--pf-t--global--spacer--xs);--pf-v6-c-code-block__header--PaddingBlockEnd:var(--pf-t--global--spacer--xs);--pf-v6-c-code-block__header--PaddingInlineEnd:var(--pf-t--global--spacer--sm);--pf-v6-c-code-block__header--PaddingInlineStart:var(--pf-t--global--spacer--sm);--pf-v6-c-code-block__content--PaddingBlockStart:var(--pf-t--global--spacer--md);--pf-v6-c-code-block__content--PaddingInlineEnd:var(--pf-t--global--spacer--md);--pf-v6-c-code-block__content--PaddingBlockEnd:var(--pf-t--global--spacer--md);--pf-v6-c-code-block__content--PaddingInlineStart:var(--pf-t--global--spacer--md);--pf-v6-c-code-block__pre--FontFamily:var(--pf-t--global--font--family--mono);--pf-v6-c-code-block__pre--FontSize:var(--pf-t--global--font--size--xs)}.pf-v6-c-code-block{background-color:var(--pf-v6-c-code-block--BackgroundColor);border-radius:var(--pf-v6-c-code-block--BorderRadius)}.pf-v6-c-code-block__header{display:flex;padding-block-start:var(--pf-v6-c-code-block__header--PaddingBlockStart);padding-block-end:var(--pf-v6-c-code-block__header--PaddingBlockEnd);padding-inline-start:var(--pf-v6-c-code-block__header--PaddingInlineStart);padding-inline-end:var(--pf-v6-c-code-block__header--PaddingInlineEnd);border-block-end:var(--pf-v6-c-code-block__header--BorderBlockEndWidth) solid var(--pf-v6-c-code-block__header--BorderBlockEndColor)}.pf-v6-c-code-block__actions{display:flex;margin-inline-start:auto}.pf-v6-c-code-block__content{padding-block-start:var(--pf-v6-c-code-block__content--PaddingBlockStart);padding-block-end:var(--pf-v6-c-code-block__content--PaddingBlockEnd);padding-inline-start:var(--pf-v6-c-code-block__content--PaddingInlineStart);padding-inline-end:var(--pf-v6-c-code-block__content--PaddingInlineEnd)}.pf-v6-c-code-block__pre{font-family:var(--pf-v6-c-code-block__pre--FontFamily);font-size:var(--pf-v6-c-code-block__pre--FontSize);overflow-wrap:break-word;white-space:pre-wrap}.pf-v6-c-code-block__code{font-family:var(--pf-v6-c-code-block__code--FontFamily,inherit)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/quickstarts",
3
- "version": "6.3.0-prerelease.5",
3
+ "version": "6.3.0-prerelease.7",
4
4
  "description": "PatternFly quick starts",
5
5
  "files": [
6
6
  "src",
@@ -66,7 +66,7 @@
66
66
  "@rollup/plugin-commonjs": "^17.0.0",
67
67
  "@rollup/plugin-json": "^4.1.0",
68
68
  "@rollup/plugin-node-resolve": "^11.1.0",
69
- "@testing-library/react": "^11.2.2",
69
+ "@testing-library/react": "^13.4.0",
70
70
  "@types/dompurify": "^3.0.5",
71
71
  "@types/enzyme": "^3.10.7",
72
72
  "@types/enzyme-adapter-react-16": "^1.0.6",
@@ -25,7 +25,7 @@ export const markdownConvert = async (markdown: string, extensions?: ShowdownExt
25
25
  return node;
26
26
  }
27
27
 
28
- // add PF content classes
28
+ // add PF content classes to standard elements (details blocks get handled separately)
29
29
  if (node.nodeType === 1) {
30
30
  const contentElements = [
31
31
  'ul',
@@ -85,7 +85,90 @@ export const markdownConvert = async (markdown: string, extensions?: ShowdownExt
85
85
  );
86
86
  const markdownWithSubstitutedCodeFences = reverseString(reverseMarkdownWithSubstitutedCodeFences);
87
87
 
88
- const parsedMarkdown = await marked.parse(markdownWithSubstitutedCodeFences);
88
+ // Fix malformed HTML entities early in the process
89
+ let preprocessedMarkdown = markdownWithSubstitutedCodeFences;
90
+ preprocessedMarkdown = preprocessedMarkdown
91
+ .replace(/&nbsp([^;])/g, ' $1')
92
+ .replace(/ /g, ' ');
93
+ preprocessedMarkdown = preprocessedMarkdown.replace(/&nbsp(?![;])/g, ' ');
94
+
95
+ // Process content in segments to ensure markdown parsing continues after HTML blocks
96
+ const htmlBlockRegex =
97
+ /(<(?:details|div|section|article)[^>]*>[\s\S]*?<\/(?:details|div|section|article)>)/g;
98
+
99
+ let parsedMarkdown = '';
100
+
101
+ // Check if there are any HTML blocks
102
+ if (htmlBlockRegex.test(preprocessedMarkdown)) {
103
+ // Reset regex for actual processing
104
+ htmlBlockRegex.lastIndex = 0;
105
+
106
+ let lastIndex = 0;
107
+ let match;
108
+
109
+ while ((match = htmlBlockRegex.exec(preprocessedMarkdown)) !== null) {
110
+ // Process markdown before the HTML block
111
+ const markdownBefore = preprocessedMarkdown.slice(lastIndex, match.index).trim();
112
+ if (markdownBefore) {
113
+ const parsed = await marked.parse(markdownBefore);
114
+ parsedMarkdown += parsed;
115
+ }
116
+
117
+ // Process the HTML block: parse markdown content inside while preserving HTML structure
118
+ let htmlBlock = match[1];
119
+
120
+ // Find and process markdown content inside HTML tags
121
+ const contentRegex = />(\s*[\s\S]*?)\s*</g;
122
+ const contentMatches = [];
123
+ let contentMatch;
124
+
125
+ while ((contentMatch = contentRegex.exec(htmlBlock)) !== null) {
126
+ const content = contentMatch[1];
127
+ // Only process content that has markdown formatting but no extension syntax
128
+ if (
129
+ content.trim() &&
130
+ !content.includes('{{') &&
131
+ (content.includes('**') || content.includes('- ') || content.includes('\n'))
132
+ ) {
133
+ // This looks like markdown content without extensions - parse it as block content
134
+ const parsedContent = await marked.parse(content.trim());
135
+ // Remove wrapping <p> tags if they exist since we're inside HTML already
136
+ const cleanedContent = parsedContent.replace(/^<p[^>]*>([\s\S]*)<\/p>[\s]*$/g, '$1');
137
+ contentMatches.push({
138
+ original: contentMatch[0],
139
+ replacement: `>${cleanedContent}<`,
140
+ });
141
+ }
142
+ }
143
+
144
+ // Apply the content replacements
145
+ contentMatches.forEach(({ original, replacement }) => {
146
+ htmlBlock = htmlBlock.replace(original, replacement);
147
+ });
148
+
149
+ // Apply extensions (like admonitions) to the processed HTML block
150
+ if (extensions) {
151
+ extensions.forEach(({ regex, replace }) => {
152
+ if (regex) {
153
+ htmlBlock = htmlBlock.replace(regex, replace);
154
+ }
155
+ });
156
+ }
157
+
158
+ parsedMarkdown += htmlBlock;
159
+ lastIndex = htmlBlockRegex.lastIndex;
160
+ }
161
+
162
+ // Process any remaining markdown after the last HTML block
163
+ const markdownAfter = preprocessedMarkdown.slice(lastIndex).trim();
164
+ if (markdownAfter) {
165
+ const parsed = await marked.parse(markdownAfter);
166
+ parsedMarkdown += parsed;
167
+ }
168
+ } else {
169
+ // No HTML blocks found, process normally
170
+ parsedMarkdown = await marked.parse(preprocessedMarkdown);
171
+ }
89
172
  // Swap the temporary tokens back to code fences before we run the extensions
90
173
  let md = parsedMarkdown.replace(/@@@/g, '```');
91
174
 
@@ -93,7 +176,7 @@ export const markdownConvert = async (markdown: string, extensions?: ShowdownExt
93
176
  // Convert code spans back to md format before we run the custom extension regexes
94
177
  md = md.replace(/<code>(.*)<\/code>/g, '`$1`');
95
178
 
96
- extensions.forEach(({ regex, replace }) => {
179
+ extensions.forEach(({ regex, replace }, _index) => {
97
180
  if (regex) {
98
181
  md = md.replace(regex, replace);
99
182
  }
@@ -102,6 +185,7 @@ export const markdownConvert = async (markdown: string, extensions?: ShowdownExt
102
185
  // Convert any remaining backticks back into code spans
103
186
  md = md.replace(/`(.*)`/g, '<code>$1</code>');
104
187
  }
188
+
105
189
  return DOMPurify.sanitize(md);
106
190
  };
107
191
 
@@ -210,7 +294,10 @@ const InlineMarkdownView: FC<InnerSyncMarkdownProps> = ({
210
294
  const id = useMemo(() => uniqueId('markdown'), []);
211
295
  return (
212
296
  <div className={css({ 'is-empty': isEmpty } as any, className)} id={id}>
213
- <div dangerouslySetInnerHTML={{ __html: markup }} />
297
+ <div
298
+ style={{ marginBlockEnd: 'var(--pf-t-global--spacer--md)' }}
299
+ dangerouslySetInnerHTML={{ __html: markup }}
300
+ />
214
301
  {renderExtension && (
215
302
  <RenderExtension renderExtension={renderExtension} selector={`#${id}`} markup={markup} />
216
303
  )}
@@ -299,6 +386,7 @@ const IFrameMarkdownView: FC<InnerSyncMarkdownProps> = ({
299
386
  return (
300
387
  <>
301
388
  <iframe
389
+ title="Markdown content preview"
302
390
  sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin"
303
391
  srcDoc={contents}
304
392
  style={{ border: '0px', display: 'block', width: '100%', height: '0' }}
@@ -0,0 +1,105 @@
1
+ // Generated by Cursor
2
+ // AI-assisted implementation with human review and modifications
3
+ import { renderHook } from '@testing-library/react';
4
+ import useAccordionShowdownExtension from '../accordion-extension';
5
+ import { ACCORDION_MARKDOWN_BUTTON_ID, ACCORDION_MARKDOWN_CONTENT_ID } from '../const';
6
+ import { marked } from 'marked';
7
+
8
+ // Mock marked
9
+ jest.mock('marked', () => ({
10
+ marked: {
11
+ parseInline: jest.fn((text) => `<em>${text}</em>`),
12
+ },
13
+ }));
14
+
15
+ // Mock DOMPurify
16
+ jest.mock('dompurify', () => ({
17
+ sanitize: jest.fn((html) => html),
18
+ }));
19
+
20
+ describe('useAccordionShowdownExtension', () => {
21
+ beforeEach(() => {
22
+ jest.clearAllMocks();
23
+ });
24
+
25
+ it('should return a showdown extension with correct properties', () => {
26
+ const { result } = renderHook(() => useAccordionShowdownExtension());
27
+ const extension = result.current;
28
+
29
+ expect(extension.type).toBe('lang');
30
+ expect(extension.regex).toEqual(/\[(.+)]{{(accordion) (&quot;(.*?)&quot;)}}/g);
31
+ expect(typeof extension.replace).toBe('function');
32
+ });
33
+
34
+ it('should match accordion syntax with HTML-encoded quotes', () => {
35
+ const { result } = renderHook(() => useAccordionShowdownExtension());
36
+ const { regex } = result.current;
37
+
38
+ const testText = '[Some content]{{accordion &quot;My Title&quot;}}';
39
+ const matches = regex.exec(testText);
40
+
41
+ expect(matches).not.toBeNull();
42
+ if (matches) {
43
+ expect(matches[1]).toBe('Some content');
44
+ expect(matches[2]).toBe('accordion');
45
+ expect(matches[4]).toBe('My Title');
46
+ }
47
+ });
48
+
49
+ it('should not match accordion syntax with regular quotes', () => {
50
+ const { result } = renderHook(() => useAccordionShowdownExtension());
51
+ const { regex } = result.current;
52
+
53
+ const testText = '[Some content]{{accordion "My Title"}}';
54
+ expect(testText.match(regex)).toBeNull();
55
+ });
56
+
57
+ it('should generate correct accordion HTML structure', () => {
58
+ const { result } = renderHook(() => useAccordionShowdownExtension());
59
+ const { replace } = result.current;
60
+
61
+ const html = replace(
62
+ '[Test content]{{accordion &quot;Test Title&quot;}}',
63
+ 'Test content',
64
+ 'accordion',
65
+ '&quot;Test Title&quot;',
66
+ 'Test Title',
67
+ );
68
+
69
+ expect(html).toContain('pf-v6-c-accordion');
70
+ expect(html).toContain('pf-v6-c-accordion__toggle');
71
+ expect(html).toContain(`${ACCORDION_MARKDOWN_BUTTON_ID}-Test-Title`);
72
+ expect(html).toContain(`${ACCORDION_MARKDOWN_CONTENT_ID}-Test-Title`);
73
+ expect(html).toContain('Test Title');
74
+ });
75
+
76
+ it('should process content through marked and sanitize HTML', () => {
77
+ const { result } = renderHook(() => useAccordionShowdownExtension());
78
+ const { replace } = result.current;
79
+
80
+ replace(
81
+ '[**Bold text**]{{accordion &quot;Title&quot;}}',
82
+ '**Bold text**',
83
+ 'accordion',
84
+ '&quot;Title&quot;',
85
+ 'Title',
86
+ );
87
+
88
+ expect(marked.parseInline).toHaveBeenCalledWith('**Bold text**');
89
+ });
90
+
91
+ it('should handle titles with spaces in IDs', () => {
92
+ const { result } = renderHook(() => useAccordionShowdownExtension());
93
+ const { replace } = result.current;
94
+
95
+ const html = replace(
96
+ '[Content]{{accordion &quot;My Test Title&quot;}}',
97
+ 'Content',
98
+ 'accordion',
99
+ '&quot;My Test Title&quot;',
100
+ 'My Test Title',
101
+ );
102
+
103
+ expect(html).toContain(`${ACCORDION_MARKDOWN_BUTTON_ID}-My-Test-Title`);
104
+ });
105
+ });
@@ -0,0 +1,121 @@
1
+ import { renderHook } from '@testing-library/react';
2
+ import useAdmonitionShowdownExtension from '../admonition-extension';
3
+ import { marked } from 'marked';
4
+
5
+ // Mock marked
6
+ jest.mock('marked', () => ({
7
+ marked: {
8
+ parseInline: jest.fn((text) => `<strong>${text}</strong>`),
9
+ },
10
+ }));
11
+
12
+ // Mock DOMPurify
13
+ jest.mock('dompurify', () => ({
14
+ sanitize: jest.fn((html) => html),
15
+ }));
16
+
17
+ describe('useAdmonitionShowdownExtension', () => {
18
+ beforeEach(() => {
19
+ jest.clearAllMocks();
20
+ });
21
+
22
+ it('should return a showdown extension with correct properties', () => {
23
+ const { result } = renderHook(() => useAdmonitionShowdownExtension());
24
+ const extension = result.current;
25
+
26
+ expect(extension.type).toBe('lang');
27
+ expect(extension.regex).toEqual(/\[(.+)]{{(admonition) ([\w-]+)}}/g);
28
+ expect(typeof extension.replace).toBe('function');
29
+ });
30
+
31
+ it('should match different admonition types', () => {
32
+ const { result } = renderHook(() => useAdmonitionShowdownExtension());
33
+ const { regex } = result.current;
34
+
35
+ const admonitionTypes = ['note', 'tip', 'important', 'warning', 'caution', 'custom-type'];
36
+
37
+ admonitionTypes.forEach((type) => {
38
+ const testText = `[Content for ${type}]{{admonition ${type}}}`;
39
+ // Reset regex state for global flag
40
+ regex.lastIndex = 0;
41
+ const matches = regex.exec(testText);
42
+
43
+ expect(matches).not.toBeNull();
44
+ if (matches) {
45
+ expect(matches[1]).toBe(`Content for ${type}`);
46
+ expect(matches[2]).toBe('admonition');
47
+ expect(matches[3]).toBe(type);
48
+ }
49
+ });
50
+ });
51
+
52
+ it('should not match malformed admonition syntax', () => {
53
+ const { result } = renderHook(() => useAdmonitionShowdownExtension());
54
+ const { regex } = result.current;
55
+
56
+ const malformedCases = [
57
+ 'Content]{{admonition note}}',
58
+ '[Content{{admonition note}}',
59
+ '[Content]{{admonition}}',
60
+ '[Content]{{notadmonition note}}',
61
+ ];
62
+
63
+ malformedCases.forEach((testCase) => {
64
+ expect(testCase.match(regex)).toBeNull();
65
+ });
66
+ });
67
+
68
+ it('should generate correct alert HTML structure', () => {
69
+ const { result } = renderHook(() => useAdmonitionShowdownExtension());
70
+ const { replace } = result.current;
71
+
72
+ const html = replace('[Test message]{{admonition note}}', 'Test message', 'admonition', 'note');
73
+
74
+ expect(html).toContain('pf-v6-c-alert');
75
+ expect(html).toContain('pf-m-info'); // note maps to info variant
76
+ expect(html).toContain('pf-m-inline');
77
+ expect(html).toContain('pfext-markdown-admonition');
78
+ expect(html).toContain('NOTE'); // uppercase title
79
+ });
80
+
81
+ it('should handle different admonition types with correct variants', () => {
82
+ const { result } = renderHook(() => useAdmonitionShowdownExtension());
83
+ const { replace } = result.current;
84
+
85
+ const testCases = [
86
+ { type: 'note', expectedClass: 'pf-m-info' },
87
+ { type: 'warning', expectedClass: 'pf-m-warning' },
88
+ { type: 'important', expectedClass: 'pf-m-danger' },
89
+ ];
90
+
91
+ testCases.forEach(({ type, expectedClass }) => {
92
+ const html = replace(`[Content]{{admonition ${type}}}`, 'Content', 'admonition', type);
93
+
94
+ expect(html).toContain(expectedClass);
95
+ expect(html).toContain(type.toUpperCase());
96
+ });
97
+ });
98
+
99
+ it('should process content through marked', () => {
100
+ const { result } = renderHook(() => useAdmonitionShowdownExtension());
101
+ const { replace } = result.current;
102
+
103
+ replace('[**Bold text**]{{admonition note}}', '**Bold text**', 'admonition', 'note');
104
+
105
+ expect(marked.parseInline).toHaveBeenCalledWith('**Bold text**');
106
+ });
107
+
108
+ it('should return original text for invalid cases', () => {
109
+ const { result } = renderHook(() => useAdmonitionShowdownExtension());
110
+ const { replace } = result.current;
111
+
112
+ // Missing content
113
+ const originalText = '[Content]{{admonition note}}';
114
+ const result1 = replace(originalText, '', 'admonition', 'note');
115
+ expect(result1).toBe(originalText);
116
+
117
+ // Wrong command
118
+ const result2 = replace(originalText, 'Content', 'not-admonition', 'note');
119
+ expect(result2).toBe(originalText);
120
+ });
121
+ });
@@ -8,34 +8,41 @@ import {
8
8
  import { renderToStaticMarkup } from 'react-dom/server';
9
9
  import { removeTemplateWhitespace } from './utils';
10
10
  import { ACCORDION_MARKDOWN_BUTTON_ID, ACCORDION_MARKDOWN_CONTENT_ID } from './const';
11
+ import { marked } from 'marked';
12
+
13
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
14
+ const DOMPurify = require('dompurify');
11
15
 
12
16
  const useAccordionShowdownExtension = () =>
13
17
  useMemo(
14
18
  () => ({
15
19
  type: 'lang',
16
- regex: /\[(.+)]{{(accordion) ("(.*?)")}}/g,
20
+ regex: /\[(.+)]{{(accordion) (&quot;(.*?)&quot;)}}/g,
17
21
  replace: (
18
22
  _text: string,
19
23
  accordionContent: string,
20
24
  _command: string,
25
+ _quotedHeading: string,
21
26
  accordionHeading: string,
22
27
  ): string => {
23
28
  const accordionId = String(accordionHeading).replace(/\s/g, '-');
24
29
 
30
+ // Process accordion content with markdown
31
+ const processedContent = marked.parseInline(accordionContent);
32
+ const sanitizedContent = DOMPurify.sanitize(processedContent);
33
+
25
34
  return removeTemplateWhitespace(
26
35
  renderToStaticMarkup(
27
- <>
28
- <Accordion asDefinitionList>
29
- <AccordionItem isExpanded={false}>
30
- <AccordionToggle id={`${ACCORDION_MARKDOWN_BUTTON_ID}-${accordionId}`}>
31
- {accordionHeading}
32
- </AccordionToggle>
33
- <AccordionContent id={`${ACCORDION_MARKDOWN_CONTENT_ID}-${accordionId}`}>
34
- {accordionContent}
35
- </AccordionContent>
36
- </AccordionItem>
37
- </Accordion>
38
- </>,
36
+ <Accordion>
37
+ <AccordionItem>
38
+ <AccordionToggle id={`${ACCORDION_MARKDOWN_BUTTON_ID}-${accordionId}`}>
39
+ {accordionHeading}
40
+ </AccordionToggle>
41
+ <AccordionContent id={`${ACCORDION_MARKDOWN_CONTENT_ID}-${accordionId}`} hidden>
42
+ <div dangerouslySetInnerHTML={{ __html: sanitizedContent }} />
43
+ </AccordionContent>
44
+ </AccordionItem>
45
+ </Accordion>,
39
46
  ),
40
47
  );
41
48
  },
@@ -14,14 +14,28 @@ const AccordionShowdownHandler: FC<AccordionShowdownComponentProps> = ({
14
14
  const [expanded, setExpanded] = useState<boolean>(false);
15
15
 
16
16
  const handleClick = () => {
17
+ const newExpanded = !expanded;
17
18
  const expandedModifier = 'pf-m-expanded';
18
19
 
19
- buttonElement.className = `pf-v6-c-accordion__toggle ${!expanded ? expandedModifier : ''}`;
20
- contentElement.hidden = expanded;
21
- contentElement.className = `pf-v6-c-accordion__expanded-content ${
22
- !expanded ? expandedModifier : ''
20
+ // Find the accordion item element (parent of the button)
21
+ const accordionItem = buttonElement.closest('.pf-v6-c-accordion__item');
22
+
23
+ // Update button - both visual state and aria-expanded
24
+ buttonElement.className = `pf-v6-c-accordion__toggle ${newExpanded ? expandedModifier : ''}`;
25
+ buttonElement.setAttribute('aria-expanded', newExpanded.toString());
26
+
27
+ // Update content - both visual state and hidden attribute
28
+ contentElement.hidden = !newExpanded;
29
+ contentElement.className = `pf-v6-c-accordion__expandable-content ${
30
+ newExpanded ? expandedModifier : ''
23
31
  }`;
24
- setExpanded(!expanded);
32
+
33
+ // Update accordion item
34
+ if (accordionItem) {
35
+ accordionItem.className = `pf-v6-c-accordion__item ${newExpanded ? expandedModifier : ''}`;
36
+ }
37
+
38
+ setExpanded(newExpanded);
25
39
  };
26
40
 
27
41
  useEventListener(buttonElement, 'click', handleClick);
@@ -4,7 +4,10 @@ import { renderToStaticMarkup } from 'react-dom/server';
4
4
  import { Alert } from '@patternfly/react-core';
5
5
  import LightbulbIcon from '@patternfly/react-icons/dist/js/icons/lightbulb-icon';
6
6
  import FireIcon from '@patternfly/react-icons/dist/js/icons/fire-icon';
7
- import QuickStartMarkdownView from '../../../../QuickStartMarkdownView';
7
+ import { marked } from 'marked';
8
+
9
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
10
+ const DOMPurify = require('dompurify');
8
11
 
9
12
  enum AdmonitionType {
10
13
  TIP = 'TIP',
@@ -33,15 +36,23 @@ const useAdmonitionShowdownExtension = () =>
33
36
  content: string,
34
37
  admonitionLabel: string,
35
38
  admonitionType: string,
36
- groupId: string,
37
39
  ): string => {
38
- if (!content || !admonitionLabel || !admonitionType || !groupId) {
40
+ if (!content || !admonitionLabel || !admonitionType) {
41
+ return text;
42
+ }
43
+ if (admonitionLabel !== 'admonition') {
39
44
  return text;
40
45
  }
41
46
  admonitionType = admonitionType.toUpperCase();
42
47
 
43
- const { variant, customIcon } = admonitionToAlertVariantMap[admonitionType];
44
- const mdContent = <QuickStartMarkdownView content={content} />;
48
+ // Process markdown content directly using marked
49
+ const processedContent = marked.parseInline(content);
50
+ const sanitizedContent = DOMPurify.sanitize(processedContent);
51
+
52
+ // Handle unknown admonition types by defaulting to NOTE
53
+ const admonitionConfig =
54
+ admonitionToAlertVariantMap[admonitionType] || admonitionToAlertVariantMap.NOTE;
55
+ const { variant, customIcon } = admonitionConfig;
45
56
  const pfAlert = (
46
57
  <Alert
47
58
  variant={variant}
@@ -50,7 +61,7 @@ const useAdmonitionShowdownExtension = () =>
50
61
  title={admonitionType}
51
62
  className="pfext-markdown-admonition"
52
63
  >
53
- {mdContent}
64
+ <div dangerouslySetInnerHTML={{ __html: sanitizedContent }} />
54
65
  </Alert>
55
66
  );
56
67
  return removeTemplateWhitespace(renderToStaticMarkup(pfAlert));
@@ -24,7 +24,9 @@ export const QuickStartDrawerContent: FC<QuickStartDrawerContentProps> = ({
24
24
  allQuickStarts = [],
25
25
  activeQuickStartState,
26
26
  } = useContext<QuickStartContextValues>(QuickStartContext);
27
- const combinedQuickStarts = allQuickStarts.concat(quickStarts);
27
+ const combinedQuickStarts = [...allQuickStarts, ...quickStarts].filter(
28
+ (qs, idx, arr) => arr.findIndex((q) => q.metadata.name === qs.metadata.name) === idx,
29
+ );
28
30
 
29
31
  const handleClose = () => {
30
32
  handleDrawerClose && handleDrawerClose(activeQuickStartState?.status);
@@ -72,10 +72,7 @@ export const QuickStartCatalogFilterCount = ({ quickStartsCount }) => {
72
72
  const { getResource } = useContext<QuickStartContextValues>(QuickStartContext);
73
73
  return (
74
74
  <ToolbarItem align={{ default: 'alignEnd' }}>
75
- {getResource('{{count, number}} item', quickStartsCount).replace(
76
- '{{count, number}}',
77
- quickStartsCount,
78
- )}
75
+ {getResource('{{count, number}} item', quickStartsCount)}
79
76
  </ToolbarItem>
80
77
  );
81
78
  };
@@ -47,7 +47,7 @@ const QuickStartIntroduction: FC<QuickStartIntroductionProps> = ({
47
47
  <p>
48
48
  {getResource(
49
49
  'In this quick start, you will complete {{count, number}} task',
50
- tasks?.length,
50
+ tasks?.length || 0,
51
51
  ).replace('{{count, number}}', tasks?.length || 0)}
52
52
  :
53
53
  </p>