Skip to content

Conversation

@sapayth
Copy link
Member

@sapayth sapayth commented Oct 8, 2025

fixes #162

User Story
As a site admin, I want to add a Sidebar block to my documentation pages so that I can display selected docs, sections, and docs with customizable order and layout, making navigation easier for users.

Description
Introduce a "Sidebar" Gutenberg block in weDocs. The block should allow selecting ocsd, including/excluding categories, defining order, and customizing layout.

Developers can follow the default Gutenberg block handbook for implementation standards and coding best practices.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added DocsGrid block with customizable layouts, pagination, and styling options for displaying documentation in grid format.
    • Added Sidebar block featuring collapsible sections, nested articles, and comprehensive styling controls for documentation navigation.
  • Chores

    • Updated WordPress development dependencies for improved build tooling.
    • Enhanced RTL and responsive styling across documentation blocks.

@coderabbitai
Copy link

coderabbitai bot commented Oct 8, 2025

Walkthrough

This PR introduces two complete WordPress Gutenberg blocks (DocsGrid and Sidebar) with editor UI, rendering logic, and styling. It also adds a component library for block controls, updates build assets and dependencies, and enhances frontend CSS stylesheets for RTL and print support.

Changes

Cohort / File(s) Summary
DocsGrid Block — Source
src/blocks/DocsGrid/index.js, src/blocks/DocsGrid/edit.js, src/blocks/DocsGrid/StyleControls.js, src/blocks/DocsGrid/block.json, src/blocks/DocsGrid/style.scss
New DocsGrid block implementation with hierarchical docs/sections/articles rendering, pagination, styling controls, and editor preview with dynamic grid layout configuration (column style, docs per page, exclude list, ordering).
DocsGrid Block — Built Assets
assets/build/blocks/DocsGrid/index.asset.php, assets/build/blocks/DocsGrid/index.js, assets/build/blocks/DocsGrid/style-index.css, assets/build/blocks/DocsGrid/style-index-rtl.css
Compiled DocsGrid block assets including dependency manifest, RTL-aware stylesheets, and CSS variables for theming pagination, grid layout, and interactive states.
Sidebar Block — React Components
src/blocks/Sidebar/components/ArticleItem.js, src/blocks/Sidebar/components/CountBadge.js, src/blocks/Sidebar/components/SectionItem.js, src/blocks/Sidebar/components/SidebarContainer.js, src/blocks/Sidebar/components/index.js
New component library for Sidebar block: expandable/collapsible sections with hierarchical article rendering, count badges, connectors, and recursive nesting support with dynamic styling.
Sidebar Block — Editor & Source
src/blocks/Sidebar/edit.js, src/blocks/Sidebar/save.js, src/blocks/Sidebar/index.js, src/blocks/Sidebar/block.json, src/blocks/Sidebar/render.php, src/blocks/Sidebar/view.js, src/blocks/Sidebar/style.css
Complete Sidebar block registration, inspector controls for query/layout/styling, server-side rendering via PHP with hierarchical docs structure, and frontend interactivity (expand/collapse, hover effects, keyboard navigation).
Sidebar Block — Built Assets
assets/build/blocks/Sidebar/block.json, assets/build/blocks/Sidebar/index.asset.php, assets/build/blocks/Sidebar/index.js, assets/build/blocks/Sidebar/render.php
Compiled Sidebar block assets including dependency manifest, block metadata, and PHP render functions for sections, articles, and styling helpers.
Block Control Components
src/components/Blocks/AlignmentControls.js, src/components/Blocks/BackgroundImageControls.js, src/components/Blocks/BorderAndShadowControls.js, src/components/Blocks/ColorsControls.js, src/components/Blocks/DimensionsControls.js, src/components/Blocks/DisplayControls.js, src/components/Blocks/TypographyControls.js
New reusable component library for responsive block editing: alignment, background images, borders/shadows, colors, dimensions, display (mobile/tablet/desktop visibility), and typography controls with per-device state management.
Frontend Styles & Print Support
assets/build/frontend.css, assets/build/frontend-rtl.css, assets/build/print.css, assets/build/print-rtl.css, assets/build/style-block.css, assets/build/style-block-rtl.css
New and updated frontend stylesheets with comprehensive Wedocs UI styling (modals, sidebars, search, icons, responsive layout, callouts, code blocks, print-friendly RTL adjustments, and search block styles).
Build & Plugin Configuration
assets/build/block.asset.php, assets/build/frontend.asset.php, assets/build/print.asset.php, webpack.config.js, package.json, wedocs.php
Updated build assets with dependency adjustments (react → react-jsx-runtime, added wp-data), webpack config entry handling, @wordpress/scripts version bump (^25.0.0 → ^30.25.0), and Sidebar block registration in plugin.
Block Registry
src/blocks/index.js
Added import of Sidebar block module to the block registry.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Multiple interconnected blocks: Two new blocks with distinct rendering paths (client-side edit/preview and server-side PHP render) introduce complexity across files.
  • High logic density: PHP render functions (render.php) contain hierarchical data processing, sorting, and styling aggregation; React components manage state, nested rendering, and keyboard/mouse interactions.
  • Diverse file types: Mix of JavaScript/JSX, PHP, CSS/SCSS, JSON manifests, and build assets requires context-switching.
  • New component library: Seven reusable control components for block editing with per-device state management add significant surface area.
  • RTL and print styling: Large CSS additions with responsive breakpoints and directional adjustments increase review scope.

Areas requiring extra attention:

  • src/blocks/Sidebar/render.php and assets/build/blocks/Sidebar/render.php — intricate hierarchical doc tree building, recursive rendering, and CSS variable aggregation
  • src/blocks/Sidebar/edit.js and assets/build/blocks/DocsGrid/edit.js — data fetching, state management, and preview rendering logic
  • src/blocks/Sidebar/view.js — DOM manipulation and event binding correctness for interactive features
  • src/components/Blocks/BorderAndShadowControls.js — complex nested state updates and immutability patterns
  • Dependency consistency between assets/build/block.asset.php and new block asset manifests (react-jsx-runtime, wp-data additions)

Possibly related PRs

  • Add docs grid #203 — Adds the DocsGrid block with shared source structure (src/blocks/DocsGrid/, assets/build/blocks/DocsGrid/), direct code-level overlap.

Suggested labels

Needs Review, enhancement, blocks

Poem

🐰 Two blocks hop into the site,
Sidebar and Grid, a cozy pair,
With collapsible sections and colors so bright,
And components galore—responsive with care!
Thump thump goes the webpack, version's renewed,
Styles flow RTL, print-friendly and true! 📚✨

Pre-merge checks and finishing touches

❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning There is a critical mismatch between the linked issue and the actual code changes. The linked issue #162 requires upgrading the async dependency from version 2.6.3 to 3.2.4, including updates to lockfiles and changelog entries. However, the changeset contains zero modifications related to the async package. Instead, the PR implements a complete Sidebar Gutenberg block, a DocsGrid block, and multiple UI component utilities. The only dependency change present is @wordpress/scripts from ^25.0.0 to ^30.25.0, which is unrelated to issue #162. The code changes do not address any of the coding requirements specified in the linked issue. Either the wrong issue was linked to this PR, or the PR description/objectives are incorrect. The actual implementation is for a Sidebar Gutenberg block feature, not an async dependency bump. Please either re-link this PR to the correct issue describing the Sidebar and DocsGrid block feature, or update the changeset to include the async dependency bump from 2.6.3 to 3.2.4 as specified in issue #162.
Out of Scope Changes Check ⚠️ Warning Based on the linked issue #162 (upgrade async dependency), all code changes in this PR are out of scope. The changeset implements a complete Sidebar Gutenberg block feature including UI components, styling, and PHP rendering logic—none of which relates to upgrading the async package. Even the only dependency change present (@wordpress/scripts update) is unrelated to the linked issue. However, if the PR were correctly linked to an issue describing a Sidebar block feature, all these changes would be in scope. The fundamental problem is the incorrect issue linkage rather than inherent out-of-scope changes. Correct the linked issue reference to match the actual PR objectives. The current PR implements a Sidebar Gutenberg block feature; link it to an appropriate issue describing this feature rather than issue #162 (async upgrade). Alternatively, if issue #162 is the correct target, revise the changeset to include the async dependency bump with updated package.json, lockfiles, and changelog entries.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "feature: sidebar gutenberg block" accurately describes the introduction of a new Sidebar Gutenberg block, which is the primary feature highlighted in the PR description. However, the changeset also introduces a DocsGrid block and multiple reusable component utilities (AlignmentControls, BackgroundImageControls, BorderAndShadowControls, etc.), which are equally significant. The title focuses narrowly on the Sidebar block while omitting other substantial additions to the codebase. While the title is clear and specific about one main feature, it does not fully represent the comprehensive scope of changes in this changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between daa0cdf and 223ce68.

📒 Files selected for processing (2)
  • package.json (1 hunks)
  • wedocs.php (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🔇 Additional comments (2)
wedocs.php (2)

186-193: Sidebar block registration verified and correct.

The block.json exists and is properly configured with valid WordPress block schema, all required properties, and the render file referenced. The implementation is solid.


50-50: Verification complete — no issues found.

The render file exists and contains the render_wedocs_sidebar callback function. Both the source (src/blocks/Sidebar/render.php) and built (assets/build/blocks/Sidebar/render.php) versions are in place, with the latter required on line 50 of wedocs.php. The implementation is properly defined and operational.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 29

🧹 Nitpick comments (26)
src/blocks/Sidebar/components/CountBadge.js (1)

14-16: Consider handling negative count values.

While checking for count === 0 is appropriate, consider also handling negative values (e.g., count <= 0) to guard against unexpected data.

Apply this diff:

-    if (count === 0) {
+    if (count <= 0) {
         return null;
     }
src/components/Blocks/AlignmentControls.js (1)

205-215: Consider using undefined instead of null for consistency.

The Reset All button sets alignment values to null, whereas ColorsControls.js (line 338-341) uses undefined for the same purpose. For consistency across control components, consider using undefined as it's the conventional way to indicate "no value set" for optional attributes.

Apply this diff for consistency:

   onClick={() => {
     setAttributes({
       alignmentControls: {
         ...alignmentControls,
         [device]: {
           ...currentAlignment,
-          textAlign: null,
-          alignItems: null,
-          justifyContent: null,
-          direction: null,
+          textAlign: undefined,
+          alignItems: undefined,
+          justifyContent: undefined,
+          direction: undefined,
         },
       },
     });
   }}
src/components/Blocks/DimensionsControls.js (1)

239-256: Consider using undefined instead of null for consistency.

The Reset All button uses null to clear dimension values, while ColorsControls.js uses undefined. For consistency across control components, consider using undefined.

src/components/Blocks/DisplayControls.js (2)

50-57: Add defensive check for displayControls.

The function assumes attributes.displayControls exists and is an object. If it's undefined or null, this will throw an error.

Apply this diff to add a safe default:

 	const toggleDeviceVisibility = (deviceKey) => {
 		setAttributes({
 			displayControls: {
-				...attributes.displayControls,
+				...(attributes.displayControls || {}),
 				[deviceKey]: !attributes.displayControls[deviceKey],
 			},
 		});
 	};

60-61: Add defensive check for device key access.

Line 61 accesses attributes.displayControls[key] without checking if displayControls exists.

Apply this diff:

 	const renderDeviceCard = ({ key, icon, label }) => {
-		const isHidden = attributes.displayControls[key];
+		const isHidden = attributes.displayControls?.[key] || false;
src/components/Blocks/BackgroundImageControls.js (1)

33-60: Consider extracting focal point configuration.

The logic for setting focal points based on size is somewhat complex and could benefit from extraction into a configuration object for better maintainability.

Consider refactoring like this:

const FOCAL_POINT_PRESETS = {
	cover: { focalPoint: null, repeat: null },
	contain: { focalPoint: { x: 0.5, y: 0.5 }, repeat: false },
	tile: { focalPoint: { x: 0.5, y: 0 }, repeat: true }
};

const handleBackgroundImageSizeChange = (value) => {
	const preset = FOCAL_POINT_PRESETS[value] || {};
	
	setAttributes({
		backgroundImageControls: {
			...backgroundImageControls,
			[device]: {
				...currentBackgroundImage,
				bgSize: value,
				bgFocalPoint: preset.focalPoint,
				bgRepeat: preset.repeat,
			},
		},
	});
};
src/components/Blocks/TypographyControls.js (2)

34-37: Add defensive checks for font families structure.

The code assumes fontFamilies[0] exists and has theme and custom properties. This could fail if the structure is different.

Apply this diff:

 	// Combine both theme and custom fonts
-	const themeFonts = fontFamilies[0]?.theme || [];
-	const customFonts = fontFamilies[0]?.custom || [];
+	const themeFonts = fontFamilies?.[0]?.theme || [];
+	const customFonts = fontFamilies?.[0]?.custom || [];
 	const validFontFamilies = [...themeFonts, ...customFonts];

77-77: Remove or clarify empty onChange handler.

The disabled SelectControl has an empty onChange={() => {}} handler. Since the control is disabled, this handler will never be called. Consider removing it or adding a comment explaining why it's present.

 						value={'default'}
-						onChange={() => {}}
 						disabled
src/blocks/Sidebar/index.js (1)

7-17: Consider adding block icon for better UX.

The block registration doesn't include an icon, which means it will use a default placeholder icon in the block inserter. Consider adding an icon to improve the user experience.

Example:

+import { folder } from '@wordpress/icons';
+
 registerBlockType(metadata.name, {
 	/**
 	 * @see ./edit.js
 	 */
 	edit: Edit,
+	icon: folder,
 
 	/**
 	 * @see ./save.js
 	 */
 	save: Save,
 });
src/blocks/Sidebar/view.js (3)

10-44: Refactor to use class toggles instead of inline styles.

The current implementation directly manipulates style.display which prevents CSS transitions and makes styling harder to maintain. Consider toggling a CSS class instead.

                 if (isExpanded) {
                     // Collapse
-                    children.style.display = 'none';
+                    children.classList.add('is-collapsed');
                     this.setAttribute('aria-expanded', 'false');
                     if (toggleButton) {
                         // Change to down arrow
-                        toggleButton.innerHTML = `
-                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="width: 16px; height: 16px;">
-                                <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
-                            </svg>
-                        `;
+                        toggleButton.classList.add('is-collapsed');
                     }
                 } else {
                     // Expand
-                    children.style.display = 'block';
+                    children.classList.remove('is-collapsed');
                     this.setAttribute('aria-expanded', 'true');
                     if (toggleButton) {
                         // Change to up arrow
-                        toggleButton.innerHTML = `
-                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="width: 16px; height: 16px;">
-                                <path stroke-linecap="round" stroke-linejoin="round" d="m4.5 15.75 7.5-7.5 7.5 7.5" />
-                            </svg>
-                        `;
+                        toggleButton.classList.remove('is-collapsed');
                     }
                 }

Then add CSS:

.wedocs-section-children.is-collapsed {
    display: none;
}

.wedocs-expand-toggle.is-collapsed svg:first-child {
    display: none;
}

.wedocs-expand-toggle:not(.is-collapsed) svg:last-child {
    display: none;
}

56-116: Consider event delegation for better performance.

The current implementation attaches individual event listeners to every section, title, and article link. For large documentation trees, this could create hundreds of listeners. Event delegation would be more efficient.

-    // Handle hover effects for sections
-    const sections = document.querySelectorAll('.wedocs-section');
-    
-    sections.forEach(section => {
-        section.addEventListener('mouseenter', function() {
-            const hoverBg = getComputedStyle(this).getPropertyValue('--section-bg-hover');
-            if (hoverBg && hoverBg.trim() !== '') {
-                this.style.backgroundColor = hoverBg;
-            }
-        });
-        
-        section.addEventListener('mouseleave', function() {
-            const normalBg = getComputedStyle(this).getPropertyValue('--section-bg');
-            this.style.backgroundColor = normalBg || '';
-        });
-    });
+    // Handle hover effects using event delegation
+    document.addEventListener('mouseenter', function(e) {
+        const section = e.target.closest('.wedocs-section');
+        if (section) {
+            const hoverBg = getComputedStyle(section).getPropertyValue('--section-bg-hover');
+            if (hoverBg && hoverBg.trim() !== '') {
+                section.style.backgroundColor = hoverBg;
+            }
+        }
+        
+        const articleLink = e.target.closest('.wedocs-article a');
+        if (articleLink) {
+            const article = articleLink.closest('.wedocs-article');
+            const hoverColor = getComputedStyle(article).getPropertyValue('--doc-list-text-color-hover');
+            if (hoverColor) {
+                articleLink.style.color = hoverColor;
+            }
+        }
+    }, true);
+    
+    document.addEventListener('mouseleave', function(e) {
+        const section = e.target.closest('.wedocs-section');
+        if (section) {
+            const normalBg = getComputedStyle(section).getPropertyValue('--section-bg');
+            section.style.backgroundColor = normalBg || '';
+        }
+        
+        const articleLink = e.target.closest('.wedocs-article a');
+        if (articleLink) {
+            const article = articleLink.closest('.wedocs-article');
+            const textColor = getComputedStyle(article).getPropertyValue('--doc-list-text-color');
+            if (textColor) {
+                articleLink.style.color = textColor;
+            }
+        }
+    }, true);

48-53: Extract toggle logic to avoid indirect click triggering.

Calling this.click() in the keyboard handler is indirect and can cause issues if the click handler changes. Extract the toggle logic into a function.

+    function toggleSection(header) {
+        const section = header.closest('.wedocs-section');
+        const children = section.querySelector('.wedocs-section-children');
+        const toggleButton = header.querySelector('.wedocs-expand-toggle');
+        const isExpanded = header.getAttribute('aria-expanded') === 'true';
+        
+        if (!children) return;
+        
+        if (isExpanded) {
+            children.classList.add('is-collapsed');
+            header.setAttribute('aria-expanded', 'false');
+            if (toggleButton) {
+                toggleButton.classList.add('is-collapsed');
+            }
+        } else {
+            children.classList.remove('is-collapsed');
+            header.setAttribute('aria-expanded', 'true');
+            if (toggleButton) {
+                toggleButton.classList.remove('is-collapsed');
+            }
+        }
+    }
+    
     sectionHeaders.forEach(header => {
         header.addEventListener('click', function(e) {
             e.preventDefault();
-            
-            const section = this.closest('.wedocs-section');
-            const children = section.querySelector('.wedocs-section-children');
-            // ... rest of toggle logic
+            toggleSection(this);
         });
         
         header.addEventListener('keydown', function(e) {
             if (e.key === 'Enter' || e.key === ' ') {
                 e.preventDefault();
-                this.click();
+                toggleSection(this);
             }
         });
     });
assets/build/blocks/DocsGrid/style-index.css (1)

13-46: Reduce duplication in pagination styles and relocate RTL-specific rule.

  • .wedocs-docs-pagination is defined twice; consider consolidating the shared rules and scoping differences (buttons vs .page-numbers) to avoid drift.
  • The [dir=rtl] arrow rule in the LTR stylesheet is redundant given the separate RTL file; keep RTL-only rules in the RTL stylesheet for clarity.

Also applies to: 217-299, 213-215

src/components/Blocks/BorderAndShadowControls.js (1)

70-81: Unify i18n text domain with the plugin.

Use wedocs as the text domain for consistent translation loading.

Apply this diff (repeat for all labels):

- label={__('Border', 'block-responsive')}
+ label={__('Border', 'wedocs')}
- name: __('Theme', 'block-responsive'),
+ name: __('Theme', 'wedocs'),
- label={__('Border Radius', 'block-responsive')}
+ label={__('Border Radius', 'wedocs')}
- <Text>{__('Drop Shadow', 'block-responsive')}</Text>
+ <Text>{__('Drop Shadow', 'wedocs')}</Text>
- label={__('Outset', 'block-responsive')}
+ label={__('Outset', 'wedocs')}
- label={__('Inset', 'block-responsive')}
+ label={__('Inset', 'wedocs')}
- label={__('X Position', 'block-responsive')}
+ label={__('X Position', 'wedocs')}
- label={__('Y Position', 'block-responsive')}
+ label={__('Y Position', 'wedocs')}
- label={__('Blur', 'block-responsive')}
+ label={__('Blur', 'wedocs')}
- label={__('Spread', 'block-responsive')}
+ label={__('Spread', 'wedocs')}
- text={__('Reset All', 'block-responsive')}
+ text={__('Reset All', 'wedocs')}

Also applies to: 95-99, 131-135, 159-166, 177-181, 185-191, 193-201, 203-209, 219-219

src/blocks/Sidebar/components/ArticleItem.js (1)

10-24: Reduce duplication; prefer CSS hovers over JS events

  • decodeHtmlEntities and getColorValue duplicate SectionItem.js helpers; extract to a small shared util.
  • Replace inline onMouseEnter/onMouseLeave color changes with CSS :hover using CSS variables for consistency.

Also applies to: 36-45, 58-66

src/blocks/Sidebar/edit.js (1)

121-124: Prefer importing apiFetch over using wp.apiFetch

Importing ensures bundling and typings: import apiFetch from '@wordpress/api-fetch' then use apiFetch({ path }).

src/blocks/Sidebar/components/SectionItem.js (1)

1-4: Remove unused import

CountBadge is imported but not used.

-import CountBadge from './CountBadge';
assets/build/blocks/Sidebar/render.php (1)

19-29: Remove or use unused variables

$section_title_tag, $article_title_tag, $count_badge_styles, $doc_list_styles, and $content/$parent are unused. Clean up or wire them into output (see parity comment).

src/blocks/Sidebar/render.php (5)

324-324: Remove unused $count_badge_styles param (and argument) or implement badge rendering

Parameter is unused; keep code lean or render the badge.

Apply:

-    function wedocs_render_section_with_articles( $section, $articles_by_section, $enable_nested_articles, $section_title_tag, $article_title_tag, $section_styles, $title_styles, $doc_list_styles, $tree_styles, $count_badge_styles, $level = 0 ) {
+    function wedocs_render_section_with_articles( $section, $articles_by_section, $enable_nested_articles, $section_title_tag, $article_title_tag, $section_styles, $title_styles, $doc_list_styles, $tree_styles, $level = 0 ) {

And adjust call:

-            $children .= wedocs_render_section_with_articles(
-                $section, $articles_by_section, $enable_nested_articles, $section_title_tag, $article_title_tag,
-                $section_styles, $title_styles, $doc_list_styles, $tree_styles, $count_badge_styles
-            );
+            $children .= wedocs_render_section_with_articles(
+                $section, $articles_by_section, $enable_nested_articles, $section_title_tag, $article_title_tag,
+                $section_styles, $title_styles, $doc_list_styles, $tree_styles
+            );

Also applies to: 204-207


340-413: Localize ARIA labels for accessibility

Hardcoded English strings for aria-labels should be translated.

Example:

-            ) . '; background: none; border: none; cursor: pointer; padding: 2px; border-radius: 2px; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px;" aria-expanded="true" aria-label="Toggle ' . esc_attr(
-                                 $section->post_title
-                             ) . ' section">
+            ) . '; background: none; border: none; cursor: pointer; padding: 2px; border-radius: 2px; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px;" aria-expanded="true" aria-label="' . esc_attr( sprintf( __( 'Toggle %s section', 'wedocs' ), $section->post_title ) ) . '">

Apply similar change where aria-label is set on headers/buttons.

Also applies to: 474-493, 575-590


142-153: Normalize boolean enableNestedArticles from attributes

The empty-string coerce is brittle; normalize robustly.

Consider:

-    if ($enable_nested_articles === '') {
-        $enable_nested_articles = true;
-    }
+    $enable_nested_articles = filter_var( $enable_nested_articles, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
+    if ( null === $enable_nested_articles ) {
+        $enable_nested_articles = true;
+    }

294-319: Sorting: normalize $order input and use spaceship operator

Guard against 'ASC' casing and improve readability.

Example:

-    function wedocs_sort_docs( $docs, $orderby, $order ) {
+    function wedocs_sort_docs( $docs, $orderby, $order ) {
+        $order = strtolower( (string) $order ) === 'desc' ? 'desc' : 'asc';
         if ( empty( $docs ) ) {
             return $docs;
         }
         usort(
             $docs, function( $a, $b ) use ( $orderby, $order ) {
             switch ( $orderby ) {
                 case 'name':
-                    $result = strcmp( $a->post_title, $b->post_title );
+                    $result = strcmp( $a->post_title, $b->post_title );
                     break;
                 case 'slug':
-                    $result = strcmp( $a->post_name, $b->post_name );
+                    $result = strcmp( $a->post_name, $b->post_name );
                     break;
                 case 'id':
-                    $result = $a->ID - $b->ID;
+                    $result = $a->ID <=> $b->ID;
                     break;
                 default:
-                    $result = $a->menu_order - $b->menu_order;
+                    $result = $a->menu_order <=> $b->menu_order;
             }
 
-            return $order === 'desc' ? - $result : $result;
+            return $order === 'desc' ? -$result : $result;
         }
         );
 
         return $docs;
     }

570-589: Avoid emoji as icon; prefer SVG for consistency and a11y

The 📄 emoji may render inconsistently. Consider an inline SVG like other icons.

assets/build/blocks/Sidebar/index.js (3)

1207-1223: Ignore lints on bundled artifacts; errors are from webpack runtime

Biome flags (use-before-declare, redeclare) are in webpack bootstrap code. Exclude built assets (assets/build/) from linting and code review. Source changes should be made under src/.


670-672: Import and declare dependency for apiFetch in source

Using wp.apiFetch assumes the global is enqueued. Prefer importing from @wordpress/api-fetch in src and adding it to the block’s asset dependencies to avoid runtime undefined globals.


158-174: Remove dead code (CountBadge) or wire it up

CountBadge is built and exported but not used anywhere. Either render it (e.g., for children counts) or drop it to reduce bundle size.

Also applies to: 206-207, 510-514

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0434ddd and daa0cdf.

⛔ Files ignored due to path filters (14)
  • assets/build/block.js.map is excluded by !**/*.map
  • assets/build/blocks/DocsGrid/index.js.map is excluded by !**/*.map
  • assets/build/blocks/DocsGrid/style-index.css.map is excluded by !**/*.map
  • assets/build/blocks/Sidebar/index.js.map is excluded by !**/*.map
  • assets/build/blocks/Sidebar/style-index.css.map is excluded by !**/*.map
  • assets/build/frontend.css.map is excluded by !**/*.map
  • assets/build/frontend.js.map is excluded by !**/*.map
  • assets/build/index.css.map is excluded by !**/*.map
  • assets/build/index.js.map is excluded by !**/*.map
  • assets/build/print.css.map is excluded by !**/*.map
  • assets/build/print.js.map is excluded by !**/*.map
  • assets/build/store.js.map is excluded by !**/*.map
  • assets/build/style-block.css.map is excluded by !**/*.map
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (45)
  • assets/build/block.asset.php (1 hunks)
  • assets/build/blocks/DocsGrid/index.asset.php (1 hunks)
  • assets/build/blocks/DocsGrid/index.js (1 hunks)
  • assets/build/blocks/DocsGrid/style-index-rtl.css (1 hunks)
  • assets/build/blocks/DocsGrid/style-index.css (1 hunks)
  • assets/build/blocks/Sidebar/block.json (1 hunks)
  • assets/build/blocks/Sidebar/index.asset.php (1 hunks)
  • assets/build/blocks/Sidebar/index.js (1 hunks)
  • assets/build/blocks/Sidebar/render.php (1 hunks)
  • assets/build/frontend-rtl.css (1 hunks)
  • assets/build/frontend.asset.php (1 hunks)
  • assets/build/frontend.css (2 hunks)
  • assets/build/frontend.js (1 hunks)
  • assets/build/index.asset.php (1 hunks)
  • assets/build/print-rtl.css (1 hunks)
  • assets/build/print.asset.php (1 hunks)
  • assets/build/print.css (2 hunks)
  • assets/build/print.js (1 hunks)
  • assets/build/store.asset.php (1 hunks)
  • assets/build/store.js (1 hunks)
  • assets/build/style-block-rtl.css (1 hunks)
  • assets/build/style-block.css (1 hunks)
  • package.json (1 hunks)
  • src/blocks/Sidebar/block.json (1 hunks)
  • src/blocks/Sidebar/components/ArticleItem.js (1 hunks)
  • src/blocks/Sidebar/components/CountBadge.js (1 hunks)
  • src/blocks/Sidebar/components/SectionItem.js (1 hunks)
  • src/blocks/Sidebar/components/SidebarContainer.js (1 hunks)
  • src/blocks/Sidebar/components/index.js (1 hunks)
  • src/blocks/Sidebar/edit.js (1 hunks)
  • src/blocks/Sidebar/index.js (1 hunks)
  • src/blocks/Sidebar/render.php (1 hunks)
  • src/blocks/Sidebar/save.js (1 hunks)
  • src/blocks/Sidebar/style.css (1 hunks)
  • src/blocks/Sidebar/view.js (1 hunks)
  • src/blocks/index.js (1 hunks)
  • src/components/Blocks/AlignmentControls.js (1 hunks)
  • src/components/Blocks/BackgroundImageControls.js (1 hunks)
  • src/components/Blocks/BorderAndShadowControls.js (1 hunks)
  • src/components/Blocks/ColorsControls.js (1 hunks)
  • src/components/Blocks/DimensionsControls.js (1 hunks)
  • src/components/Blocks/DisplayControls.js (1 hunks)
  • src/components/Blocks/TypographyControls.js (1 hunks)
  • webpack.config.js (1 hunks)
  • wedocs.php (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (17)
src/blocks/Sidebar/components/CountBadge.js (3)
src/blocks/Sidebar/edit.js (1)
  • attributes (9-23)
src/blocks/Sidebar/components/ArticleItem.js (2)
  • attributes (3-8)
  • getColorValue (22-24)
src/blocks/Sidebar/components/SectionItem.js (2)
  • attributes (8-13)
  • getColorValue (24-26)
src/blocks/Sidebar/components/ArticleItem.js (4)
src/blocks/Sidebar/edit.js (1)
  • attributes (9-23)
src/blocks/Sidebar/components/SectionItem.js (7)
  • attributes (8-13)
  • decodeHtmlEntities (16-21)
  • indentation (29-29)
  • getColorValue (24-26)
  • iconStyle (59-63)
  • TitleTag (69-69)
  • children (70-70)
src/blocks/Sidebar/components/CountBadge.js (2)
  • attributes (2-2)
  • getColorValue (5-7)
src/blocks/Sidebar/view.js (1)
  • hoverColor (104-104)
src/blocks/Sidebar/components/SidebarContainer.js (3)
src/blocks/Sidebar/edit.js (2)
  • sections (82-82)
  • attributes (9-23)
src/blocks/Sidebar/components/SectionItem.js (2)
  • SectionItem (5-236)
  • attributes (8-13)
src/blocks/Sidebar/components/ArticleItem.js (1)
  • attributes (3-8)
src/blocks/Sidebar/components/SectionItem.js (2)
src/blocks/Sidebar/edit.js (1)
  • attributes (9-23)
src/blocks/Sidebar/components/ArticleItem.js (8)
  • attributes (3-8)
  • decodeHtmlEntities (11-16)
  • getColorValue (22-24)
  • indentation (19-19)
  • iconStyle (36-40)
  • TitleTag (47-47)
  • children (48-48)
  • ArticleItem (1-144)
src/components/Blocks/DimensionsControls.js (5)
src/components/Blocks/AlignmentControls.js (1)
  • attributes (27-27)
src/components/Blocks/BackgroundImageControls.js (1)
  • attributes (15-15)
src/components/Blocks/BorderAndShadowControls.js (1)
  • attributes (22-22)
src/components/Blocks/ColorsControls.js (1)
  • attributes (18-18)
src/components/Blocks/TypographyControls.js (1)
  • attributes (29-29)
src/blocks/Sidebar/edit.js (3)
src/blocks/Sidebar/components/ArticleItem.js (1)
  • attributes (3-8)
src/blocks/Sidebar/components/SectionItem.js (1)
  • attributes (8-13)
src/blocks/Sidebar/components/SidebarContainer.js (1)
  • SidebarContainer (4-26)
src/blocks/Sidebar/index.js (2)
src/blocks/Sidebar/edit.js (1)
  • Edit (8-467)
src/blocks/Sidebar/save.js (1)
  • Save (1-5)
src/components/Blocks/BorderAndShadowControls.js (5)
src/components/Blocks/AlignmentControls.js (1)
  • attributes (27-27)
src/components/Blocks/BackgroundImageControls.js (1)
  • attributes (15-15)
src/components/Blocks/ColorsControls.js (1)
  • attributes (18-18)
src/components/Blocks/DimensionsControls.js (1)
  • attributes (12-12)
src/components/Blocks/TypographyControls.js (1)
  • attributes (29-29)
assets/build/store.js (10)
src/components/Documentations/index.js (3)
  • docs (19-22)
  • loading (29-32)
  • parentDocs (24-27)
src/components/DocListing/index.js (3)
  • docs (27-29)
  • loading (37-40)
  • sections (103-103)
src/components/SelectBox.js (1)
  • pages (16-16)
src/blocks/DocsGrid/edit.js (2)
  • loading (18-18)
  • wp (16-16)
src/components/DocListing/ListingHeader.js (1)
  • loading (13-16)
src/blocks/Sidebar/edit.js (1)
  • sections (82-82)
src/components/Documentations/ParentDocs.js (2)
  • sections (36-40)
  • articles (42-46)
src/components/AddArticleModal.js (1)
  • articles (35-39)
src/components/DocListing/QuickEditModal.js (1)
  • articles (34-38)
src/components/DocListing/DocSections.js (2)
  • articles (70-70)
  • settings (86-89)
src/components/Blocks/AlignmentControls.js (5)
src/components/Blocks/BackgroundImageControls.js (1)
  • attributes (15-15)
src/components/Blocks/BorderAndShadowControls.js (1)
  • attributes (22-22)
src/components/Blocks/ColorsControls.js (1)
  • attributes (18-18)
src/components/Blocks/DimensionsControls.js (1)
  • attributes (12-12)
src/components/Blocks/TypographyControls.js (1)
  • attributes (29-29)
assets/build/blocks/DocsGrid/index.js (1)
src/blocks/Sidebar/edit.js (3)
  • attributes (9-23)
  • processDocsData (142-238)
  • sections (82-82)
src/components/Blocks/BackgroundImageControls.js (1)
src/blocks/CustomControls/UnitControl.js (1)
  • UnitControl (4-27)
src/components/Blocks/TypographyControls.js (9)
src/blocks/Sidebar/edit.js (1)
  • attributes (9-23)
src/blocks/Sidebar/components/ArticleItem.js (1)
  • attributes (3-8)
src/blocks/Sidebar/components/SectionItem.js (1)
  • attributes (8-13)
src/blocks/Sidebar/components/CountBadge.js (1)
  • attributes (2-2)
src/components/Blocks/AlignmentControls.js (1)
  • attributes (27-27)
src/components/Blocks/BackgroundImageControls.js (1)
  • attributes (15-15)
src/components/Blocks/BorderAndShadowControls.js (1)
  • attributes (22-22)
src/components/Blocks/ColorsControls.js (1)
  • attributes (18-18)
src/components/Blocks/DimensionsControls.js (1)
  • attributes (12-12)
src/components/Blocks/ColorsControls.js (1)
src/blocks/Sidebar/edit.js (1)
  • useSelect (30-36)
src/blocks/Sidebar/render.php (1)
assets/build/blocks/Sidebar/render.php (3)
  • render_wedocs_sidebar (11-153)
  • wedocs_sort_docs (158-192)
  • wedocs_render_section_with_articles (197-226)
assets/build/blocks/Sidebar/render.php (2)
src/blocks/Sidebar/render.php (3)
  • render_wedocs_sidebar (142-289)
  • wedocs_sort_docs (294-319)
  • wedocs_render_section_with_articles (324-521)
includes/Walker.php (2)
  • Walker (10-22)
  • start_el (15-21)
src/components/Blocks/DisplayControls.js (6)
src/components/Blocks/AlignmentControls.js (1)
  • attributes (27-27)
src/components/Blocks/BackgroundImageControls.js (1)
  • attributes (15-15)
src/components/Blocks/BorderAndShadowControls.js (1)
  • attributes (22-22)
src/components/Blocks/ColorsControls.js (1)
  • attributes (18-18)
src/components/Blocks/DimensionsControls.js (1)
  • attributes (12-12)
src/components/Blocks/TypographyControls.js (1)
  • attributes (29-29)
🪛 Biome (2.1.2)
src/blocks/Sidebar/style.css

[error] 74-74: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

padding is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

assets/build/print-rtl.css

[error] 40-40: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

white-space is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 65-65: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

font-size is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

assets/build/store.js

[error] 321-324: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 325-325: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 375-375: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)


[error] 376-376: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)

assets/build/blocks/DocsGrid/index.js

[error] 1040-1040: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1047-1047: Shouldn't redeclare 'i'. Consider to delete it or rename it.

'i' is defined here:

(lint/suspicious/noRedeclare)


[error] 1048-1048: Shouldn't redeclare 'chunkIds'. Consider to delete it or rename it.

'chunkIds' is defined here:

(lint/suspicious/noRedeclare)


[error] 1048-1048: Shouldn't redeclare 'fn'. Consider to delete it or rename it.

'fn' is defined here:

(lint/suspicious/noRedeclare)


[error] 1048-1048: Shouldn't redeclare 'priority'. Consider to delete it or rename it.

'priority' is defined here:

(lint/suspicious/noRedeclare)

assets/build/style-block.css

[error] 54-54: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

width is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

assets/build/frontend-rtl.css

[error] 326-326: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

display is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 493-493: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

white-space is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 518-518: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

font-size is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

assets/build/style-block-rtl.css

[error] 54-54: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

width is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

assets/build/blocks/Sidebar/index.js

[error] 1210-1210: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1217-1217: Shouldn't redeclare 'i'. Consider to delete it or rename it.

'i' is defined here:

(lint/suspicious/noRedeclare)


[error] 1218-1218: Shouldn't redeclare 'chunkIds'. Consider to delete it or rename it.

'chunkIds' is defined here:

(lint/suspicious/noRedeclare)


[error] 1218-1218: Shouldn't redeclare 'fn'. Consider to delete it or rename it.

'fn' is defined here:

(lint/suspicious/noRedeclare)


[error] 1218-1218: Shouldn't redeclare 'priority'. Consider to delete it or rename it.

'priority' is defined here:

(lint/suspicious/noRedeclare)

🪛 PHPMD (2.15.0)
src/blocks/Sidebar/render.php

142-142: Avoid unused parameters such as '$content'. (undefined)

(UnusedFormalParameter)


157-157: Avoid unused local variables such as '$container_styles'. (undefined)

(UnusedLocalVariable)


324-324: Avoid unused parameters such as '$count_badge_styles'. (undefined)

(UnusedFormalParameter)

assets/build/blocks/Sidebar/render.php

11-11: Avoid unused parameters such as '$content'. (undefined)

(UnusedFormalParameter)


19-19: Avoid unused local variables such as '$section_title_tag'. (undefined)

(UnusedLocalVariable)


20-20: Avoid unused local variables such as '$article_title_tag'. (undefined)

(UnusedLocalVariable)


26-26: Avoid unused local variables such as '$count_badge_styles'. (undefined)

(UnusedLocalVariable)


27-27: Avoid unused local variables such as '$doc_list_styles'. (undefined)

(UnusedLocalVariable)


32-32: Avoid unused local variables such as '$parent'. (undefined)

(UnusedLocalVariable)

🔇 Additional comments (29)
assets/build/print.css (1)

1-186: LGTM!

Build artifact with updated pipeline metadata and source map reference. No functional CSS changes detected.

assets/build/print.asset.php (1)

1-1: LGTM!

Standard asset manifest version bump for cache invalidation.

assets/build/frontend.js (1)

1-28: LGTM!

Standard webpack bootstrap runtime for ES module interop. No concerns.

assets/build/print.js (1)

1-28: LGTM!

Standard webpack bootstrap runtime, consistent with other build outputs.

src/blocks/Sidebar/components/CountBadge.js (1)

18-26: LGTM!

The badge rendering logic is clean with proper accessibility support via aria-label.

assets/build/style-block-rtl.css (2)

53-54: Vendor prefix pattern is intentional.

The duplicate width properties flagged by static analysis are intentional vendor prefixing. The -moz-fit-content prefix ensures compatibility with older Firefox versions, while fit-content provides the standard fallback. This is a common progressive enhancement pattern in CSS.


1-137: LGTM!

RTL styling for the Wedocs search block is comprehensive and properly structured. The CSS variables, layout rules, and accessibility considerations are well-implemented.

webpack.config.js (1)

9-9: Verify @wordpress/scripts defaultConfig.entry API. Unable to locate the upstream webpack config locally; please confirm that in @wordpress/scripts v^30.25.0+, defaultConfig.entry is indeed a function and that using ...defaultConfig.entry() aligns with the official API.

package.json (1)

33-33: Select format for breaking changes overview. Would you prefer a short summary of the breaking changes across @wordpress/scripts v25→30 or a detailed changelog with links for each version?

assets/build/block.asset.php (1)

1-1: LGTM!

The dependency update from react to react-jsx-runtime aligns with the modern JSX transform introduced in React 17+. The addition of wp-data suggests proper integration with WordPress data stores.

src/components/Blocks/ColorsControls.js (1)

17-351: LGTM!

The color controls component follows WordPress block editor patterns correctly:

  • Proper use of useSelect to fetch theme colors and gradients
  • Consistent per-device attribute management with proper spread operators
  • Appropriate use of experimental components with ESLint disable comment
  • Reset functionality correctly clears values while preserving other device settings
src/components/Blocks/AlignmentControls.js (1)

26-222: LGTM!

The alignment controls component follows the established patterns:

  • Consistent per-device attribute management
  • Proper use of WordPress icon components
  • Clear separation of concerns with individual handlers
src/blocks/Sidebar/block.json (1)

1-118: LGTM!

The block manifest is well-structured:

  • Uses latest schema and API version 3
  • Comprehensive attribute definitions with appropriate types and defaults
  • Proper asset file references for editor and frontend
  • Support configuration appropriately enables spacing and background customization
src/components/Blocks/DimensionsControls.js (1)

11-261: LGTM!

The dimension controls component is well-implemented:

  • Proper use of WordPress experimental components
  • Consistent per-device attribute management
  • Comprehensive coverage of dimension properties (padding, margin, width, height)
  • Clear UI organization with appropriate labels
assets/build/store.asset.php (1)

1-1: LGTM!

The asset version bump aligns with the build changes introduced in this PR.

src/blocks/index.js (1)

3-3: LGTM!

The Sidebar block import follows the same pattern as the existing blocks and properly integrates into the block registration system.

assets/build/frontend.asset.php (1)

1-1: LGTM!

The asset version bump reflects the build changes in this PR.

assets/build/frontend.css (1)

1-3: LGTM!

The addition of build metadata comments and sourcemap reference is standard for build artifacts. No functional changes to CSS.

Also applies to: 1223-1224

src/blocks/Sidebar/index.js (1)

5-5: Retain style import. This import is required for the bundler to generate the style-index.css file declared in block.json.

assets/build/blocks/Sidebar/index.asset.php (1)

1-1: LGTM! Standard WordPress block asset manifest.

The dependencies and version hash are correctly formatted for a server-rendered Gutenberg block.

src/blocks/Sidebar/save.js (1)

1-7: LGTM! Correct pattern for server-rendered blocks.

Returning null from the save function is the standard approach for dynamic blocks that render server-side via PHP. The comment clearly documents this behavior.

wedocs.php (2)

50-50: LGTM! Sidebar render file inclusion.

The require_once statement properly includes the Sidebar block's render callback, following the same pattern as the DocsGrid block.


187-193: LGTM! Sidebar block registration.

The block registration follows WordPress best practices and maintains consistency with the existing DocsGrid block registration pattern. The render callback is properly configured.

assets/build/index.asset.php (1)

1-1: LGTM! Updated for modern JSX transform.

The addition of react-jsx-runtime aligns with the new JSX transform introduced in React 17+, which is now the standard for WordPress block development.

src/blocks/Sidebar/components/index.js (1)

1-4: LGTM! Clean barrel export pattern.

The barrel export provides a clean public API for the Sidebar components, allowing consumers to import from a single entry point.

src/blocks/Sidebar/components/SidebarContainer.js (1)

20-20: Tailwind CSS is configured
Confirmed tailwind.config.js, tailwindcss dependency, and wide use of utility classes—no changes needed.

assets/build/store.js (1)

1-20: No async dependency detected
package.json and lockfiles contain no async entries. Confirm whether async@3.2.4 is required or if issue #162 can be closed.

assets/build/blocks/DocsGrid/index.js (1)

1036-1055: Ignore lints on webpack runtime in built artifacts

Biome warnings about redeclarations/use-before-declaration are from webpack runtime scaffolding. Safe to ignore in built files; don’t patch compiled output.

Also applies to: 1047-1048

assets/build/blocks/Sidebar/index.js (1)

11-11: Block attribute parity: ensure server supports all editor options

The editor exposes “Count” ordering (block.json). Confirm render.php supports it (currently missing before fix) and that style attributes (e.g., container background) match frontend output.

@@ -0,0 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'c2ad1e7060a95f9ac780');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Inconsistent with AI-generated summary.

The AI summary states that wp-data is included in the dependencies array, but the actual code does not include it. The Sidebar block includes wp-data but DocsGrid does not, while DocsGrid includes wp-primitives that Sidebar lacks.

Verify whether the DocsGrid block requires wp-data for its functionality. If the block uses WordPress data stores or selectors, the dependency should be included.


🏁 Script executed:

#!/bin/bash
# Description: Check if DocsGrid source files use wp-data APIs

# Search for wp-data usage in DocsGrid source files
rg -n --type=js -C3 -g '!**/build/**' -g '**/DocsGrid/**' '@wordpress/data|useSelect|useDispatch|select|dispatch'

Length of output: 81305


Include wp-data in DocsGrid block dependencies
DocsGrid edit.js invokes wp.data.useSelect → enqueue 'wp-data'.

In assets/build/blocks/DocsGrid/index.asset.php, add 'wp-data' to the dependencies array:

 <?php return array(
-   'dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives'),
+   'dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-data'),
    'version'   => 'c2ad1e7060a95f9ac780'
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'c2ad1e7060a95f9ac780');
<?php return array(
'dependencies' => array(
'react-jsx-runtime',
'wp-block-editor',
'wp-blocks',
'wp-components',
'wp-element',
'wp-i18n',
'wp-primitives',
'wp-data',
),
'version' => 'c2ad1e7060a95f9ac780',
);
🤖 Prompt for AI Agents
In assets/build/blocks/DocsGrid/index.asset.php around line 1, the block
dependencies array is missing 'wp-data' even though DocsGrid edit.js calls
wp.data.useSelect; update the dependencies array to include 'wp-data' (add
'wp-data' as an element in the returned 'dependencies' array) so the built block
enqueues the data module at runtime.

Comment on lines +884 to +886
className: `wedocs-docs-grid ${getGridClass()}`,
children: loading ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(Spinner, {}) : displayDocs.map(doc => renderGridItem(doc, applyStyles()))
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Spinner is undefined in bundle — import and reference it from components

The compiled bundle renders but there’s no import or qualified reference. This will throw at runtime.

Fix in source (src/blocks/DocsGrid/edit.js):

- import { __ } from '@wordpress/i18n';
+ import { __ } from '@wordpress/i18n';
+ import { Spinner } from '@wordpress/components';

And ensure usage is <Spinner /> (named import) so the bundle emits _wordpress_components__.Spinner.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
className: `wedocs-docs-grid ${getGridClass()}`,
children: loading ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(Spinner, {}) : displayDocs.map(doc => renderGridItem(doc, applyStyles()))
})
import { __ } from '@wordpress/i18n';
import { Spinner } from '@wordpress/components';
🤖 Prompt for AI Agents
In assets/build/blocks/DocsGrid/index.js around lines 884-886 the compiled
bundle renders <Spinner /> but Spinner is not imported, causing a runtime error;
update the source file src/blocks/DocsGrid/edit.js to add a named import for
Spinner from @wordpress/components (e.g. import { Spinner } from
'@wordpress/components') and ensure the component usage is the named <Spinner />
so the bundle emits the correct _wordpress_components_.Spinner reference.

Comment on lines +182 to +186
.wedocs-docs-grid__articles li ::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-left: 0.5rem;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix incorrect ::marker selector spacing (won’t apply).

Use li::marker (no space). The current li ::marker will not style list markers in RTL either.

Apply this diff:

-.wedocs-docs-grid__articles li ::marker {
+.wedocs-docs-grid__articles li::marker {
   content: "•";
   color: var(--wedocs-doc-children-active-color, #0073aa);
-  margin-left: 0.5rem;
+  margin-left: 0.5rem;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.wedocs-docs-grid__articles li ::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-left: 0.5rem;
}
.wedocs-docs-grid__articles li::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-left: 0.5rem;
}
🤖 Prompt for AI Agents
In assets/build/blocks/DocsGrid/style-index-rtl.css around lines 182–186 the
selector "li ::marker" is incorrect (the space prevents the ::marker
pseudo-element from applying); change it to "li::marker" (no space) and keep the
same declarations (content, color, margin-left) so list markers are properly
styled in RTL.

Comment on lines +182 to +186
.wedocs-docs-grid__articles li ::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-right: 0.5rem;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix incorrect ::marker selector spacing (won’t apply).

Use li::marker (no space). The current li ::marker targets a descendant’s marker and won’t affect the list item bullet.

Apply this diff:

-.wedocs-docs-grid__articles li ::marker {
+.wedocs-docs-grid__articles li::marker {
   content: "•";
   color: var(--wedocs-doc-children-active-color, #0073aa);
   margin-right: 0.5rem;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.wedocs-docs-grid__articles li ::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-right: 0.5rem;
}
.wedocs-docs-grid__articles li::marker {
content: "•";
color: var(--wedocs-doc-children-active-color, #0073aa);
margin-right: 0.5rem;
}
🤖 Prompt for AI Agents
In assets/build/blocks/DocsGrid/style-index.css around lines 182 to 186, the
selector uses "li ::marker" (a space) which targets a descendant's marker and
won't style the list item's bullet; change it to "li::marker" (no space) so the
rule applies to the list item marker, keeping the same declarations (content,
color, margin-right).

Comment on lines +10 to +19
"supports": {
"html": true,
"spacing": {
"padding": true
},
"color": {
"background": true,
"text": false
}
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Disable HTML editing for this dynamic block; add textdomain.

  • For server-rendered blocks, set "html": false to prevent editing raw HTML that won’t persist through render.
  • Consider adding "textdomain": "wedocs" for consistent translations.

Apply this diff:

   "supports": {
-    "html": true,
+    "html": false,
     "spacing": {
       "padding": true
     },
     "color": {
       "background": true,
       "text": false
     }
   },
+  "textdomain": "wedocs",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"supports": {
"html": true,
"spacing": {
"padding": true
},
"color": {
"background": true,
"text": false
}
},
"supports": {
"html": false,
"spacing": {
"padding": true
},
"color": {
"background": true,
"text": false
}
},
"textdomain": "wedocs",
🤖 Prompt for AI Agents
In assets/build/blocks/Sidebar/block.json around lines 10 to 19, the block
currently allows raw HTML editing and lacks a textdomain; update the "supports"
object to set "html" to false and add "textdomain": "wedocs" at the same level
(ensuring valid JSON structure and commas), so server-rendered content can't be
edited as raw HTML and translations use the wedocs textdomain.

Comment on lines +71 to +75
padding: 8px 12px;
background-color: var(--tree-header-bg, transparent);
color: var(--tree-header-text, inherit);
padding: var(--tree-header-padding, 8px 12px);
border-radius: var(--tree-header-border-radius, 0);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove duplicate padding declaration.

The padding property is declared twice (lines 71 and 74). The second declaration with a CSS variable overrides the first fixed value.

Apply this diff to remove the duplicate:

   align-items: center;
   justify-content: space-between;
   cursor: pointer;
-  padding: 8px 12px;
   background-color: var(--tree-header-bg, transparent);
   color: var(--tree-header-text, inherit);
   padding: var(--tree-header-padding, 8px 12px);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
padding: 8px 12px;
background-color: var(--tree-header-bg, transparent);
color: var(--tree-header-text, inherit);
padding: var(--tree-header-padding, 8px 12px);
border-radius: var(--tree-header-border-radius, 0);
align-items: center;
justify-content: space-between;
cursor: pointer;
background-color: var(--tree-header-bg, transparent);
color: var(--tree-header-text, inherit);
padding: var(--tree-header-padding, 8px 12px);
border-radius: var(--tree-header-border-radius, 0);
🧰 Tools
🪛 Biome (2.1.2)

[error] 74-74: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

padding is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🤖 Prompt for AI Agents
In src/blocks/Sidebar/style.css around lines 71 to 75, remove the duplicate
padding declaration so only the CSS variable-based padding remains (delete the
fixed `padding: 8px 12px;` line); ensure the remaining `padding:
var(--tree-header-padding, 8px 12px);` provides the default value and no other
padding declarations in this block conflict.

Comment on lines +1 to +244
import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
import {
Button,
FocalPointPicker,
ToggleControl,
__experimentalUnitControl as UnitControl,
Flex,
FlexItem,
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';

const BackgroundImageControls = ({ attributes, setAttributes, device }) => {
const { backgroundImageControls } = attributes;
const currentBackgroundImage = backgroundImageControls[device] || {};

const ALLOWED_MEDIA_TYPES = ['image'];

// Handle focal point change
const handleFocalPointChange = (newFocalPoint) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgFocalPoint: newFocalPoint,
},
},
});
};

const handleBackgroundImageSizeChange = (value) => {
let newFocalPoint = currentBackgroundImage.bgFocalPoint || {};
let newBgRepeat = currentBackgroundImage.bgRepeat || false;

// Set focal point and repeat based on size
if (value === 'cover') {
newFocalPoint = null;
newBgRepeat = null;
} else if (value === 'contain') {
newFocalPoint = { x: 0.5, y: 0.5 }; // 50% 50%
newBgRepeat = false;
} else if (value === 'tile') {
newFocalPoint = { x: 0.5, y: 0 }; // 50% 0px
newBgRepeat = true;
}

setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgSize: value,
bgFocalPoint: newFocalPoint,
bgRepeat: newBgRepeat,
},
},
});
};

return (
<div
className="block-responsive-background-image-controls"
style={{
display: 'flex',
flexDirection: 'column',
gap: '16px',
}}
>
<MediaUploadCheck>
<MediaUpload
onSelect={(media) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgUrl: media.url,
bgId: media.id,
},
},
});
}}
allowedTypes={ALLOWED_MEDIA_TYPES}
value={currentBackgroundImage.bgId}
render={({ open }) => (
<Button
__next40pxDefaultSize
onClick={open}
style={{
width: '100%',
justifyContent: 'center',
border: '1px solid #ddd',
}}
>
{currentBackgroundImage.bgUrl
? __(
'Change Background Image',
'block-responsive'
)
: __(
'Add Background Image',
'block-responsive'
)}
</Button>
)}
/>
</MediaUploadCheck>
{currentBackgroundImage.bgUrl && (
<>
<FocalPointPicker
__nextHasNoMarginBottom
url={currentBackgroundImage.bgUrl || ''}
value={currentBackgroundImage.bgFocalPoint || {}}
onDragStart={handleFocalPointChange}
onDrag={handleFocalPointChange}
onChange={handleFocalPointChange}
/>
<ToggleControl
__nextHasNoMarginBottom
label={__('Fixed background', 'block-responsive')}
checked={currentBackgroundImage.bgFixed || false}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgFixed: value,
},
},
});
}}
/>
<ToggleGroupControl
label={__('Size', 'block-responsive')}
value={currentBackgroundImage.bgSize || 'cover'}
onChange={handleBackgroundImageSizeChange}
isBlock
__nextHasNoMarginBottom
__next40pxDefaultSize
>
<ToggleGroupControlOption
value="cover"
label={__('Cover', 'block-responsive')}
/>
<ToggleGroupControlOption
value="contain"
label={__('Contain', 'block-responsive')}
/>
<ToggleGroupControlOption
value="tile"
label={__('Tile', 'block-responsive')}
/>
</ToggleGroupControl>
<Flex
style={{
gap: '8px',
justifyContent: 'flex-start',
}}
>
<FlexItem style={{ maxWidth: '100px' }}>
<UnitControl
__next40pxDefaultSize
value={currentBackgroundImage.bgWidth || 'auto'}
disabled={
currentBackgroundImage.bgSize !== 'tile'
}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgWidth: value,
},
},
});
}}
placeholder={__('Auto', 'block-responsive')}
/>
</FlexItem>
<FlexItem>
<ToggleControl
__nextHasNoMarginBottom
label={__('Repeat', 'block-responsive')}
disabled={
!(
currentBackgroundImage.bgSize ===
'contain' ||
currentBackgroundImage.bgSize === 'tile'
)
}
checked={
currentBackgroundImage.bgRepeat || false
}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgRepeat: value,
},
},
});
}}
/>
</FlexItem>
</Flex>

<Button
__next40pxDefaultSize
variant="secondary"
isDestructive
text={__('Reset All', 'block-responsive')}
style={{
width: '100%',
justifyContent: 'center',
}}
onClick={() => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgUrl: null,
bgId: null,
bgFocalPoint: null,
bgFixed: null,
bgSize: null,
bgWidth: null,
bgRepeat: null,
},
},
});
}}
/>
</>
)}
</div>
);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent text domain throughout the file.

The component uses 'block-responsive' as the text domain across all localized strings (lines 100, 104, 122, 137, 146, 150, 154, 181, 187, 217), but should use 'wedocs' to match the plugin's text domain.

Example fix for line 100:

-										'Change Background Image',
-										'block-responsive'
+										'Change Background Image',
+										'wedocs'

Apply similar changes to all other __() calls in this file.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
import {
Button,
FocalPointPicker,
ToggleControl,
__experimentalUnitControl as UnitControl,
Flex,
FlexItem,
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
const BackgroundImageControls = ({ attributes, setAttributes, device }) => {
const { backgroundImageControls } = attributes;
const currentBackgroundImage = backgroundImageControls[device] || {};
const ALLOWED_MEDIA_TYPES = ['image'];
// Handle focal point change
const handleFocalPointChange = (newFocalPoint) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgFocalPoint: newFocalPoint,
},
},
});
};
const handleBackgroundImageSizeChange = (value) => {
let newFocalPoint = currentBackgroundImage.bgFocalPoint || {};
let newBgRepeat = currentBackgroundImage.bgRepeat || false;
// Set focal point and repeat based on size
if (value === 'cover') {
newFocalPoint = null;
newBgRepeat = null;
} else if (value === 'contain') {
newFocalPoint = { x: 0.5, y: 0.5 }; // 50% 50%
newBgRepeat = false;
} else if (value === 'tile') {
newFocalPoint = { x: 0.5, y: 0 }; // 50% 0px
newBgRepeat = true;
}
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgSize: value,
bgFocalPoint: newFocalPoint,
bgRepeat: newBgRepeat,
},
},
});
};
return (
<div
className="block-responsive-background-image-controls"
style={{
display: 'flex',
flexDirection: 'column',
gap: '16px',
}}
>
<MediaUploadCheck>
<MediaUpload
onSelect={(media) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgUrl: media.url,
bgId: media.id,
},
},
});
}}
allowedTypes={ALLOWED_MEDIA_TYPES}
value={currentBackgroundImage.bgId}
render={({ open }) => (
<Button
__next40pxDefaultSize
onClick={open}
style={{
width: '100%',
justifyContent: 'center',
border: '1px solid #ddd',
}}
>
{currentBackgroundImage.bgUrl
? __(
'Change Background Image',
'block-responsive'
)
: __(
'Add Background Image',
'block-responsive'
)}
</Button>
)}
/>
</MediaUploadCheck>
{currentBackgroundImage.bgUrl && (
<>
<FocalPointPicker
__nextHasNoMarginBottom
url={currentBackgroundImage.bgUrl || ''}
value={currentBackgroundImage.bgFocalPoint || {}}
onDragStart={handleFocalPointChange}
onDrag={handleFocalPointChange}
onChange={handleFocalPointChange}
/>
<ToggleControl
__nextHasNoMarginBottom
label={__('Fixed background', 'block-responsive')}
checked={currentBackgroundImage.bgFixed || false}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgFixed: value,
},
},
});
}}
/>
<ToggleGroupControl
label={__('Size', 'block-responsive')}
value={currentBackgroundImage.bgSize || 'cover'}
onChange={handleBackgroundImageSizeChange}
isBlock
__nextHasNoMarginBottom
__next40pxDefaultSize
>
<ToggleGroupControlOption
value="cover"
label={__('Cover', 'block-responsive')}
/>
<ToggleGroupControlOption
value="contain"
label={__('Contain', 'block-responsive')}
/>
<ToggleGroupControlOption
value="tile"
label={__('Tile', 'block-responsive')}
/>
</ToggleGroupControl>
<Flex
style={{
gap: '8px',
justifyContent: 'flex-start',
}}
>
<FlexItem style={{ maxWidth: '100px' }}>
<UnitControl
__next40pxDefaultSize
value={currentBackgroundImage.bgWidth || 'auto'}
disabled={
currentBackgroundImage.bgSize !== 'tile'
}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgWidth: value,
},
},
});
}}
placeholder={__('Auto', 'block-responsive')}
/>
</FlexItem>
<FlexItem>
<ToggleControl
__nextHasNoMarginBottom
label={__('Repeat', 'block-responsive')}
disabled={
!(
currentBackgroundImage.bgSize ===
'contain' ||
currentBackgroundImage.bgSize === 'tile'
)
}
checked={
currentBackgroundImage.bgRepeat || false
}
onChange={(value) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgRepeat: value,
},
},
});
}}
/>
</FlexItem>
</Flex>
<Button
__next40pxDefaultSize
variant="secondary"
isDestructive
text={__('Reset All', 'block-responsive')}
style={{
width: '100%',
justifyContent: 'center',
}}
onClick={() => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgUrl: null,
bgId: null,
bgFocalPoint: null,
bgFixed: null,
bgSize: null,
bgWidth: null,
bgRepeat: null,
},
},
});
}}
/>
</>
)}
</div>
);
};
<MediaUpload
onSelect={(media) => {
setAttributes({
backgroundImageControls: {
...backgroundImageControls,
[device]: {
...currentBackgroundImage,
bgUrl: media.url,
bgId: media.id,
},
},
});
}}
allowedTypes={ALLOWED_MEDIA_TYPES}
value={currentBackgroundImage.bgId}
render={({ open }) => (
<Button
__next40pxDefaultSize
onClick={open}
style={{
width: '100%',
justifyContent: 'center',
border: '1px solid #ddd',
}}
>
{currentBackgroundImage.bgUrl
? __(
'Change Background Image',
'wedocs'
)
: __(
'Add Background Image',
'wedocs'
)}
</Button>
)}
/>
🤖 Prompt for AI Agents
In src/components/Blocks/BackgroundImageControls.js lines ~100–217, all
localization calls use the wrong text domain 'block-responsive'; replace every
instance of __('...','block-responsive') with __('...','wedocs') (i.e., update
all __() calls in the file to use 'wedocs' as the second argument) and run a
quick grep to ensure no remaining occurrences of 'block-responsive' in this
file.

Comment on lines +21 to +25
const BorderAndShadowControls = ({ attributes, setAttributes, device }) => {
const { borderAndShadowControls } = attributes;
const currentBorderAndShadow = borderAndShadowControls[device] || {};
const themeColors = useSetting('color.palette');

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard against undefined attributes to prevent runtime crash.

borderAndShadowControls[device] will throw if borderAndShadowControls is undefined. Default it safely.

Apply this diff:

-const { borderAndShadowControls } = attributes;
-const currentBorderAndShadow = borderAndShadowControls[device] || {};
+const { borderAndShadowControls = {} } = attributes;
+const currentBorderAndShadow = borderAndShadowControls?.[device] || {};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const BorderAndShadowControls = ({ attributes, setAttributes, device }) => {
const { borderAndShadowControls } = attributes;
const currentBorderAndShadow = borderAndShadowControls[device] || {};
const themeColors = useSetting('color.palette');
const BorderAndShadowControls = ({ attributes, setAttributes, device }) => {
const { borderAndShadowControls = {} } = attributes;
const currentBorderAndShadow = borderAndShadowControls?.[device] || {};
const themeColors = useSetting('color.palette');
// …
🤖 Prompt for AI Agents
In src/components/Blocks/BorderAndShadowControls.js around lines 21 to 25, guard
against attributes or attributes.borderAndShadowControls being undefined before
indexing by device; replace the direct access with a safe default (for example
destructure from attributes || {}, and compute currentBorderAndShadow as
(borderAndShadowControls && borderAndShadowControls[device]) || {} or use
optional chaining with a fallback) so the code never attempts to read properties
of undefined.

{
key: 'mobile',
icon: mobile,
label: __('Hide on mobile', 'block-responsive'),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent text domain.

The component uses 'block-responsive' as the text domain, but based on the PR context (weDocs plugin) and other files in the codebase, it should use 'wedocs' for consistency.

Apply this diff to fix the text domain:

-			label: __('Hide on mobile', 'block-responsive'),
+			label: __('Hide on mobile', 'wedocs'),
-			label: __('Hide on tablet', 'block-responsive'),
+			label: __('Hide on tablet', 'wedocs'),
-			label: __('Hide on desktop', 'block-responsive'),
+			label: __('Hide on desktop', 'wedocs'),
-				{__('Display Options', 'block-responsive')}
+				{__('Display Options', 'wedocs')}

Also applies to: 16-16, 21-21, 90-90

🤖 Prompt for AI Agents
In src/components/Blocks/DisplayControls.js around lines 11, 16, 21 and 90, the
i18n text domain is incorrectly set to 'block-responsive'; update each
__('...','block-responsive') and _x(...,'block-responsive') occurrences on those
lines to use the correct text domain 'wedocs' so all translation calls match the
project convention.

Comment on lines +1 to +274
import { __ } from '@wordpress/i18n';
import {
__experimentalFontFamilyControl as FontFamilyControl,
LineHeightControl,
useSetting,
useSettings,
FontSizePicker,
__experimentalFontAppearanceControl as FontAppearanceControl,
} from '@wordpress/block-editor';
import {
Flex,
FlexItem,
Button,
__experimentalUnitControl as UnitControl,
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon,
SelectControl,
} from '@wordpress/components';
import {
lineSolid,
formatUnderline,
formatStrikethrough,
formatUppercase,
formatLowercase,
formatCapitalize,
} from '@wordpress/icons';

const TypographyControls = ({ attributes, setAttributes, device }) => {
const { typographyControls } = attributes;
const currentTypography = typographyControls[device] || {};
const fontSizes = useSetting('typography.fontSizes');
const fontFamilies = useSettings('typography.fontFamilies');

// Combine both theme and custom fonts
const themeFonts = fontFamilies[0]?.theme || [];
const customFonts = fontFamilies[0]?.custom || [];
const validFontFamilies = [...themeFonts, ...customFonts];

return (
<>
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '16px',
}}
>
{validFontFamilies.length > 0 ? (
<FontFamilyControl
__next40pxDefaultSize
__nextHasNoMarginBottom
fontFamilies={validFontFamilies}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontFamily: value,
},
},
});
}}
value={currentTypography.fontFamily || ''}
/>
) : (
<div className="block-responsive-font-control-disabled">
<SelectControl
__next40pxDefaultSize
__nextHasNoMarginBottom
label={__('Font', 'block-responsive')}
help={__(
'Not supported in classic themes.',
'block-responsive'
)}
value={'default'}
onChange={() => {}}
disabled
options={[
{
disabled: true,
label: __('Default', 'block-responsive'),
value: 'default',
},
]}
/>
</div>
)}

<FontSizePicker
__next40pxDefaultSize
fontSizes={fontSizes}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontSize: value,
},
},
});
}}
value={currentTypography.fontSize || ''}
withSlider
withReset={false}
/>

<Flex style={{ gap: '16px' }}>
<FlexItem isBlock>
<FontAppearanceControl
__next40pxDefaultSize
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontAppearance: value,
},
},
});
}}
value={currentTypography.fontAppearance || ''}
/>
</FlexItem>
<FlexItem isBlock>
<LineHeightControl
__next40pxDefaultSize
__unstableInputWidth="auto"
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
lineHeight: value,
},
},
});
}}
value={currentTypography.lineHeight || ''}
/>
</FlexItem>
</Flex>

<Flex style={{ gap: '16px' }}>
<FlexItem isBlock>
<UnitControl
label={__('Letter spacing', 'block-responsive')}
__next40pxDefaultSize
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
letterSpacing: value,
},
},
});
}}
value={currentTypography.letterSpacing || ''}
/>
</FlexItem>
<FlexItem isBlock>
<ToggleGroupControl
isDeselectable
label={__('Decoration', 'block-responsive')}
value={currentTypography.textDecoration || ''}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
textDecoration: value,
},
},
});
}}
__next40pxDefaultSize
__nextHasNoMarginBottom
>
<ToggleGroupControlOptionIcon
value="none"
label={__('None', 'block-responsive')}
icon={lineSolid}
/>
<ToggleGroupControlOptionIcon
value="underline"
label={__('Underline', 'block-responsive')}
icon={formatUnderline}
/>
<ToggleGroupControlOptionIcon
value="line-through"
label={__('Strikethrough', 'block-responsive')}
icon={formatStrikethrough}
/>
</ToggleGroupControl>
</FlexItem>
</Flex>

<ToggleGroupControl
isDeselectable
label={__('Letter case', 'block-responsive')}
value={currentTypography.textTransform || ''}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
textTransform: value,
},
},
});
}}
__next40pxDefaultSize
__nextHasNoMarginBottom
>
<ToggleGroupControlOptionIcon
value="none"
label={__('None', 'block-responsive')}
icon={lineSolid}
/>
<ToggleGroupControlOptionIcon
value="uppercase"
label={__('Uppercase', 'block-responsive')}
icon={formatUppercase}
/>
<ToggleGroupControlOptionIcon
value="lowercase"
label={__('Lowercase', 'block-responsive')}
icon={formatLowercase}
/>
<ToggleGroupControlOptionIcon
value="capitalize"
label={__('Capitalize', 'block-responsive')}
icon={formatCapitalize}
/>
</ToggleGroupControl>
</div>
<Button
__next40pxDefaultSize
variant="secondary"
isDestructive
text={__('Reset All', 'block-responsive')}
style={{
width: '100%',
justifyContent: 'center',
marginTop: '16px',
}}
onClick={() => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...currentTypography,
fontFamily: null,
fontSize: null,
fontAppearance: null,
lineHeight: null,
letterSpacing: null,
textDecoration: null,
textTransform: null,
},
},
});
}}
/>
</>
);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent text domain throughout the file.

The component uses 'block-responsive' as the text domain across all localized strings, but should use 'wedocs' to match the plugin's text domain.

Lines affected: 71, 73, 82, 150, 169, 187-188, 192-193, 197-198, 206, 224-225, 229-230, 234-235, 239-240, 248.

Apply this pattern to all __() calls:

-					label={__('Font', 'block-responsive')}
+					label={__('Font', 'wedocs')}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { __ } from '@wordpress/i18n';
import {
__experimentalFontFamilyControl as FontFamilyControl,
LineHeightControl,
useSetting,
useSettings,
FontSizePicker,
__experimentalFontAppearanceControl as FontAppearanceControl,
} from '@wordpress/block-editor';
import {
Flex,
FlexItem,
Button,
__experimentalUnitControl as UnitControl,
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon,
SelectControl,
} from '@wordpress/components';
import {
lineSolid,
formatUnderline,
formatStrikethrough,
formatUppercase,
formatLowercase,
formatCapitalize,
} from '@wordpress/icons';
const TypographyControls = ({ attributes, setAttributes, device }) => {
const { typographyControls } = attributes;
const currentTypography = typographyControls[device] || {};
const fontSizes = useSetting('typography.fontSizes');
const fontFamilies = useSettings('typography.fontFamilies');
// Combine both theme and custom fonts
const themeFonts = fontFamilies[0]?.theme || [];
const customFonts = fontFamilies[0]?.custom || [];
const validFontFamilies = [...themeFonts, ...customFonts];
return (
<>
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '16px',
}}
>
{validFontFamilies.length > 0 ? (
<FontFamilyControl
__next40pxDefaultSize
__nextHasNoMarginBottom
fontFamilies={validFontFamilies}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontFamily: value,
},
},
});
}}
value={currentTypography.fontFamily || ''}
/>
) : (
<div className="block-responsive-font-control-disabled">
<SelectControl
__next40pxDefaultSize
__nextHasNoMarginBottom
label={__('Font', 'block-responsive')}
help={__(
'Not supported in classic themes.',
'block-responsive'
)}
value={'default'}
onChange={() => {}}
disabled
options={[
{
disabled: true,
label: __('Default', 'block-responsive'),
value: 'default',
},
]}
/>
</div>
)}
<FontSizePicker
__next40pxDefaultSize
fontSizes={fontSizes}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontSize: value,
},
},
});
}}
value={currentTypography.fontSize || ''}
withSlider
withReset={false}
/>
<Flex style={{ gap: '16px' }}>
<FlexItem isBlock>
<FontAppearanceControl
__next40pxDefaultSize
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
fontAppearance: value,
},
},
});
}}
value={currentTypography.fontAppearance || ''}
/>
</FlexItem>
<FlexItem isBlock>
<LineHeightControl
__next40pxDefaultSize
__unstableInputWidth="auto"
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
lineHeight: value,
},
},
});
}}
value={currentTypography.lineHeight || ''}
/>
</FlexItem>
</Flex>
<Flex style={{ gap: '16px' }}>
<FlexItem isBlock>
<UnitControl
label={__('Letter spacing', 'block-responsive')}
__next40pxDefaultSize
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
letterSpacing: value,
},
},
});
}}
value={currentTypography.letterSpacing || ''}
/>
</FlexItem>
<FlexItem isBlock>
<ToggleGroupControl
isDeselectable
label={__('Decoration', 'block-responsive')}
value={currentTypography.textDecoration || ''}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
textDecoration: value,
},
},
});
}}
__next40pxDefaultSize
__nextHasNoMarginBottom
>
<ToggleGroupControlOptionIcon
value="none"
label={__('None', 'block-responsive')}
icon={lineSolid}
/>
<ToggleGroupControlOptionIcon
value="underline"
label={__('Underline', 'block-responsive')}
icon={formatUnderline}
/>
<ToggleGroupControlOptionIcon
value="line-through"
label={__('Strikethrough', 'block-responsive')}
icon={formatStrikethrough}
/>
</ToggleGroupControl>
</FlexItem>
</Flex>
<ToggleGroupControl
isDeselectable
label={__('Letter case', 'block-responsive')}
value={currentTypography.textTransform || ''}
onChange={(value) => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...typographyControls[device],
textTransform: value,
},
},
});
}}
__next40pxDefaultSize
__nextHasNoMarginBottom
>
<ToggleGroupControlOptionIcon
value="none"
label={__('None', 'block-responsive')}
icon={lineSolid}
/>
<ToggleGroupControlOptionIcon
value="uppercase"
label={__('Uppercase', 'block-responsive')}
icon={formatUppercase}
/>
<ToggleGroupControlOptionIcon
value="lowercase"
label={__('Lowercase', 'block-responsive')}
icon={formatLowercase}
/>
<ToggleGroupControlOptionIcon
value="capitalize"
label={__('Capitalize', 'block-responsive')}
icon={formatCapitalize}
/>
</ToggleGroupControl>
</div>
<Button
__next40pxDefaultSize
variant="secondary"
isDestructive
text={__('Reset All', 'block-responsive')}
style={{
width: '100%',
justifyContent: 'center',
marginTop: '16px',
}}
onClick={() => {
setAttributes({
typographyControls: {
...typographyControls,
[device]: {
...currentTypography,
fontFamily: null,
fontSize: null,
fontAppearance: null,
lineHeight: null,
letterSpacing: null,
textDecoration: null,
textTransform: null,
},
},
});
}}
/>
</>
);
};
<div className="block-responsive-font-control-disabled">
<SelectControl
__next40pxDefaultSize
__nextHasNoMarginBottom
label={__( 'Font', 'wedocs' )}
help={__(
'Not supported in classic themes.',
'block-responsive'
)}
value={'default'}
onChange={() => {}}
disabled
options={[
{
disabled: true,
label={__( 'Default', 'wedocs' )}
value: 'default',
},
]}
/>
</div>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants