-
Notifications
You must be signed in to change notification settings - Fork 96
Feat/block contributors block #241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
WalkthroughAdds multiple new Gutenberg blocks (Contributors, DocsGrid, TableOfContents, Dynamic TOC, AdvanceContributors), editor UI components, JS/PHP helper modules, extensive CSS assets, store/data modules, and related build asset updates; also updates plugin bootstrap to register new blocks and localize assetsUrl while commenting out a template hook. Changes
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 17
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
assets/build/block.js (1)
452-466: Manual contributor list silently truncates at 100 users.The fetch at
wp.apiFetch({ path: '/wp/v2/users?per_page=100&context=edit' })only ever returns the first page of results. On any install with >100 users, the majority of contributors simply never appear in the “Select Contributors” checklist, so manual selection becomes unusable. Please either paginate through all pages (leveraging theX-WP-TotalPagesheader) or switch to a search-based picker that can request further pages on demand.
🧹 Nitpick comments (31)
src/blocks/Contributors/save.js (1)
1-9: Trim unused blockProps call in dynamic save.Because this block renders exclusively on the server,
useBlockProps.save()isn’t needed and just leaves an unused variable behind. Dropping it keeps the file lint-clean without changing behavior.-import { useBlockProps } from '@wordpress/block-editor'; - -const Save = () => { - const blockProps = useBlockProps.save(); - - // Since this is a dynamic block that uses PHP rendering, - // we return null to let the server-side render function handle the output - return null; -}; +const Save = () => null; export default Save;wedocs.php (1)
326-336: Namespace the new helper to prevent global collisions.By declaring
dequeue_wedocs_pro_frontend_css()in the global namespace, we risk clashing with other plugins/themes. Please wrap the function in your plugin namespace or convert it to a class method to avoid polluting the global scope.Example:
- function dequeue_wedocs_pro_frontend_css() { +namespace WeDevs\WeDocs; + +function dequeue_wedocs_pro_frontend_css() { … } -add_action( 'wp_enqueue_scripts', 'dequeue_wedocs_pro_frontend_css', 20 ); +add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\\dequeue_wedocs_pro_frontend_css', 20 );assets/build/style-block.css (1)
3-3: Drop the!importantoverrides from responsive avatar sizing.The
!importanthere blocks consumers from resizing avatars via inline styles. Removing it keeps responsive tweaks while allowing attribute-driven styling.Remove the
!importantflags from the mobile avatar rules so inline styles still win.src/blocks/components/TabSystem.js (1)
43-55: Handle non-array children safely.
children.mapthrows when only one child is passed (React gives an object, not an array). Wrap withReact.Children.toArray()to keep this flexible and future-proof.- {children.map((child, index) => { + {React.Children.toArray(children).map((child, index) => { …src/blocks/components/BorderControl.js (1)
1-10: Use stable components (where available) instead of experimental aliases.If your target WordPress/Gutenberg version supports stable exports, prefer UnitControl, BoxControl, and Spacer to avoid deprecation churn.
Apply this diff (verify version compatibility first):
import { PanelBody, - SelectControl, - __experimentalUnitControl as UnitControl, - __experimentalBoxControl as BoxControl, - __experimentalSpacer as Spacer + SelectControl, + UnitControl, + BoxControl, + Spacer } from '@wordpress/components';src/blocks/Contributors/edit.js (4)
272-277: Use stable React keys; avoid Math.random().Random keys break reconciliation and hurt performance.
Apply this diff:
- <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: attributes.contributorGap || '10px' }}> - {attributes.showAvatar && displayContributors.map(contributor => { + <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: attributes.contributorGap || '10px' }}> + {attributes.showAvatar && displayContributors.map((contributor, index) => { // Handle both API response format and demo format const contributorName = contributor.name || contributor.display_name || 'Unknown'; - const contributorId = contributor.id || contributor.ID || Math.random(); + const contributorId = contributor.id || contributor.ID || contributor.slug || `contributor-${index}`;
316-322: Use WP date utilities and honor custom format in editor preview.Match frontend by using @wordpress/date (site locale/timezone) and respect attributes.dateFormat/customDateFormat.
Example change (imports required at top):
- {attributes.datePrefix} {new Date().toLocaleDateString('en-US', { - year: 'numeric', - month: 'long', - day: 'numeric' - })} + {attributes.datePrefix}{' '} + { ( () => { + const { dateI18n, __experimentalGetSettings: getSettings } = wp.date || {}; + const fmt = attributes.dateFormat === 'custom' ? attributes.customDateFormat : (wp?.date ? getSettings().formats.date : 'F j, Y'); + return (wp?.date && dateI18n) ? dateI18n(fmt, new Date()) : new Date().toLocaleDateString(); + })() }And prefer importing: import { dateI18n, __experimentalGetSettings as getSettings } from '@wordpress/date';
63-76: Confirm wp.apiFetch availability or switch to module import.Ensure the script declares a dependency on wp-api-fetch so wp.apiFetch exists, or import from '@wordpress/api-fetch'.
If switching:
- import apiFetch from '@wordpress/api-fetch';
- Replace wp.apiFetch(...) with apiFetch(...).
Also applies to: 89-96, 101-111, 119-125, 130-145, 139-141
200-205: Global assets URL dependency.Verify weDocsAdminScriptVars.assetsUrl is always localized on editor pages; add a safe fallback to avoid broken images if undefined.
Also applies to: 278-283
src/blocks/Contributors/block.json (2)
35-38: Type the array items for selectedContributorsExplicit item type avoids accidental string serialization and eases validation.
"selectedContributors": { "type": "array", - "default": [] + "default": [], + "items": { "type": "number" } },
30-34: Naming consistency: “Title” vs “Contributor Title”You have both “title” (string), “contributorTitleColor/…Typography/…HoverColor” and a removed “titleColor”. Consider consistently using “title*” for the block heading (e.g., titleColor, titleTypography, titleHoverColor) to keep the public API coherent.
Also applies to: 130-134, 182-202, 220-236
assets/build/index.css (1)
3001-3030: Artboard sizes: confirm these are consumedIf these utility sizes aren’t referenced by templates/components, consider dropping them to keep the build slimmer.
src/blocks/Contributors/edit-old.js (4)
1-27: Use package API instead of global wp.apiFetchImport apiFetch from @wordpress/api-fetch to avoid relying on a global and to benefit from middleware (nonce, preloading).
import { useState, useEffect } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; +import apiFetch from '@wordpress/api-fetch';
55-63: Switch to apiFetch importReplace wp.apiFetch with the imported apiFetch.
- wp.apiFetch({ path: '/wp/v2/users?per_page=100&context=edit' }) + apiFetch({ path: '/wp/v2/users?per_page=100&context=edit' }) .then(users => {
29-29: Remove unused clientIdclientId isn’t used.
- const { attributes, setAttributes, clientId } = props; + const { attributes, setAttributes } = props;
66-72: Remove dead selectorcurrentPost is computed but never used.
- const currentPost = useSelect((select) => { - const { getCurrentPostId, getCurrentPostType } = select('core/editor') || {}; - if (!getCurrentPostId) return null; - - return select(coreStore).getEntityRecord('postType', getCurrentPostType(), getCurrentPostId()); - }, []);src/blocks/helpers/block-styles.php (1)
251-281: Scoped responsive CSS is fineBlock-scoped selectors keep CSS contained. Consider aligning breakpoints with WP defaults if you adopt more blocks.
webpack.config.js (1)
5-5: Remove unused @wordpress/icons import.The destructured
imageis not used and adds an unnecessary dependency load in Node.-const { image } = require('@wordpress/icons');src/blocks/components/TypographyControl.js (1)
3-8: Remove unused ToggleControl import.It’s imported but not used.
import { PanelBody, SelectControl, - ToggleControl, __experimentalUnitControl as UnitControl, __experimentalSpacer as Spacer } from '@wordpress/components';src/blocks/components/DimensionControl.js (1)
31-37: 'auto' is not a unit; avoid listing it in UnitControl units.
UnitControlexpects standard units; 'auto' is a CSS value. Use a toggle/select to setvalue="auto"and disable the numeric control instead of exposing it as a unit.Would you like a patch that adds an “Auto width/height” ToggleControl and disables the UnitControl when enabled?
Also applies to: 49-54
src/blocks/components/ShadowControl.js (1)
25-109: LGTM — coherent shadow editor with sensible defaults.Merges state safely and gates controls behind an enable toggle.
Optional: add an "Inset" toggle to support
insetbox-shadow.src/blocks/helpers/block-helpers.js (2)
77-83: Default typography param to prevent crashes on undefined.Align with other helpers that tolerate missing inputs.
-export const generateTypographyStyles = (typography) => { +export const generateTypographyStyles = (typography = {}) => {
374-377: Guard against window being undefined (SSR/Node).Prevents errors if called in non-browser contexts.
-export const isBreakpoint = (breakpoint) => { +export const isBreakpoint = (breakpoint) => { const breakpoints = getBreakpoints(); - const width = window.innerWidth; + const width = typeof window !== 'undefined' ? window.innerWidth : Number.MAX_SAFE_INTEGER;src/blocks/Contributors/style.scss (3)
33-38: Limit transitions to specific properties for performanceAvoid
transition: all; restrict to the properties you animate.- transition: all 0.3s ease; + transition: transform 0.2s ease, box-shadow 0.2s ease;
49-55: Make default icon color theme-friendly (avoid hard-coded WP blue)Use a CSS variable fallback so themes can override easily.
- background-color: #0073aa; - color: white; + background-color: var(--wedocs-accent, var(--wp--preset--color--primary, #0073aa)); + color: var(--wp--preset--color--background, #fff);
68-75: Add keyboard focus styles for linksProvide a visible focus indicator, not just hover.
&:hover { text-decoration: underline; } + &:focus-visible { + text-decoration: underline; + outline: 2px solid currentColor; + outline-offset: 2px; + }src/blocks/components/BackgroundControl.js (5)
29-29: Provide a default panel titleUse a sensible fallback when
labelisn’t passed.- <PanelBody title={label} initialOpen={false}> + <PanelBody title={ label || __('Background', 'wedocs') } initialOpen={false}>
3-8: Use stable UI where possible; avoid experimental Spacer
__experimentalSpacermay change. Prefer simple CSS gaps/margins or stable layout primitives (e.g., Flex) to avoid future breakage.Confirm your target WP/Gutenberg version guarantees
__experimentalSpacerstability.
57-66: Prefer GradientPicker over free-form gradient textImproves UX, ensures valid gradients, and aligns with core components.
- {backgroundType === 'gradient' && showGradient && ( - <TextControl - label={__('Gradient CSS', 'wedocs')} - value={backgroundGradient || ''} - onChange={onBackgroundGradientChange} - placeholder="linear-gradient(45deg, #ff0000, #00ff00)" - help={__('Enter CSS gradient value', 'wedocs')} - /> - )} + { backgroundType === 'gradient' && showGradient && ( + <GradientPicker + value={ backgroundGradient || '' } + onChange={ onBackgroundGradientChange } + /> + ) }And add the import:
import { PanelBody, RadioControl, TextControl, Button, - __experimentalSpacer as Spacer + __experimentalSpacer as Spacer, + GradientPicker } from '@wordpress/components';
68-70: Hide image controls when gradient is selectedAvoid conflicting background inputs; show image controls only for the classic type.
- {/* Background Image */} - {showImage && ( + {/* Background Image (classic only) */} + { showImage && backgroundType === 'classic' && (
15-27: Harden props with safe defaultsIf any onChange callbacks are omitted, the component will throw. Consider default no-ops to improve resilience.
-const BackgroundControl = ({ +const BackgroundControl = ({ label, - backgroundType = 'classic', - onBackgroundTypeChange, + backgroundType = 'classic', + onBackgroundTypeChange = () => {}, backgroundColor, - onBackgroundColorChange, + onBackgroundColorChange = () => {}, backgroundGradient, - onBackgroundGradientChange, - backgroundImage = {}, - onBackgroundImageChange, + onBackgroundGradientChange = () => {}, + backgroundImage = {}, + onBackgroundImageChange = () => {}, showGradient = true, showImage = true }) => {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (4)
assets/img/demo-avatar/avatar_1.pngis excluded by!**/*.pngassets/img/demo-avatar/avatar_2.pngis excluded by!**/*.pngsrc/blocks/Contributors/demo-avtar/avatar_1.pngis excluded by!**/*.pngsrc/blocks/Contributors/demo-avtar/avatar_2.pngis excluded by!**/*.png
📒 Files selected for processing (30)
assets/build/block.asset.php(1 hunks)assets/build/block.js(1 hunks)assets/build/blocks/Contributors/block.json(1 hunks)assets/build/blocks/Contributors/render.php(1 hunks)assets/build/index.asset.php(1 hunks)assets/build/index.css(9 hunks)assets/build/style-block.css(1 hunks)includes/Assets.php(1 hunks)includes/Frontend.php(2 hunks)src/blocks/Contributors/block.json(1 hunks)src/blocks/Contributors/edit-old.js(1 hunks)src/blocks/Contributors/edit.js(1 hunks)src/blocks/Contributors/index.js(1 hunks)src/blocks/Contributors/render.php(1 hunks)src/blocks/Contributors/save.js(1 hunks)src/blocks/Contributors/style.scss(1 hunks)src/blocks/components/BackgroundControl.js(1 hunks)src/blocks/components/BorderControl.js(1 hunks)src/blocks/components/DimensionControl.js(1 hunks)src/blocks/components/ShadowControl.js(1 hunks)src/blocks/components/SpacingControl.js(1 hunks)src/blocks/components/TabSystem.js(1 hunks)src/blocks/components/TypographyControl.js(1 hunks)src/blocks/helpers/README.md(1 hunks)src/blocks/helpers/block-helpers.js(1 hunks)src/blocks/helpers/block-styles.php(1 hunks)src/blocks/helpers/index.js(1 hunks)src/blocks/index.js(1 hunks)webpack.config.js(1 hunks)wedocs.php(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
src/blocks/components/TypographyControl.js (1)
src/blocks/CustomControls/UnitControl.js (1)
UnitControl(4-27)
src/blocks/Contributors/render.php (2)
src/blocks/helpers/block-styles.php (8)
wedocs_build_background_styles(134-152)wedocs_build_spacing_styles(58-70)wedocs_build_border_styles(81-101)wedocs_build_shadow_styles(109-123)wedocs_build_element_styles(179-228)wedocs_generate_block_id(160-162)wedocs_styles_to_css(236-242)wedocs_generate_responsive_css(251-281)src/components/Documentations/ParentDocs.js (1)
contributors(54-58)
assets/build/blocks/Contributors/render.php (2)
src/blocks/helpers/block-styles.php (8)
wedocs_build_background_styles(134-152)wedocs_build_spacing_styles(58-70)wedocs_build_border_styles(81-101)wedocs_build_shadow_styles(109-123)wedocs_build_element_styles(179-228)wedocs_generate_block_id(160-162)wedocs_styles_to_css(236-242)wedocs_generate_responsive_css(251-281)src/components/Documentations/ParentDocs.js (1)
contributors(54-58)
src/blocks/components/DimensionControl.js (1)
src/blocks/CustomControls/UnitControl.js (1)
UnitControl(4-27)
src/blocks/Contributors/edit-old.js (1)
src/blocks/Contributors/edit.js (6)
Edit(29-669)props(30-30)users(31-31)isLoadingUsers(32-32)blockProps(36-52)renderPreview(169-326)
src/blocks/Contributors/save.js (2)
src/blocks/Contributors/edit-old.js (1)
blockProps(33-49)src/blocks/Contributors/edit.js (1)
blockProps(36-52)
src/blocks/Contributors/edit.js (8)
src/blocks/Contributors/edit-old.js (6)
Edit(28-564)props(29-29)users(30-30)isLoadingUsers(31-31)currentPost(66-71)renderPreview(73-164)src/blocks/components/BackgroundControl.js (1)
BackgroundControl(15-110)src/blocks/components/SpacingControl.js (1)
SpacingControl(9-88)src/blocks/components/BorderControl.js (1)
BorderControl(11-116)src/blocks/components/ShadowControl.js (1)
ShadowControl(10-111)src/blocks/components/TypographyControl.js (1)
TypographyControl(11-173)src/blocks/components/DimensionControl.js (1)
DimensionControl(8-60)src/blocks/components/TabSystem.js (1)
TabSystem(5-59)
src/blocks/helpers/block-styles.php (1)
src/blocks/helpers/block-helpers.js (5)
matches(259-259)matches(280-280)number(283-283)unit(262-262)unit(284-284)
src/blocks/Contributors/index.js (1)
src/blocks/Contributors/edit.js (1)
Edit(29-669)
src/blocks/components/ShadowControl.js (1)
src/blocks/CustomControls/UnitControl.js (1)
UnitControl(4-27)
🪛 PHPMD (2.15.0)
src/blocks/Contributors/render.php
10-10: Avoid unused parameters such as '$content'. (undefined)
(UnusedFormalParameter)
10-10: Avoid unused parameters such as '$block'. (undefined)
(UnusedFormalParameter)
assets/build/blocks/Contributors/render.php
10-10: Avoid unused parameters such as '$content'. (undefined)
(UnusedFormalParameter)
10-10: Avoid unused parameters such as '$block'. (undefined)
(UnusedFormalParameter)
🪛 Biome (2.1.2)
assets/build/block.js
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
🔇 Additional comments (22)
src/blocks/index.js (1)
3-3: Contributors block wire-up looks good.Importing the new Contributors module here neatly enrolls it with the rest of the block registrations. No issues spotted.
assets/build/index.asset.php (1)
1-1: Asset manifest version bump acknowledged.The dependency list is unchanged and the new hash looks consistent with a rebuilt bundle. All good.
includes/Assets.php (1)
45-45: Admin bundle now gets the assets base URL.Exposing
assetsUrlalongside the existing AJAX data mirrors what the frontend already receives, so the admin UI can now resolve shared assets without hard-coding paths. Looks solid.includes/Frontend.php (1)
81-82: Frontend also benefits from the assets base URL.Mirroring the admin-side addition,
weDocs_Vars.assetsUrlgives the frontend script a stable base path for shared assets. Nice improvement.assets/build/blocks/Contributors/render.php (1)
10-392: Same functional issues as src version; avoid duplicate function definitions.This file duplicates render_wedocs_contributors_block. Ensure only one copy is loaded to prevent fatal redeclare. See comments on src/blocks/Contributors/render.php for logic fixes (author/meta handling, post guard).
src/blocks/Contributors/block.json (1)
55-67: Background precedence: gradient vs imageCurrent schema allows both gradient and image. In render you’ll end up with two background-image declarations; the last one wins (image overrides gradient). If that’s intentional, OK; otherwise consider supporting multiple layers or mutually excluding types.
Also applies to: 64-67, 141-149
assets/build/index.css (6)
1996-2010: Custom checkbox base styles look goodSolid, scoped base with CSS vars; works well with state rules below.
2501-2527: Accessible focus/checked/indeterminate states for .checkboxGood focus-visible outline and robust ARIA/attr state handling.
2542-2546: RTL parity for checkmarkNice RTL-specific image mirroring.
2114-2120: Duplicate .menu.horizontal rules – verify cascadeThese repeat existing menu.horizontal styles. Check that duplication doesn’t inadvertently change specificity/order in your bundle.
Also applies to: 2599-2606
4796-4804: New text-transform and decoration utilitiesUseful additions and consistent with existing underline utility.
Also applies to: 4947-4952
5069-5072: Blur utilityLooks fine; ensure this doesn’t defeat any backdrop/filter performance budgets on low-end devices.
src/blocks/helpers/block-styles.php (2)
134-149: Background layering: gradient + imageBoth set background-image; the latter (image) overrides gradient. If layering is desired, combine with a comma-separated background-image; otherwise, keep as-is.
290-312: Good utility for CSS unit sanitizationThis should be applied widely (as suggested above) to harden inline style construction.
assets/build/block.asset.php (1)
1-1: Asset manifest update looks correct.New dependencies (wp-core-data, wp-data) align with typical data usage in editor blocks. Version bump is expected from rebuild.
Ensure the PHP registration enqueues this asset file (block.asset.php) with
wp_register_scriptso these handles are honored.src/blocks/components/SpacingControl.js (1)
4-7: Using __experimental components—confirm target WP/Gutenberg compatibility.
__experimentalBoxControl,__experimentalUnitControl, and__experimentalSpacercan change across releases. Verify the target WP version ships compatible props.src/blocks/helpers/README.md (1)
1-120: Docs read well and match helpers.Clear mapping of PHP/JS helpers and usage examples.
src/blocks/components/TypographyControl.js (1)
116-126: Replace ‘normal’ fallbacks with empty string in UnitControl
UnitControl expects numeric+unit values; passing'normal'may cause parse errors. InTypographyControl.jsupdate thevalueprops for line height and letter spacing to usevalue={value.lineHeight || ''}andvalue={value.letterSpacing || ''}so the default CSS applies.src/blocks/Contributors/style.scss (1)
9-12: Verify root class matches server-rendered markupEnsure the PHP render adds
.wedocs-contributorson the root so these styles apply in both editor and frontend.src/blocks/Contributors/index.js (2)
4-4: Confirm style enqueue strategy (editor vs frontend)Importing
./style.scssin JS ensures editor styles via the block script. For frontend, confirmstyle/editorStylehandles are declared in block.json or enqueued in PHP for the dynamic block.
15-16: Dynamic block save is correctReturning
nullis appropriate for server-side rendering.src/blocks/components/BackgroundControl.js (1)
10-13: PanelColorSettings deprecation risk
PanelColorSettingshas seen deprecation/migration towards Color controls/ToolsPanel in newer Gutenberg. Not blocking for your current versions, but plan to migrate to keep parity with core.Please confirm the minimum WordPress/Gutenberg version you target so we can suggest the exact replacement API and code.
| "titleColor": { | ||
| "type": "string", | ||
| "default": "#fff" | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong default title color undermines readability.
With titleColor defaulting to #fff while the block background defaults to a light gray, the title is effectively invisible out of the box. Please pick a contrasting default (e.g. the same dark gray used elsewhere).
Update titleColor to a darker default (e.g., #333333) so the block renders legibly without manual tweaks.
🤖 Prompt for AI Agents
In assets/build/blocks/Contributors/block.json around lines 26 to 29, the
titleColor default is set to "#fff" which yields poor contrast on the block's
light gray background; change the default value to a darker hex such as
"#333333" to ensure readable title text by updating the titleColor default to
the new darker color.
|
|
||
| // override the theme template | ||
| add_filter( 'template_include', [ $this, 'template_loader' ], 20 ); | ||
| // add_filter( 'template_include', [ $this, 'template_loader' ], 20 ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don’t drop the template loader hook.
Commenting out add_filter( 'template_include', … ) stops the plugin from supplying its fallback single-doc template. In themes without a dedicated single-docs.php, this regresses the docs experience to the theme’s generic single view (or worse, a 404). Please leave the filter active unless there’s a replacement mechanism in place.
- // add_filter( 'template_include', [ $this, 'template_loader' ], 20 );
+ add_filter( 'template_include', [ $this, 'template_loader' ], 20 );🤖 Prompt for AI Agents
In includes/Frontend.php around line 39, the template loader hook was commented
out which prevents the plugin from providing its fallback single-doc template;
restore the add_filter( 'template_include', [ $this, 'template_loader' ], 20 );
call so the plugin can supply its single-doc template in themes that lack
single-docs.php, ensure the template_loader method still exists and returns the
correct template path, and avoid registering duplicate filters (check for
existing hook before adding if necessary).
| "description": "Display the author(s)/contributors of a doc along with the last updated date.", | ||
| "supports": { | ||
| "html": false | ||
| }, | ||
| "editorScript": "file:./index.js", | ||
| "editorStyle": "file:./index.css", | ||
| "style": "file:./style-index.css", | ||
| "render": "file:./render.php", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add textdomain for block JSON i18n
Include the plugin textdomain so title/description can be localized by WordPress tooling.
"description": "Display the author(s)/contributors of a doc along with the last updated date.",
+ "textdomain": "wedocs",
"supports": {📝 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.
| "description": "Display the author(s)/contributors of a doc along with the last updated date.", | |
| "supports": { | |
| "html": false | |
| }, | |
| "editorScript": "file:./index.js", | |
| "editorStyle": "file:./index.css", | |
| "style": "file:./style-index.css", | |
| "render": "file:./render.php", | |
| "description": "Display the author(s)/contributors of a doc along with the last updated date.", | |
| "textdomain": "wedocs", | |
| "supports": { | |
| "html": false | |
| }, | |
| "editorScript": "file:./index.js", | |
| "editorStyle": "file:./index.css", | |
| "style": "file:./style-index.css", | |
| "render": "file:./render.php", |
🤖 Prompt for AI Agents
In src/blocks/Contributors/block.json around lines 9 to 16, the block.json is
missing a textdomain property so the title/description aren’t picked up by WP
i18n tools; add a "textdomain" key with your plugin's actual textdomain (e.g.,
"your-plugin-slug") at the top level of the JSON so tooling can extract/localize
strings for the block.
| "titleColor": { | ||
| "type": "string", | ||
| "default": "#fff" | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Remove unused/duplicated titleColor attribute
The heading color is controlled by contributorTitleColor below. titleColor isn’t referenced in the editor/render path and will be hard to remove later if shipped.
- "titleColor": {
- "type": "string",
- "default": "#fff"
- },📝 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.
| "titleColor": { | |
| "type": "string", | |
| "default": "#fff" | |
| }, |
🤖 Prompt for AI Agents
In src/blocks/Contributors/block.json around lines 26 to 29, remove the unused
duplicated "titleColor" attribute (type/string default "#fff") because heading
color is already controlled by contributorTitleColor; update the JSON by
deleting that property entry and any trailing comma adjustments so the object
remains valid JSON, and run a quick search to confirm no references to
"titleColor" remain in editor/render code before committing.
| const Edit = (props) => { | ||
| const { attributes, setAttributes, clientId } = props; | ||
| const [users, setUsers] = useState([]); | ||
| const [isLoadingUsers, setIsLoadingUsers] = useState(false); | ||
|
|
||
| const blockProps = useBlockProps({ | ||
| className: `wedocs-contributors ${attributes.additionalCssClass}`, | ||
| style: { | ||
| backgroundColor: attributes.backgroundType === 'classic' ? attributes.backgroundColor : undefined, | ||
| backgroundImage: attributes.backgroundType === 'gradient' ? attributes.backgroundGradient : | ||
| (attributes.backgroundImage?.url ? `url(${attributes.backgroundImage.url})` : undefined), | ||
| padding: `${attributes.padding.top} ${attributes.padding.right} ${attributes.padding.bottom} ${attributes.padding.left}`, | ||
| margin: `${attributes.margin.top} ${attributes.margin.right} ${attributes.margin.bottom} ${attributes.margin.left}`, | ||
| borderStyle: attributes.borderStyle !== 'none' ? attributes.borderStyle : undefined, | ||
| borderWidth: attributes.borderStyle !== 'none' ? | ||
| `${attributes.borderWidth.top} ${attributes.borderWidth.right} ${attributes.borderWidth.bottom} ${attributes.borderWidth.left}` : undefined, | ||
| borderColor: attributes.borderStyle !== 'none' ? attributes.borderColor : undefined, | ||
| borderRadius: attributes.borderRadius, | ||
| boxShadow: attributes.boxShadow.enabled ? | ||
| `${attributes.boxShadow.horizontal} ${attributes.boxShadow.vertical} ${attributes.boxShadow.blur} ${attributes.boxShadow.spread} ${attributes.boxShadow.color}` : undefined | ||
| } | ||
| }); | ||
|
|
||
| // Fetch users when component mounts or when manual selection mode is active | ||
| useEffect(() => { | ||
| if (attributes.contributorDisplayMode === 'manual') { | ||
| setIsLoadingUsers(true); | ||
| wp.apiFetch({ path: '/wp/v2/users?per_page=100&context=edit' }) | ||
| .then(users => { | ||
| setUsers(users); | ||
| setIsLoadingUsers(false); | ||
| }) | ||
| .catch(() => { | ||
| setIsLoadingUsers(false); | ||
| }); | ||
| } | ||
| }, [attributes.contributorDisplayMode]); | ||
|
|
||
| const currentPost = useSelect((select) => { | ||
| const { getCurrentPostId, getCurrentPostType } = select('core/editor') || {}; | ||
| if (!getCurrentPostId) return null; | ||
|
|
||
| return select(coreStore).getEntityRecord('postType', getCurrentPostType(), getCurrentPostId()); | ||
| }, []); | ||
|
|
||
| const renderPreview = () => { | ||
| if (attributes.contributorDisplayMode === 'manual' && attributes.selectedContributors.length === 0) { | ||
| return ( | ||
| <Placeholder | ||
| icon="groups" | ||
| label={__('Doc Contributors', 'wedocs')} | ||
| instructions={__('Select contributors from the settings panel.', 'wedocs')} | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| // Mock data for preview | ||
| const mockContributors = attributes.contributorDisplayMode === 'main_author' ? | ||
| [{ id: 1, name: 'John Doe', avatar_urls: { 48: 'https://via.placeholder.com/48' } }] : | ||
| [ | ||
| { id: 1, name: 'John Doe', avatar_urls: { 48: 'https://via.placeholder.com/48' } }, | ||
| { id: 2, name: 'Jane Smith', avatar_urls: { 48: 'https://via.placeholder.com/48' } } | ||
| ]; | ||
|
|
||
| const avatarStyle = { | ||
| width: attributes.avatarSize, | ||
| height: attributes.avatarSize, | ||
| borderRadius: attributes.avatarShape === 'circle' ? '50%' : | ||
| (attributes.avatarShape === 'rounded' ? attributes.avatarBorderRadius : '0'), | ||
| borderStyle: attributes.avatarBorderStyle !== 'none' ? attributes.avatarBorderStyle : undefined, | ||
| borderColor: attributes.avatarBorderStyle !== 'none' ? attributes.avatarBorderColor : undefined, | ||
| borderWidth: attributes.avatarBorderStyle !== 'none' ? '2px' : undefined | ||
| }; | ||
|
|
||
| const nameStyle = { | ||
| color: attributes.nameColor, | ||
| fontSize: attributes.nameTypography.fontSize, | ||
| fontWeight: attributes.nameTypography.fontWeight, | ||
| fontStyle: attributes.nameTypography.fontStyle | ||
| }; | ||
| const contributorTitleStyle = { | ||
| color: attributes.contributorTitleColor, | ||
| fontSize: attributes.contributorTitleTypography.fontSize, | ||
| fontWeight: attributes.contributorTitleTypography.fontWeight, | ||
| fontStyle: attributes.contributorTitleTypography.fontStyle | ||
| }; | ||
|
|
||
| const dateStyle = { | ||
| color: attributes.dateColor, | ||
| fontSize: attributes.dateTypography.fontSize, | ||
| fontWeight: attributes.dateTypography.fontWeight, | ||
| fontStyle: attributes.dateTypography.fontStyle | ||
| }; | ||
|
|
||
| return ( | ||
| <div> | ||
| {attributes.showTitle && ( | ||
| <h3 style={{ marginBottom: '10px', fontSize: '16px', fontWeight: '600', ...contributorTitleStyle}}> | ||
| {attributes.title} | ||
| </h3> | ||
| )} | ||
|
|
||
| <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '10px' }}> | ||
| {attributes.showAvatar && mockContributors.map(contributor => ( | ||
| <div key={contributor.id} style={{ display: 'flex', alignItems: 'center', gap: '8px' }}> | ||
| {attributes.avatarType === 'user_avatar' ? ( | ||
| <img | ||
| src={contributor.avatar_urls[48]} | ||
| alt={contributor.name} | ||
| style={avatarStyle} | ||
| /> | ||
| ) : ( | ||
| <div style={{...avatarStyle, backgroundColor: '#0073aa', display: 'flex', alignItems: 'center', justifyContent: 'center'}}> | ||
| <svg width="16" height="16" fill="white" viewBox="0 0 24 24"> | ||
| <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/> | ||
| </svg> | ||
| </div> | ||
| )} | ||
| <span style={nameStyle}>{contributor.name}</span> | ||
| </div> | ||
| ))} | ||
| </div> | ||
|
|
||
| {attributes.showLastUpdated && ( | ||
| <div style={{ marginTop: '10px' }}> | ||
| <span style={dateStyle}> | ||
| {attributes.datePrefix} {new Date().toLocaleDateString('en-US', { | ||
| year: 'numeric', | ||
| month: 'long', | ||
| day: 'numeric' | ||
| })} | ||
| </span> | ||
| </div> | ||
| )} | ||
| </div> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate/legacy Edit – remove the old file
There’s already a primary Edit (src/blocks/Contributors/edit.js). Keeping edit-old.js invites drift and confusion. If not referenced in block.json, delete it.
Also applies to: 166-567
🤖 Prompt for AI Agents
In src/blocks/Contributors/edit-old.js lines 28-164 (and similarly lines
166-567) there is a duplicate/legacy Edit component that conflicts with
src/blocks/Contributors/edit.js; remove this file if it is not referenced by
block.json or any imports, or update block.json/imports to point to the
canonical edit.js and delete edit-old.js to avoid drift; before deleting, grep
the repo for any references to edit-old.js, ensure no active imports or
registrations depend on it, run a quick build/test to confirm nothing breaks,
then remove the file and commit the change.
| function wedocs_build_typography_styles($typography) { | ||
| $styles = []; | ||
|
|
||
| if (isset($typography['fontFamily']) && $typography['fontFamily'] !== 'default') { | ||
| $styles[] = 'font-family: ' . esc_attr($typography['fontFamily']); | ||
| } | ||
| if (isset($typography['fontSize'])) { | ||
| $styles[] = 'font-size: ' . esc_attr($typography['fontSize']); | ||
| } | ||
| if (isset($typography['fontWeight'])) { | ||
| $styles[] = 'font-weight: ' . esc_attr($typography['fontWeight']); | ||
| } | ||
| if (isset($typography['fontStyle'])) { | ||
| $styles[] = 'font-style: ' . esc_attr($typography['fontStyle']); | ||
| } | ||
| if (isset($typography['lineHeight']) && $typography['lineHeight'] !== 'normal') { | ||
| $styles[] = 'line-height: ' . esc_attr($typography['lineHeight']); | ||
| } | ||
| if (isset($typography['letterSpacing']) && $typography['letterSpacing'] !== 'normal') { | ||
| $styles[] = 'letter-spacing: ' . esc_attr($typography['letterSpacing']); | ||
| } | ||
| if (isset($typography['textTransform']) && $typography['textTransform'] !== 'none') { | ||
| $styles[] = 'text-transform: ' . esc_attr($typography['textTransform']); | ||
| } | ||
| if (isset($typography['textDecoration']) && $typography['textDecoration'] !== 'none') { | ||
| $styles[] = 'text-decoration: ' . esc_attr($typography['textDecoration']); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Sanitize dimension-like typography values
Use the provided wedocs_sanitize_css_value for fontSize, lineHeight, letterSpacing. Quote font-family values with spaces.
- if (isset($typography['fontFamily']) && $typography['fontFamily'] !== 'default') {
- $styles[] = 'font-family: ' . esc_attr($typography['fontFamily']);
- }
- if (isset($typography['fontSize'])) {
- $styles[] = 'font-size: ' . esc_attr($typography['fontSize']);
- }
+ if (isset($typography['fontFamily']) && $typography['fontFamily'] !== 'default') {
+ $font = trim($typography['fontFamily']);
+ $styles[] = 'font-family: ' . (str_contains($font, ' ') ? '"' . esc_attr($font) . '"' : esc_attr($font));
+ }
+ if (isset($typography['fontSize'])) {
+ $styles[] = 'font-size: ' . wedocs_sanitize_css_value($typography['fontSize']);
+ }
if (isset($typography['fontWeight'])) {
$styles[] = 'font-weight: ' . esc_attr($typography['fontWeight']);
}
if (isset($typography['fontStyle'])) {
$styles[] = 'font-style: ' . esc_attr($typography['fontStyle']);
}
- if (isset($typography['lineHeight']) && $typography['lineHeight'] !== 'normal') {
- $styles[] = 'line-height: ' . esc_attr($typography['lineHeight']);
- }
- if (isset($typography['letterSpacing']) && $typography['letterSpacing'] !== 'normal') {
- $styles[] = 'letter-spacing: ' . esc_attr($typography['letterSpacing']);
- }
+ if (isset($typography['lineHeight']) && $typography['lineHeight'] !== 'normal') {
+ $styles[] = 'line-height: ' . wedocs_sanitize_css_value($typography['lineHeight']);
+ }
+ if (isset($typography['letterSpacing']) && $typTypography['letterSpacing'] !== 'normal') {
+ $styles[] = 'letter-spacing: ' . wedocs_sanitize_css_value($typography['letterSpacing']);
+ }Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/blocks/helpers/block-styles.php around lines 20 to 47, update typography
sanitization: when building styles, use the existing wedocs_sanitize_css_value()
for fontSize, lineHeight and letterSpacing instead of raw esc_attr values; for
fontFamily, keep esc_attr but wrap the value in quotes only if it contains
whitespace (e.g., check for space and produce '"Family Name"' vs unquoted
single-word family) to ensure correct CSS; preserve existing checks for defaults
and other properties and apply esc_attr to all values passed into
wedocs_sanitize_css_value or placed into quotes.
| function wedocs_build_spacing_styles($padding, $margin) { | ||
| $styles = []; | ||
|
|
||
| if (!empty($padding)) { | ||
| $styles[] = 'padding: ' . esc_attr($padding['top'] ?? '0px') . ' ' . esc_attr($padding['right'] ?? '0px') . ' ' . esc_attr($padding['bottom'] ?? '0px') . ' ' . esc_attr($padding['left'] ?? '0px'); | ||
| } | ||
|
|
||
| if (!empty($margin)) { | ||
| $styles[] = 'margin: ' . esc_attr($margin['top'] ?? '0px') . ' ' . esc_attr($margin['right'] ?? '0px') . ' ' . esc_attr($margin['bottom'] ?? '0px') . ' ' . esc_attr($margin['left'] ?? '0px'); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Sanitize spacing values
Avoid raw attribute passthrough for padding/margin.
- if (!empty($padding)) {
- $styles[] = 'padding: ' . esc_attr($padding['top'] ?? '0px') . ' ' . esc_attr($padding['right'] ?? '0px') . ' ' . esc_attr($padding['bottom'] ?? '0px') . ' ' . esc_attr($padding['left'] ?? '0px');
- }
+ if (!empty($padding)) {
+ $styles[] = sprintf(
+ 'padding: %s %s %s %s',
+ wedocs_sanitize_css_value($padding['top'] ?? '0px'),
+ wedocs_sanitize_css_value($padding['right'] ?? '0px'),
+ wedocs_sanitize_css_value($padding['bottom'] ?? '0px'),
+ wedocs_sanitize_css_value($padding['left'] ?? '0px')
+ );
+ }
- if (!empty($margin)) {
- $styles[] = 'margin: ' . esc_attr($margin['top'] ?? '0px') . ' ' . esc_attr($margin['right'] ?? '0px') . ' ' . esc_attr($margin['bottom'] ?? '0px') . ' ' . esc_attr($margin['left'] ?? '0px');
- }
+ if (!empty($margin)) {
+ $styles[] = sprintf(
+ 'margin: %s %s %s %s',
+ wedocs_sanitize_css_value($margin['top'] ?? '0px'),
+ wedocs_sanitize_css_value($margin['right'] ?? '0px'),
+ wedocs_sanitize_css_value($margin['bottom'] ?? '0px'),
+ wedocs_sanitize_css_value($margin['left'] ?? '0px')
+ );
+ }📝 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.
| function wedocs_build_spacing_styles($padding, $margin) { | |
| $styles = []; | |
| if (!empty($padding)) { | |
| $styles[] = 'padding: ' . esc_attr($padding['top'] ?? '0px') . ' ' . esc_attr($padding['right'] ?? '0px') . ' ' . esc_attr($padding['bottom'] ?? '0px') . ' ' . esc_attr($padding['left'] ?? '0px'); | |
| } | |
| if (!empty($margin)) { | |
| $styles[] = 'margin: ' . esc_attr($margin['top'] ?? '0px') . ' ' . esc_attr($margin['right'] ?? '0px') . ' ' . esc_attr($margin['bottom'] ?? '0px') . ' ' . esc_attr($margin['left'] ?? '0px'); | |
| } | |
| function wedocs_build_spacing_styles($padding, $margin) { | |
| $styles = []; | |
| if (!empty($padding)) { | |
| $styles[] = sprintf( | |
| 'padding: %s %s %s %s', | |
| wedocs_sanitize_css_value($padding['top'] ?? '0px'), | |
| wedocs_sanitize_css_value($padding['right'] ?? '0px'), | |
| wedocs_sanitize_css_value($padding['bottom'] ?? '0px'), | |
| wedocs_sanitize_css_value($padding['left'] ?? '0px') | |
| ); | |
| } | |
| if (!empty($margin)) { | |
| $styles[] = sprintf( | |
| 'margin: %s %s %s %s', | |
| wedocs_sanitize_css_value($margin['top'] ?? '0px'), | |
| wedocs_sanitize_css_value($margin['right'] ?? '0px'), | |
| wedocs_sanitize_css_value($margin['bottom'] ?? '0px'), | |
| wedocs_sanitize_css_value($margin['left'] ?? '0px') | |
| ); | |
| } | |
| // …rest of function… | |
| } |
| if (!empty($border_width)) { | ||
| $styles[] = 'border-width: ' . esc_attr($border_width['top'] ?? '1px') . ' ' . esc_attr($border_width['right'] ?? '1px') . ' ' . esc_attr($border_width['bottom'] ?? '1px') . ' ' . esc_attr($border_width['left'] ?? '1px'); | ||
| } | ||
|
|
||
| if ($border_color) { | ||
| $styles[] = 'border-color: ' . esc_attr($border_color); | ||
| } | ||
| } | ||
|
|
||
| if ($border_radius) { | ||
| $styles[] = 'border-radius: ' . esc_attr($border_radius); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Sanitize border widths and radius
Prevent unsafe CSS in widths/radius.
- if (!empty($border_width)) {
- $styles[] = 'border-width: ' . esc_attr($border_width['top'] ?? '1px') . ' ' . esc_attr($border_width['right'] ?? '1px') . ' ' . esc_attr($border_width['bottom'] ?? '1px') . ' ' . esc_attr($border_width['left'] ?? '1px');
- }
+ if (!empty($border_width)) {
+ $styles[] = sprintf(
+ 'border-width: %s %s %s %s',
+ wedocs_sanitize_css_value($border_width['top'] ?? '1px'),
+ wedocs_sanitize_css_value($border_width['right'] ?? '1px'),
+ wedocs_sanitize_css_value($border_width['bottom'] ?? '1px'),
+ wedocs_sanitize_css_value($border_width['left'] ?? '1px')
+ );
+ }
...
- if ($border_radius) {
- $styles[] = 'border-radius: ' . esc_attr($border_radius);
- }
+ if ($border_radius) {
+ $styles[] = 'border-radius: ' . wedocs_sanitize_css_value($border_radius, ['px','em','rem','%']);
+ }📝 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.
| if (!empty($border_width)) { | |
| $styles[] = 'border-width: ' . esc_attr($border_width['top'] ?? '1px') . ' ' . esc_attr($border_width['right'] ?? '1px') . ' ' . esc_attr($border_width['bottom'] ?? '1px') . ' ' . esc_attr($border_width['left'] ?? '1px'); | |
| } | |
| if ($border_color) { | |
| $styles[] = 'border-color: ' . esc_attr($border_color); | |
| } | |
| } | |
| if ($border_radius) { | |
| $styles[] = 'border-radius: ' . esc_attr($border_radius); | |
| } | |
| if (!empty($border_width)) { | |
| $styles[] = sprintf( | |
| 'border-width: %s %s %s %s', | |
| wedocs_sanitize_css_value($border_width['top'] ?? '1px'), | |
| wedocs_sanitize_css_value($border_width['right'] ?? '1px'), | |
| wedocs_sanitize_css_value($border_width['bottom']?? '1px'), | |
| wedocs_sanitize_css_value($border_width['left'] ?? '1px') | |
| ); | |
| } | |
| if ($border_color) { | |
| $styles[] = 'border-color: ' . esc_attr($border_color); | |
| } | |
| } | |
| if ($border_radius) { | |
| $styles[] = 'border-radius: ' . wedocs_sanitize_css_value( | |
| $border_radius, | |
| ['px', 'em', 'rem', '%'] | |
| ); | |
| } |
| // Export all helper functions | ||
| export { | ||
| generateBlockStyles, | ||
| generateTypographyStyles, | ||
| generateSpacingStyles, | ||
| generateElementStyles, | ||
| generateCustomProperties, | ||
| debounce, | ||
| isValidCSSValue, | ||
| convertToPx, | ||
| classNames, | ||
| getBreakpoints, | ||
| isBreakpoint | ||
| } from './block-helpers'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix default export: local names are undefined (re‑export doesn’t create bindings).
export { ... } from './block-helpers' does not create local bindings, so the default export object references undefined identifiers at runtime. Replace with a barrel + namespace import.
Apply this diff:
-// Export all helper functions
-export {
- generateBlockStyles,
- generateTypographyStyles,
- generateSpacingStyles,
- generateElementStyles,
- generateCustomProperties,
- debounce,
- isValidCSSValue,
- convertToPx,
- classNames,
- getBreakpoints,
- isBreakpoint
-} from './block-helpers';
-
-// Export default object with all helpers
-export default {
- generateBlockStyles,
- generateTypographyStyles,
- generateSpacingStyles,
- generateElementStyles,
- generateCustomProperties,
- debounce,
- isValidCSSValue,
- convertToPx,
- classNames,
- getBreakpoints,
- isBreakpoint
-};
+export * from './block-helpers';
+import * as helpers from './block-helpers';
+export default helpers;Also applies to: 25-38
🤖 Prompt for AI Agents
In src/blocks/helpers/index.js around lines 10 to 23 (and similarly lines 25 to
38), the current re-export form doesn't create local bindings so the default
export object will reference undefined names at runtime; replace the direct
re-exports with a namespace import (e.g. import * as helpers from
'./block-helpers') and then re-export the needed named exports from that
namespace (or re-export them via export const X = helpers.X) and add a default
export of the namespace (export default helpers) so all identifiers are real
local bindings and the default export is valid.
| require_once plugin_dir_path(__FILE__) . 'src/blocks/helpers/block-styles.php'; | ||
| require_once plugin_dir_path(__FILE__) . 'assets/build/blocks/DocsGrid/render.php'; | ||
| require_once plugin_dir_path(__FILE__) . 'assets/build/blocks/Contributors/render.php'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard render_wedocs_contributors_block() availability before registration.
register_block_type() will fatally error if render_wedocs_contributors_block() isn’t loaded (e.g., load order issues or missing build artifact). Please ensure the function exists before passing it as the render callback.
Add a defensive check before registration:
+if ( function_exists( 'render_wedocs_contributors_block' ) ) {
register_block_type(
plugin_dir_path( __FILE__ ) . 'assets/build/blocks/Contributors',
array(
'render_callback' => 'render_wedocs_contributors_block'
)
);
+}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In wedocs.php around lines 49 to 52, the code calls register_block_type() with
render_wedocs_contributors_block as the render callback but does not verify that
the function is defined; add a defensive check using
function_exists('render_wedocs_contributors_block') before registering the block
and only pass the callback if it exists (otherwise register without the callback
or register a safe fallback that returns an empty string and/or log an error) so
missing build/load-order issues do not cause a fatal error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
assets/build/index.css (3)
2599-2606: Make “bordered” horizontal menu styles RTL‑safeUse logical properties (with fallback) so start side is cleared correctly in RTL.
Option A (logical prop):
-.menu.horizontal > li.bordered > a, - .menu.horizontal > li.bordered > button, - .menu.horizontal > li.bordered > span { - border-left-width: 0px; +.menu.horizontal > li.bordered > a, + .menu.horizontal > li.bordered > button, + .menu.horizontal > li.bordered > span { + border-inline-start-width: 0;Option B (fallback for older browsers):
[dir="rtl"] .menu.horizontal > li.bordered > a, [dir="rtl"] .menu.horizontal > li.bordered > button, [dir="rtl"] .menu.horizontal > li.bordered > span { border-right-width: 0; }
3001-3030: Prevent artboard overflow on small containers (optional)Fixed widths can overflow. Consider constraining max-width.
Add a shared rule:
/* Constrain rotated phone artboards */ .artboard.phone-1.horizontal, .artboard.phone-2.horizontal, .artboard.phone-3.horizontal, .artboard.phone-4.horizontal, .artboard.phone-5.horizontal, .artboard.phone-6.horizontal, .artboard.phone-1.artboard-horizontal, .artboard.phone-2.artboard-horizontal, .artboard.phone-3.artboard-horizontal, .artboard.phone-4.artboard-horizontal, .artboard.phone-5.artboard-horizontal, .artboard.phone-6.artboard-horizontal { max-width: 100%; }
5134-5137: Blur filter can be costly; use sparinglyConsider applying on small elements only, and only when needed (avoid on large containers). If toggled frequently, you may add will-change: filter on the element just before use.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
assets/build/index.css(6 hunks)includes/Assets.php(1 hunks)wedocs.php(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- includes/Assets.php
- wedocs.php
🔇 Additional comments (2)
assets/build/index.css (2)
4854-4862: Text transform utilities look goodScoping uppercase/lowercase/capitalize under .wedocs-document is appropriate.
5012-5017: Decoration utilities LGTMoverline and line-through additions are fine and consistent.
| .menu.horizontal { | ||
| display: inline-flex; | ||
| flex-direction: row; | ||
| } | ||
| .menu.horizontal :where(li) { | ||
| flex-direction: row; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scope horizontal menu styles to top-level items to avoid breaking submenus
Using a descendant selector will cascade into nested li. Constrain to direct children.
Apply:
-.menu.horizontal :where(li) {
- flex-direction: row;
-}
+.menu.horizontal > :where(li) {
+ flex-direction: row;
+}📝 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.
| .menu.horizontal { | |
| display: inline-flex; | |
| flex-direction: row; | |
| } | |
| .menu.horizontal :where(li) { | |
| flex-direction: row; | |
| } | |
| .menu.horizontal { | |
| display: inline-flex; | |
| flex-direction: row; | |
| } | |
| .menu.horizontal > :where(li) { | |
| flex-direction: row; | |
| } |
🤖 Prompt for AI Agents
In assets/build/index.css around lines 2114-2120, the selector ".menu.horizontal
:where(li)" uses a descendant combinator and incorrectly applies styles to
nested list items; change it to target only direct children by replacing the
selector with ".menu.horizontal > :where(li)" (or simply ".menu.horizontal >
li") so only top-level li get the flex-direction and prevent submenus from
inheriting the rule.
|
No changes could be noticed! @iftakharul-islam vai |
…DevsOfficial/wedocs-plugin into feat/Block-Contributors-Block
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 26
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
assets/build/frontend.css (1)
1-1224: Remove generated build artifacts from version control
Remove all files under assets/build (including frontend.css) from the repo (e.g.,git rm --cached -r assets/build), add assets/build/ to .gitignore, and rely on your build/CI pipeline to regenerate these assets.
♻️ Duplicate comments (2)
assets/build/blocks/TableOfContents/index.css (1)
1-22: Duplicate of assets/build/block.css.This file is identical to
assets/build/block.css. See the review comment on that file for details.assets/build/blocks/Contributors/style-index.css (1)
1-139: Code duplication: Identical to AdvanceContributors stylesheet.This file is byte-for-byte identical to
assets/build/blocks/AdvanceContributors/style-index.css(see earlier review comment). This duplication suggests:
- The Contributors and AdvanceContributors blocks may have overlapping purposes
- The shared styles should be extracted into a common stylesheet
- One of the blocks might be redundant
This issue was already flagged in the review of
assets/build/blocks/AdvanceContributors/style-index.css. The verification script provided there will help identify the extent of duplication between these two blocks.Consider:
- Extracting common styles into a shared stylesheet (e.g.,
contributors-common.css)- Consolidating the blocks if they serve the same purpose
- Clearly differentiating the blocks if they serve different purposes
🧹 Nitpick comments (9)
src/blocks/AdvanceContributors/save.js (1)
3-9: Remove unused blockProps variable.The
blockPropsvariable is assigned but never used. Since this is a dynamic block that returnsnull(server-side rendering), there's no need to calluseBlockProps.save().Apply this diff to simplify the component:
-const Save = () => { - const blockProps = useBlockProps.save(); - +const Save = () => { // Since this is a dynamic block that uses PHP rendering, // we return null to let the server-side render function handle the output return null; };Alternatively, if block attributes need to be preserved in the HTML comment for backward compatibility, keep
useBlockProps.save()but use it:const Save = () => { const blockProps = useBlockProps.save(); // Since this is a dynamic block that uses PHP rendering, // we return null to let the server-side render function handle the output - return null; + return <div {...blockProps} />; };src/blocks/AdvanceContributors/index.js (1)
12-15: Clarify JSDoc reference to save.js.The JSDoc comment references
./save.js, but the actualsavefunction is defined inline as() => null. This could confuse developers looking for a separate save.js file.Consider either:
- Importing and using the Save component from save.js:
import { registerBlockType } from "@wordpress/blocks"; import Edit from "./edit"; +import Save from "./save"; import metadata from "./block.json"; import "./style.scss"; registerBlockType(metadata.name, { /** * @see ./edit.js */ edit: Edit, /** * @see ./save.js */ - save: () => null, + save: Save, });
- Or updating the JSDoc to reflect the inline implementation:
/** - * @see ./save.js + * Dynamic block - server-side rendering only */ save: () => null,assets/build/blocks/AdvanceContributors/style-index.css (2)
54-55: Consider using CSS custom properties for theme consistency.Hardcoded color values (
#0073aa,#4a90a4) reduce theme flexibility. Consider using CSS custom properties that can be defined at the theme level.For example:
-.default-icon { - background-color: #0073aa; +.default-icon { + background-color: var(--wedocs-primary-color, #0073aa); color: white; }-@media (prefers-color-scheme: dark) { - .wedocs-contributors .contributor-item .contributor-avatar .default-icon { - background-color: #4a90a4; +@media (prefers-color-scheme: dark) { + .wedocs-contributors .contributor-item .contributor-avatar .default-icon { + background-color: var(--wedocs-primary-color-dark, #4a90a4); } }Also applies to: 126-127
95-97: Excessive use of !important declarations.Multiple
!importantdeclarations (lines 95-97, 107-108, 115-119) suggest specificity issues in the CSS architecture. While some are justified for accessibility overrides (reduced-motion), others like the mobile avatar sizing could be refactored to avoid!important.Consider increasing selector specificity or restructuring the cascade instead of relying on
!importantfor non-accessibility overrides. For accessibility-related!important(reduced-motion, high-contrast), the usage is appropriate and should remain.Also applies to: 107-108, 115-119
assets/build/blocks/TableOfContents/style-index.css (1)
10-11: Replace hardcoded colors with CSS custom properties.Multiple hardcoded color values (
#f9f9f9,#e0e0e0,#666,#0073aa) reduce theme flexibility and maintainability.Define these as CSS custom properties:
+:root { + --wedocs-toc-bg: #f9f9f9; + --wedocs-toc-border: #e0e0e0; + --wedocs-toc-text-muted: #666; + --wedocs-toc-accent: #0073aa; +} + .wp-block-wedocs-table-of-contents { - background-color: #f9f9f9; - border: 1px solid #e0e0e0; + background-color: var(--wedocs-toc-bg); + border: 1px solid var(--wedocs-toc-border); border-radius: 5px;Also applies to: 18-20, 54-56, 68-69, 121-122
assets/build/blocks/DocsGrid/style-index-rtl.css (1)
30-45: Extensive hardcoded color values reduce theme flexibility.Multiple hardcoded colors throughout the stylesheet (borders, backgrounds, text colors, pagination colors) should use CSS custom properties for better theme integration and maintainability.
Consider defining a consistent color system:
:root { --wedocs-primary: #0073aa; --wedocs-primary-hover: #005177; --wedocs-text-primary: #333; --wedocs-text-secondary: #757575; --wedocs-border: #ddd; --wedocs-background: #fff; --wedocs-background-hover: #f5f5f5; }Then replace hardcoded values with these custom properties throughout the stylesheet.
Also applies to: 81-82, 177-185, 196-207, 233-260
src/blocks/AdvanceContributors/style.scss (2)
105-108: Avoid !important for sizing constraints.Using
!importantfor mobile avatar sizing (lines 106-107) suggests a specificity issue. Consider restructuring the selector specificity instead.Instead of:
.contributor-avatar { img, .default-icon { width: 28px !important; height: 28px !important; } }Increase selector specificity:
@media (max-width: 480px) { .wedocs-contributors .contributors-container .contributor-item .contributor-avatar img, .wedocs-contributors .contributors-container .contributor-item .contributor-avatar .default-icon { width: 28px; height: 28px; } }
53-54: Use SCSS variables for color consistency.Hardcoded colors (
#0073aa,#4a90a4) should be defined as SCSS variables at the top of the file for easier maintenance and theme consistency.Add at the top of the file:
$wedocs-primary-color: #0073aa; $wedocs-primary-color-dark: #4a90a4; $wedocs-text-white: white;Then use throughout:
.default-icon { background-color: $wedocs-primary-color; color: $wedocs-text-white; } @media (prefers-color-scheme: dark) { .contributor-item { .contributor-avatar .default-icon { background-color: $wedocs-primary-color-dark; } } }Also applies to: 154-155
assets/build/blocks/TableOfContents/block.json (1)
35-45: <!-- [scratchpad]
[task review_comment_verification 1/1]
[observations]
- TableOfContents block.json defines
colorsControls.defaultwith onlydesktop.- AdvanceContributors and other blocks include
desktop,tablet, andmobile.- Code uses
colorsControls[device] || {}and handles missing device keys without errors.
[analysis]- Missing tablet/mobile defaults won’t break functionality but deviates from other blocks’ attribute shapes.
- For consistency and predictable UI, it’s advisable to include all device keys.
[pending]- None
[done]
Verified inconsistency and code behavior.
[/scratchpad]Include tablet and mobile defaults for colorsControls (assets/build/blocks/TableOfContents/block.json:35-45)
Addtabletandmobilekeys to thecolorsControls.defaultobject to match the responsive attribute shape of other blocks and ensure consistent UI behavior.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (23)
assets/build/block.css.mapis excluded by!**/*.mapassets/build/block.js.mapis excluded by!**/*.mapassets/build/blocks/AdvanceContributors/index.js.mapis excluded by!**/*.mapassets/build/blocks/AdvanceContributors/style-index.css.mapis excluded by!**/*.mapassets/build/blocks/Contributors/index.js.mapis excluded by!**/*.mapassets/build/blocks/Contributors/style-index.css.mapis excluded by!**/*.mapassets/build/blocks/DocsGrid/index.js.mapis excluded by!**/*.mapassets/build/blocks/DocsGrid/style-index.css.mapis excluded by!**/*.mapassets/build/blocks/TableOfContents/index.css.mapis excluded by!**/*.mapassets/build/blocks/TableOfContents/index.js.mapis excluded by!**/*.mapassets/build/blocks/TableOfContents/style-index.css.mapis excluded by!**/*.mapassets/build/blocks/TableOfContents/view.js.mapis excluded by!**/*.mapassets/build/frontend.css.mapis excluded by!**/*.mapassets/build/frontend.js.mapis excluded by!**/*.mapassets/build/index.css.mapis excluded by!**/*.mapassets/build/index.js.mapis excluded by!**/*.mapassets/build/print.css.mapis excluded by!**/*.mapassets/build/print.js.mapis excluded by!**/*.mapassets/build/store.js.mapis excluded by!**/*.mapassets/build/style-block.css.mapis excluded by!**/*.mappackage-lock.jsonis excluded by!**/package-lock.jsonsrc/blocks/AdvanceContributors/demo-avtar/avatar_1.pngis excluded by!**/*.pngsrc/blocks/AdvanceContributors/demo-avtar/avatar_2.pngis excluded by!**/*.png
📒 Files selected for processing (64)
assets/build/block-rtl.css(1 hunks)assets/build/block.asset.php(1 hunks)assets/build/block.css(1 hunks)assets/build/blocks/AdvanceContributors/block.json(1 hunks)assets/build/blocks/AdvanceContributors/index.asset.php(1 hunks)assets/build/blocks/AdvanceContributors/render.php(1 hunks)assets/build/blocks/AdvanceContributors/style-index-rtl.css(1 hunks)assets/build/blocks/AdvanceContributors/style-index.css(1 hunks)assets/build/blocks/Contributors/index.asset.php(1 hunks)assets/build/blocks/Contributors/index.js(1 hunks)assets/build/blocks/Contributors/style-index-rtl.css(1 hunks)assets/build/blocks/Contributors/style-index.css(1 hunks)assets/build/blocks/DocsGrid/index.asset.php(1 hunks)assets/build/blocks/DocsGrid/index.js(1 hunks)assets/build/blocks/DocsGrid/render.php(1 hunks)assets/build/blocks/DocsGrid/style-index-rtl.css(1 hunks)assets/build/blocks/DocsGrid/style-index.css(1 hunks)assets/build/blocks/TableOfContents/block.json(1 hunks)assets/build/blocks/TableOfContents/index-rtl.css(1 hunks)assets/build/blocks/TableOfContents/index.asset.php(1 hunks)assets/build/blocks/TableOfContents/index.css(1 hunks)assets/build/blocks/TableOfContents/index.js(1 hunks)assets/build/blocks/TableOfContents/render.php(1 hunks)assets/build/blocks/TableOfContents/style-index-rtl.css(1 hunks)assets/build/blocks/TableOfContents/style-index.css(1 hunks)assets/build/blocks/TableOfContents/view.asset.php(1 hunks)assets/build/blocks/TableOfContents/view.js(1 hunks)assets/build/blocks/dynamic-table-of-contents/build/block.json(1 hunks)assets/build/blocks/dynamic-table-of-contents/build/index.asset.php(1 hunks)assets/build/blocks/dynamic-table-of-contents/build/index.js(1 hunks)assets/build/blocks/dynamic-table-of-contents/build/render.php(1 hunks)assets/build/blocks/dynamic-table-of-contents/build/view.asset.php(1 hunks)assets/build/blocks/dynamic-table-of-contents/build/view.js(1 hunks)assets/build/blocks/dynamic-table-of-contents/src/block.json(1 hunks)assets/build/blocks/dynamic-table-of-contents/src/index-rtl.css(1 hunks)assets/build/blocks/dynamic-table-of-contents/src/index.asset.php(1 hunks)assets/build/blocks/dynamic-table-of-contents/src/index.css(1 hunks)assets/build/blocks/dynamic-table-of-contents/src/index.js(1 hunks)assets/build/blocks/dynamic-table-of-contents/src/render.php(1 hunks)assets/build/blocks/dynamic-table-of-contents/src/style-index-rtl.css(1 hunks)assets/build/blocks/dynamic-table-of-contents/src/style-index.css(1 hunks)assets/build/blocks/dynamic-table-of-contents/src/view.asset.php(1 hunks)assets/build/blocks/dynamic-table-of-contents/src/view.js(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/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)includes/Assets.php(2 hunks)package.json(1 hunks)src/blocks/AdvanceContributors/block.json(1 hunks)src/blocks/AdvanceContributors/edit-old.js(1 hunks)src/blocks/AdvanceContributors/edit.js(1 hunks)src/blocks/AdvanceContributors/index.js(1 hunks)src/blocks/AdvanceContributors/render.php(1 hunks)src/blocks/AdvanceContributors/save.js(1 hunks)src/blocks/AdvanceContributors/style.scss(1 hunks)
✅ Files skipped from review due to trivial changes (15)
- assets/build/blocks/TableOfContents/view.asset.php
- assets/build/block-rtl.css
- assets/build/print.asset.php
- assets/build/blocks/dynamic-table-of-contents/src/index.css
- assets/build/blocks/AdvanceContributors/index.asset.php
- assets/build/print.css
- assets/build/blocks/AdvanceContributors/style-index-rtl.css
- assets/build/blocks/dynamic-table-of-contents/src/view.asset.php
- assets/build/blocks/dynamic-table-of-contents/src/index-rtl.css
- assets/build/blocks/dynamic-table-of-contents/build/view.asset.php
- assets/build/store.asset.php
- assets/build/frontend.asset.php
- assets/build/blocks/dynamic-table-of-contents/src/block.json
- assets/build/blocks/DocsGrid/style-index.css
- assets/build/blocks/DocsGrid/index.asset.php
🚧 Files skipped from review as they are similar to previous changes (1)
- includes/Assets.php
🧰 Additional context used
🧬 Code graph analysis (11)
src/blocks/AdvanceContributors/edit.js (6)
src/blocks/commonControls/TypographyControls.js (2)
currentTypography(30-30)TypographyControls(28-274)src/blocks/commonControls/DimensionsControls.js (2)
currentDimensions(13-13)DimensionsControls(11-261)src/blocks/commonControls/AlignmentControls.js (2)
currentAlignment(28-28)AlignmentControls(26-222)src/blocks/commonControls/BackgroundImageControls.js (2)
currentBackgroundImage(16-16)BackgroundImageControls(14-244)src/blocks/commonControls/BorderAndShadowControls.js (1)
BorderAndShadowControls(21-240)src/blocks/commonControls/DisplayControls.js (1)
DisplayControls(5-100)
src/blocks/AdvanceContributors/render.php (1)
src/components/Documentations/ParentDocs.js (1)
contributors(54-58)
assets/build/blocks/dynamic-table-of-contents/build/render.php (1)
src/blocks/TableOfContents/view.js (7)
content(153-153)level(98-98)text(99-99)html(89-89)counters(94-94)indent(116-116)numbers(122-122)
assets/build/blocks/TableOfContents/render.php (1)
src/blocks/TableOfContents/view.js (7)
content(153-153)level(98-98)text(99-99)html(89-89)counters(94-94)indent(116-116)numbers(122-122)
assets/build/blocks/dynamic-table-of-contents/src/render.php (1)
src/blocks/TableOfContents/view.js (7)
content(153-153)level(98-98)text(99-99)html(89-89)counters(94-94)indent(116-116)numbers(122-122)
assets/build/blocks/AdvanceContributors/render.php (1)
src/components/Documentations/ParentDocs.js (1)
contributors(54-58)
src/blocks/AdvanceContributors/edit-old.js (2)
src/blocks/DocsGrid/edit.js (1)
wp(16-16)src/blocks/CustomControls/UnitControl.js (1)
UnitControl(4-27)
assets/build/blocks/DocsGrid/render.php (1)
src/blocks/DocsGrid/edit.js (1)
attributes(20-48)
assets/build/blocks/TableOfContents/index.js (2)
src/blocks/commonControls/BorderAndShadowControls.js (1)
themeColors(24-24)src/blocks/TableOfContents/view.js (7)
content(153-153)supportedHeadings(42-42)showHierarchy(43-43)showNumbering(44-44)indent(116-116)numberText(119-119)level(98-98)
assets/build/blocks/Contributors/index.js (1)
src/components/Documentations/ParentDocs.js (1)
contributors(54-58)
assets/build/store.js (9)
src/components/DocListing/index.js (3)
docs(27-29)loading(37-40)sections(103-103)src/components/Documentations/index.js (3)
docs(19-22)loading(29-32)parentDocs(24-27)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/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)
🪛 Biome (2.1.2)
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/blocks/dynamic-table-of-contents/build/view.js
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
assets/build/blocks/dynamic-table-of-contents/build/index.js
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: Shouldn't redeclare 'l'. Consider to delete it or rename it.
'l' is defined here:
(lint/suspicious/noRedeclare)
[error] 1-1: Shouldn't redeclare 'n'. Consider to delete it or rename it.
'n' is defined here:
(lint/suspicious/noRedeclare)
[error] 1-1: Shouldn't redeclare 'a'. Consider to delete it or rename it.
'a' is defined here:
(lint/suspicious/noRedeclare)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
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/blocks/dynamic-table-of-contents/src/index.js
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: Shouldn't redeclare 'l'. Consider to delete it or rename it.
'l' is defined here:
(lint/suspicious/noRedeclare)
[error] 1-1: Shouldn't redeclare 'n'. Consider to delete it or rename it.
'n' is defined here:
(lint/suspicious/noRedeclare)
[error] 1-1: Shouldn't redeclare 'a'. Consider to delete it or rename it.
'a' is defined here:
(lint/suspicious/noRedeclare)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
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/blocks/dynamic-table-of-contents/src/view.js
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
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/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/blocks/TableOfContents/index.js
[error] 1079-1079: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1086-1086: Shouldn't redeclare 'i'. Consider to delete it or rename it.
'i' is defined here:
(lint/suspicious/noRedeclare)
[error] 1087-1087: Shouldn't redeclare 'chunkIds'. Consider to delete it or rename it.
'chunkIds' is defined here:
(lint/suspicious/noRedeclare)
[error] 1087-1087: Shouldn't redeclare 'fn'. Consider to delete it or rename it.
'fn' is defined here:
(lint/suspicious/noRedeclare)
[error] 1087-1087: Shouldn't redeclare 'priority'. Consider to delete it or rename it.
'priority' is defined here:
(lint/suspicious/noRedeclare)
assets/build/blocks/Contributors/index.js
[error] 1790-1790: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1797-1797: Shouldn't redeclare 'i'. Consider to delete it or rename it.
'i' is defined here:
(lint/suspicious/noRedeclare)
[error] 1798-1798: Shouldn't redeclare 'chunkIds'. Consider to delete it or rename it.
'chunkIds' is defined here:
(lint/suspicious/noRedeclare)
[error] 1798-1798: Shouldn't redeclare 'fn'. Consider to delete it or rename it.
'fn' is defined here:
(lint/suspicious/noRedeclare)
[error] 1798-1798: Shouldn't redeclare 'priority'. Consider to delete it or rename it.
'priority' is defined here:
(lint/suspicious/noRedeclare)
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)
🪛 PHPMD (2.15.0)
src/blocks/AdvanceContributors/render.php
10-10: Avoid unused parameters such as '$content'. (undefined)
(UnusedFormalParameter)
10-10: Avoid unused parameters such as '$block'. (undefined)
(UnusedFormalParameter)
assets/build/blocks/TableOfContents/render.php
308-308: Avoid unused parameters such as '$content'. (undefined)
(UnusedFormalParameter)
308-308: Avoid unused parameters such as '$block'. (undefined)
(UnusedFormalParameter)
328-328: Avoid unused local variables such as '$list_hover_color'. (undefined)
(UnusedLocalVariable)
330-330: Avoid unused local variables such as '$smooth_scroll'. (undefined)
(UnusedLocalVariable)
assets/build/blocks/AdvanceContributors/render.php
10-10: Avoid unused parameters such as '$content'. (undefined)
(UnusedFormalParameter)
10-10: Avoid unused parameters such as '$block'. (undefined)
(UnusedFormalParameter)
assets/build/blocks/DocsGrid/render.php
183-183: Avoid unused local variables such as '$total_pages'. (undefined)
(UnusedLocalVariable)
228-228: Avoid unused local variables such as '$total_articles'. (undefined)
(UnusedLocalVariable)
🔇 Additional comments (19)
assets/build/print-rtl.css (3)
52-52: LGTM: RTL-specific properties are correctly implemented.The RTL adaptations are properly applied:
- Line 52:
float: rightfor definition term positioning- Line 72: Margin adjusted for RTL text flow
- Line 84:
border-rightinstead ofborder-leftfor callout styling- Line 165:
text-align: rightfor table cellsAlso applies to: 72-72, 84-84, 165-165
144-147: LGTM: Standard print stylesheet pattern for displaying URLs.The CSS correctly displays link URLs after anchor text when printing, which is a best practice for print stylesheets. The exclusion of
.anchorjs-linkprevents anchor navigation links from cluttering the printed output.
1-184: Verify whether build artifacts should be committed.This file is also a generated build artifact. As with
assets/build/print.js, consider whether build artifacts should be committed to the repository.Please verify:
- Are CSS build artifacts intentionally committed in this repository?
- Is there a
.gitignorerule that should excludeassets/build/?The same verification script from the
print.jsreview can help check the repository's build artifact strategy.assets/build/block.asset.php (1)
1-1: Dependency updates align with modern WordPress/React patterns.The replacement of
'react'with'react-jsx-runtime'reflects the modern JSX transform introduced in React 17+. The additions of'wp-core-data'and'wp-data'indicate integration with WordPress data stores, which is appropriate for dynamic block functionality.However, this file is a generated build artifact. Verify whether build artifacts should be committed to the repository.
assets/build/blocks/dynamic-table-of-contents/src/index.asset.php (1)
1-1: Build artifact - dependencies are appropriate for a Gutenberg block.This PHP asset manifest contains standard WordPress Gutenberg block dependencies. However, as a generated build artifact, verify whether it should be committed to version control.
assets/build/style-block.css (2)
53-54: Vendor prefix fallback is correct, not a duplicate.The static analysis tool flagged lines 53-54 as duplicate properties, but this is a vendor prefix fallback pattern:
- Line 53:
width: -moz-fit-content;(Firefox-specific)- Line 54:
width: fit-content;(standard property)This is the correct way to handle vendor prefixes - older browsers use the prefixed version, modern browsers use the standard property. This is intentional and not an error.
1-139: Build artifact should be verified for version control inclusion.This is a generated CSS bundle. Verify whether build artifacts should be committed to the repository.
assets/build/frontend.js (1)
1-28: Standard webpack build artifact.This is generated webpack runtime/bootstrap code. Verify whether build artifacts should be committed to version control.
assets/build/blocks/TableOfContents/index-rtl.css (1)
1-20: RTL styles are appropriate, but verify build artifact inclusion.The RTL-specific styles for the Table of Contents block look correct:
- Mobile notice with proper RTL border positioning (border-right instead of border-left)
- Appropriate hover states for links
However, this is a generated build artifact. Verify whether it should be committed to version control.
assets/build/style-block-rtl.css (3)
53-54: Vendor prefix fallback is correct, not a duplicate.Similar to the LTR version, the static analysis tool flagged lines 53-54 as duplicate properties, but this is an intentional vendor prefix fallback pattern for browser compatibility.
47-62: RTL layout adjustments are correct.The RTL-specific changes properly flip the layout:
- Line 47:
left: 0(instead ofright: 0in LTR) for search submit button- Line 62:
margin-right: auto(instead ofmargin-left: autoin LTR)These are appropriate RTL adaptations.
1-137: Build artifact should be verified for version control inclusion.This is a generated RTL CSS bundle. Verify whether build artifacts should be committed to the repository.
assets/build/blocks/Contributors/index.asset.php (1)
1-1: LGTM!The asset manifest correctly declares WordPress dependencies (
wp-blocks,wp-element,wp-block-editor, etc.) needed for a Gutenberg block, along with a version hash for cache busting.assets/build/blocks/Contributors/style-index-rtl.css (1)
1-137: LGTM! Well-structured RTL styles with excellent accessibility support.The RTL stylesheet correctly handles directionality for flex layouts and includes comprehensive accessibility features:
- High contrast mode support (lines 105-112)
- Reduced motion preferences (lines 113-123)
- Dark mode support (lines 124-128)
- Print optimizations (lines 129-137)
- Responsive breakpoints for mobile/tablet
assets/build/blocks/TableOfContents/block.json (1)
1-159: LGTM! Well-structured block manifest.The block configuration is comprehensive and well-organized:
- Clear attribute definitions with appropriate types and defaults
- Good use of server-side rendering via
render.php- Proper asset declarations for editor and frontend
- Supports essential block features (anchor, color controls)
assets/build/blocks/DocsGrid/style-index-rtl.css (1)
213-215: Good RTL support for directional indicators.The RTL-specific arrow direction (
content: "←") for the details link is a good practice for RTL layouts, ensuring visual indicators remain intuitive for right-to-left readers.src/blocks/AdvanceContributors/style.scss (1)
122-148: Excellent accessibility support!The implementation of accessibility features is commendable:
- High contrast mode support (lines 123-133)
- Reduced motion support (lines 136-148)
- Dark mode support (lines 151-157)
- Print styles (lines 160-171)
The use of
!importantin reduced-motion contexts (lines 138, 141, 146) is appropriate as these are accessibility overrides that should take precedence.assets/build/blocks/TableOfContents/index.asset.php (1)
1-1: Standard WordPress asset manifest format.This file follows the standard WordPress asset manifest format used by
@wordpress/dependency-extraction-webpack-plugin. The dependencies and version hash are automatically generated during the build process.Note: As a build artifact, this file would typically be gitignored and generated during deployment (see earlier comment about build artifacts).
assets/build/blocks/AdvanceContributors/block.json (1)
17-331: Well-structured and comprehensive attribute definitions.The block manifest demonstrates excellent organization:
- Consistent per-device attribute structure (desktop/tablet/mobile)
- Appropriate use of enums for validation (
contributorDisplayMode,avatarType,avatarShape,linkBehavior)- Sensible default values
- Clear attribute types
| /*!***************************************************************************************************************************************************************************************************************************************************************!*\ | ||
| !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/blocks/TableOfContents/editor.scss ***! | ||
| \***************************************************************************************************************************************************************************************************************************************************************/ | ||
| /** | ||
| * The following styles get applied inside the editor only. | ||
| */ | ||
| .wp-block-wedocs-table-of-contents .toc-mobile-notice { | ||
| background-color: rgba(0, 115, 170, 0.1); | ||
| padding: 5px 10px; | ||
| border-radius: 3px; | ||
| border-left: 3px solid #0073aa; | ||
| color: #0073aa; | ||
| font-size: 12px; | ||
| } | ||
| .wp-block-wedocs-table-of-contents .toc-content .toc-list li a { | ||
| cursor: default; | ||
| } | ||
| .wp-block-wedocs-table-of-contents .toc-content .toc-list li a:hover { | ||
| color: #0073aa; | ||
| } | ||
|
|
||
| /*# sourceMappingURL=block.css.map*/ No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove duplicate CSS file.
This file appears to be a duplicate of assets/build/blocks/TableOfContents/index.css. Both files contain identical editor-only styles for the Table of Contents block. Having duplicate stylesheets increases bundle size and maintenance overhead.
Consider removing one of these files and updating the build configuration to reference a single source of truth for the Table of Contents editor styles.
🤖 Prompt for AI Agents
In assets/build/block.css around lines 1 to 22, this file duplicates the
editor-only Table of Contents styles already present in
assets/build/blocks/TableOfContents/index.css; remove the redundant file and
update build/config references to point to the single canonical stylesheet
(prefer the blocks/TableOfContents source), remove any import or entry that
emits assets/build/block.css from the build pipeline, and ensure source maps and
any registrations (enqueue/block registration) now reference the remaining CSS
so the editor still receives the styles.
| { | ||
| "$schema": "https://schemas.wp.org/trunk/block.json", | ||
| "apiVersion": 3, | ||
| "name": "wedocs/contributors", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Critical: Potential block name collision.
The block name is wedocs/contributors (line 4), which may conflict with another Contributors block mentioned in the AI summary (assets/build/blocks/Contributors/block.json). Each block must have a unique name in WordPress.
Verify whether there's a naming conflict:
If both blocks are intended to be separate, one should be renamed (e.g., wedocs/advance-contributors vs wedocs/contributors).
🏁 Script executed:
#!/bin/bash
echo "=== Searching for block registrations with 'wedocs/contributors' ==="
rg -n "wedocs/contributors" --type=json --type=js --type=php
echo -e "\n=== Listing all block.json files and their names ==="
fd -e json block.json -x sh -c 'echo "File: {}"; jq -r ".name" {}'
echo -e "\n=== Checking for duplicate block names ==="
fd -e json block.json -x jq -r ".name" {} | sort | uniq -dLength of output: 15571
Rename AdvanceContributors block name: Change the block name in src/blocks/AdvanceContributors/block.json and assets/build/blocks/AdvanceContributors/block.json from wedocs/contributors to wedocs/advance-contributors to avoid collision with the existing Contributors block.
🤖 Prompt for AI Agents
In assets/build/blocks/AdvanceContributors/block.json around line 4 (and
likewise update src/blocks/AdvanceContributors/block.json), the block "name" is
currently "wedocs/contributors" which collides with the existing Contributors
block; change the "name" value to "wedocs/advance-contributors" in both JSON
files, ensure the JSON remains valid (commas/quotes intact), and verify any
references/imports/registration code use the new slug so the build and block
registration remain consistent.
| return $output; | ||
| } | ||
| render_wedocs_advance_contributors_block( $attributes, $content, $block ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return the rendered markup (built asset)
The compiled render file needs the same return render_wedocs_advance_contributors_block(...) change as the source; otherwise the block still outputs 1. Please regenerate the build after fixing the source.
🤖 Prompt for AI Agents
In assets/build/blocks/AdvanceContributors/render.php around lines 497-499 the
compiled file calls render_wedocs_advance_contributors_block($attributes,
$content, $block); without returning it, so the block outputs `1`; change that
call to return render_wedocs_advance_contributors_block($attributes, $content,
$block); to return the rendered markup and then regenerate the build from source
so the compiled asset matches the source change.
| /*!******************************************************************************************************************************************************************************************************************************************************************!*\ | ||
| !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/blocks/AdvanceContributors/style.scss ***! | ||
| \******************************************************************************************************************************************************************************************************************************************************************/ | ||
| /** | ||
| * Frontend styles for the Contributors block | ||
| */ | ||
| .contributors-tab-system .components-button-group { | ||
| display: flex; | ||
| } | ||
|
|
||
| .wedocs-contributors .contributors-container { | ||
| display: flex; | ||
| align-items: center; | ||
| flex-wrap: wrap; | ||
| gap: 10px; | ||
| margin-bottom: 10px; | ||
| } | ||
| @media (max-width: 768px) { | ||
| .wedocs-contributors .contributors-container { | ||
| flex-direction: column; | ||
| align-items: flex-start; | ||
| gap: 8px; | ||
| } | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 8px; | ||
| } | ||
| @media (max-width: 768px) { | ||
| .wedocs-contributors .contributors-container .contributor-item { | ||
| width: 100%; | ||
| } | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item .contributor-avatar { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| transition: all 0.3s ease; | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item .contributor-avatar.avatar-hover:hover { | ||
| transform: scale(1.1); | ||
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item .contributor-avatar img { | ||
| display: block; | ||
| -o-object-fit: cover; | ||
| object-fit: cover; | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item .contributor-avatar .default-icon { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| background-color: #0073aa; | ||
| color: white; | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item .contributor-avatar .default-icon svg { | ||
| width: 60%; | ||
| height: 60%; | ||
| fill: currentColor; | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item .contributor-name { | ||
| transition: color 0.3s ease; | ||
| text-decoration: none; | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item .contributor-name:hover { | ||
| text-decoration: underline; | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item .contributor-name.no-link { | ||
| cursor: default; | ||
| } | ||
| .wedocs-contributors .last-updated { | ||
| margin-top: 10px; | ||
| font-style: italic; | ||
| } | ||
| @media (max-width: 768px) { | ||
| .wedocs-contributors .last-updated { | ||
| margin-top: 8px; | ||
| font-size: 0.9em; | ||
| } | ||
| } | ||
| .wedocs-contributors .contributors-title { | ||
| margin: 0 0 10px 0; | ||
| font-weight: 600; | ||
| font-size: 16px; | ||
| } | ||
| @media (max-width: 480px) { | ||
| .wedocs-contributors .contributors-container { | ||
| gap: 6px; | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item { | ||
| gap: 6px; | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item .contributor-avatar img, .wedocs-contributors .contributors-container .contributor-item .contributor-avatar .default-icon { | ||
| width: 28px !important; | ||
| height: 28px !important; | ||
| } | ||
| .wedocs-contributors .contributors-container .contributor-item .contributor-name { | ||
| font-size: 0.9em; | ||
| } | ||
| .wedocs-contributors .last-updated { | ||
| font-size: 0.8em; | ||
| } | ||
| } | ||
| @media (prefers-contrast: high) { | ||
| .wedocs-contributors .contributor-item .contributor-avatar { | ||
| border: 2px solid currentColor !important; | ||
| } | ||
| .wedocs-contributors .contributor-item .contributor-name { | ||
| text-decoration: underline; | ||
| } | ||
| } | ||
| @media (prefers-reduced-motion: reduce) { | ||
| .wedocs-contributors .contributor-avatar { | ||
| transition: none !important; | ||
| } | ||
| .wedocs-contributors .contributor-avatar.avatar-hover:hover { | ||
| transform: none !important; | ||
| } | ||
| .wedocs-contributors .contributor-name { | ||
| transition: none !important; | ||
| } | ||
| } | ||
| @media (prefers-color-scheme: dark) { | ||
| .wedocs-contributors .contributor-item .contributor-avatar .default-icon { | ||
| background-color: #4a90a4; | ||
| } | ||
| } | ||
| @media print { | ||
| .wedocs-contributors .contributors-container { | ||
| flex-direction: column; | ||
| align-items: flex-start; | ||
| } | ||
| .wedocs-contributors .contributor-item .contributor-avatar { | ||
| display: none; | ||
| } | ||
| } | ||
|
|
||
| /*# sourceMappingURL=style-index.css.map*/ No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify if build artifacts should be committed to the repository.
This file appears to be a compiled build artifact (based on the webpack loader comment at lines 1-3 and the source map reference at line 139). Build artifacts are typically excluded from version control via .gitignore and generated during deployment.
Additionally, this file is identical to assets/build/blocks/Contributors/style-index.css, suggesting code duplication between the Contributors and AdvanceContributors blocks.
Run the following script to verify:
- Whether build directories are gitignored
- The extent of duplication between these two blocks
🏁 Script executed:
#!/bin/bash
# Check if build directories are gitignored
echo "=== Checking .gitignore for build artifacts ==="
if [ -f .gitignore ]; then
grep -E "(assets/build|/build/|\.map)" .gitignore || echo "No build artifact patterns found in .gitignore"
else
echo ".gitignore not found"
fi
echo -e "\n=== Comparing AdvanceContributors and Contributors CSS files ==="
if [ -f "assets/build/blocks/Contributors/style-index.css" ] && [ -f "assets/build/blocks/AdvanceContributors/style-index.css" ]; then
diff assets/build/blocks/Contributors/style-index.css assets/build/blocks/AdvanceContributors/style-index.css
if [ $? -eq 0 ]; then
echo "Files are identical - duplication confirmed"
else
echo "Files differ"
fi
else
echo "One or both files not found"
fi
echo -e "\n=== Checking for other duplicate style files ==="
fd -e css -e scss style-index assets/build/blocks/ -x md5sum {} \; | sort | uniq -w32 -DLength of output: 1808
Exclude compiled CSS and consolidate duplicated styles
- Add
assets/build/blocks/**/style-index.cssand.css.mapto.gitignore, remove these committed build artifacts - Extract common SCSS into a shared partial and import it in both
AdvanceContributorsandContributorsblocks instead of duplicating the output
🤖 Prompt for AI Agents
assets/build/blocks/AdvanceContributors/style-index.css lines 1-139: The review
requests removing committed compiled CSS artifacts and eliminating duplicated
styles; to fix, add assets/build/blocks/**/style-index.css and their .css.map
files to .gitignore, remove the tracked compiled files from the repo (git rm
--cached or delete and commit), and regenerate the build so they’re not
re-added; next, refactor the duplicated output by extracting the shared rules
into a new SCSS partial (e.g., _contributors-common.scss), import that partial
into the AdvanceContributors and Contributors block SCSS entry files, remove
duplicated SCSS from each block, rebuild to verify the compiled output still
contains necessary styles, and commit only the source SCSS and updated
.gitignore.
| const Edit = ({ | ||
| attributes, | ||
| setAttributes | ||
| }) => { | ||
| const blockProps = (0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_3__.useBlockProps)(); | ||
| const { | ||
| useSelect | ||
| } = wp.data; | ||
| const [currentPage, setCurrentPage] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_2__.useState)(1); | ||
| const [loading, setLoading] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_2__.useState)(false); | ||
| const { | ||
| hideDocGrid, | ||
| docStyle, | ||
| docsPerPage, | ||
| excludeDocs, | ||
| order, | ||
| orderBy, | ||
| sectionsPerDoc, | ||
| articlesPerSection, | ||
| showDocArticle, | ||
| keepArticlesCollapsed, | ||
| showViewDetails, | ||
| gridPadding, | ||
| gridMargin, | ||
| docTitleColor, | ||
| docChildrenActiveColor, | ||
| borderType, | ||
| borderRadius, | ||
| borderWidth, | ||
| borderColor, | ||
| buttonBorderRadius, | ||
| buttonPadding, | ||
| buttonMargin, | ||
| buttonColor, | ||
| buttonHoverColor, | ||
| buttonTextColor, | ||
| buttonText, | ||
| buttonHoverTextColor | ||
| } = attributes; | ||
| const applyStyles = () => { | ||
| const paddings = gridPadding ? `${gridPadding.top} ${gridPadding.right} ${gridPadding.bottom} ${gridPadding.left}` : ''; | ||
| const margins = gridMargin ? `${gridMargin.top} ${gridMargin.right} ${gridMargin.bottom} ${gridMargin.left}` : ''; | ||
| const btnPaddings = buttonPadding ? `${buttonPadding.top} ${buttonPadding.right} ${buttonPadding.bottom} ${buttonPadding.left}` : ''; | ||
| const btnradius = buttonBorderRadius || '8px'; | ||
| const btnMargins = buttonMargin ? `${buttonMargin.top} ${buttonMargin.right} ${buttonMargin.bottom} ${buttonMargin.left}` : ''; | ||
| return { | ||
| item: { | ||
| padding: paddings, | ||
| margin: margins, | ||
| borderStyle: borderType || 'solid', | ||
| borderWidth: borderWidth || '1px', | ||
| borderColor: borderColor || 'rgba(0, 0, 0, 0.1)', | ||
| borderRadius: borderRadius || '8px', | ||
| backgroundColor: '#fff' | ||
| }, | ||
| title: { | ||
| color: docTitleColor || '#1e1e1e' | ||
| }, | ||
| children: { | ||
| color: docChildrenActiveColor || '#0073aa' | ||
| }, | ||
| button: { | ||
| padding: btnPaddings, | ||
| margin: btnMargins, | ||
| backgroundColor: buttonColor || '#0073aa', | ||
| color: buttonTextColor || '#ffffff', | ||
| text: buttonText || (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('View Details', 'wedocs'), | ||
| borderRadius: btnradius || '8px', | ||
| '--hover-bg': buttonHoverColor || '#005177', | ||
| '--hover-color': buttonHoverTextColor || '#ffffff' | ||
| } | ||
| }; | ||
| }; | ||
| const renderGridItem = (doc, styles) => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", { | ||
| className: "wedocs-docs-grid__item", | ||
| style: styles.item, | ||
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("h3", { | ||
| className: "wedocs-docs-grid__title", | ||
| style: styles.title, | ||
| children: doc.title.rendered | ||
| }), renderSections(doc, styles), showViewDetails && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { | ||
| className: "wedocs-docs-grid__details", | ||
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("span", { | ||
| className: "wedocs-docs-grid__details-link", | ||
| style: styles.button, | ||
| children: styles.button.text | ||
| }) | ||
| })] | ||
| }, doc.id); | ||
| const renderSections = (doc, styles) => { | ||
| if (!doc.sections) return null; | ||
| return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", { | ||
| className: `wedocs-docs-grid__sections ${keepArticlesCollapsed ? 'is-collapsed' : ''}`, | ||
| children: [doc.sections.map(section => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", { | ||
| className: "wedocs-docs-grid__section", | ||
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("h4", { | ||
| className: "wedocs-docs-grid__section-title", | ||
| style: { | ||
| ...styles.title, | ||
| display: 'flex', | ||
| justifyContent: 'space-between', | ||
| alignItems: 'center' | ||
| }, | ||
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("span", { | ||
| children: section.title.rendered | ||
| }), showDocArticle && section.articles && section.articles.length > 0 && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("svg", { | ||
| fill: "none", | ||
| viewBox: "0 0 24 24", | ||
| width: "16", | ||
| strokeWidth: "2", | ||
| stroke: "#acb8c4", | ||
| className: keepArticlesCollapsed ? '' : 'active', | ||
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("path", { | ||
| strokeLinecap: "round", | ||
| strokeLinejoin: "round", | ||
| d: "M19.5 8.25l-7.5 7.5-7.5-7.5" | ||
| }) | ||
| })] | ||
| }), showDocArticle && !keepArticlesCollapsed && section.articles && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("ul", { | ||
| className: "wedocs-docs-grid__articles", | ||
| children: section.articles.map(article => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("li", { | ||
| className: "wedocs-docs-grid__article", | ||
| style: styles.children, | ||
| children: article.title.rendered | ||
| }, article.id)) | ||
| })] | ||
| }, section.id)), doc.sections.length === 0 && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("span", { | ||
| className: "inside", | ||
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("svg", { | ||
| fill: "none", | ||
| viewBox: "0 0 24 24", | ||
| "stroke-width": "1.5", | ||
| stroke: "currentColor", | ||
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("path", { | ||
| "stroke-linecap": "round", | ||
| "stroke-linejoin": "round", | ||
| d: "M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" | ||
| }) | ||
| }), (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('This document has no sections yet. Check back later or wait for the author to add content.', 'wedocs')] | ||
| })] | ||
| }); | ||
| }; | ||
|
|
||
| // Control options | ||
| const docStyles = [{ | ||
| label: '1x1', | ||
| value: '1x1' | ||
| }, { | ||
| label: '1x2', | ||
| value: '1x2' | ||
| }]; | ||
| const docsPerPageOptions = [{ | ||
| label: 'All', | ||
| value: 'all' | ||
| }, ...Array.from({ | ||
| length: 10 | ||
| }, (_, i) => ({ | ||
| label: String(i + 1), | ||
| value: String(i + 1) | ||
| }))]; | ||
| const orderByOptions = [{ | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('weDocs Order', 'wedocs'), | ||
| value: 'menu_order' | ||
| }, { | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('ID', 'wedocs'), | ||
| value: 'id' | ||
| }, { | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Name', 'wedocs'), | ||
| value: 'title' | ||
| }]; | ||
| const orderOptions = [{ | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Ascending', 'wedocs'), | ||
| value: 'asc' | ||
| }, { | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Descending', 'wedocs'), | ||
| value: 'desc' | ||
| }]; | ||
| const countOptions = [{ | ||
| label: 'All', | ||
| value: 'all' | ||
| }, ...Array.from({ | ||
| length: 10 | ||
| }, (_, i) => ({ | ||
| label: String(i + 1), | ||
| value: String(i + 1) | ||
| }))]; | ||
| // Get published docs | ||
| const { | ||
| pages, | ||
| sections, | ||
| articles | ||
| } = useSelect(select => { | ||
| const { | ||
| getEntityRecords | ||
| } = select('core'); | ||
| const docs = getEntityRecords('postType', 'docs', { | ||
| status: 'publish', | ||
| per_page: -1, | ||
| parent: 0, | ||
| orderby: orderBy, | ||
| order: order | ||
| }); | ||
|
|
||
| // Get all sections (docs children) | ||
| const allSections = docs ? getEntityRecords('postType', 'docs', { | ||
| status: 'publish', | ||
| parent_in: docs.map(doc => doc.id), | ||
| per_page: -1 | ||
| }) : null; | ||
|
|
||
| // Get all articles (sections children) | ||
| const allArticles = allSections ? getEntityRecords('postType', 'docs', { | ||
| status: 'publish', | ||
| parent_in: allSections.map(section => section.id), | ||
| per_page: -1 | ||
| }) : null; | ||
| return { | ||
| pages: docs, | ||
| sections: allSections, | ||
| articles: allArticles | ||
| }; | ||
| }, [orderBy, order]); | ||
| const processDocsData = () => { | ||
| if (!pages || !sections || !articles) return []; | ||
|
|
||
| // Filter and sort docs based on settings | ||
| let processedDocs = [...pages]; | ||
|
|
||
| // Apply exclude filter | ||
| if (excludeDocs && excludeDocs.length > 0) { | ||
| processedDocs = processedDocs.filter(doc => !excludeDocs.includes(doc.id.toString())); | ||
| } | ||
|
|
||
| // Process each doc with its sections and articles | ||
| processedDocs = processedDocs.map(doc => { | ||
| // Get sections for this doc | ||
| let docSections = sections.filter(section => section.parent === doc.id); | ||
|
|
||
| // Limit sections if specified | ||
| if (sectionsPerDoc !== 'all') { | ||
| docSections = docSections.slice(0, parseInt(sectionsPerDoc)); | ||
| } | ||
|
|
||
| // Process sections with their articles | ||
| docSections = docSections.map(section => { | ||
| let sectionArticles = articles.filter(article => article.parent === section.id); | ||
|
|
||
| // Limit articles if specified | ||
| if (articlesPerSection !== 'all') { | ||
| sectionArticles = sectionArticles.slice(0, parseInt(articlesPerSection)); | ||
| } | ||
| return { | ||
| ...section, | ||
| articles: sectionArticles | ||
| }; | ||
| }); | ||
|
|
||
| // Calculate total articles for the doc | ||
| const totalArticles = docSections.reduce((total, section) => total + section.articles.length, 0); | ||
| return { | ||
| ...doc, | ||
| sections: docSections, | ||
| articleCount: totalArticles | ||
| }; | ||
| }); | ||
| return processedDocs; | ||
| }; | ||
| // Handle pagination | ||
| const getPagedDocs = docs => { | ||
| if (docsPerPage === 'all') return docs; | ||
| const perPage = parseInt(docsPerPage); | ||
| const start = (currentPage - 1) * perPage; | ||
| const end = start + perPage; | ||
| return docs.slice(start, end); | ||
| }; | ||
|
|
||
| // Get final display docs | ||
| const getDisplayDocs = () => { | ||
| const processedDocs = processDocsData(); | ||
| return getPagedDocs(processedDocs); | ||
| }; | ||
|
|
||
| // Pagination controls | ||
| const renderPagination = totalDocs => { | ||
| if (docsPerPage === 'all') return null; | ||
| const totalPages = Math.ceil(totalDocs.length / parseInt(docsPerPage)); | ||
|
|
||
| // Create style objects for pagination buttons | ||
| const paginationBaseStyle = { | ||
| padding: '8px 12px', | ||
| margin: '0 4px', | ||
| backgroundColor: attributes.paginationBackgroundColor || '#fff', | ||
| color: attributes.paginationTextColor || '#333', | ||
| border: `1px solid ${attributes.paginationBorderColor || '#ddd'}`, | ||
| borderRadius: attributes.borderRadius || '4px', | ||
| cursor: 'pointer', | ||
| transition: 'all 0.2s ease', | ||
| textDecoration: 'none', | ||
| display: 'inline-block', | ||
| minWidth: '32px', | ||
| textAlign: 'center', | ||
| fontFamily: 'inherit', | ||
| fontSize: '14px', | ||
| lineHeight: '1.4' | ||
| }; | ||
|
|
||
| // Active button style | ||
| const activeStyle = { | ||
| ...paginationBaseStyle, | ||
| backgroundColor: attributes.paginationHoverColor || '#f5f5f5', | ||
| borderColor: attributes.paginationHoverColor || '#ccc', | ||
| color: attributes.paginationTextHoverColor || '#0073aa' | ||
| }; | ||
|
|
||
| // Hover styles will be handled by CSS custom properties | ||
| const customProperties = { | ||
| '--pagination-hover-bg': attributes.paginationHoverColor || '#f5f5f5', | ||
| '--pagination-hover-color': attributes.paginationTextHoverColor || '#0073aa', | ||
| '--pagination-hover-border': attributes.paginationHoverColor || '#ccc' | ||
| }; | ||
| return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", { | ||
| className: "wedocs-docs-pagination", | ||
| style: { | ||
| margin: '30px 0', | ||
| textAlign: 'center', | ||
| ...customProperties | ||
| }, | ||
| children: [currentPage > 1 && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("button", { | ||
| style: paginationBaseStyle, | ||
| onClick: () => setCurrentPage(currentPage - 1), | ||
| className: "wedocs-docs-pagination__button", | ||
| children: "\u2190" | ||
| }), Array.from({ | ||
| length: totalPages | ||
| }, (_, i) => { | ||
| const pageNum = i + 1; | ||
| const isCurrentPage = currentPage === pageNum; | ||
| return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("button", { | ||
| style: isCurrentPage ? activeStyle : paginationBaseStyle, | ||
| className: `wedocs-docs-pagination__button ${isCurrentPage ? 'is-active' : ''}`, | ||
| onClick: () => setCurrentPage(pageNum), | ||
| children: pageNum | ||
| }, pageNum); | ||
| }), currentPage < totalPages && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("button", { | ||
| style: paginationBaseStyle, | ||
| onClick: () => setCurrentPage(currentPage + 1), | ||
| className: "wedocs-docs-pagination__button", | ||
| children: "\u2192" | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("style", { | ||
| children: ` | ||
| .wedocs-docs-pagination__button:hover:not(.is-active) { | ||
| background-color: var(--pagination-hover-bg) !important; | ||
| color: var(--pagination-hover-color) !important; | ||
| border-color: var(--pagination-hover-border) !important; | ||
| } | ||
| ` | ||
| })] | ||
| }); | ||
| }; | ||
| const displayDocs = getDisplayDocs(); | ||
| // Create a mapping of ID to title for suggestions | ||
| const docsMap = pages ? pages.reduce((acc, page) => { | ||
| acc[page.id] = page.title.rendered; | ||
| return acc; | ||
| }, {}) : {}; | ||
|
|
||
| // Prepare docs options for FormTokenField | ||
| const docsOptions = pages ? pages.map(page => ({ | ||
| value: page.id.toString(), | ||
| label: page.title.rendered | ||
| })) : []; | ||
|
|
||
| // Update handlers | ||
| const updateAttribute = attributeName => value => { | ||
| setAttributes({ | ||
| [attributeName]: value | ||
| }); | ||
| }; | ||
|
|
||
| // Transform IDs to titles for FormTokenField display | ||
| const excludeDocsDisplay = excludeDocs ? excludeDocs.map(id => docsMap[id] || id) : []; | ||
|
|
||
| // Handle token changes | ||
| const handleExcludeDocsChange = tokens => { | ||
| // Convert titles back to IDs | ||
| const newExcludeDocs = tokens.map(token => { | ||
| // Find the ID for this title | ||
| const found = Object.entries(docsMap).find(([id, title]) => title === token); | ||
| return found ? found[0] : token; | ||
| }); | ||
| setAttributes({ | ||
| excludeDocs: newExcludeDocs | ||
| }); | ||
| }; | ||
| const getGridClass = () => { | ||
| return `wedocs-docs-grid--${docStyle}`; | ||
| }; | ||
| return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__.Fragment, { | ||
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_3__.InspectorControls, { | ||
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.PanelBody, { | ||
| title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Doc Grid Settings', 'wedocs'), | ||
| icon: _wordpress_icons__WEBPACK_IMPORTED_MODULE_1__["default"], | ||
| initialOpen: false, | ||
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | ||
| value: docStyle, | ||
| options: docStyles, | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('DOCS GRID COLUMN STYLE', 'wedocs'), | ||
| onChange: updateAttribute('docStyle') | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | ||
| value: docsPerPage, | ||
| options: docsPerPageOptions, | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Docs per page', 'wedocs'), | ||
| onChange: updateAttribute('docsPerPage') | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.FormTokenField, { | ||
| value: excludeDocsDisplay, | ||
| suggestions: Object.values(docsMap), | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Exclude Docs', 'wedocs'), | ||
| onChange: handleExcludeDocsChange | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | ||
| value: order, | ||
| options: orderOptions, | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Order', 'wedocs'), | ||
| onChange: updateAttribute('order') | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | ||
| value: orderBy, | ||
| options: orderByOptions, | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Order by', 'wedocs'), | ||
| onChange: updateAttribute('orderBy') | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | ||
| value: sectionsPerDoc, | ||
| options: countOptions, | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Sections per doc', 'wedocs'), | ||
| onChange: updateAttribute('sectionsPerDoc') | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | ||
| value: articlesPerSection, | ||
| options: countOptions, | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Articles per section', 'wedocs'), | ||
| onChange: updateAttribute('articlesPerSection') | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.PanelRow, { | ||
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.ToggleControl, { | ||
| checked: showDocArticle, | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Show Doc Article', 'wedocs'), | ||
| onChange: updateAttribute('showDocArticle') | ||
| }) | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.PanelRow, { | ||
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.ToggleControl, { | ||
| checked: keepArticlesCollapsed, | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Keep Article Collapsed', 'wedocs'), | ||
| onChange: updateAttribute('keepArticlesCollapsed') | ||
| }) | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.PanelRow, { | ||
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.ToggleControl, { | ||
| checked: showViewDetails, | ||
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Show View Details Button', 'wedocs'), | ||
| onChange: updateAttribute('showViewDetails') | ||
| }) | ||
| })] | ||
| }) | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_3__.InspectorControls, { | ||
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_StyleControls__WEBPACK_IMPORTED_MODULE_5__["default"], { | ||
| attributes: attributes, | ||
| setAttributes: setAttributes | ||
| }) | ||
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { | ||
| ...blockProps, | ||
| children: hideDocGrid ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { | ||
| className: "backdrop" | ||
| }) : /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { | ||
| className: "wedocs-block-wrapper", | ||
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { | ||
| className: `wedocs-docs-grid ${getGridClass()}`, | ||
| children: loading ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(Spinner, {}) : displayDocs.map(doc => renderGridItem(doc, applyStyles())) | ||
| }) | ||
| }) | ||
| })] | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import Spinner before using it
renderGridItem renders <Spinner/>, but the component is never imported, so the editor throws ReferenceError: Spinner is not defined. Import it from @wordpress/components along with the other controls:
-import { PanelBody, SelectControl, FormTokenField, PanelRow, ToggleControl, TextControl } from '@wordpress/components';
+import {
+ PanelBody,
+ SelectControl,
+ FormTokenField,
+ PanelRow,
+ ToggleControl,
+ TextControl,
+ Spinner,
+} from '@wordpress/components';(or reference wp.components.Spinner). Without this, the Docs Grid block breaks whenever it enters the loading state.
📝 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.
| const Edit = ({ | |
| attributes, | |
| setAttributes | |
| }) => { | |
| const blockProps = (0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_3__.useBlockProps)(); | |
| const { | |
| useSelect | |
| } = wp.data; | |
| const [currentPage, setCurrentPage] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_2__.useState)(1); | |
| const [loading, setLoading] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_2__.useState)(false); | |
| const { | |
| hideDocGrid, | |
| docStyle, | |
| docsPerPage, | |
| excludeDocs, | |
| order, | |
| orderBy, | |
| sectionsPerDoc, | |
| articlesPerSection, | |
| showDocArticle, | |
| keepArticlesCollapsed, | |
| showViewDetails, | |
| gridPadding, | |
| gridMargin, | |
| docTitleColor, | |
| docChildrenActiveColor, | |
| borderType, | |
| borderRadius, | |
| borderWidth, | |
| borderColor, | |
| buttonBorderRadius, | |
| buttonPadding, | |
| buttonMargin, | |
| buttonColor, | |
| buttonHoverColor, | |
| buttonTextColor, | |
| buttonText, | |
| buttonHoverTextColor | |
| } = attributes; | |
| const applyStyles = () => { | |
| const paddings = gridPadding ? `${gridPadding.top} ${gridPadding.right} ${gridPadding.bottom} ${gridPadding.left}` : ''; | |
| const margins = gridMargin ? `${gridMargin.top} ${gridMargin.right} ${gridMargin.bottom} ${gridMargin.left}` : ''; | |
| const btnPaddings = buttonPadding ? `${buttonPadding.top} ${buttonPadding.right} ${buttonPadding.bottom} ${buttonPadding.left}` : ''; | |
| const btnradius = buttonBorderRadius || '8px'; | |
| const btnMargins = buttonMargin ? `${buttonMargin.top} ${buttonMargin.right} ${buttonMargin.bottom} ${buttonMargin.left}` : ''; | |
| return { | |
| item: { | |
| padding: paddings, | |
| margin: margins, | |
| borderStyle: borderType || 'solid', | |
| borderWidth: borderWidth || '1px', | |
| borderColor: borderColor || 'rgba(0, 0, 0, 0.1)', | |
| borderRadius: borderRadius || '8px', | |
| backgroundColor: '#fff' | |
| }, | |
| title: { | |
| color: docTitleColor || '#1e1e1e' | |
| }, | |
| children: { | |
| color: docChildrenActiveColor || '#0073aa' | |
| }, | |
| button: { | |
| padding: btnPaddings, | |
| margin: btnMargins, | |
| backgroundColor: buttonColor || '#0073aa', | |
| color: buttonTextColor || '#ffffff', | |
| text: buttonText || (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('View Details', 'wedocs'), | |
| borderRadius: btnradius || '8px', | |
| '--hover-bg': buttonHoverColor || '#005177', | |
| '--hover-color': buttonHoverTextColor || '#ffffff' | |
| } | |
| }; | |
| }; | |
| const renderGridItem = (doc, styles) => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", { | |
| className: "wedocs-docs-grid__item", | |
| style: styles.item, | |
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("h3", { | |
| className: "wedocs-docs-grid__title", | |
| style: styles.title, | |
| children: doc.title.rendered | |
| }), renderSections(doc, styles), showViewDetails && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { | |
| className: "wedocs-docs-grid__details", | |
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("span", { | |
| className: "wedocs-docs-grid__details-link", | |
| style: styles.button, | |
| children: styles.button.text | |
| }) | |
| })] | |
| }, doc.id); | |
| const renderSections = (doc, styles) => { | |
| if (!doc.sections) return null; | |
| return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", { | |
| className: `wedocs-docs-grid__sections ${keepArticlesCollapsed ? 'is-collapsed' : ''}`, | |
| children: [doc.sections.map(section => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", { | |
| className: "wedocs-docs-grid__section", | |
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("h4", { | |
| className: "wedocs-docs-grid__section-title", | |
| style: { | |
| ...styles.title, | |
| display: 'flex', | |
| justifyContent: 'space-between', | |
| alignItems: 'center' | |
| }, | |
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("span", { | |
| children: section.title.rendered | |
| }), showDocArticle && section.articles && section.articles.length > 0 && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("svg", { | |
| fill: "none", | |
| viewBox: "0 0 24 24", | |
| width: "16", | |
| strokeWidth: "2", | |
| stroke: "#acb8c4", | |
| className: keepArticlesCollapsed ? '' : 'active', | |
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("path", { | |
| strokeLinecap: "round", | |
| strokeLinejoin: "round", | |
| d: "M19.5 8.25l-7.5 7.5-7.5-7.5" | |
| }) | |
| })] | |
| }), showDocArticle && !keepArticlesCollapsed && section.articles && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("ul", { | |
| className: "wedocs-docs-grid__articles", | |
| children: section.articles.map(article => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("li", { | |
| className: "wedocs-docs-grid__article", | |
| style: styles.children, | |
| children: article.title.rendered | |
| }, article.id)) | |
| })] | |
| }, section.id)), doc.sections.length === 0 && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("span", { | |
| className: "inside", | |
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("svg", { | |
| fill: "none", | |
| viewBox: "0 0 24 24", | |
| "stroke-width": "1.5", | |
| stroke: "currentColor", | |
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("path", { | |
| "stroke-linecap": "round", | |
| "stroke-linejoin": "round", | |
| d: "M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" | |
| }) | |
| }), (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('This document has no sections yet. Check back later or wait for the author to add content.', 'wedocs')] | |
| })] | |
| }); | |
| }; | |
| // Control options | |
| const docStyles = [{ | |
| label: '1x1', | |
| value: '1x1' | |
| }, { | |
| label: '1x2', | |
| value: '1x2' | |
| }]; | |
| const docsPerPageOptions = [{ | |
| label: 'All', | |
| value: 'all' | |
| }, ...Array.from({ | |
| length: 10 | |
| }, (_, i) => ({ | |
| label: String(i + 1), | |
| value: String(i + 1) | |
| }))]; | |
| const orderByOptions = [{ | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('weDocs Order', 'wedocs'), | |
| value: 'menu_order' | |
| }, { | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('ID', 'wedocs'), | |
| value: 'id' | |
| }, { | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Name', 'wedocs'), | |
| value: 'title' | |
| }]; | |
| const orderOptions = [{ | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Ascending', 'wedocs'), | |
| value: 'asc' | |
| }, { | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Descending', 'wedocs'), | |
| value: 'desc' | |
| }]; | |
| const countOptions = [{ | |
| label: 'All', | |
| value: 'all' | |
| }, ...Array.from({ | |
| length: 10 | |
| }, (_, i) => ({ | |
| label: String(i + 1), | |
| value: String(i + 1) | |
| }))]; | |
| // Get published docs | |
| const { | |
| pages, | |
| sections, | |
| articles | |
| } = useSelect(select => { | |
| const { | |
| getEntityRecords | |
| } = select('core'); | |
| const docs = getEntityRecords('postType', 'docs', { | |
| status: 'publish', | |
| per_page: -1, | |
| parent: 0, | |
| orderby: orderBy, | |
| order: order | |
| }); | |
| // Get all sections (docs children) | |
| const allSections = docs ? getEntityRecords('postType', 'docs', { | |
| status: 'publish', | |
| parent_in: docs.map(doc => doc.id), | |
| per_page: -1 | |
| }) : null; | |
| // Get all articles (sections children) | |
| const allArticles = allSections ? getEntityRecords('postType', 'docs', { | |
| status: 'publish', | |
| parent_in: allSections.map(section => section.id), | |
| per_page: -1 | |
| }) : null; | |
| return { | |
| pages: docs, | |
| sections: allSections, | |
| articles: allArticles | |
| }; | |
| }, [orderBy, order]); | |
| const processDocsData = () => { | |
| if (!pages || !sections || !articles) return []; | |
| // Filter and sort docs based on settings | |
| let processedDocs = [...pages]; | |
| // Apply exclude filter | |
| if (excludeDocs && excludeDocs.length > 0) { | |
| processedDocs = processedDocs.filter(doc => !excludeDocs.includes(doc.id.toString())); | |
| } | |
| // Process each doc with its sections and articles | |
| processedDocs = processedDocs.map(doc => { | |
| // Get sections for this doc | |
| let docSections = sections.filter(section => section.parent === doc.id); | |
| // Limit sections if specified | |
| if (sectionsPerDoc !== 'all') { | |
| docSections = docSections.slice(0, parseInt(sectionsPerDoc)); | |
| } | |
| // Process sections with their articles | |
| docSections = docSections.map(section => { | |
| let sectionArticles = articles.filter(article => article.parent === section.id); | |
| // Limit articles if specified | |
| if (articlesPerSection !== 'all') { | |
| sectionArticles = sectionArticles.slice(0, parseInt(articlesPerSection)); | |
| } | |
| return { | |
| ...section, | |
| articles: sectionArticles | |
| }; | |
| }); | |
| // Calculate total articles for the doc | |
| const totalArticles = docSections.reduce((total, section) => total + section.articles.length, 0); | |
| return { | |
| ...doc, | |
| sections: docSections, | |
| articleCount: totalArticles | |
| }; | |
| }); | |
| return processedDocs; | |
| }; | |
| // Handle pagination | |
| const getPagedDocs = docs => { | |
| if (docsPerPage === 'all') return docs; | |
| const perPage = parseInt(docsPerPage); | |
| const start = (currentPage - 1) * perPage; | |
| const end = start + perPage; | |
| return docs.slice(start, end); | |
| }; | |
| // Get final display docs | |
| const getDisplayDocs = () => { | |
| const processedDocs = processDocsData(); | |
| return getPagedDocs(processedDocs); | |
| }; | |
| // Pagination controls | |
| const renderPagination = totalDocs => { | |
| if (docsPerPage === 'all') return null; | |
| const totalPages = Math.ceil(totalDocs.length / parseInt(docsPerPage)); | |
| // Create style objects for pagination buttons | |
| const paginationBaseStyle = { | |
| padding: '8px 12px', | |
| margin: '0 4px', | |
| backgroundColor: attributes.paginationBackgroundColor || '#fff', | |
| color: attributes.paginationTextColor || '#333', | |
| border: `1px solid ${attributes.paginationBorderColor || '#ddd'}`, | |
| borderRadius: attributes.borderRadius || '4px', | |
| cursor: 'pointer', | |
| transition: 'all 0.2s ease', | |
| textDecoration: 'none', | |
| display: 'inline-block', | |
| minWidth: '32px', | |
| textAlign: 'center', | |
| fontFamily: 'inherit', | |
| fontSize: '14px', | |
| lineHeight: '1.4' | |
| }; | |
| // Active button style | |
| const activeStyle = { | |
| ...paginationBaseStyle, | |
| backgroundColor: attributes.paginationHoverColor || '#f5f5f5', | |
| borderColor: attributes.paginationHoverColor || '#ccc', | |
| color: attributes.paginationTextHoverColor || '#0073aa' | |
| }; | |
| // Hover styles will be handled by CSS custom properties | |
| const customProperties = { | |
| '--pagination-hover-bg': attributes.paginationHoverColor || '#f5f5f5', | |
| '--pagination-hover-color': attributes.paginationTextHoverColor || '#0073aa', | |
| '--pagination-hover-border': attributes.paginationHoverColor || '#ccc' | |
| }; | |
| return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", { | |
| className: "wedocs-docs-pagination", | |
| style: { | |
| margin: '30px 0', | |
| textAlign: 'center', | |
| ...customProperties | |
| }, | |
| children: [currentPage > 1 && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("button", { | |
| style: paginationBaseStyle, | |
| onClick: () => setCurrentPage(currentPage - 1), | |
| className: "wedocs-docs-pagination__button", | |
| children: "\u2190" | |
| }), Array.from({ | |
| length: totalPages | |
| }, (_, i) => { | |
| const pageNum = i + 1; | |
| const isCurrentPage = currentPage === pageNum; | |
| return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("button", { | |
| style: isCurrentPage ? activeStyle : paginationBaseStyle, | |
| className: `wedocs-docs-pagination__button ${isCurrentPage ? 'is-active' : ''}`, | |
| onClick: () => setCurrentPage(pageNum), | |
| children: pageNum | |
| }, pageNum); | |
| }), currentPage < totalPages && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("button", { | |
| style: paginationBaseStyle, | |
| onClick: () => setCurrentPage(currentPage + 1), | |
| className: "wedocs-docs-pagination__button", | |
| children: "\u2192" | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("style", { | |
| children: ` | |
| .wedocs-docs-pagination__button:hover:not(.is-active) { | |
| background-color: var(--pagination-hover-bg) !important; | |
| color: var(--pagination-hover-color) !important; | |
| border-color: var(--pagination-hover-border) !important; | |
| } | |
| ` | |
| })] | |
| }); | |
| }; | |
| const displayDocs = getDisplayDocs(); | |
| // Create a mapping of ID to title for suggestions | |
| const docsMap = pages ? pages.reduce((acc, page) => { | |
| acc[page.id] = page.title.rendered; | |
| return acc; | |
| }, {}) : {}; | |
| // Prepare docs options for FormTokenField | |
| const docsOptions = pages ? pages.map(page => ({ | |
| value: page.id.toString(), | |
| label: page.title.rendered | |
| })) : []; | |
| // Update handlers | |
| const updateAttribute = attributeName => value => { | |
| setAttributes({ | |
| [attributeName]: value | |
| }); | |
| }; | |
| // Transform IDs to titles for FormTokenField display | |
| const excludeDocsDisplay = excludeDocs ? excludeDocs.map(id => docsMap[id] || id) : []; | |
| // Handle token changes | |
| const handleExcludeDocsChange = tokens => { | |
| // Convert titles back to IDs | |
| const newExcludeDocs = tokens.map(token => { | |
| // Find the ID for this title | |
| const found = Object.entries(docsMap).find(([id, title]) => title === token); | |
| return found ? found[0] : token; | |
| }); | |
| setAttributes({ | |
| excludeDocs: newExcludeDocs | |
| }); | |
| }; | |
| const getGridClass = () => { | |
| return `wedocs-docs-grid--${docStyle}`; | |
| }; | |
| return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__.Fragment, { | |
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_3__.InspectorControls, { | |
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.PanelBody, { | |
| title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Doc Grid Settings', 'wedocs'), | |
| icon: _wordpress_icons__WEBPACK_IMPORTED_MODULE_1__["default"], | |
| initialOpen: false, | |
| children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | |
| value: docStyle, | |
| options: docStyles, | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('DOCS GRID COLUMN STYLE', 'wedocs'), | |
| onChange: updateAttribute('docStyle') | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | |
| value: docsPerPage, | |
| options: docsPerPageOptions, | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Docs per page', 'wedocs'), | |
| onChange: updateAttribute('docsPerPage') | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.FormTokenField, { | |
| value: excludeDocsDisplay, | |
| suggestions: Object.values(docsMap), | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Exclude Docs', 'wedocs'), | |
| onChange: handleExcludeDocsChange | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | |
| value: order, | |
| options: orderOptions, | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Order', 'wedocs'), | |
| onChange: updateAttribute('order') | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | |
| value: orderBy, | |
| options: orderByOptions, | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Order by', 'wedocs'), | |
| onChange: updateAttribute('orderBy') | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | |
| value: sectionsPerDoc, | |
| options: countOptions, | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Sections per doc', 'wedocs'), | |
| onChange: updateAttribute('sectionsPerDoc') | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.SelectControl, { | |
| value: articlesPerSection, | |
| options: countOptions, | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Articles per section', 'wedocs'), | |
| onChange: updateAttribute('articlesPerSection') | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.PanelRow, { | |
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.ToggleControl, { | |
| checked: showDocArticle, | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Show Doc Article', 'wedocs'), | |
| onChange: updateAttribute('showDocArticle') | |
| }) | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.PanelRow, { | |
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.ToggleControl, { | |
| checked: keepArticlesCollapsed, | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Keep Article Collapsed', 'wedocs'), | |
| onChange: updateAttribute('keepArticlesCollapsed') | |
| }) | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.PanelRow, { | |
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_4__.ToggleControl, { | |
| checked: showViewDetails, | |
| label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Show View Details Button', 'wedocs'), | |
| onChange: updateAttribute('showViewDetails') | |
| }) | |
| })] | |
| }) | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_3__.InspectorControls, { | |
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_StyleControls__WEBPACK_IMPORTED_MODULE_5__["default"], { | |
| attributes: attributes, | |
| setAttributes: setAttributes | |
| }) | |
| }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { | |
| ...blockProps, | |
| children: hideDocGrid ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { | |
| className: "backdrop" | |
| }) : /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { | |
| className: "wedocs-block-wrapper", | |
| children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { | |
| 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 { | |
| PanelBody, | |
| SelectControl, | |
| FormTokenField, | |
| PanelRow, | |
| ToggleControl, | |
| TextControl, | |
| Spinner, | |
| } from '@wordpress/components'; |
🤖 Prompt for AI Agents
In assets/build/blocks/DocsGrid/index.js around lines 414 to 889, the code uses
<Spinner/> in the render but never imports it, causing a ReferenceError; add
Spinner to the existing imports from @wordpress/components (or use
wp.components.Spinner) at the top of the file so the component is defined where
used, then rebuild to ensure the editor no longer throws when loading.
| "release": "npm run version:replace && npm run build && npm run make-pot:local && npm run zip:create" | ||
| }, | ||
| "devDependencies": { | ||
| "@wordpress/scripts": "^30.15.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify breaking changes in @wordpress/scripts upgrade from v25 to v30.
This is a significant version jump (25.0.0 → 30.15.0) for the WordPress build tooling package. Major version increments can introduce breaking changes in build configuration, webpack settings, or babel transforms.
Verify this upgrade:
-
Check for breaking changes in the WordPress scripts changelog:
-
Verify the build process still works correctly:
🏁 Script executed:
#!/bin/bash
# Check if package-lock.json or yarn.lock was updated
git diff --name-only | grep -E "(package-lock.json|yarn.lock)"
# Verify build scripts are defined
echo "Build scripts defined:"
cat package.json | grep -A 1 '"scripts"'Length of output: 70
🌐 Web query:
What are the breaking changes between @wordpress/scripts version 25.0.0 and 30.15.0?
💡 Result:
I can fetch the exact, cited breaking-change list from the @wordpress/scripts changelog — do you want me to look it up now and summarize each breaking change between 25.0.0 and 30.15.0?
Commit updated lockfile and review breaking changes for @wordpress/scripts bump
- No package-lock.json or yarn.lock updates detected after bump to ^30.15.0; run
npm installoryarnand commit the updated lockfile. - Review the @wordpress/scripts changelog for breaking changes between v25.0.0 → v30.15.0 and adjust build config if needed.
- Confirm the build and CI pass successfully after upgrading.
🤖 Prompt for AI Agents
In package.json around line 30, the @wordpress/scripts dependency was bumped to
^30.15.0 but no lockfile was updated and breaking changes may exist; run your
package manager (npm install or yarn) to regenerate package-lock.json or
yarn.lock and commit that updated lockfile, review the @wordpress/scripts
changelog for breaking changes between v25.0.0 and v30.15.0 and adjust any
build/webpack/babel/scripts config accordingly (update config fields, presets,
or plugin usage as required), then run the full build and CI locally and fix any
failing tests or lint/build errors before pushing the updated lockfile and
changes.
| // Border and Shadow | ||
| border: currentBorderShadow.border ? `${currentBorderShadow.border.width || '0'} ${currentBorderShadow.border.style || 'solid'} ${currentBorderShadow.border.color || 'transparent'}` : undefined, | ||
| borderRadius: currentBorderShadow.borderRadius ? `${currentBorderShadow.borderRadius.topLeft || '0'} ${currentBorderShadow.borderRadius.topRight || '0'} ${currentBorderShadow.borderRadius.bottomRight || '0'} ${currentBorderShadow.borderRadius.bottomLeft || '0'}` : undefined, | ||
| boxShadow: currentBorderShadow.boxShadow && currentBorderShadow.boxShadow.x ? `${currentBorderShadow.boxShadow.inset ? 'inset ' : ''}${currentBorderShadow.boxShadow.x || '0px'} ${currentBorderShadow.boxShadow.y || '0px'} ${currentBorderShadow.boxShadow.blur || '0px'} ${currentBorderShadow.boxShadow.spread || '0px'} ${currentBorderShadow.boxShadow.color || 'rgba(0,0,0,0.2)'}` : undefined, | ||
|
|
||
| // Background Image | ||
| backgroundImage: currentBackgroundImage.bgUrl ? `url(${currentBackgroundImage.bgUrl})` : undefined, | ||
| backgroundSize: currentBackgroundImage.bgSize || undefined, | ||
| backgroundPosition: currentBackgroundImage.bgFocalPoint ? `${currentBackgroundImage.bgFocalPoint.x * 100}% ${currentBackgroundImage.bgFocalPoint.y * 100}%` : undefined, | ||
| backgroundRepeat: currentBackgroundImage.bgRepeat ? 'repeat' : 'no-repeat', | ||
| backgroundAttachment: currentBackgroundImage.bgFixed ? 'fixed' : 'scroll', | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Border & shadow preview never honor user settings
getResponsiveStyles expects border and boxShadow.x/y, but the schema (see block.json Lines 254-276) only provides borderStyle, borderWidth, borderColor, and boxShadow.horizontal/vertical/.... As shipped, any border or shadow configured in the inspector is ignored in the editor preview, so users cannot verify their styling choices. Please build the style string from the actual attribute shape before returning blockProps.
Apply this diff to fix the mapping:
- border: currentBorderShadow.border ? `${currentBorderShadow.border.width || '0'} ${currentBorderShadow.border.style || 'solid'} ${currentBorderShadow.border.color || 'transparent'}` : undefined,
- borderRadius: currentBorderShadow.borderRadius ? `${currentBorderShadow.borderRadius.topLeft || '0'} ${currentBorderShadow.borderRadius.topRight || '0'} ${currentBorderShadow.borderRadius.bottomRight || '0'} ${currentBorderShadow.borderRadius.bottomLeft || '0'}` : undefined,
- boxShadow: currentBorderShadow.boxShadow && currentBorderShadow.boxShadow.x ? `${currentBorderShadow.boxShadow.inset ? 'inset ' : ''}${currentBorderShadow.boxShadow.x || '0px'} ${currentBorderShadow.boxShadow.y || '0px'} ${currentBorderShadow.boxShadow.blur || '0px'} ${currentBorderShadow.boxShadow.spread || '0px'} ${currentBorderShadow.boxShadow.color || 'rgba(0,0,0,0.2)'}` : undefined,
+ borderStyle: currentBorderShadow.borderStyle || undefined,
+ borderWidth: currentBorderShadow.borderWidth
+ ? `${currentBorderShadow.borderWidth.top || '0'} ${currentBorderShadow.borderWidth.right || '0'} ${currentBorderShadow.borderWidth.bottom || '0'} ${currentBorderShadow.borderWidth.left || '0'}`
+ : undefined,
+ borderColor: currentBorderShadow.borderColor || undefined,
+ borderRadius: currentBorderShadow.borderRadius
+ ? `${currentBorderShadow.borderRadius.topLeft || '0'} ${currentBorderShadow.borderRadius.topRight || '0'} ${currentBorderShadow.borderRadius.bottomRight || '0'} ${currentBorderShadow.borderRadius.bottomLeft || '0'}`
+ : undefined,
+ boxShadow: currentBorderShadow.boxShadow?.enabled
+ ? `${currentBorderShadow.boxShadow.inset ? 'inset ' : ''}${currentBorderShadow.boxShadow.horizontal || '0px'} ${currentBorderShadow.boxShadow.vertical || '0px'} ${currentBorderShadow.boxShadow.blur || '0px'} ${currentBorderShadow.boxShadow.spread || '0px'} ${currentBorderShadow.boxShadow.color || 'rgba(0,0,0,0.2)'}`
+ : undefined,Based on block.json
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/blocks/AdvanceContributors/edit.js around lines 100 to 111, the preview
builds CSS from fields like currentBorderShadow.border and
currentBorderShadow.boxShadow.x but the block schema actually exposes
borderStyle/borderWidth/borderColor and
boxShadow.horizontal/vertical/blur/spread/inset/color (and similarly named
radius keys), so the editor never shows user-configured borders/shadows; update
the style construction to read the real attribute names: compose border using
`${borderWidth || '0'} ${borderStyle || 'solid'} ${borderColor ||
'transparent'}`, build borderRadius from the schema radius keys
(topLeft/topRight/bottomRight/bottomLeft), and build boxShadow using
`boxShadow.horizontal`, `boxShadow.vertical`, `boxShadow.blur`,
`boxShadow.spread`, `boxShadow.inset`, and `boxShadow.color` (convert inset
boolean to 'inset ' when true); also ensure background and other fallbacks
remain unchanged, then return the updated blockProps so the preview reflects the
inspector values.
| switch ($contributor_display_mode) { | ||
| case 'main_author': | ||
| $author_id = get_post_field('post_author', $post->ID); | ||
| if ($author_id) { | ||
| $author_user = get_userdata($author_id); | ||
| if ($author_user) { | ||
| $contributors[] = $author_user; | ||
| } | ||
| } | ||
| break; | ||
|
|
||
| case 'manual': | ||
| if (!empty($selected_contributors)) { | ||
| foreach ($selected_contributors as $user_id) { | ||
| $user = get_userdata($user_id); | ||
| if ($user) { | ||
| $contributors[] = $user; | ||
| } | ||
| } | ||
| } | ||
| break; | ||
|
|
||
| case 'all': | ||
| default: | ||
| // Get post author | ||
| $author_id = get_post_field('post_author', $post->ID); | ||
| if ($author_id && ($author_user = get_userdata($author_id))) { | ||
| $contributors[] = $author_user; | ||
| } | ||
|
|
||
| // Get additional contributors from revisions | ||
| if ($post) { | ||
| $revisions = wp_get_post_revisions($post->ID); | ||
| $contributor_ids = [$author_id]; | ||
|
|
||
| foreach ($revisions as $revision) { | ||
| $revision_author = get_post_field('post_author', $revision->ID); | ||
| if (!in_array($revision_author, $contributor_ids)) { | ||
| $contributor_ids[] = $revision_author; | ||
| $user = get_userdata($revision_author); | ||
| if ($user) { | ||
| $contributors[] = $user; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| break; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard against missing global post
When the block is rendered outside of the loop (e.g. in Site Editor, patterns), get_post() can return null, so the subsequent $post->ID access fatals (Attempt to read property "ID" on null). Bail out early if no post is available.
- $post = get_post();
+ $post = get_post();
+ if ( ! $post ) {
+ return '';
+ }🤖 Prompt for AI Agents
src/blocks/AdvanceContributors/render.php around lines 48 to 95: the code
assumes $post is present and accesses $post->ID which can fatal when rendering
outside the loop (get_post() may return null); fix by retrieving the current
post early (e.g. $post = $post ?? get_post()) and if $post is null bail out
immediately (return early or set $contributors empty) before any use of
$post->ID so all switch cases below are safe.
| // Helper function to generate responsive CSS | ||
| function generate_responsive_css($block_id, $controls, $device_suffix = '') { | ||
| $css = ''; | ||
|
|
||
| if (empty($controls)) { | ||
| return $css; | ||
| } | ||
|
|
||
| $selector = '.' . $block_id . $device_suffix; | ||
| $rules = []; | ||
|
|
||
| // Typography | ||
| if (isset($controls['fontFamily']) && $controls['fontFamily']) { | ||
| $rules[] = 'font-family: ' . esc_attr($controls['fontFamily']); | ||
| } | ||
| if (isset($controls['fontSize']) && $controls['fontSize']) { | ||
| $rules[] = 'font-size: ' . esc_attr($controls['fontSize']); | ||
| } | ||
| if (isset($controls['fontAppearance']['fontWeight']) && $controls['fontAppearance']['fontWeight']) { | ||
| $rules[] = 'font-weight: ' . esc_attr($controls['fontAppearance']['fontWeight']); | ||
| } | ||
| if (isset($controls['fontAppearance']['fontStyle']) && $controls['fontAppearance']['fontStyle']) { | ||
| $rules[] = 'font-style: ' . esc_attr($controls['fontAppearance']['fontStyle']); | ||
| } | ||
| if (isset($controls['lineHeight']) && $controls['lineHeight']) { | ||
| $rules[] = 'line-height: ' . esc_attr($controls['lineHeight']); | ||
| } | ||
| if (isset($controls['letterSpacing']) && $controls['letterSpacing']) { | ||
| $rules[] = 'letter-spacing: ' . esc_attr($controls['letterSpacing']); | ||
| } | ||
| if (isset($controls['textDecoration']) && $controls['textDecoration']) { | ||
| $rules[] = 'text-decoration: ' . esc_attr($controls['textDecoration']); | ||
| } | ||
| if (isset($controls['textTransform']) && $controls['textTransform']) { | ||
| $rules[] = 'text-transform: ' . esc_attr($controls['textTransform']); | ||
| } | ||
|
|
||
| // Colors | ||
| if (isset($controls['textColor']) && $controls['textColor']) { | ||
| $rules[] = 'color: ' . esc_attr($controls['textColor']); | ||
| } | ||
| if (isset($controls['backgroundColor']) && $controls['backgroundColor']) { | ||
| $rules[] = 'background-color: ' . esc_attr($controls['backgroundColor']); | ||
| } | ||
|
|
||
| // Dimensions | ||
| if (isset($controls['width']) && $controls['width']) { | ||
| $rules[] = 'width: ' . esc_attr($controls['width']); | ||
| } | ||
| if (isset($controls['minWidth']) && $controls['minWidth']) { | ||
| $rules[] = 'min-width: ' . esc_attr($controls['minWidth']); | ||
| } | ||
| if (isset($controls['maxWidth']) && $controls['maxWidth']) { | ||
| $rules[] = 'max-width: ' . esc_attr($controls['maxWidth']); | ||
| } | ||
| if (isset($controls['height']) && $controls['height']) { | ||
| $rules[] = 'height: ' . esc_attr($controls['height']); | ||
| } | ||
| if (isset($controls['minHeight']) && $controls['minHeight']) { | ||
| $rules[] = 'min-height: ' . esc_attr($controls['minHeight']); | ||
| } | ||
| if (isset($controls['maxHeight']) && $controls['maxHeight']) { | ||
| $rules[] = 'max-height: ' . esc_attr($controls['maxHeight']); | ||
| } | ||
|
|
||
| // Padding | ||
| if (isset($controls['padding']) && is_array($controls['padding'])) { | ||
| $padding_values = []; | ||
| $padding_values[] = $controls['padding']['top'] ?? '0'; | ||
| $padding_values[] = $controls['padding']['right'] ?? '0'; | ||
| $padding_values[] = $controls['padding']['bottom'] ?? '0'; | ||
| $padding_values[] = $controls['padding']['left'] ?? '0'; | ||
| $rules[] = 'padding: ' . implode(' ', $padding_values); | ||
| } | ||
|
|
||
| // Margin | ||
| if (isset($controls['margin']) && is_array($controls['margin'])) { | ||
| $margin_values = []; | ||
| $margin_values[] = $controls['margin']['top'] ?? '0'; | ||
| $margin_values[] = $controls['margin']['right'] ?? '0'; | ||
| $margin_values[] = $controls['margin']['bottom'] ?? '0'; | ||
| $margin_values[] = $controls['margin']['left'] ?? '0'; | ||
| $rules[] = 'margin: ' . implode(' ', $margin_values); | ||
| } | ||
|
|
||
| // Alignment | ||
| if (isset($controls['textAlign']) && $controls['textAlign']) { | ||
| $rules[] = 'text-align: ' . esc_attr($controls['textAlign']); | ||
| } | ||
| if (isset($controls['alignItems']) && $controls['alignItems']) { | ||
| $rules[] = 'align-items: ' . esc_attr($controls['alignItems']); | ||
| } | ||
| if (isset($controls['justifyContent']) && $controls['justifyContent']) { | ||
| $rules[] = 'justify-content: ' . esc_attr($controls['justifyContent']); | ||
| } | ||
| if (isset($controls['direction']) && $controls['direction']) { | ||
| $rules[] = 'flex-direction: ' . esc_attr($controls['direction']); | ||
| } | ||
|
|
||
| // Border | ||
| if (isset($controls['border']) && is_array($controls['border'])) { | ||
| $border = $controls['border']; | ||
| if (isset($border['width']) && isset($border['style']) && isset($border['color'])) { | ||
| $rules[] = 'border: ' . esc_attr($border['width']) . ' ' . esc_attr($border['style']) . ' ' . esc_attr($border['color']); | ||
| } | ||
| } | ||
|
|
||
| // Border Radius | ||
| if (isset($controls['borderRadius']) && is_array($controls['borderRadius'])) { | ||
| $radius = $controls['borderRadius']; | ||
| $radius_values = []; | ||
| $radius_values[] = $radius['topLeft'] ?? '0'; | ||
| $radius_values[] = $radius['topRight'] ?? '0'; | ||
| $radius_values[] = $radius['bottomRight'] ?? '0'; | ||
| $radius_values[] = $radius['bottomLeft'] ?? '0'; | ||
| $rules[] = 'border-radius: ' . implode(' ', $radius_values); | ||
| } | ||
|
|
||
| // Box Shadow | ||
| if (isset($controls['boxShadow']) && is_array($controls['boxShadow']) && isset($controls['boxShadow']['x'])) { | ||
| $shadow = $controls['boxShadow']; | ||
| $shadow_value = ''; | ||
| if (isset($shadow['inset']) && $shadow['inset']) { | ||
| $shadow_value .= 'inset '; | ||
| } | ||
| $shadow_value .= esc_attr($shadow['x']) . ' '; | ||
| $shadow_value .= esc_attr($shadow['y']) . ' '; | ||
| $shadow_value .= esc_attr($shadow['blur']) . ' '; | ||
| $shadow_value .= esc_attr($shadow['spread']) . ' '; | ||
| $shadow_value .= esc_attr($shadow['color']); | ||
| $rules[] = 'box-shadow: ' . $shadow_value; | ||
| } | ||
|
|
||
| // Background Image | ||
| if (isset($controls['bgUrl']) && $controls['bgUrl']) { | ||
| $rules[] = 'background-image: url(' . esc_url($controls['bgUrl']) . ')'; | ||
|
|
||
| if (isset($controls['bgSize']) && $controls['bgSize']) { | ||
| $rules[] = 'background-size: ' . esc_attr($controls['bgSize']); | ||
| } | ||
|
|
||
| if (isset($controls['bgFocalPoint']) && is_array($controls['bgFocalPoint'])) { | ||
| $focal = $controls['bgFocalPoint']; | ||
| $rules[] = 'background-position: ' . ($focal['x'] * 100) . '% ' . ($focal['y'] * 100) . '%'; | ||
| } | ||
|
|
||
| if (isset($controls['bgRepeat'])) { | ||
| $rules[] = 'background-repeat: ' . ($controls['bgRepeat'] ? 'repeat' : 'no-repeat'); | ||
| } | ||
|
|
||
| if (isset($controls['bgFixed']) && $controls['bgFixed']) { | ||
| $rules[] = 'background-attachment: fixed'; | ||
| } | ||
| } | ||
|
|
||
| // Display | ||
| if (isset($controls['display']) && $controls['display']) { | ||
| $rules[] = 'display: ' . esc_attr($controls['display']); | ||
| } | ||
| if (isset($controls['visibility']) && $controls['visibility']) { | ||
| $rules[] = 'visibility: ' . esc_attr($controls['visibility']); | ||
| } | ||
| if (isset($controls['overflow']) && $controls['overflow']) { | ||
| $rules[] = 'overflow: ' . esc_attr($controls['overflow']); | ||
| } | ||
| if (isset($controls['zIndex']) && $controls['zIndex']) { | ||
| $rules[] = 'z-index: ' . esc_attr($controls['zIndex']); | ||
| } | ||
|
|
||
| if (!empty($rules)) { | ||
| $css .= $selector . ' { ' . implode('; ', $rules) . '; }'; | ||
| } | ||
|
|
||
| return $css; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid redefining generate_responsive_css
Declaring generate_responsive_css() inside the render callback registers a global function the first time it runs, and attempting to declare it again on the next render triggers Cannot redeclare generate_responsive_css(). Wrap it in a closure (or move it out with a unique name) so the callback remains reusable.
- function generate_responsive_css($block_id, $controls, $device_suffix = '') {
+ $generate_responsive_css = static function( $block_id, $controls, $device_suffix = '' ) {
$css = '';
…
- return $css;
- }
+ return $css;
+ };
…
- $responsive_css .= generate_responsive_css($block_id, $device_controls);
+ $responsive_css .= $generate_responsive_css( $block_id, $device_controls );
…
- $responsive_css .= '@media (max-width: 1024px) { ' . generate_responsive_css($block_id, $device_controls) . ' }';
+ $responsive_css .= '@media (max-width: 1024px) { ' . $generate_responsive_css( $block_id, $device_controls ) . ' }';
…
- $responsive_css .= '@media (max-width: 768px) { ' . generate_responsive_css($block_id, $device_controls) . ' }';
+ $responsive_css .= '@media (max-width: 768px) { ' . $generate_responsive_css( $block_id, $device_controls ) . ' }';Committable suggestion skipped: line range outside the PR's diff.
| return $output; | ||
| } | ||
| render_wedocs_advance_contributors_block( $attributes, $content, $block ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return the rendered markup
This file is used as the block’s render callback in block.json. Without an explicit return, include just yields 1, so the block outputs 1 instead of the generated markup.
-}
-render_wedocs_advance_contributors_block( $attributes, $content, $block );
+}
+return render_wedocs_advance_contributors_block( $attributes, $content, $block );🤖 Prompt for AI Agents
In src/blocks/AdvanceContributors/render.php around lines 497 to 499, the render
callback ends by calling render_wedocs_advance_contributors_block(...) without
returning its output; currently the include returns 1. Update the function so it
returns the rendered markup string instead of echoing/including it — call the
render function and return its result (or buffer the output and return the
buffer) so the block outputs the generated markup rather than "1".
Summary by CodeRabbit