Skip to content

Conversation

@krugazul
Copy link
Collaborator

@krugazul krugazul commented Dec 5, 2025

Overview

This PR implements comprehensive improvements to fast-facts and meta data display to ensure single-line presentation for short content and graceful wrapping for longer content.

Changes Made

Block Enhancements

  • Enhanced prefix display: Added bold prefix text to multiple blocks for improved clarity and consistency
  • Layout improvements: Updated block structures and variations for better content organization
  • Icon handling: Improved icon name sanitization and server-side rendering for Icons block
  • Responsive design: Enhanced mobile and desktop display compatibility

Key Block Updates

  • Paragraph Prefix Setting: New inspector controls for prefix text and bold options on paragraphs that have bindings.
  • Duration & Group Size Blocks: Enhanced prefix text with translation support
  • Travel Styles Block: Added bold prefix for improved visibility
  • Single Supplement Block: Enhanced prefix text structure
  • Best Time to Visit Block: Updated content structure with bold prefix
  • Departs/Ends In Blocks: Added location prefix text for clarity
  • Destination Blocks: Enhanced destination display with bold prefix
  • Price Block: Added starting price prefix for clarity
  • Accommodation Type Block: Updated layout with flex display and prefix
  • Check-in/Check-out Time Blocks: Enhanced content structure
  • Facts Wrapper Blocks: Added duration and country prefixes with bold styling
  • Rating Block: Enhanced display with bold prefix and improved layout
  • Special Interests Block: Added bold prefix for interests display
  • Language & Visitor Type Blocks: Enhanced with bold prefix display
  • Number of Rooms Block: Added bold prefix for unit display clarity

Technical Improvements

  • Asset Management: Updated version numbers across multiple block assets
  • WordPress Dependencies: Re-added @wordpress/blocks and @wordpress/block-library
  • CSS Optimization: Minified icon block styles for better performance
  • Security: Enhanced icon name sanitization for improved security
  • Server-side Rendering: Implemented for Icons block for cleaner templates

Testing

  • Desktop display verification
  • Mobile responsive testing
  • Block variation functionality
  • Icon display and alignment
  • Prefix text display and formatting

Closes

Closes #514

Related

Summary by CodeRabbit

  • New Features

    • Icons block: configurable icon selection with server-side rendering.
    • Paragraph prefix system: addable prefix text with bold option for meta-driven paragraphs.
  • Improvements

    • Consolidated many label blocks into inline bold prefixes for cleaner single-line displays.
    • Updated variation layouts and vertical alignment for consistent editor rendering.
    • Broadened variation support to include accommodation and tour post types.

✏️ Tip: You can customize this high-level summary in your review settings.

tibiii and others added 30 commits December 4, 2025 12:30
- Minified CSS for both RTL and standard stylesheets to reduce file size.
- Consolidated multiple CSS rules into single lines for better maintainability.
- Ensured consistent styling for icon sizes across different font size classes.
…sibility and update structure for better content display
…on and update content structure for improved display
…ons and update content structure for improved display
…dity and update content structure for improved display
- Updated asset versions for best-time-to-visit, departs-from, destination-to-tour, ends-in, and travel-styles blocks.
- Modified JavaScript for best-time-to-visit block to include layout settings and corrected prefix text.
- Adjusted layout settings for departs-from, destination-to-tour, and ends-in blocks to use flex layout.
- Fixed prefix text for travel-styles block to include a space after the label.
- Changed `prefixText` attribute to `prefix` in various blocks including `best-time-to-visit`, `booking-validity`, `checkin-time`, `checkout-time`, `departs-from`, `destination-to-accommodation`, `destination-to-tour`, `duration`, `ends-in`, `facts-country-wrapper`, `facts-regions-wrapper`, `group-size`, `minimum-child-age`, `number-of-rooms`, `price`, `rating`, `single-supplement-wrapper`, `special-interests`, `spoken-languages`, and `suggested-visitor-types`.
- Updated the handling of prefix attributes in the `paragraph-prefix` component and related filters.
- Adjusted the logic in `class-bindings.php` to accommodate the new attribute name.
…d visitor types

- Updated asset versions for spoken languages and suggested visitor types blocks.
- Modified JavaScript files for spoken languages and suggested visitor types to include new block variations.
- Added vertical alignment property set to 'top' for multiple blocks including best time to visit, booking validity, check-in time, check-out time, departs from, destination to accommodation, destination to tour, duration, ends in, facts country wrapper, facts regions wrapper, number of rooms, price, rating, single supplement wrapper, special interests, and others.
@krugazul krugazul linked an issue Dec 5, 2025 that may be closed by this pull request
12 tasks
@github-actions github-actions bot added lang:php PHP code area:ci Build and CI pipelines area:dependencies Composer/npm dependency work lang:css Stylesheets lang:javascript area:block-editor labels Dec 5, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 5, 2025

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: String must contain at most 250 character(s) at "tone_instructions"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

Consolidates many block label/structure changes to single-line paragraphs with bold prefixes; switches numerous block variation layouts from constrained to flex (nowrap, top-aligned); adds a paragraph prefix system (attributes + editor UI + server render hook); introduces an Icons block with server-side SVG rendering and a helper; bumps many build asset versions and moves certain WP packages to devDependencies.

Changes

Cohort / File(s) Change Summary
Block variation layout + prefixes
src/blocks/{accommodation-type,best-time-to-visit,booking-validity,checkin-time,checkout-time,departs-from,destination-to-accommodation,destination-to-tour,duration,ends-in,facts-country-wrapper,facts-regions-wrapper,group-size,minimum-child-age,number-of-rooms,price,rating,single-supplement-wrapper,special-interests,spoken-languages,suggested-visitor-types,travel-styles}/..., build/blocks/...
Changed variation layouts from constrained → flex with nowrap and verticalAlignment: top; removed separate label paragraphs and inlined labels via new prefix + prefixBold attributes on paragraph/post-terms blocks; updated examples/block.json payloads accordingly.
Paragraph prefix system (editor + render)
build/paragraph-prefix.asset.php, build/paragraph-prefix.js, src/build/paragraph-prefix.js?, src/blocks/paragraph-prefix.js?, includes/classes/blocks/class-bindings.php, includes/classes/blocks/class-registration.php
Added editor filter/inspector UI to expose prefix (string) and prefixBold (bool) for core/paragraph; register attributes during block registration; added render_paragraph_prefix_block() PHP filter to prepend and optionally bold/escape prefixes in rendered paragraph HTML; enqueued new admin variation script.
Icons block + SVG helper
src/blocks/icons/{block.json,index.js,render.php,style.scss}, build/blocks/icons/{index.asset.php,style-index*.css,render.php}, includes/functions.php
New Icons block with server-side renderer (render.php); manifest adds render: file:render.php and attributes iconType/iconName; block save returns null; added lsx_to_get_icon_svg( $icon_type, $icon_name ) to read/sanitize SVGs and expose lsx_to_icon_svg filter; CSS adds vertical-align: middle.
Asset version bumps
build/blocks/*/index.asset.php, build/paragraph-prefix.asset.php, build/blocks/...
Updated many build asset version hashes (cache-busting); mostly no functional change.
Registration scope / control tweaks
src/blocks/{best-time-to-visit,single-supplement-wrapper, ... }/index.js, src/blocks/.../index.js
Expanded conditional registration postTypes/templateSlugs (e.g., include accommodation), refactored local variable names used by registration guards; preserved overall registration flow.
Minor PHP/legacy tweaks
includes/classes/legacy/class-accommodation.php, includes/functions.php
Adjusted inline CSS vertical-align for rating stars (sub → unset); added lsx_to_get_icon_svg function.
Package manifest
package.json
Moved @wordpress/blocks from dependencies → devDependencies; added @wordpress/block-library and adjusted devDependencies.
Changelog
changelog.md
Added "Fast-Facts Meta Display Enhancement" entry summarising changes.

Sequence Diagram(s)

sequenceDiagram
  participant Editor as Block Editor (JS)
  participant Server as WP PHP (render.php)
  participant Helper as lsx_to_get_icon_svg()
  participant FS as File System (icons/*.svg)

  Editor->>Server: Request post render (front-end / server-side block_render)
  Server->>Helper: lsx_to_get_icon_svg(iconType, iconName)
  Helper->>FS: read SVG file (kebab-case path)
  FS-->>Helper: SVG content (or empty)
  Helper->>Server: sanitized SVG (wp_kses) or empty
  alt SVG found
    Server->>Editor: return block HTML with <span class="block-icon-svg">SVG</span>
  else SVG missing
    Server-->>Editor: return empty / no-output for icon block
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Focus areas that may need extra attention:
    • includes/classes/blocks/class-bindings.php — ensure regex insertion is robust for varied paragraph HTML and XSS-safe escaping.
    • includes/functions.php — check path construction, kebab-case conversion, file existence checks and wp_kses allowed tags set.
    • src/blocks/icons/render.php and block.json — validate early-return conditions and wrapper attributes.
    • Spot-check a sample of updated block variations to confirm prefix/prefixBold attribute usage matches editor UI and server render behavior.

Possibly related issues

  • #515 — Tour Info & Metadata Enhancements: implements the single-line fast-facts/meta display, paragraph prefix system and icons described by the epic.

Possibly related PRs

  • #645 — overlaps block variation changes for checkin/checkout time (same files).
  • #667 — overlaps on conditional registration, icons and block variation updates (same areas).
  • #696 — related changes to block registration, icons and shared utilities (same code-level surface).

Suggested labels

Enhancement, comp:block-variations, comp:block-json, comp:block-editor

Suggested reviewers

  • tibiii

Poem

🐰
I hopped through blocks with nimble paws,
Brought prefixes bold to tidy laws.
Flex rows now line in single cheer,
Icons sparkle, SVGs appear.
A rabbit's nibble — neat blocks here!

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'Enhancement: Single-Line Fast-Facts Meta Display Implementation' clearly and specifically describes the main objective of the changeset, which is implementing single-line display for fast-facts and meta data blocks.
Linked Issues check ✅ Passed The PR successfully implements the linked issue #514 objectives: adds prefix attributes to 20+ blocks for single-line display, updates layouts to flex with nowrap, improves responsive design, and implements server-side rendering for icons.
Out of Scope Changes check ✅ Passed All changes align with the PR objectives. Block layout modifications, prefix implementations, icon sanitization, dependency updates, and CSS adjustments all support the single-line display enhancement. No unrelated changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch enhancement/fast-facts-meta-display

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

❤️ Share

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

@github-actions github-actions bot added status:needs-review Awaiting code review meta:needs-changelog Requires a changelog entry before merge and removed status:needs-review Awaiting code review labels Dec 5, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 23

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (12)
src/blocks/minimum-child-age/index.js (1)

99-113: Align example preview with the new prefix/prefixBold structure

The meta-bound core/paragraph here correctly uses prefix and prefixBold: true to render “Minimum Child Age:” inline with the value, which supports the single-line fast-facts behaviour you’re aiming for.

However, the example configuration below still uses the older pattern (icon + bold label paragraph in the first group, and an unprefixed value paragraph in the second group). That means the inserter preview no longer reflects the actual block layout or its single-line label/value behaviour.

Consider updating the example’s innerBlocks so that:

  • The label is provided via prefix/prefixBold on the value paragraph, and
  • The title group preview mirrors the runtime structure (icon-only title, label/value in the content group).

This will make the preview more truthful and help authors visually confirm the intended fast-facts layout.

Also applies to: 126-175

src/blocks/single-supplement-wrapper/index.js (2)

1-8: Update docblock to reflect accommodation post type support

The docblock at line 5 states "Only available on tour post type edit screens." but the code at lines 125–128 registers for both tour and accommodation post types. Update the docblock to accurately reflect both:

- * Only available on tour post type edit screens.
+ * Only available on tour and accommodation post type edit screens.

The usage of identical values for both postTypes and templateSlugs parameters is consistent with other blocks in the codebase (e.g., included, not-included) and is a valid pattern for this helper function.


71-87: Add trailing space to prefix and update example to use prefix/prefixBold attributes

The real block at line 84 uses prefix: __('Single supplement:', 'tour-operator') without a trailing space, while the example at line 114 uses 'Single supplement: ' with a trailing space. Additionally, the example hard-codes the <strong> tag instead of using the prefixBold attribute that the real block employs.

To ensure consistent rendering and avoid duplicating markup logic:

  1. Add a trailing space to the prefix value at line 84: __('Single supplement: ', 'tour-operator')
  2. Update the example paragraph (lines 112–116) to use the same prefix, prefixBold, and className attributes as the real block
-                                prefix : __('Single supplement:', 'tour-operator'),
+                                prefix: __('Single supplement: ', 'tour-operator'),

and update the example:

                                name: 'core/paragraph',
                                attributes: {
+                                    className: 'amount',
+                                    prefix: __('Single supplement: ', 'tour-operator'),
+                                    prefixBold: true,
-                                    content: '<strong>' + __('Single supplement: ', 'tour-operator') + '</strong>' + '$299',
+                                    content: '$299',
                                },
includes/classes/legacy/class-accommodation.php (1)

165-186: Star icon alignment change is safe; consider matching icons block styling

The switch to vertical-align: unset on the rating star image is functionally safe and does not introduce security or accessibility regressions (the stars are decorative and alt="" is correct). If you want visual consistency with the new icons block, you may want to consider vertical-align: middle here as well, but that’s optional and purely presentational.

src/blocks/destination-to-accommodation/block.json (1)

22-34: The block.json example does not properly demonstrate the prefix attribute system.

The example paragraph shows hardcoded HTML content ("content": "<strong>Location:</strong> Cape Town, Johannesburg") but should demonstrate the actual prefix and prefixBold attributes used by the render_paragraph_prefix_block hook. The paragraph inner block should include:

{
  "content": "Cape Town, Johannesburg",
  "prefix": "Location:",
  "prefixBold": true
}

The current example is misleading because it doesn't reflect how the block is actually configured in index.js, where the prefix rendering system dynamically applies the prefix via server-side processing. Update the example to match the actual attribute-based implementation.

src/blocks/duration/index.js (2)

56-62: Add trailing comma for consistency.

Line 61 is missing a trailing comma after the closing brace, which is inconsistent with JavaScript best practices and WordPress coding standards.

Apply this diff:

                            'lsx-tour-operator/icons',
                            {
                                iconType: 'outline',
                                iconName: 'durationIcon',
                            },
-                        ]
+                        ],
                    ],

125-129: Update example block to match new prefix pattern.

The example block still uses the old format with inline <strong> tags concatenated with content, whilst the actual block structure now uses the prefix and prefixBold attributes. This inconsistency may confuse developers and doesn't accurately represent the block's behaviour.

Consider updating the example to reflect the new prefix-based approach:

                                     {
                                         name: 'core/paragraph',
                                         attributes: {
-                                            content: '<strong>' + __('Duration: ', 'tour-operator') + '</strong>' + ' ' + __('7 Days', 'tour-operator'),
+                                            content: __('7', 'tour-operator'),
                                         },
                                     },
+                                    {
+                                        name: 'core/paragraph',
+                                        attributes: {
+                                            content: __('Days', 'tour-operator'),
+                                        },
+                                    },
                                 ],
src/blocks/special-interests/index.js (2)

123-171: Align example structure with the new prefix‑based layout

The example still uses a separate <strong>Special Interests:</strong> paragraph next to the icon, while the actual variation now expects the label to come from prefix on the bound paragraph.

For a clearer editor experience, consider updating the example to mirror the real innerBlocks structure (icon group + content group with a prefixed paragraph), so users see a preview that matches what will be inserted.


103-118: Fix Special Interests prefix label and ensure it's translatable

The bound paragraph currently uses a hard‑coded string "Duration:", which is both the wrong label for this block and lacks a translation wrapper. The block is titled "Special Interests" but the prefix says "Duration:".

Update as follows:

-                                prefix : "Duration:",
+                                prefix: __('Special Interests: ', 'tour-operator'),

This aligns the label with the block purpose, ensures the string is translatable (the __() function is already imported), and maintains consistency with other user‑facing text in this file that properly use i18n.

src/blocks/destination-to-tour/index.js (1)

71-86: Add trailing space to Destinations prefix for correct output

The paragraph renders with prefix : __('Destinations:', 'tour-operator'), which will concatenate without spacing because the colon matches the renderer's punctuation check. Update to:

-                                prefix : __('Destinations:', 'tour-operator'),
+                                prefix: __('Destinations: ', 'tour-operator'),

Also remove the space before the colon per WordPress JavaScript coding standards.

src/blocks/best-time-to-visit/index.js (1)

127-127: Missing semicolon after function expression.

As per coding guidelines, statements should be terminated with semicolons.

-    }
+    };
src/blocks/booking-validity/index.js (1)

89-110: Consider accessibility for date range display.

The date range is split across three separate paragraph blocks (start date, hyphen, end date). Screen readers may announce these as separate elements, potentially losing the relationship context. Consider adding an aria-label to the parent group to provide full context, or using a single paragraph with the combined date range.

Verify screen reader behaviour with this structure to ensure the date range is announced coherently.

♻️ Duplicate comments (1)
build/blocks/departs-from/index.js (1)

1-1: Build reflects incorrect prefix from source file.

This minified build contains prefix:"Duration:" which is incorrect for the Departs From block. This will be resolved once the source file (src/blocks/departs-from/index.js) is fixed and rebuilt.

@@ -1 +1 @@
!function(){"use strict";var o=window.wp.i18n;wp.domReady(()=>{!function(o,t,e,r={}){return function(o){const{postTypes:t=[],templateSlugs:e=[],registerFunction:r,timeout:n=100}=o;if(!r||"function"!=typeof r)throw new Error("registerFunction is required and must be a function");return function(){const{select:o}=wp.data;let a=!1,c=!1;const i=()=>{if(a||c)return a;if(c=!0,(()=>{try{const r=o("core/editor")?.getCurrentPostType(),n=o("core/editor")?.getEditedPostSlug();return!!r&&(!!t.includes(r)||!("wp_template"!==r&&"wp_template_part"!==r||!n||!(e.length>0))&&e.some(o=>"string"==typeof o?n.includes(o):o instanceof RegExp&&o.test(n)))}catch(o){return console.error("Error in shouldRegister:",o),!1}})())try{return r(),a=!0,c=!1,!0}catch(o){return console.error("Error during block registration:",o),c=!1,!1}return c=!1,!1};setTimeout(()=>{if(!i()){let o=!1;const t=wp.data.subscribe(()=>{o||i()&&(o=!0,t())})}},n)}}({postTypes:["accommodation"],templateSlugs:["accommodation"],registerFunction:e,...r})}(0,0,()=>{wp.blocks.registerBlockVariation("core/group",{name:"lsx-tour-operator/accommodation-type",title:(0,o.__)("Accommodation type","tour-operator"),icon:"admin-multisite",category:"lsx-tour-operator",description:(0,o.__)("Displays the accommodation type(s).","tour-operator"),keywords:[(0,o.__)("accommodation","tour-operator"),(0,o.__)("type","tour-operator")],isActive:(o,t)=>o.className===t.className,attributes:{metadata:{name:(0,o.__)("Accommodation type","tour-operator")},className:"lsx-accommodation-type-wrapper",layout:{type:"constrained"}},innerBlocks:[["core/group",{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},[["lsx-tour-operator/icons",{iconType:"solid",iconName:"accommodationTypeIcon"}],["core/paragraph",{content:"<strong>"+(0,o.__)("Accommodation Type","tour-operator")+"</strong>:"}]]],["core/group",{layout:{type:"flex",flexWrap:"nowrap"}},[["core/post-terms",{term:"accommodation-type"}]]]],example:{innerBlocks:[{name:"core/group",attributes:{layout:{type:"flex",flexWrap:"nowrap"}},innerBlocks:[{name:"core/group",attributes:{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},innerBlocks:[{name:"lsx-tour-operator/icons",attributes:{iconType:"solid",iconName:"accommodationTypeIcon"}},{name:"core/paragraph",attributes:{content:"<strong>"+(0,o.__)("Accommodation Type: ","tour-operator")+"</strong> "+(0,o.__)("Hotel","tour-operator")}}]}]}]}})})()})}(); No newline at end of file
!function(){"use strict";var o=window.wp.i18n;wp.domReady(()=>{!function(o,t,e,r={}){return function(o){const{postTypes:t=[],templateSlugs:e=[],registerFunction:r,timeout:n=100}=o;if(!r||"function"!=typeof r)throw new Error("registerFunction is required and must be a function");return function(){const{select:o}=wp.data;let a=!1,c=!1;const i=()=>{if(a||c)return a;if(c=!0,(()=>{try{const r=o("core/editor")?.getCurrentPostType(),n=o("core/editor")?.getEditedPostSlug();return!!r&&(!!t.includes(r)||!("wp_template"!==r&&"wp_template_part"!==r||!n||!(e.length>0))&&e.some(o=>"string"==typeof o?n.includes(o):o instanceof RegExp&&o.test(n)))}catch(o){return console.error("Error in shouldRegister:",o),!1}})())try{return r(),a=!0,c=!1,!0}catch(o){return console.error("Error during block registration:",o),c=!1,!1}return c=!1,!1};setTimeout(()=>{if(!i()){let o=!1;const t=wp.data.subscribe(()=>{o||i()&&(o=!0,t())})}},n)}}({postTypes:["accommodation"],templateSlugs:["accommodation"],registerFunction:e,...r})}(0,0,()=>{wp.blocks.registerBlockVariation("core/group",{name:"lsx-tour-operator/accommodation-type",title:(0,o.__)("Accommodation type","tour-operator"),icon:"admin-multisite",category:"lsx-tour-operator",description:(0,o.__)("Displays the accommodation type(s).","tour-operator"),keywords:[(0,o.__)("accommodation","tour-operator"),(0,o.__)("type","tour-operator")],isActive:(o,t)=>o.className===t.className,attributes:{metadata:{name:(0,o.__)("Accommodation type","tour-operator")},className:"lsx-accommodation-type-wrapper",layout:{type:"flex",flexWrap:"nowrap"}},innerBlocks:[["core/group",{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},[["lsx-tour-operator/icons",{iconType:"solid",iconName:"accommodationTypeIcon"}]]],["core/group",{layout:{type:"flex",flexWrap:"nowrap"}},[["core/post-terms",{term:"accommodation-type",prefix:"<strong>"+(0,o.__)("Accommodation Type: ","tour-operator")+"</strong>"}]]]],example:{innerBlocks:[{name:"core/group",attributes:{layout:{type:"flex",flexWrap:"nowrap"}},innerBlocks:[{name:"core/group",attributes:{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},innerBlocks:[{name:"lsx-tour-operator/icons",attributes:{iconType:"solid",iconName:"accommodationTypeIcon"}},{name:"core/paragraph",attributes:{content:"<strong>"+(0,o.__)("Accommodation Type: ","tour-operator")+"</strong> "+(0,o.__)("Hotel","tour-operator")}}]}]}]}})})()})}(); No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Search for the source file in the blocks directory
find . -path "*/src/blocks/accommodation-type*" -name "*.js" -type f

Repository: lightspeedwp/tour-operator

Length of output: 110


🏁 Script executed:

# Check file size and content
wc -l ./src/blocks/accommodation-type/index.js
echo "---"
cat -n ./src/blocks/accommodation-type/index.js

Repository: lightspeedwp/tour-operator

Length of output: 3994


Escape HTML strings in block attributes.

The prefix attribute on line 72 and the content attribute on line 109 concatenate HTML strings without proper escaping. These should be escaped using WordPress functions like wp.escapeHtml() or handled through proper sanitization to prevent potential XSS vulnerabilities. Ensure all HTML output in block attributes complies with WordPress security standards for escaped content.

🤖 Prompt for AI Agents
In build/blocks/accommodation-type/index.js around lines 72 and 109, the block
attributes concatenate translated strings into HTML without escaping (prefix:
"<strong>"+__(...)+ "</strong>" and content: "<strong>"+__(...)+ "</strong>
"+__(...)), which risks XSS; fix by escaping the translated strings with
wp.escapeHtml() before inserting them into HTML and/or construct these
attributes using a safe HTML wrapper (e.g. use wp.element.RawHTML for trusted
markup) so that the dynamic text is always escaped/sanitized rather than
directly concatenated into HTML.

@@ -1 +1 @@
!function(){"use strict";var t=window.wp.i18n;wp.domReady(()=>{!function(t,o,r,e={}){return function(t){const{postTypes:o=[],templateSlugs:r=[],registerFunction:e,timeout:n=100}=t;if(!e||"function"!=typeof e)throw new Error("registerFunction is required and must be a function");return function(){const{select:t}=wp.data;let a=!1,i=!1;const s=()=>{if(a||i)return a;if(i=!0,(()=>{try{const e=t("core/editor")?.getCurrentPostType(),n=t("core/editor")?.getEditedPostSlug();return!!e&&(!!o.includes(e)||!("wp_template"!==e&&"wp_template_part"!==e||!n||!(r.length>0))&&r.some(t=>"string"==typeof t?n.includes(t):t instanceof RegExp&&t.test(n)))}catch(t){return console.error("Error in shouldRegister:",t),!1}})())try{return e(),a=!0,i=!1,!0}catch(t){return console.error("Error during block registration:",t),i=!1,!1}return i=!1,!1};setTimeout(()=>{if(!s()){let t=!1;const o=wp.data.subscribe(()=>{t||s()&&(t=!0,o())})}},n)}}({postTypes:["tour"],templateSlugs:["tour"],registerFunction:r,...e})}(0,0,()=>{wp.blocks.registerBlockVariation("core/group",{name:"lsx-tour-operator/booking-validity",title:(0,t.__)("Booking validity","tour-operator"),icon:"calendar",category:"lsx-tour-operator",description:(0,t.__)("Displays the booking validity period for a tour.","tour-operator"),keywords:[(0,t.__)("booking","tour-operator"),(0,t.__)("validity","tour-operator"),(0,t.__)("tour","tour-operator")],isActive:(t,o)=>t.className===o.className,attributes:{metadata:{name:(0,t.__)("Booking validity","tour-operator")},className:"lsx-booking-validity-wrapper",layout:{type:"flex",flexWrap:"nowrap"}},innerBlocks:[["core/group",{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},[["lsx-tour-operator/icons",{iconType:"solid",iconName:"bookingValidityIcon"}],["core/paragraph",{fontSize:"x-small",content:"<strong>"+(0,t.__)("Booking validity:","tour-operator")+"</strong>"}]]],["core/group",{layout:{type:"flex",flexWrap:"nowrap"}},[["core/paragraph",{metadata:{bindings:{content:{source:"lsx/post-meta",args:{key:"booking_validity_start"}}}},content:""}],["core/paragraph",{content:"-"}],["core/paragraph",{metadata:{bindings:{content:{source:"lsx/post-meta",args:{key:"booking_validity_end"}}}},content:"End"}]]]],example:{innerBlocks:[{name:"core/group",attributes:{},innerBlocks:[{name:"core/group",attributes:{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},innerBlocks:[{name:"lsx-tour-operator/icons",attributes:{iconType:"solid",iconName:"bookingValidityIcon"}},{name:"core/paragraph",attributes:{content:"<strong>"+(0,t.__)("Booking validity: ","tour-operator")+"</strong>"+(0,t.__)("Start Date - End Date","tour-operator")}}]}]}]}})})()})}(); No newline at end of file
!function(){"use strict";var t=window.wp.i18n;wp.domReady(()=>{!function(t,o,r,e={}){return function(t){const{postTypes:o=[],templateSlugs:r=[],registerFunction:e,timeout:n=100}=t;if(!e||"function"!=typeof e)throw new Error("registerFunction is required and must be a function");return function(){const{select:t}=wp.data;let a=!1,i=!1;const s=()=>{if(a||i)return a;if(i=!0,(()=>{try{const e=t("core/editor")?.getCurrentPostType(),n=t("core/editor")?.getEditedPostSlug();return!!e&&(!!o.includes(e)||!("wp_template"!==e&&"wp_template_part"!==e||!n||!(r.length>0))&&r.some(t=>"string"==typeof t?n.includes(t):t instanceof RegExp&&t.test(n)))}catch(t){return console.error("Error in shouldRegister:",t),!1}})())try{return e(),a=!0,i=!1,!0}catch(t){return console.error("Error during block registration:",t),i=!1,!1}return i=!1,!1};setTimeout(()=>{if(!s()){let t=!1;const o=wp.data.subscribe(()=>{t||s()&&(t=!0,o())})}},n)}}({postTypes:["tour"],templateSlugs:["tour"],registerFunction:r,...e})}(0,0,()=>{wp.blocks.registerBlockVariation("core/group",{name:"lsx-tour-operator/booking-validity",title:(0,t.__)("Booking validity","tour-operator"),icon:"calendar",category:"lsx-tour-operator",description:(0,t.__)("Displays the booking validity period for a tour.","tour-operator"),keywords:[(0,t.__)("booking","tour-operator"),(0,t.__)("validity","tour-operator"),(0,t.__)("tour","tour-operator")],isActive:(t,o)=>t.className===o.className,attributes:{metadata:{name:(0,t.__)("Booking validity","tour-operator")},className:"lsx-booking-validity-wrapper",layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"top"}},innerBlocks:[["core/group",{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},[["lsx-tour-operator/icons",{iconType:"solid",iconName:"bookingValidityIcon"}]]],["core/group",{layout:{type:"flex",flexWrap:"nowrap"}},[["core/paragraph",{metadata:{bindings:{content:{source:"lsx/post-meta",args:{key:"booking_validity_start"}}}},prefix:(0,t.__)("Booking validity:","tour-operator"),prefixBold:!0,content:""}],["core/paragraph",{content:"-"}],["core/paragraph",{metadata:{bindings:{content:{source:"lsx/post-meta",args:{key:"booking_validity_end"}}}},content:"End"}]]]],example:{innerBlocks:[{name:"core/group",attributes:{},innerBlocks:[{name:"core/group",attributes:{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},innerBlocks:[{name:"lsx-tour-operator/icons",attributes:{iconType:"solid",iconName:"bookingValidityIcon"}},{name:"core/paragraph",attributes:{content:"<strong>"+(0,t.__)("Booking validity: ","tour-operator")+"</strong>"+(0,t.__)("Start Date - End Date","tour-operator")}}]}]}]}})})()})}(); No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Localise or remove hard-coded “End” fallback

The new prefix-based setup for booking validity looks good and uses __() correctly, but the last paragraph still has a hard-coded English fallback:

content:"End"

Since this is user-facing, consider either:

  • Wrapping it in the i18n call (in the source file) so the build becomes content:(0,t.__)("End","tour-operator"), or
  • Setting content:"" and relying entirely on the bound booking_validity_end meta so there is no untranslated fallback string.

This keeps the block fully localisable and avoids stray English text in non-English sites.

🤖 Prompt for AI Agents
In build/blocks/booking-validity/index.js around line 1, the paragraph fallback
uses a hard-coded English string content:"End" which is not localised; update
the original source block definition (not the generated build) to either wrap
that fallback with the i18n call so it becomes content: __( "End",
"tour-operator" ) or remove the fallback by setting content:"" and rely on the
bound booking_validity_end meta; apply the change in the source JS/JSX that
generates this build and re-run the build so the built file reflects the
localisation change.

@@ -1 +1 @@
!function(){"use strict";var e=window.wp.i18n;wp.domReady(()=>{!function(e,t,r,o={}){return function(e){const{postTypes:t=[],templateSlugs:r=[],registerFunction:o,timeout:n=100}=e;if(!o||"function"!=typeof o)throw new Error("registerFunction is required and must be a function");return function(){const{select:e}=wp.data;let a=!1,s=!1;const i=()=>{if(a||s)return a;if(s=!0,(()=>{try{const o=e("core/editor")?.getCurrentPostType(),n=e("core/editor")?.getEditedPostSlug();return!!o&&(!!t.includes(o)||!("wp_template"!==o&&"wp_template_part"!==o||!n||!(r.length>0))&&r.some(e=>"string"==typeof e?n.includes(e):e instanceof RegExp&&e.test(n)))}catch(e){return console.error("Error in shouldRegister:",e),!1}})())try{return o(),a=!0,s=!1,!0}catch(e){return console.error("Error during block registration:",e),s=!1,!1}return s=!1,!1};setTimeout(()=>{if(!i()){let e=!1;const t=wp.data.subscribe(()=>{e||i()&&(e=!0,t())})}},n)}}({postTypes:["tour"],templateSlugs:["tour"],registerFunction:r,...o})}(0,0,()=>{wp.blocks.registerBlockVariation("core/group",{name:"lsx-tour-operator/ends-in",title:(0,e.__)("Ends in","tour-operator"),description:(0,e.__)("Displays the destination where the tour ends.","tour-operator"),icon:wp.element.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:20,height:20,viewBox:"0 0 20 20",fill:"none"},wp.element.createElement("path",{d:"M13.0813 8.03477L9.30937 2.11602C9.15938 1.87852 8.91563 1.71602 8.64062 1.66915L7.29375 1.43165C6.95625 1.37227 6.6625 1.65977 6.7125 1.99727L7.4625 7.04727L4.18125 6.46915L3.125 4.5379C3.01562 4.33477 2.81875 4.19415 2.59687 4.15665L2.0625 4.0629C1.75625 4.00977 1.475 4.24727 1.475 4.55665L1.49375 7.87852C1.5 8.84415 2.19375 9.66915 3.14687 9.8379L3.56875 9.9129L16.6187 12.2129C17.5719 12.3816 18.4781 11.7441 18.6469 10.7941C18.8156 9.84415 18.1781 8.93477 17.2281 8.76602L13.0813 8.03477ZM8 14.0004C8.55312 14.0004 9 13.5535 9 13.0004C9 12.4473 8.55312 12.0004 8 12.0004C7.44688 12.0004 7 12.4473 7 13.0004C7 13.5535 7.44688 14.0004 8 14.0004ZM12.1 13.5223C12.1 12.9691 11.6531 12.5223 11.1 12.5223C10.5469 12.5223 10.1 12.9691 10.1 13.5223C10.1 14.0754 10.5469 14.5223 11.1 14.5223C11.6531 14.5223 12.1 14.0754 12.1 13.5223ZM2 16.0004C1.44687 16.0004 1 16.4473 1 17.0004C1 17.5535 1.44687 18.0004 2 18.0004H18C18.5531 18.0004 19 17.5535 19 17.0004C19 16.4473 18.5531 16.0004 18 16.0004H2Z",fill:"#currentColor"})),category:"lsx-tour-operator",keywords:[(0,e.__)("arrival","tour-operator"),(0,e.__)("ends in","tour-operator"),(0,e.__)("to","tour-operator")],isActive:(e,t)=>e.className===t.className,attributes:{metadata:{name:(0,e.__)("Ends in","tour-operator")},className:"lsx-ends-in-wrapper",layout:{type:"constrained"}},innerBlocks:[["core/group",{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},[["lsx-tour-operator/icons",{iconType:"outline",iconName:"departsFromEndsInIcon"}],["core/paragraph",{content:"<strong>"+(0,e.__)("Ends In:","tour-operator")+"</strong>"}]]],["core/group",{layout:{type:"flex",flexWrap:"nowrap"}},[["core/paragraph",{metadata:{bindings:{content:{source:"lsx/post-connection",args:{key:"ends_in"}}}},content:""}]]]],example:{innerBlocks:[{name:"core/group",attributes:{},innerBlocks:[{name:"core/group",attributes:{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},innerBlocks:[{name:"lsx-tour-operator/icons",attributes:{iconType:"outline",iconName:"departsFromEndsInIcon"}},{name:"core/paragraph",attributes:{content:"<strong>"+(0,e.__)("Ends In:","tour-operator")+"</strong> "+(0,e.__)("Cape Town","tour-operator")}}]}]}]}})})()})}(); No newline at end of file
!function(){"use strict";var e=window.wp.i18n;wp.domReady(()=>{!function(e,t,r,o={}){return function(e){const{postTypes:t=[],templateSlugs:r=[],registerFunction:o,timeout:n=100}=e;if(!o||"function"!=typeof o)throw new Error("registerFunction is required and must be a function");return function(){const{select:e}=wp.data;let a=!1,i=!1;const s=()=>{if(a||i)return a;if(i=!0,(()=>{try{const o=e("core/editor")?.getCurrentPostType(),n=e("core/editor")?.getEditedPostSlug();return!!o&&(!!t.includes(o)||!("wp_template"!==o&&"wp_template_part"!==o||!n||!(r.length>0))&&r.some(e=>"string"==typeof e?n.includes(e):e instanceof RegExp&&e.test(n)))}catch(e){return console.error("Error in shouldRegister:",e),!1}})())try{return o(),a=!0,i=!1,!0}catch(e){return console.error("Error during block registration:",e),i=!1,!1}return i=!1,!1};setTimeout(()=>{if(!s()){let e=!1;const t=wp.data.subscribe(()=>{e||s()&&(e=!0,t())})}},n)}}({postTypes:["tour"],templateSlugs:["tour"],registerFunction:r,...o})}(0,0,()=>{wp.blocks.registerBlockVariation("core/group",{name:"lsx-tour-operator/ends-in",title:(0,e.__)("Ends in","tour-operator"),description:(0,e.__)("Displays the destination where the tour ends.","tour-operator"),icon:wp.element.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:20,height:20,viewBox:"0 0 20 20",fill:"none"},wp.element.createElement("path",{d:"M13.0813 8.03477L9.30937 2.11602C9.15938 1.87852 8.91563 1.71602 8.64062 1.66915L7.29375 1.43165C6.95625 1.37227 6.6625 1.65977 6.7125 1.99727L7.4625 7.04727L4.18125 6.46915L3.125 4.5379C3.01562 4.33477 2.81875 4.19415 2.59687 4.15665L2.0625 4.0629C1.75625 4.00977 1.475 4.24727 1.475 4.55665L1.49375 7.87852C1.5 8.84415 2.19375 9.66915 3.14687 9.8379L3.56875 9.9129L16.6187 12.2129C17.5719 12.3816 18.4781 11.7441 18.6469 10.7941C18.8156 9.84415 18.1781 8.93477 17.2281 8.76602L13.0813 8.03477ZM8 14.0004C8.55312 14.0004 9 13.5535 9 13.0004C9 12.4473 8.55312 12.0004 8 12.0004C7.44688 12.0004 7 12.4473 7 13.0004C7 13.5535 7.44688 14.0004 8 14.0004ZM12.1 13.5223C12.1 12.9691 11.6531 12.5223 11.1 12.5223C10.5469 12.5223 10.1 12.9691 10.1 13.5223C10.1 14.0754 10.5469 14.5223 11.1 14.5223C11.6531 14.5223 12.1 14.0754 12.1 13.5223ZM2 16.0004C1.44687 16.0004 1 16.4473 1 17.0004C1 17.5535 1.44687 18.0004 2 18.0004H18C18.5531 18.0004 19 17.5535 19 17.0004C19 16.4473 18.5531 16.0004 18 16.0004H2Z",fill:"#currentColor"})),category:"lsx-tour-operator",keywords:[(0,e.__)("arrival","tour-operator"),(0,e.__)("ends in","tour-operator"),(0,e.__)("to","tour-operator")],isActive:(e,t)=>e.className===t.className,attributes:{metadata:{name:(0,e.__)("Ends in","tour-operator")},className:"lsx-ends-in-wrapper",layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"top"}},innerBlocks:[["core/group",{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},[["lsx-tour-operator/icons",{iconType:"outline",iconName:"departsFromEndsInIcon"}]]],["core/group",{layout:{type:"flex",flexWrap:"nowrap"}},[["core/paragraph",{metadata:{bindings:{content:{source:"lsx/post-connection",args:{key:"ends_in"}}}},prefix:(0,e.__)("Ends In:","tour-operator"),prefixBold:!0,content:""}]]]],example:{innerBlocks:[{name:"core/group",attributes:{},innerBlocks:[{name:"core/group",attributes:{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},innerBlocks:[{name:"lsx-tour-operator/icons",attributes:{iconType:"outline",iconName:"departsFromEndsInIcon"}},{name:"core/paragraph",attributes:{content:"<strong>"+(0,e.__)("Ends In:","tour-operator")+"</strong> "+(0,e.__)("Cape Town","tour-operator")}}]}]}]}})})()})}(); No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find and examine the source file for ends-in block

echo "=== Searching for ends-in source file ==="
fd "ends-in" src/blocks/ -t d 2>/dev/null || echo "Directory not found with fd"

# Alternative approach - list src/blocks structure
echo "=== Structure of src/blocks ==="
find src/blocks -maxdepth 2 -type f -name "*.js" 2>/dev/null | head -20

echo "=== Checking for ends-in source files ==="
find . -path "*/src/*blocks*ends-in*" -type f 2>/dev/null

# Look for any ends-in related source
echo "=== Any ends-in files in src ==="
find src -name "*ends-in*" 2>/dev/null

Repository: lightspeedwp/tour-operator

Length of output: 1186


🏁 Script executed:

#!/bin/bash
# Check build and source directories more broadly

echo "=== Build directory structure ==="
ls -la build/blocks/ 2>/dev/null | head -20

echo "=== Source blocks directory ==="
ls -la src/blocks/ 2>/dev/null | head -20

echo "=== Looking for source TypeScript/JSX files ==="
find src/blocks -name "*.ts" -o -name "*.tsx" -o -name "*.jsx" 2>/dev/null | head -20

Repository: lightspeedwp/tour-operator

Length of output: 2709


🏁 Script executed:

#!/bin/bash
# Search for the minified file and any related source
echo "=== File info about build/blocks/ends-in/index.js ==="
ls -lh build/blocks/ends-in/index.js 2>/dev/null
wc -l build/blocks/ends-in/index.js 2>/dev/null

echo "=== Checking for corresponding source ==="
git ls-files | grep -i "ends-in" 2>/dev/null

echo "=== All JavaScript/TypeScript files in repository ==="
git ls-files | grep -E "\.(js|ts|jsx|tsx)$" | grep -i block | head -30

Repository: lightspeedwp/tour-operator

Length of output: 1696


🏁 Script executed:

#!/bin/bash
# Read the source file
echo "=== Source file: src/blocks/ends-in/index.js ==="
cat -n src/blocks/ends-in/index.js

echo -e "\n=== Block configuration ==="
cat -n src/blocks/ends-in/block.json

Repository: lightspeedwp/tour-operator

Length of output: 10066


🏁 Script executed:

#!/bin/bash
# Check for ESLint configuration and any linting issues
echo "=== ESLint/Prettier config ==="
find . -maxdepth 2 -name ".eslintrc*" -o -name "prettier.config*" | head -5

# Check if there are any obvious formatting issues
echo -e "\n=== Checking for multiple consecutive blank lines ==="
grep -n "^$" src/blocks/ends-in/index.js | tail -5

# Check indentation consistency
echo -e "\n=== Indentation check (lines with tabs vs spaces) ==="
grep -P "\t" src/blocks/ends-in/index.js | head -5

# Verify all imports are used
echo -e "\n=== Checking import usage ==="
echo "registerForPostTypesAndTemplates imported on line 12:"
grep -n "registerForPostTypesAndTemplates" src/blocks/ends-in/index.js

Repository: lightspeedwp/tour-operator

Length of output: 581


🏁 Script executed:

#!/bin/bash
# Check WordPress coding standards compliance more thoroughly
echo "=== Check for security escaping patterns ==="
grep -n "esc_" src/blocks/ends-in/index.js || echo "No direct escaping needed (uses __() for i18n)"

echo -e "\n=== Check for nonce verification ==="
grep -n "wp_nonce\|nonce\|_wpnonce\|check_admin_referer" src/blocks/ends-in/index.js || echo "No nonce needed (block registration only)"

echo -e "\n=== Verify HTML in example content ==="
grep -n "<strong>" src/blocks/ends-in/index.js

echo -e "\n=== Check semicolon termination ==="
tail -20 src/blocks/ends-in/index.js | grep -E "^[^/].*[};,)]$"

Repository: lightspeedwp/tour-operator

Length of output: 919


🏁 Script executed:

#!/bin/bash
# Verify the indentation issue more precisely
echo "=== Detailed indentation analysis around lines 49-53 ==="
sed -n '48,54p' src/blocks/ends-in/index.js | cat -A

echo -e "\n=== Check rest of file for tab usage ==="
echo "Total lines with tabs in file:"
grep -c $'\t' src/blocks/ends-in/index.js

echo -e "\nLines with tabs:"
grep -n $'\t' src/blocks/ends-in/index.js

Repository: lightspeedwp/tour-operator

Length of output: 601


🏁 Script executed:

#!/bin/bash
# Verify line 97 spacing issue
echo "=== Check line 97 prefix spacing ==="
sed -n '97p' src/blocks/ends-in/index.js | cat -A

Repository: lightspeedwp/tour-operator

Length of output: 165


Fix indentation and spacing inconsistencies in source file.

The source file at src/blocks/ends-in/index.js contains indentation and spacing issues that violate WordPress Coding Standards:

  • Lines 49–53: Use tabs instead of spaces for the layout object
  • Lines 97–98: Use tabs instead of spaces for the prefix and prefixBold properties
  • Line 97: Extra space before colon in prefix : (should be prefix: )

Convert all tabs to spaces for consistent indentation matching the rest of the file, and remove the extra space on line 97.

🤖 Prompt for AI Agents
In build/blocks/ends-in/index.js around lines 49–53 and 97–98, the file has
inconsistent indentation and an extra space before the colon on the prefix
property; fix by replacing any tab characters in those lines with the same
space-based indentation used elsewhere in the file, normalize spacing for the
layout object and the prefix/prefixBold properties to match the project's spaces
style, remove the extra space so "prefix : " becomes "prefix: ", and trim any
trailing whitespace on the affected lines.

Comment on lines +19 to +28
$icon_type = isset( $attributes['iconType'] ) ? sanitize_key( $attributes['iconType'] ) : 'outline';
$icon_name = isset( $attributes['iconName'] ) ? $attributes['iconName'] : '';

// If no icon name is provided, return nothing.
if ( empty( $icon_name ) ) {
return;
}

// Get the SVG content.
$svg_content = lsx_to_get_icon_svg( $icon_type, $icon_name );
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cd build/blocks/icons && pwd && cat -n render.php | sed -n '1,35p'

Repository: lightspeedwp/tour-operator

Length of output: 1175


🏁 Script executed:

rg -nP --type=php -A40 'function lsx_to_get_icon_svg'

Repository: lightspeedwp/tour-operator

Length of output: 2302


Add explicit path traversal prevention for iconName.

The $icon_name on line 20 is assigned directly from user input without sanitization. The lsx_to_get_icon_svg() function does not prevent path traversal sequences like ../ from being processed, relying only on file_exists() as a weak secondary check. Apply basename() to strip directory components:

 $icon_type = isset( $attributes['iconType'] ) ? sanitize_key( $attributes['iconType'] ) : 'outline';
-$icon_name = isset( $attributes['iconName'] ) ? $attributes['iconName'] : '';
+$icon_name = isset( $attributes['iconName'] ) ? basename( $attributes['iconName'] ) : '';

Alternatively, validate that $icon_name contains only allowed characters (alphanumerics and hyphens) before passing to lsx_to_get_icon_svg().

📝 Committable suggestion

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

Suggested change
$icon_type = isset( $attributes['iconType'] ) ? sanitize_key( $attributes['iconType'] ) : 'outline';
$icon_name = isset( $attributes['iconName'] ) ? $attributes['iconName'] : '';
// If no icon name is provided, return nothing.
if ( empty( $icon_name ) ) {
return;
}
// Get the SVG content.
$svg_content = lsx_to_get_icon_svg( $icon_type, $icon_name );
$icon_type = isset( $attributes['iconType'] ) ? sanitize_key( $attributes['iconType'] ) : 'outline';
$icon_name = isset( $attributes['iconName'] ) ? basename( $attributes['iconName'] ) : '';
// If no icon name is provided, return nothing.
if ( empty( $icon_name ) ) {
return;
}
// Get the SVG content.
$svg_content = lsx_to_get_icon_svg( $icon_type, $icon_name );
🤖 Prompt for AI Agents
In build/blocks/icons/render.php around lines 19 to 28, $icon_name is taken from
user input without sanitization which can allow path traversal; sanitize it
before passing to lsx_to_get_icon_svg() by stripping directory components with
basename($icon_name) and/or validating it against a strict pattern (e.g. allow
only alphanumerics and hyphens via preg_match) and if validation fails return
early; then pass the sanitized/validated value to lsx_to_get_icon_svg().

Comment on lines +81 to +82
prefix : __('Number of Units:', 'tour-operator'),
prefixBold: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n src/blocks/number-of-rooms/index.js | head -120

Repository: lightspeedwp/tour-operator

Length of output: 5340


Standardize terminology: block is titled "Number of Rooms" but prefix label displays "Number of Units:"

The block's title, metadata name, and meta key all use "Number of Rooms" (lines 17, 31, 76), but the user-facing prefix label on lines 81-82 and the example on line 110 display "Number of Units:". This inconsistency will confuse users—the block name doesn't match the displayed label. Standardize to "Number of Rooms" throughout, including the prefix strings and example content.

🤖 Prompt for AI Agents
In src/blocks/number-of-rooms/index.js around lines 81-82 (and the example text
at ~line 110), the displayed prefix and example use "Number of Units:" while the
block title/metadata use "Number of Rooms", causing inconsistent UX; update the
user-facing strings to "Number of Rooms:" (and corresponding example content) so
they match the block title/metadata, and ensure the i18n calls
(__('...','tour-operator')) are updated to the new "Number of Rooms:" text.

layout: {
type: 'flex',
flexWrap: 'nowrap',
verticalAlignment: 'top'
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Indentation inconsistency: tabs mixed with spaces.

Lines 40, 63, 92-93, and 148 appear to use tabs while the surrounding code uses spaces for indentation. This affects code readability and should be consistent.

🤖 Prompt for AI Agents
In src/blocks/rating/index.js around lines 40, 63, 92-93, and 148, there are
mixed tabs and spaces causing inconsistent indentation; replace any tabs on
those lines with the project's standard indentation (spaces) to match
surrounding code, reformat the affected lines so they use only spaces, and run
the project's formatter or linter to ensure consistency across the file.

…old prefixes for clarity; update 20+ blocks for consistent prefix formatting and responsive layout improvements.
@github-actions github-actions bot added lang:md Markdown content/docs status:needs-review Awaiting code review and removed status:needs-review Awaiting code review labels Dec 5, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/blocks/special-interests/index.js (1)

92-121: Align example with prefix-based label to match actual structure

At runtime the Interests Content paragraph uses prefix and prefixBold to render the “Special Interests:” label inline with the meta value, but the example still hardcodes a separate bold label paragraph in the first group and leaves the second paragraph as value-only content. This means inserter previews won’t mirror the real variation structure.

Recommend updating the example so the first group holds only the icon, and the second group’s paragraph carries both prefix/prefixBold and the example content, e.g.:

             example: {
                 attributes: {
                     className: 'lsx-special-interests-wrapper',
                 },
                 innerBlocks: [
                     {
                         name: 'core/group',
                         attributes: {
                             layout: {
                                 type: 'flex',
                                 flexWrap: 'nowrap',
                                 verticalAlignment: 'middle',
                             },
                         },
-                        innerBlocks: [
-                            {
-                                name: 'lsx-tour-operator/icons',
-                                attributes: {
-                                    iconType: 'solid',
-                                    iconName: 'specialInterestsIcon',
-                                },
-                            },
-                            {
-                                name: 'core/paragraph',
-                                attributes: {
-                                    content: '<strong>' + __('Special Interests:', 'tour-operator') + '</strong>',
-                                },
-                            },
-                        ],
+                        innerBlocks: [
+                            {
+                                name: 'lsx-tour-operator/icons',
+                                attributes: {
+                                    iconType: 'solid',
+                                    iconName: 'specialInterestsIcon',
+                                },
+                            },
+                        ],
                     },
                     {
                         name: 'core/group',
                         attributes: {
                             layout: {
                                 type: 'flex',
                                 flexWrap: 'nowrap',
                             },
                         },
                         innerBlocks: [
                             {
                                 name: 'core/paragraph',
                                 attributes: {
-                                    content: __('Wildlife viewing, Photography, Cultural experiences, Adventure activities', 'tour-operator'),
+                                    prefix: __('Special Interests:', 'tour-operator'),
+                                    prefixBold: true,
+                                    content: __('Wildlife viewing, Photography, Cultural experiences, Adventure activities', 'tour-operator'),
                                 },
                             },
                         ],
                     },
                 ],
             },

This keeps the example aligned with the new single-line prefix approach and avoids divergent editor previews.

Also applies to: 123-171

src/blocks/departs-from/index.js (1)

30-33: SVG icon fill should use currentColor (without #).

The path's fill is set to '#currentColor', which is not a valid CSS color keyword. SVG fill attributes accept the currentColor keyword to inherit the text color, but the hash prefix (#) is not valid in this context—it's used for hex color references, not keywords. Remove the # so the icon inherits the surrounding text color properly.

-                    fill: '#currentColor',
+                    fill: 'currentColor',
♻️ Duplicate comments (1)
src/blocks/facts-regions-wrapper/index.js (1)

74-88: Minor: Align prefix label with example and visual copy

The live paragraph uses prefix: __( 'Regions', 'tour-operator' ), while the example still shows '<strong>' + __('Regions: ', 'tour-operator') + '</strong>'…, so the actual label will render without the colon even though the example (and likely the design) expects “Regions:”. Please confirm whether dropping the colon is intentional; if not, consider updating the prefix (and/or the example) to a consistent, localised “Regions:” label.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between da97126 and ddef6e4.

📒 Files selected for processing (10)
  • build/blocks/departs-from/index.asset.php (1 hunks)
  • build/blocks/departs-from/index.js (1 hunks)
  • build/blocks/facts-regions-wrapper/index.asset.php (1 hunks)
  • build/blocks/facts-regions-wrapper/index.js (1 hunks)
  • build/blocks/special-interests/index.asset.php (1 hunks)
  • build/blocks/special-interests/index.js (1 hunks)
  • changelog.md (1 hunks)
  • src/blocks/departs-from/index.js (3 hunks)
  • src/blocks/facts-regions-wrapper/index.js (3 hunks)
  • src/blocks/special-interests/index.js (3 hunks)
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{php,js,ts,jsx,tsx,vue}

📄 CodeRabbit inference engine (.github/instructions/reviews.instructions.md)

Verify input is properly escaped and sanitized, security capabilities/nonce checks are in place

Files:

  • src/blocks/facts-regions-wrapper/index.js
  • src/blocks/special-interests/index.js
  • build/blocks/special-interests/index.js
  • build/blocks/special-interests/index.asset.php
  • src/blocks/departs-from/index.js
  • build/blocks/departs-from/index.asset.php
  • build/blocks/facts-regions-wrapper/index.js
  • build/blocks/facts-regions-wrapper/index.asset.php
  • build/blocks/departs-from/index.js
**/*.{js,ts,jsx,tsx,css,scss,sass}

📄 CodeRabbit inference engine (.github/instructions/reviews.instructions.md)

Avoid heavy re-renders, minimize CSS/JS payload, and implement lazy-loading where possible

Files:

  • src/blocks/facts-regions-wrapper/index.js
  • src/blocks/special-interests/index.js
  • build/blocks/special-interests/index.js
  • src/blocks/departs-from/index.js
  • build/blocks/facts-regions-wrapper/index.js
  • build/blocks/departs-from/index.js
**/*.{js,ts,jsx,tsx,php,py,java,go,rb}

📄 CodeRabbit inference engine (.github/instructions/reviews.instructions.md)

Verify CI pipeline is passing and no TODO comments are left in code before release

Files:

  • src/blocks/facts-regions-wrapper/index.js
  • src/blocks/special-interests/index.js
  • build/blocks/special-interests/index.js
  • build/blocks/special-interests/index.asset.php
  • src/blocks/departs-from/index.js
  • build/blocks/departs-from/index.asset.php
  • build/blocks/facts-regions-wrapper/index.js
  • build/blocks/facts-regions-wrapper/index.asset.php
  • build/blocks/departs-from/index.js
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use semicolons to terminate statements in JavaScript block code

Ensure all generated code follows ESLint rules and WordPress Coding Standards before deployment

Files:

  • src/blocks/facts-regions-wrapper/index.js
  • src/blocks/special-interests/index.js
  • build/blocks/special-interests/index.js
  • src/blocks/departs-from/index.js
  • build/blocks/facts-regions-wrapper/index.js
  • build/blocks/departs-from/index.js
**/*.{php,js,jsx,ts,tsx,json}

📄 CodeRabbit inference engine (GEMINI.md)

Follow WordPress Coding Standards including proper namespacing, security practices (sanitization/escaping), and code organization

Files:

  • src/blocks/facts-regions-wrapper/index.js
  • src/blocks/special-interests/index.js
  • build/blocks/special-interests/index.js
  • build/blocks/special-interests/index.asset.php
  • src/blocks/departs-from/index.js
  • build/blocks/departs-from/index.asset.php
  • build/blocks/facts-regions-wrapper/index.js
  • build/blocks/facts-regions-wrapper/index.asset.php
  • build/blocks/departs-from/index.js
**/*.{js,jsx,ts,tsx,php}

📄 CodeRabbit inference engine (GEMINI.md)

Implement accessibility features following WCAG 2.2 AA standards in all block components and patterns

Files:

  • src/blocks/facts-regions-wrapper/index.js
  • src/blocks/special-interests/index.js
  • build/blocks/special-interests/index.js
  • build/blocks/special-interests/index.asset.php
  • src/blocks/departs-from/index.js
  • build/blocks/departs-from/index.asset.php
  • build/blocks/facts-regions-wrapper/index.js
  • build/blocks/facts-regions-wrapper/index.asset.php
  • build/blocks/departs-from/index.js
**/*.{php,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Validate generated code against WordPress standards, test thoroughly, check security implications, and review for proper sanitization/escaping

Files:

  • src/blocks/facts-regions-wrapper/index.js
  • src/blocks/special-interests/index.js
  • build/blocks/special-interests/index.js
  • build/blocks/special-interests/index.asset.php
  • src/blocks/departs-from/index.js
  • build/blocks/departs-from/index.asset.php
  • build/blocks/facts-regions-wrapper/index.js
  • build/blocks/facts-regions-wrapper/index.asset.php
  • build/blocks/departs-from/index.js
**/*.{js,jsx,ts,tsx,php,scss,css}

📄 CodeRabbit inference engine (GEMINI.md)

Use camelCase for variable and function names, kebab-case for CSS classes, and snake_case for PHP variable names per WordPress Coding Standards

Files:

  • src/blocks/facts-regions-wrapper/index.js
  • src/blocks/special-interests/index.js
  • build/blocks/special-interests/index.js
  • build/blocks/special-interests/index.asset.php
  • src/blocks/departs-from/index.js
  • build/blocks/departs-from/index.asset.php
  • build/blocks/facts-regions-wrapper/index.js
  • build/blocks/facts-regions-wrapper/index.asset.php
  • build/blocks/departs-from/index.js
**/*.{js,jsx,ts,tsx,scss,css}

📄 CodeRabbit inference engine (GEMINI.md)

For performance optimization, implement code splitting, lazy loading, and minimize CSS/JavaScript bundle sizes in block components

Files:

  • src/blocks/facts-regions-wrapper/index.js
  • src/blocks/special-interests/index.js
  • build/blocks/special-interests/index.js
  • src/blocks/departs-from/index.js
  • build/blocks/facts-regions-wrapper/index.js
  • build/blocks/departs-from/index.js
src/blocks/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Block API v3 standards when developing blocks

Files:

  • src/blocks/facts-regions-wrapper/index.js
  • src/blocks/special-interests/index.js
  • src/blocks/departs-from/index.js
{src/blocks/**/*.{js,jsx,ts,tsx},src/**/*.php,inc/**/*.php}

📄 CodeRabbit inference engine (AGENTS.md)

Apply WCAG 2.2 AA accessibility standards to all blocks and UI components

Files:

  • src/blocks/facts-regions-wrapper/index.js
  • src/blocks/special-interests/index.js
  • src/blocks/departs-from/index.js
{README.md,CHANGELOG.md,CHANGELOG,*.md}

📄 CodeRabbit inference engine (.github/instructions/reviews.instructions.md)

Update README or pattern documentation and prepare CHANGELOG entry for documentation completeness

Files:

  • changelog.md
**/*.{html,htm,jsx,tsx,vue,php}

📄 CodeRabbit inference engine (.github/instructions/reviews.instructions.md)

Ensure keyboard navigation paths are accessible, semantic HTML is used, alt text is provided for images, and color contrast meets accessibility standards

Files:

  • build/blocks/special-interests/index.asset.php
  • build/blocks/departs-from/index.asset.php
  • build/blocks/facts-regions-wrapper/index.asset.php
**/blocks/**/*.php

📄 CodeRabbit inference engine (CLAUDE.md)

PHP render callbacks must be properly documented with descriptions of attributes and return values

Files:

  • build/blocks/special-interests/index.asset.php
  • build/blocks/departs-from/index.asset.php
  • build/blocks/facts-regions-wrapper/index.asset.php
**/*.php

📄 CodeRabbit inference engine (AGENTS.md)

Follow WordPress Coding Standards (WPCS) for all WordPress code

Files:

  • build/blocks/special-interests/index.asset.php
  • build/blocks/departs-from/index.asset.php
  • build/blocks/facts-regions-wrapper/index.asset.php
🧬 Code graph analysis (2)
build/blocks/special-interests/index.js (1)
build/blocks/accommodation-related-tour/index.js (5)
  • e (1-1)
  • e (1-1)
  • e (1-1)
  • n (1-1)
  • s (1-1)
build/blocks/facts-regions-wrapper/index.js (1)
build/blocks/tour-related-tour/index.js (1)
  • i (1-1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary
🔇 Additional comments (11)
src/blocks/facts-regions-wrapper/index.js (2)

38-42: Outer layout top alignment is appropriate for single-line facts rows

Setting verticalAlignment: 'top' on the wrapper flex layout should help keep multi-line content aligned consistently across different facts rows without any obvious side effects. This aligns with the broader layout pattern in this PR.


55-62: Icons inner group structure looks sound

The inner core/group with a single lsx-tour-operator/icons block, using a fixed destinationIcon name and iconType: 'solid', is straightforward and avoids any dynamic or unsafe inputs. This is lean and should behave well in terms of performance and rendering.

build/blocks/special-interests/index.js (1)

1-1: The prefix in the code is already correctly set to "Special Interests:" in both the source file (src/blocks/special-interests/index.js line 116) and the build artifact. There is no previous incorrect "Duration:" prefix to resolve—the code has been correct as-is.

Likely an incorrect or invalid review comment.

build/blocks/special-interests/index.asset.php (1)

1-1: Asset version bump looks correct

The array structure and dependencies are unchanged, and the new version string will correctly trigger cache-busting for the rebuilt block assets. No further action needed here.

src/blocks/special-interests/index.js (2)

57-66: Flex layout change supports single-line meta layout

Switching the wrapper attributes to layout: { type: 'flex', flexWrap: 'nowrap', verticalAlignment: 'top' } is consistent with the fast-facts pattern and should keep the icon + content inline while allowing the text itself to wrap gracefully on smaller viewports. No issues from a block registration point of view.


69-89: Confirm icon‑only title group remains accessible

With the Title group now effectively containing only the lsx-tour-operator/icons block, please confirm the icon markup is either marked as decorative (e.g. aria-hidden="true") or that the textual label exposed via the content paragraph/prefix is reliably associated for assistive technologies. This will ensure the change does not regress screen‑reader usability.

build/blocks/facts-regions-wrapper/index.js (1)

1-1: Prefix-based layout aligns well with single-line fast-facts objective

The variation config (flex layout with flexWrap: "nowrap" on the wrapper and the group around the prefixed paragraph, plus verticalAlignment: "top" on the outer layout) should keep each Regions fact on a single visual line for short values and allow clean wrapping when the value is longer. Moving the “Regions” label into prefix with prefixBold: true is consistent with the new prefix system and keeps the label/value pairing semantically together without introducing new sanitisation or accessibility risks in this JS layer.

build/blocks/departs-from/index.asset.php (1)

1-1: Asset version bump only – no functional impact.

This file just updates the asset version hash while keeping dependencies unchanged, which is appropriate for the underlying block updates.

src/blocks/departs-from/index.js (2)

47-52: Flex wrapper layout supports single-line Fast Facts and tidy wrapping.

Switching the wrapper to a flex layout with flexWrap: 'nowrap' and verticalAlignment: 'top' keeps the icon and content together on one line for short values while top-aligning longer, wrapped content, which matches the Fast Facts single-line and graceful-wrapping objectives.


84-99: Prefix configuration for “Departs From” looks correct and resolves the earlier label issue.

Adding a bold, translatable prefix of “Departs From:” on the bound paragraph keeps the label inline with the dynamic departs_from value and avoids the extra label block, aligning with the new prefix pattern and fixing the previous “Duration:” copy problem.

build/blocks/departs-from/index.js (1)

1-1: Generated bundle matches the updated departs-from variation.

The minified registration code correctly mirrors the src changes (flex layout with top alignment and the “Departs From:” prefix on the bound paragraph). As this is a build artefact, any future adjustments should be made in src/blocks/departs-from/index.js and re-built rather than editing this file directly.

@@ -1 +1 @@
!function(){"use strict";var t=window.wp.i18n;wp.domReady(()=>{!function(t,e,r,o={}){return function(t){const{postTypes:e=[],templateSlugs:r=[],registerFunction:o,timeout:n=100}=t;if(!o||"function"!=typeof o)throw new Error("registerFunction is required and must be a function");return function(){const{select:t}=wp.data;let i=!1,a=!1;const s=()=>{if(i||a)return i;if(a=!0,(()=>{try{const o=t("core/editor")?.getCurrentPostType(),n=t("core/editor")?.getEditedPostSlug();return!!o&&(!!e.includes(o)||!("wp_template"!==o&&"wp_template_part"!==o||!n||!(r.length>0))&&r.some(t=>"string"==typeof t?n.includes(t):t instanceof RegExp&&t.test(n)))}catch(t){return console.error("Error in shouldRegister:",t),!1}})())try{return o(),i=!0,a=!1,!0}catch(t){return console.error("Error during block registration:",t),a=!1,!1}return a=!1,!1};setTimeout(()=>{if(!s()){let t=!1;const e=wp.data.subscribe(()=>{t||s()&&(t=!0,e())})}},n)}}({postTypes:["destination"],templateSlugs:["destination","country","region"],registerFunction:r,...o})}(0,0,()=>{wp.blocks.registerBlockVariation("core/group",{name:"lsx-tour-operator/facts-regions-wrapper",title:(0,t.__)("Regions list","tour-operator"),icon:"admin-site-alt",category:"lsx-tour-operator",description:(0,t.__)("Displays a list of regions associated with this destination.","tour-operator"),keywords:[(0,t.__)("regions","tour-operator"),(0,t.__)("destination","tour-operator"),(0,t.__)("location","tour-operator"),(0,t.__)("facts","tour-operator")],isActive:(t,e)=>t.className===e.className,attributes:{metadata:{name:(0,t.__)("Regions list","tour-operator")},className:"facts-regions-query-wrapper",layout:{type:"flex",flexWrap:"nowrap"}},innerBlocks:[["core/group",{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},[["lsx-tour-operator/icons",{iconType:"solid",iconName:"destinationIcon"}],["core/paragraph",{content:`<strong>${(0,t.__)("Regions","tour-operator")}</strong>`}]]],["core/group",{layout:{type:"flex",flexWrap:"nowrap"}},[["core/paragraph",{metadata:{bindings:{content:{source:"lsx/post-connection",args:{key:"post_children"}}}},content:""}]]]],example:{innerBlocks:[{name:"core/group",attributes:{},innerBlocks:[{name:"core/group",attributes:{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},innerBlocks:[{name:"lsx-tour-operator/icons",attributes:{iconType:"solid",iconName:"destinationIcon"}},{name:"core/paragraph",attributes:{content:"<strong>"+(0,t.__)("Regions: ","tour-operator")+"</strong> "+(0,t.__)("Kilimanjaro region","tour-operator")}}]}]}]}})})()})}(); No newline at end of file
!function(){"use strict";var t=window.wp.i18n;wp.domReady(()=>{!function(t,e,r,o={}){return function(t){const{postTypes:e=[],templateSlugs:r=[],registerFunction:o,timeout:n=100}=t;if(!o||"function"!=typeof o)throw new Error("registerFunction is required and must be a function");return function(){const{select:t}=wp.data;let i=!1,a=!1;const s=()=>{if(i||a)return i;if(a=!0,(()=>{try{const o=t("core/editor")?.getCurrentPostType(),n=t("core/editor")?.getEditedPostSlug();return!!o&&(!!e.includes(o)||!("wp_template"!==o&&"wp_template_part"!==o||!n||!(r.length>0))&&r.some(t=>"string"==typeof t?n.includes(t):t instanceof RegExp&&t.test(n)))}catch(t){return console.error("Error in shouldRegister:",t),!1}})())try{return o(),i=!0,a=!1,!0}catch(t){return console.error("Error during block registration:",t),a=!1,!1}return a=!1,!1};setTimeout(()=>{if(!s()){let t=!1;const e=wp.data.subscribe(()=>{t||s()&&(t=!0,e())})}},n)}}({postTypes:["destination"],templateSlugs:["destination","country","region"],registerFunction:r,...o})}(0,0,()=>{wp.blocks.registerBlockVariation("core/group",{name:"lsx-tour-operator/facts-regions-wrapper",title:(0,t.__)("Regions list","tour-operator"),icon:"admin-site-alt",category:"lsx-tour-operator",description:(0,t.__)("Displays a list of regions associated with this destination.","tour-operator"),keywords:[(0,t.__)("regions","tour-operator"),(0,t.__)("destination","tour-operator"),(0,t.__)("location","tour-operator"),(0,t.__)("facts","tour-operator")],isActive:(t,e)=>t.className===e.className,attributes:{metadata:{name:(0,t.__)("Regions list","tour-operator")},className:"facts-regions-query-wrapper",layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"top"}},innerBlocks:[["core/group",{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},[["lsx-tour-operator/icons",{iconType:"solid",iconName:"destinationIcon"}]]],["core/group",{layout:{type:"flex",flexWrap:"nowrap"}},[["core/paragraph",{metadata:{bindings:{content:{source:"lsx/post-connection",args:{key:"post_children"}}}},prefix:(0,t.__)("Regions","tour-operator"),prefixBold:!0,content:""}]]]],example:{innerBlocks:[{name:"core/group",attributes:{},innerBlocks:[{name:"core/group",attributes:{layout:{type:"flex",flexWrap:"nowrap",verticalAlignment:"middle"}},innerBlocks:[{name:"lsx-tour-operator/icons",attributes:{iconType:"solid",iconName:"destinationIcon"}},{name:"core/paragraph",attributes:{content:"<strong>"+(0,t.__)("Regions: ","tour-operator")+"</strong> "+(0,t.__)("Kilimanjaro region","tour-operator")}}]}]}]}})})()})}(); No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Align the example preview with the new prefix-based label

In the example config, the paragraph still uses inline HTML in content ("<strong>Regions: </strong> …"), while the real inner block now uses prefix + prefixBold with an empty content bound via metadata. For editorial clarity and easier visual QA, consider updating the example to mirror the actual structure (icon group + prefixed paragraph) so the inserter/preview behaves like the real variation.

🤖 Prompt for AI Agents
In build/blocks/facts-regions-wrapper/index.js around lines 1 to 1, the block
variation example uses a paragraph with inline HTML in its content
("<strong>Regions: </strong> …") which no longer matches the actual block
structure that uses an icon group plus a paragraph using prefix and prefixBold
with content bound via metadata; update the example to mirror the real
innerBlocks: make the example contain the icon group block followed by a
paragraph block that uses prefix:(0,t.__)("Regions","tour-operator"),
prefixBold:true and an empty content (or content bound via the same metadata
shape) so the inserter/preview reflects the real variation.

### Enhancements

#### Block System Improvements
- **Fast-Facts Meta Display Enhancement** - Implemented single-line display for fast-facts and meta data blocks with bold prefixes for improved clarity. Enhanced 20+ blocks including duration, travel styles, accommodation type, check-in/out times, ratings, and language blocks with consistent prefix formatting and responsive layout improvements - [#802](https://github.com/lightspeedwp/tour-operator/pull/802), Issue [#514](https://github.com/lightspeedwp/tour-operator/issues/514)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Expand changelog entry to document all significant technical improvements.

The current entry captures the fast-facts display enhancements but omits key technical additions documented in the PR objectives and AI summary, specifically:

  • Icons block server-side SVG rendering enhancement and icon sanitization
  • New Paragraph Prefix Block implementation
  • Asset version bumps and dependency updates
  • Mobile responsive design refinements

Per coding guidelines, CHANGELOG entries should document changes comprehensively for completeness. Consider consolidating all related improvements into this entry or splitting into separate entries if they represent distinct features.

Suggested expanded version:

- **Fast-Facts Meta Display Enhancement** - Implemented single-line display for fast-facts and meta data blocks with bold prefixes for improved clarity. Enhanced 20+ blocks including duration, travel styles, accommodation type, check-in/out times, ratings, and language blocks with consistent prefix formatting and responsive layout improvements - [#802](https://github.com/lightspeedwp/tour-operator/pull/802), Issue [#514](https://github.com/lightspeedwp/tour-operator/issues/514)
+ **Fast-Facts Meta Display Enhancement** - Implemented single-line display for fast-facts and meta data blocks with bold prefixes for improved clarity. Enhanced 20+ blocks including duration, travel styles, accommodation type, check-in/out times, ratings, and language blocks with consistent prefix formatting and responsive layout improvements. Added new Paragraph Prefix Block with editor controls and server-side rendering. Enhanced Icons block with server-side SVG rendering and improved icon name sanitization. Updated asset versions and re-integrated @wordpress/blocks and @wordpress/block-library dependencies for improved frontend rendering - [#802](https://github.com/lightspeedwp/tour-operator/pull/802), Issue [#514](https://github.com/lightspeedwp/tour-operator/issues/514)
📝 Committable suggestion

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

Suggested change
- **Fast-Facts Meta Display Enhancement** - Implemented single-line display for fast-facts and meta data blocks with bold prefixes for improved clarity. Enhanced 20+ blocks including duration, travel styles, accommodation type, check-in/out times, ratings, and language blocks with consistent prefix formatting and responsive layout improvements - [#802](https://github.com/lightspeedwp/tour-operator/pull/802), Issue [#514](https://github.com/lightspeedwp/tour-operator/issues/514)
- **Fast-Facts Meta Display Enhancement** - Implemented single-line display for fast-facts and meta data blocks with bold prefixes for improved clarity. Enhanced 20+ blocks including duration, travel styles, accommodation type, check-in/out times, ratings, and language blocks with consistent prefix formatting and responsive layout improvements. Added new Paragraph Prefix Block with editor controls and server-side rendering. Enhanced Icons block with server-side SVG rendering and improved icon name sanitization. Updated asset versions and re-integrated @wordpress/blocks and @wordpress/block-library dependencies for improved frontend rendering - [#802](https://github.com/lightspeedwp/tour-operator/pull/802), Issue [#514](https://github.com/lightspeedwp/tour-operator/issues/514)
🤖 Prompt for AI Agents
In changelog.md around line 36, the Fast-Facts entry omits several significant
technical changes from the PR; update this entry to include the missing items
(server-side SVG rendering and icon sanitization for the icons block, the new
Paragraph Prefix Block, asset version bumps/dependency updates, and mobile
responsive refinements), and either consolidate them into the existing bullet
with clear comma-separated clauses and links to the PR/issue or create separate
changelog bullets for each distinct feature (include PR #802 and any relevant
issue links), keeping tone consistent with other entries and preserving
reference links and short context for each item.

@krugazul krugazul requested a review from tibiii December 5, 2025 14:43
@krugazul krugazul self-assigned this Dec 5, 2025
@github-actions github-actions bot added status:needs-review Awaiting code review and removed status:needs-review Awaiting code review labels Dec 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:block-editor area:ci Build and CI pipelines area:dependencies Composer/npm dependency work lang:css Stylesheets lang:javascript lang:md Markdown content/docs lang:php PHP code meta:needs-changelog Requires a changelog entry before merge status:needs-review Awaiting code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Single-Line Fast-Facts Meta Display

3 participants