@patternfly/documentation-framework 6.31.12 → 6.31.13

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 CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## 6.31.13 (2025-11-21)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Updates overview pages across website. ([#4880](https://github.com/patternfly/patternfly-org/issues/4880)) ([7871f1c](https://github.com/patternfly/patternfly-org/commit/7871f1c47d4a1b91b5cd1b16b4017aaf80252812))
12
+
13
+
14
+
15
+
16
+
6
17
  ## 6.31.12 (2025-11-20)
7
18
 
8
19
  **Note:** Version bump only for package @patternfly/documentation-framework
@@ -35,7 +35,8 @@ export const SectionGallery = ({
35
35
  hasGridImages = true,
36
36
  hasListText = true,
37
37
  hasListImages = true,
38
- isFullWidth = true
38
+ isFullWidth = true,
39
+ onlyShowInGalleryData = false
39
40
  }) => (
40
41
  <SectionGalleryWrapper
41
42
  illustrations={illustrations}
@@ -46,6 +47,7 @@ export const SectionGallery = ({
46
47
  galleryItemsData={galleryItemsData}
47
48
  initialLayout={initialLayout}
48
49
  isFullWidth={isFullWidth}
50
+ onlyShowInGalleryData={onlyShowInGalleryData}
49
51
  >
50
52
  {(sectionGalleryItems, searchTerm, setSearchTerm, layoutView, setLayoutView) => (
51
53
  <>
@@ -2,6 +2,26 @@ import React from 'react';
2
2
  import { useLocation } from '@reach/router';
3
3
  import { groupedRoutes } from '../../routes';
4
4
 
5
+ /**
6
+ * Converts a hyphenated or lowercase string to sentence case
7
+ * Example: "design-tokens" -> "Design tokens"
8
+ * Example: "colors" -> "Colors"
9
+ */
10
+ const toSentenceCase = (str) => {
11
+ if (!str) return str;
12
+ return str
13
+ .split('-')
14
+ .map((word, index) => {
15
+ if (index === 0) {
16
+ // Capitalize first letter of first word only
17
+ return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
18
+ }
19
+ // Keep all other words lowercase
20
+ return word.toLowerCase();
21
+ })
22
+ .join(' ');
23
+ };
24
+
5
25
  export const SectionGalleryWrapper = ({
6
26
  section,
7
27
  subsection,
@@ -11,6 +31,7 @@ export const SectionGalleryWrapper = ({
11
31
  parseSubsections,
12
32
  initialLayout,
13
33
  isFullWidth,
34
+ onlyShowInGalleryData = false,
14
35
  children,
15
36
  }) => {
16
37
  let sectionRoutes = subsection
@@ -24,12 +45,50 @@ export const SectionGalleryWrapper = ({
24
45
  </div>
25
46
  );
26
47
  }
27
- if (!includeSubsections || parseSubsections) {
48
+
49
+ // If includeSubsections is true and we're at the section level (not a specific subsection),
50
+ // we need to include subsections themselves as items (not their contents)
51
+ if (includeSubsections && !subsection && groupedRoutes[section]) {
52
+ const allRoutes = {};
53
+ // First, add top-level items (non-subsections)
54
+ Object.entries(sectionRoutes).forEach(([navName, routeData]) => {
55
+ if (navName === 'isSubsection' || navName === 'sortValue' || navName === 'subsectionSortValue') {
56
+ return;
57
+ }
58
+ if (typeof routeData !== 'object' || routeData === null) {
59
+ return;
60
+ }
61
+ // Only add if it's not a subsection
62
+ if (!routeData.isSubsection) {
63
+ allRoutes[navName] = routeData;
64
+ }
65
+ });
66
+
67
+ // Then, add subsections themselves as single items (not their contents)
68
+ Object.entries(groupedRoutes[section]).forEach(([navName, routeData]) => {
69
+ if (navName === 'isSubsection' || navName === 'sortValue' || navName === 'subsectionSortValue') {
70
+ return;
71
+ }
72
+ if (typeof routeData !== 'object' || routeData === null) {
73
+ return;
74
+ }
75
+ // If this is a subsection, add the subsection itself as an item
76
+ if (routeData.isSubsection) {
77
+ allRoutes[navName] = routeData;
78
+ }
79
+ });
80
+
81
+ sectionRoutes = allRoutes;
82
+ } else if (!includeSubsections || parseSubsections) {
28
83
  const sectionRoutesArr = Object.entries(sectionRoutes);
29
84
  // loop through galleryItems object and build new object to handle subsections
30
85
  sectionRoutes = sectionRoutesArr.reduce((acc, [navName, routeData]) => {
31
- // exit immediately if current item is isSubsection flag
32
- if (navName === 'isSubsection') {
86
+ // exit immediately if current item is isSubsection flag or other metadata properties
87
+ if (navName === 'isSubsection' || navName === 'sortValue' || navName === 'subsectionSortValue') {
88
+ return acc;
89
+ }
90
+ // Skip primitive values (metadata properties like sortValue are numbers)
91
+ if (typeof routeData !== 'object' || routeData === null) {
33
92
  return acc;
34
93
  }
35
94
  // add current item
@@ -40,8 +99,11 @@ export const SectionGalleryWrapper = ({
40
99
  if (parseSubsections && routeData.isSubsection) {
41
100
  // loop through each subsection item & add
42
101
  Object.entries(routeData).map(([subitemName, subitemData]) => {
43
- if (subitemName !== 'isSubsection') {
44
- acc[subitemName] = subitemData;
102
+ if (subitemName !== 'isSubsection' && subitemName !== 'sortValue' && subitemName !== 'subsectionSortValue') {
103
+ // Skip primitive values
104
+ if (typeof subitemData === 'object' && subitemData !== null) {
105
+ acc[subitemName] = subitemData;
106
+ }
45
107
  }
46
108
  });
47
109
  }
@@ -53,11 +115,32 @@ export const SectionGalleryWrapper = ({
53
115
  const [searchTerm, setSearchTerm] = React.useState('');
54
116
  const [layoutView, setLayoutView] = React.useState(initialLayout);
55
117
  const filteredItems = Object.entries(sectionRoutes).filter(
56
- ([itemName, { slug }]) =>
118
+ ([itemName, itemData]) => {
119
+ // Skip metadata properties
120
+ if (itemName === 'isSubsection' || itemName === 'sortValue' || itemName === 'subsectionSortValue') {
121
+ return false;
122
+ }
123
+ // Skip primitive values (metadata properties)
124
+ if (typeof itemData !== 'object' || itemData === null) {
125
+ return false;
126
+ }
127
+ // For subsections, slug will be computed later from first page
128
+ // For regular items, they must have a slug
129
+ if (!itemData.isSubsection && !itemData.slug) {
130
+ return false;
131
+ }
132
+ const slug = itemData.slug;
133
+ // For subsections without slug yet, we'll compute it later, so don't filter by slug
134
+ if (!slug) {
135
+ return itemName.toLowerCase().includes(searchTerm.toLowerCase());
136
+ }
57
137
  // exclude current gallery page from results - check for trailing /
58
- !location.pathname.endsWith(slug) &&
59
- !location.pathname.endsWith(`${slug}/`) &&
60
- itemName.toLowerCase().includes(searchTerm.toLowerCase())
138
+ return (
139
+ !location.pathname.endsWith(slug) &&
140
+ !location.pathname.endsWith(`${slug}/`) &&
141
+ itemName.toLowerCase().includes(searchTerm.toLowerCase())
142
+ );
143
+ }
61
144
  );
62
145
  const sectionGalleryItems = filteredItems
63
146
  .sort(([itemName1], [itemName2]) => itemName1.localeCompare(itemName2))
@@ -76,8 +159,35 @@ export const SectionGalleryWrapper = ({
76
159
  }
77
160
  const { sources, isSubsection = false } = itemData;
78
161
  // Subsections don't have title or id, default to itemName aka sidenav text
79
- const title = itemData.title || itemName;
80
- const id = itemData.id || title;
162
+ // Convert itemName to sentence case if no title is provided
163
+ let title = itemData.title || toSentenceCase(itemName);
164
+ let id = itemData.id || title;
165
+
166
+ // For extensions section, try to extract extension name from slug to match JSON keys
167
+ // This handles cases where extensions have id: Overview or other IDs but we need to match JSON keys
168
+ // The JSON keys are dasherized (e.g., "component-groups"), so we extract from slug
169
+ if (section === 'extensions' && itemData.slug && galleryItemsData) {
170
+ // Extract extension name from slug like /extensions/topology/overview -> topology
171
+ // or /extensions/component-groups/overview -> component-groups
172
+ // Also handle /extensions/react-topology/... -> topology (remove react- prefix)
173
+ const slugParts = itemData.slug.split('/').filter(Boolean);
174
+ if (slugParts.length >= 2 && slugParts[0] === 'extensions') {
175
+ let extensionName = slugParts[1]; // e.g., "component-groups" or "react-topology"
176
+ // Remove "react-" prefix if present (e.g., "react-topology" -> "topology")
177
+ if (extensionName.startsWith('react-')) {
178
+ extensionName = extensionName.replace(/^react-/, '');
179
+ }
180
+ // Check if this extension name exists in galleryItemsData
181
+ if (galleryItemsData[extensionName]) {
182
+ // Use extension name as id for JSON lookup (TextSummary converts to dasherized)
183
+ id = extensionName;
184
+ // Update title to extension name in sentence case if id was "Overview" or matches itemName
185
+ if (itemData.id === 'Overview' || itemName === 'Overview' || !itemData.title) {
186
+ title = toSentenceCase(extensionName);
187
+ }
188
+ }
189
+ }
190
+ }
81
191
  // Display beta label if tab other than a '-next' tab is marked Beta
82
192
  const isDeprecated =
83
193
  !isSubsection &&
@@ -138,6 +248,23 @@ export const SectionGalleryWrapper = ({
138
248
  id,
139
249
  galleryItemsData,
140
250
  };
251
+ })
252
+ .filter((item) => {
253
+ // If onlyShowInGalleryData is true, filter to only items that exist in galleryItemsData
254
+ if (!onlyShowInGalleryData || !galleryItemsData) {
255
+ return true;
256
+ }
257
+ // Try matching by itemName first (already in dasherized format from routes)
258
+ if (galleryItemsData[item.itemName]) {
259
+ return true;
260
+ }
261
+ // Convert id to dasherized format to match JSON keys (lowercase, spaces to hyphens)
262
+ const dasherizedId = item.id
263
+ .split(' ')
264
+ .join('-')
265
+ .toLowerCase();
266
+ // Check if this item exists in galleryItemsData
267
+ return galleryItemsData[dasherizedId] !== undefined;
141
268
  });
142
269
 
143
270
  return (
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@patternfly/documentation-framework",
3
3
  "description": "A framework to build documentation for PatternFly.",
4
- "version": "6.31.12",
4
+ "version": "6.31.13",
5
5
  "author": "Red Hat",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -12,7 +12,7 @@
12
12
  "@babel/preset-env": "7.27.1",
13
13
  "@babel/preset-react": "^7.24.1",
14
14
  "@mdx-js/util": "1.6.16",
15
- "@patternfly/ast-helpers": "^1.4.0-alpha.321",
15
+ "@patternfly/ast-helpers": "^1.4.0-alpha.322",
16
16
  "@reach/router": "npm:@gatsbyjs/reach-router@1.3.9",
17
17
  "autoprefixer": "10.4.19",
18
18
  "babel-loader": "^9.1.3",
@@ -89,5 +89,5 @@
89
89
  "http-cache-semantics": ">=4.1.1",
90
90
  "nanoid": "3.3.8"
91
91
  },
92
- "gitHead": "81261fa8463451483e8157cfd1d98ecaca5670a1"
92
+ "gitHead": "8a0fdd37daa06820bfdd6e7c91ac12513ec54ec1"
93
93
  }