Skip to content

Conversation

@betterdancing
Copy link
Contributor

@betterdancing betterdancing commented Jan 20, 2026

English | 简体中文

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)
  • Built its own designer, fully self-validated

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

Background and solution

What is the current behavior?

页面schema中的样式类,css以字符串形式呈现,不利于展示和阅读,尤其是字符串很长的时候

Issue Number: N/A

What is the new behavior?

将页面schema中的css以对象形式呈现,同时处理回显和出码的逻辑

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Styling now supports CSS objects in addition to strings across the app.
    • Live style updates now detect nested property changes for immediate application.
    • Style generation/serialization now consistently handles object-based styles.
  • Chores

    • Added a utility to convert CSS objects to CSS strings and unified parsing flows.

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

@github-actions github-actions bot added the enhancement New feature or request label Jan 20, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

Walkthrough

Adds a CSS normalization utility obJectCssToString, integrates it across style handling, broadens initStyle to accept objects, and enables deep watching of activeSchema.css so nested CSS-object changes trigger page CSS updates.

Changes

Cohort / File(s) Summary
Utility Function Addition
packages/utils/src/utils/index.ts
New exported obJectCssToString(css) converts CSS-in-JS objects to formatted CSS strings; returns strings unchanged.
Package Dependency
packages/vue-generator/package.json
Added workspace dependency @opentiny/tiny-engine-utils.
Style Normalization & Parsing
packages/settings/styles/src/components/classNamesContainer/index.vue, packages/settings/styles/src/js/useStyle.ts
Replaced direct formatting with object/string normalization: use cssStringToObject parser and obJectCssToString to produce normalized CSS strings before saving/parsing.
Render & Page Styling Integration
packages/canvas/render/src/RenderMain.ts, packages/canvas/render/src/material-function/page-getter.ts, packages/plugins/page/src/composable/usePage.ts
RenderMain watcher for activeSchema.css now uses { deep: true }. initStyle updated to accept `string
Vue SFC Style Generation
packages/vue-generator/src/generator/vue/sfc/generateStyle.js
Imports obJectCssToString and uses it to transform CSS objects into strings for SFC style output.

Sequence Diagram(s)

sequenceDiagram
  participant Editor as Editor/UI
  participant Settings as Styles Component
  participant Utils as obJectCssToString
  participant Parser as CSS Parser
  participant Renderer as RenderMain
  participant Generator as Vue Generator

  Editor->>Settings: edit/save CSS (string or object)
  Settings->>Utils: obJectCssToString(content)
  Utils-->>Settings: css string
  Settings->>Parser: cssStringToObject / parser(css string)
  Parser-->>Settings: parsed object/state
  Settings->>Renderer: update schema.css (object)
  Renderer->>Renderer: watcher (deep: true) triggers setPageCss
  Renderer->>Generator: initStyle(key, cssObject)
  Generator->>Utils: obJectCssToString(cssObject)
  Utils-->>Generator: css string for SFC output
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I nibble code, convert object to string,
Hop deep through watchers, hear the changelog sing,
Styles once scattered now neatly align,
A rabbit’s small patch makes the pages shine. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: representing CSS in the page schema as an object instead of a string, which directly addresses the core changes across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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

❤️ Share

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

Copy link
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: 2

🤖 Fix all issues with AI agents
In `@packages/settings/styles/src/components/classNamesContainer/index.vue`:
- Around line 450-474: The custom regex parser cssStringToObject is dropping
complex CSS constructs (at-rules like `@media/`@keyframes, multiple selectors, and
property values containing semicolons or braces); replace its use with the
existing CSS parser/stringify utilities used in updateGlobalStyle() so the code
round-trips without loss — locate cssStringToObject and change the logic to
parse the input using the shared parser API and to serialize using the matching
stringify utility (following updateGlobalStyle()’s pattern) so `@rules`, grouped
selectors and literal property values (e.g., content: ";") are preserved.

In `@packages/utils/src/utils/index.ts`:
- Around line 462-479: The function obJectCssToString should guard against css
being null or undefined (and non-object) to avoid runtime crashes; at the top of
obJectCssToString check if css is null/undefined and return an empty string (or
if typeof css === 'string' keep returning it), and when iterating ensure
properties and properties[property] are accessed only if properties is truthy
(skip null/undefined property objects) so the for-in loops never run on null;
update obJectCssToString accordingly to early-return for falsy/non-object inputs
and to safely handle missing nested property objects.
🧹 Nitpick comments (3)
packages/settings/styles/src/components/classNamesContainer/index.vue (1)

476-483: Rename cssString to reflect it’s now an object.
Minor clarity improvement.

✏️ Suggested rename
-  const cssString = cssStringToObject(content)
+  const cssObject = cssStringToObject(content)
...
-  updateSchema({ css: cssString })
+  updateSchema({ css: cssObject })
packages/canvas/render/src/material-function/page-getter.ts (2)

5-7: Unconventional function naming: obJectCssToString

The utility function name uses unusual casing (obJect with capital 'J'). Consider renaming to objectCssToString for consistency with standard camelCase conventions. This would need to be updated in packages/utils/src/utils/index.ts where it's defined.


21-39: Integration looks correct; consider a more specific type.

The changes correctly handle both string and object CSS content:

  • Early return guards against falsy content
  • Conversion via obJectCssToString happens before handleScopedCss (which expects a string)

The type object is quite broad. For improved type safety, consider defining a more specific type:

type CssObject = Record<string, Record<string, string>>
export function initStyle(key: string, content: string | CssObject)

This aligns with the structure expected by obJectCssToString (selector → properties → values).

Comment on lines +450 to +474
const cssStringToObject = (cssString) => {
cssString = cssString.replace(/\s+/g, ' ').trim()
const result = {}
const regex = /([^{]+)\{([^}]+)\}/g
let match
while ((match = regex.exec(cssString)) !== null) {
const selector = match[1].trim()
const properties = match[2].trim()
const propertiesObj = {}
const propertyRegex = /([^{;]+):([^;]+)/g
let propertyMatch
while ((propertyMatch = propertyRegex.exec(properties)) !== null) {
const key = propertyMatch[1].trim()
const value = propertyMatch[2].trim()
propertiesObj[key] = value
}
result[selector] = propertiesObj
}
return result
}
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:

# Locate the file and explore its structure
find . -name "index.vue" -path "*/classNamesContainer/*" -type f

Repository: opentiny/tiny-engine

Length of output: 135


🏁 Script executed:

# Find the parser module
find . -name "parser.ts" -o -name "parser.js" | grep -E "js/parser|parser\.ts|parser\.js"

Repository: opentiny/tiny-engine

Length of output: 160


🏁 Script executed:

# Explore the directory structure
ls -la packages/settings/styles/src/

Repository: opentiny/tiny-engine

Length of output: 407


🏁 Script executed:

# Read the index.vue file to see the cssStringToObject function in context
wc -l packages/settings/styles/src/components/classNamesContainer/index.vue

Repository: opentiny/tiny-engine

Length of output: 137


🏁 Script executed:

# Read the parser module
cat -n packages/settings/styles/src/js/parser.ts

Repository: opentiny/tiny-engine

Length of output: 7696


🏁 Script executed:

# Read the relevant section of index.vue around lines 450-474
sed -n '440,490p' packages/settings/styles/src/components/classNamesContainer/index.vue

Repository: opentiny/tiny-engine

Length of output: 1281


🏁 Script executed:

# Check the imports at the top of index.vue
head -50 packages/settings/styles/src/components/classNamesContainer/index.vue

Repository: opentiny/tiny-engine

Length of output: 2272


🏁 Script executed:

# Search for how css is used after being saved via updateSchema
rg -n "updateSchema.*css|css.*parseList|css.*stringify" packages/settings/styles/src/components/classNamesContainer/ -A 3 -B 3

Repository: opentiny/tiny-engine

Length of output: 765


🏁 Script executed:

# Check if there's any usage of parser elsewhere in the codebase for CSS serialization
rg -n "useStyle|parser.*css|stringify" packages/settings/styles/src/components/classNamesContainer/index.vue

Repository: opentiny/tiny-engine

Length of output: 310


🏁 Script executed:

# Look for how css data is processed when loading/editing
rg -n "state\.cssContent|cssContent" packages/settings/styles/src/components/classNamesContainer/index.vue -B 2 -A 2

Repository: opentiny/tiny-engine

Length of output: 222


🏁 Script executed:

# Check the useStyle hook to understand the data structure and how css is used
cat -n packages/settings/styles/src/js/useStyle.ts

Repository: opentiny/tiny-engine

Length of output: 13340


🏁 Script executed:

# Look for updateSchema implementation to see what it expects for css parameter
rg -n "updateSchema" packages/settings/styles/src/ -B 5 -A 10 | head -60

Repository: opentiny/tiny-engine

Length of output: 4823


🏁 Script executed:

# Look at the code-configurator component to understand what "content" parameter contains
rg -n "code-configurator" packages/settings/styles/src/components/classNamesContainer/index.vue -B 5 -A 10

Repository: opentiny/tiny-engine

Length of output: 1153


🏁 Script executed:

# Check how save function is called and what `@save` event provides
rg -n "@save|save.*content" packages/settings/styles/src/components/classNamesContainer/index.vue -B 2 -A 2

Repository: opentiny/tiny-engine

Length of output: 361


🏁 Script executed:

# Check what obJectCssToString does and how it relates to the reverse operation
rg -n "obJectCssToString" packages/ -B 2 -A 5

Repository: opentiny/tiny-engine

Length of output: 4370


🏁 Script executed:

# Get the full implementation of obJectCssToString
sed -n '462,500p' packages/utils/src/utils/index.ts

Repository: opentiny/tiny-engine

Length of output: 482


🏁 Script executed:

# Test cssStringToObject with complex CSS to understand its limitations
python3 << 'EOF'
import re

def cssStringToObject(cssString):
  cssString = cssString.replace(/\s+/g, ' ').strip()
  result = {}
  regex = r'([^{]+)\{([^}]+)\}'
  
  for match in re.finditer(regex, cssString):
    selector = match.group(1).strip()
    properties = match.group(2).strip()
    
    propertiesObj = {}
    propertyRegex = r'([^{;]+):([^;]+)'
    
    for propMatch in re.finditer(propertyRegex, properties):
      key = propMatch.group(1).strip()
      value = propMatch.group(2).strip()
      propertiesObj[key] = value
    
    result[selector] = propertiesObj
  
  return result

# Test cases
test_cases = [
  ('.simple { color: red; }', 'Simple selector'),
  ('.a, .b { color: blue; }', 'Multiple selectors (comma)'),
  ('@media (max-width: 600px) { .box { width: 100%; } }', '@media query'),
  ('@keyframes slide { from { left: 0; } to { left: 100%; } }', '@keyframes'),
  ('.with-pseudo:hover { color: green; }', 'Pseudo-class'),
  ('.content { content: ";"; }', 'Content with semicolon'),
  ('.test { font-family: "Arial, sans-serif"; }', 'Value with comma'),
]

for css, description in test_cases:
  result = cssStringToObject(css)
  print(f"\n{description}:")
  print(f"  Input: {css}")
  print(f"  Output: {result}")
  print(f"  Success: {bool(result)}")
EOF

Repository: opentiny/tiny-engine

Length of output: 150


🏁 Script executed:

# Test the regex parser with specific edge cases using JavaScript/Node
node << 'EOF'
const cssStringToObject = (cssString) => {
  cssString = cssString.replace(/\s+/g, ' ').trim()
  const result = {}
  const regex = /([^{]+)\{([^}]+)\}/g

  let match
  while ((match = regex.exec(cssString)) !== null) {
    const selector = match[1].trim()
    const properties = match[2].trim()

    const propertiesObj = {}

    const propertyRegex = /([^{;]+):([^;]+)/g
    let propertyMatch

    while ((propertyMatch = propertyRegex.exec(properties)) !== null) {
      const key = propertyMatch[1].trim()
      const value = propertyMatch[2].trim()
      propertiesObj[key] = value
    }

    result[selector] = propertiesObj
  }
  return result
}

const testCases = [
  { input: '.simple { color: red; }', desc: 'Simple selector' },
  { input: '.a, .b { color: blue; }', desc: 'Multiple selectors' },
  { input: '@media (max-width: 600px) { .box { width: 100%; } }', desc: '@media query' },
  { input: '.content { content: ";"; }', desc: 'Content with semicolon' },
  { input: '.test { background: url("data:image/svg+xml;..."); }', desc: 'Value with braces' },
]

testCases.forEach(({ input, desc }) => {
  const result = cssStringToObject(input)
  console.log(`\n${desc}:`)
  console.log(`  Input: ${input}`)
  console.log(`  Output: ${JSON.stringify(result)}`)
  console.log(`  Data loss: ${Object.keys(result).length === 0 ? 'YES' : 'PARTIAL'}`)
})
EOF

Repository: opentiny/tiny-engine

Length of output: 728


🏁 Script executed:

# Check what the parser module returns for complex CSS
sed -n '75,144p' packages/settings/styles/src/js/parser.ts | head -60

Repository: opentiny/tiny-engine

Length of output: 1276


🏁 Script executed:

# Verify the exact format updateSchema expects by checking if there are type definitions or usage patterns
rg -n "updateSchema.*css|css.*:" packages/settings/styles/src/ -A 2 -B 2 | head -40

Repository: opentiny/tiny-engine

Length of output: 2311


🏁 Script executed:

# Check if there's documentation or schema definition for what the css property should be
find packages -name "*.ts" -o -name "*.d.ts" | xargs grep -l "schema.*css\|css.*schema" | head -5

Repository: opentiny/tiny-engine

Length of output: 107


🏁 Script executed:

# Let's trace through what happens when updateSchema receives css parameter
# Check the useEditor to see the pattern more clearly
cat -n packages/settings/styles/src/js/useEditor.ts

Repository: opentiny/tiny-engine

Length of output: 2686


🏁 Script executed:

# Verify what format the save function should pass
# Look at the complete flow in index.vue around the save function
sed -n '470,490p' packages/settings/styles/src/components/classNamesContainer/index.vue

Repository: opentiny/tiny-engine

Length of output: 524


🏁 Script executed:

# Check what type of css parameter updateSchema actually expects
rg -n "pageSchema\.css\s*=" packages/settings/styles/src/ -B 2 -A 2

Repository: opentiny/tiny-engine

Length of output: 46


🏁 Script executed:

# Look for where the schema.css is read back
rg -n "getPageSchema.*css|schema\.css" packages/settings/styles/src/js/useStyle.ts -B 2 -A 5

Repository: opentiny/tiny-engine

Length of output: 336


🏁 Script executed:

# Check the watch that loads CSS from schema to understand the expected format
sed -n '176,189p' packages/settings/styles/src/js/useStyle.ts

Repository: opentiny/tiny-engine

Length of output: 424


🏁 Script executed:

# Understand the data flow: what gets stored and retrieved
# Check if css can be string or object in the schema
rg -n "css\s*:" packages/ -t ts -t vue | grep -E "schema.*css|css.*schema" | head -20

Repository: opentiny/tiny-engine

Length of output: 91


🏁 Script executed:

# Trace through a complete example: save -> updateSchema -> load
# Check how updateGlobalStyleStr preserves data
sed -n '268,293p' packages/settings/styles/src/js/useStyle.ts

Repository: opentiny/tiny-engine

Length of output: 692


🏁 Script executed:

# Final verification: trace the exact data type expected by updateSchema
# Look at how useEditor passes css to updateSchema (line 61)
sed -n '59,64p' packages/settings/styles/src/js/useEditor.ts

Repository: opentiny/tiny-engine

Length of output: 216


🏁 Script executed:

# And compare to how updateGlobalStyleStr does it
sed -n '261,266p' packages/settings/styles/src/js/useStyle.ts

Repository: opentiny/tiny-engine

Length of output: 225


🏁 Script executed:

# Verify what format the schema expects when it's loaded back
# Check line 180 in useStyle.ts more carefully
node << 'EOF'
// Simulate the obJectCssToString with different inputs

function obJectCssToString(css) {
  if (typeof css === 'string') {
    return css
  }
  let cssString = ''
  
  for (const selector in css) {
    const properties = css[selector]
    let ruleString = `${selector} {\r\n`
    
    for (const property in properties) {
      ruleString += ` ${property}: ${properties[property]};\r\n`
    }
    
    ruleString += '}\n'
    cssString += ruleString
  }
  return cssString
}

// Test with regex-based parser output
const regexOutput = {
  ".simple": { "color": "red" },
  ".a, .b": { "color": "blue" }  // Multiple selectors stored as-is
}

// Test with proper parser output structure
const parserOutput = {
  ".simple": { "mouseState": "", "pureSelector": ".simple", "rules": { "color": "red" } },
  ".a": { "mouseState": "", "pureSelector": ".a", "rules": { "color": "blue" } }
}

console.log("Regex output converted:")
console.log(obJectCssToString(regexOutput))
console.log("\nParser output with rules only:")
console.log(obJectCssToString(Object.fromEntries(
  Object.entries(parserOutput).map(([sel, val]) => [sel, val.rules])
)))
EOF

Repository: opentiny/tiny-engine

Length of output: 225


🏁 Script executed:

# Final check: what does updateSchema actually store and how is it retrieved?
# Look for the actual updateSchema implementation
rg -n "const updateSchema|export.*updateSchema" packages/ -t ts -A 5 | head -30

Repository: opentiny/tiny-engine

Length of output: 1077


🏁 Script executed:

# Verify the actual type that updateSchema stores for css
rg -n "css:" packages/canvas -t ts | grep -v "cssContent\|cssString\|cssClass" | head -20

Repository: opentiny/tiny-engine

Length of output: 401


Regex CSS parser causes silent data loss for complex CSS rules.

cssStringToObject cannot preserve @media, @keyframes, multiple selectors, or property values containing ; or }. This causes corruption when saving and reloading CSS (e.g., content: ";" becomes content: "", and @media rules lose their wrapper).

Use the existing parser and stringify utilities consistently, following the pattern in updateGlobalStyle():

-const cssStringToObject = (cssString) => {
-  cssString = cssString.replace(/\s+/g, ' ').trim()
-  const result = {}
-  const regex = /([^{]+)\{([^}]+)\}/g
-  ...
-  return result
-}

 const save = ({ content }) => {
-  const cssString = cssStringToObject(content)
+  const { parseList, styleObject } = parser(content)
+  const cssString = stringify(parseList, styleObject)
   const { addHistory } = useHistory()
   const { updateRect } = useCanvas().canvasApi.value
   const { updateSchema } = useCanvas()

This preserves all CSS structures through the round-trip.

🤖 Prompt for AI Agents
In `@packages/settings/styles/src/components/classNamesContainer/index.vue` around
lines 450 - 474, The custom regex parser cssStringToObject is dropping complex
CSS constructs (at-rules like `@media/`@keyframes, multiple selectors, and
property values containing semicolons or braces); replace its use with the
existing CSS parser/stringify utilities used in updateGlobalStyle() so the code
round-trips without loss — locate cssStringToObject and change the logic to
parse the input using the shared parser API and to serialize using the matching
stringify utility (following updateGlobalStyle()’s pattern) so `@rules`, grouped
selectors and literal property values (e.g., content: ";") are preserved.

Comment on lines +462 to +479
export const obJectCssToString = (css) => {
if (typeof css === 'string') {
return css
}
let cssString = ''

for (const selector in css) {
const properties = css[selector]
let ruleString = `${selector} {\r\n`

for (const property in properties) {
ruleString += ` ${property}: ${properties[property]};\r\n`
}

ruleString += '}\n'
cssString += ruleString
}
return cssString
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

Guard against null/undefined to avoid runtime crashes.
for (const selector in css) throws when css is null/undefined, which is a common state for empty schemas.

🐛 Suggested fix
 export const obJectCssToString = (css) => {
+  if (!css) {
+    return ''
+  }
   if (typeof css === 'string') {
     return css
   }
+  if (typeof css !== 'object') {
+    return ''
+  }
   let cssString = ''
 
-  for (const selector in css) {
-    const properties = css[selector]
+  for (const [selector, properties] of Object.entries(css)) {
     let ruleString = `${selector} {\r\n`
 
-    for (const property in properties) {
-      ruleString += ` ${property}: ${properties[property]};\r\n`
+    for (const [property, value] of Object.entries(properties || {})) {
+      ruleString += ` ${property}: ${value};\r\n`
     }
🤖 Prompt for AI Agents
In `@packages/utils/src/utils/index.ts` around lines 462 - 479, The function
obJectCssToString should guard against css being null or undefined (and
non-object) to avoid runtime crashes; at the top of obJectCssToString check if
css is null/undefined and return an empty string (or if typeof css === 'string'
keep returning it), and when iterating ensure properties and
properties[property] are accessed only if properties is truthy (skip
null/undefined property objects) so the for-in loops never run on null; update
obJectCssToString accordingly to early-return for falsy/non-object inputs and to
safely handle missing nested property objects.

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: 2

🤖 Fix all issues with AI agents
In `@packages/plugins/page/src/composable/usePage.ts`:
- Around line 134-140: When materialsOptions.useBaseStyle is true the code
accesses materialsOptions.blockBaseStyle and materialsOptions.componentBaseStyle
without null checks; add guards so you only reference .className and .style when
blockBaseStyle/componentBaseStyle are defined. Update the block that builds
cssObject (the parseStyle calls and computed keys) to check existence of
materialsOptions.blockBaseStyle and materialsOptions.componentBaseStyle (and
their .className/.style) before adding those entries to cssObject, falling back
to skipping the entry if missing. Keep parseStyle and cssObject merging logic
unchanged except for these presence checks.
- Around line 119-129: The parseStyle function must robustly handle
empty/whitespace items, keys/values with extra spaces, and values that contain
colons; update parseStyle to first trim the incoming styleString and skip any
empty items, for each non-empty item find the first colon index (instead of
.split) to separate key and value, trim both key and value, and only assign when
the colon exists and value is defined (skip malformed entries) so values like
url(http://...) or data:... are preserved and whitespace-only segments don't
cause .trim() on undefined.
🧹 Nitpick comments (2)
packages/plugins/page/src/composable/usePage.ts (2)

117-143: Function name generateCssString no longer reflects its behavior.

The function now returns a CSS object, not a string. Consider renaming to generateCssObject or similar for clarity.


118-118: Consider using proper types instead of any.

Using any for cssObject and styleObj loses type safety. A simple record type would improve maintainability.

Suggested typing
-  let cssObject: any = {}
+  let cssObject: Record<string, Record<string, string>> = {}
-    const styleObj: any = {}
+    const styleObj: Record<string, string> = {}

Also applies to: 120-120

Comment on lines +134 to 140
if (materialsOptions.useBaseStyle) {
cssObject = {
...cssObject,
[`.${materialsOptions.blockBaseStyle.className}`]: parseStyle(materialsOptions.blockBaseStyle.style),
[`.${materialsOptions.componentBaseStyle.className}`]: parseStyle(materialsOptions.componentBaseStyle.style)
}
}
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

Missing null guards for blockBaseStyle and componentBaseStyle.

When materialsOptions.useBaseStyle is truthy, this code assumes blockBaseStyle and componentBaseStyle exist with valid className and style properties. Unlike line 130 which guards pageBaseStyle, these properties are accessed unconditionally and will throw if undefined.

Proposed fix
   if (materialsOptions.useBaseStyle) {
-    cssObject = {
-      ...cssObject,
-      [`.${materialsOptions.blockBaseStyle.className}`]: parseStyle(materialsOptions.blockBaseStyle.style),
-      [`.${materialsOptions.componentBaseStyle.className}`]: parseStyle(materialsOptions.componentBaseStyle.style)
-    }
+    const { blockBaseStyle, componentBaseStyle } = materialsOptions
+    if (blockBaseStyle?.className && blockBaseStyle?.style) {
+      cssObject[`.${blockBaseStyle.className}`] = parseStyle(blockBaseStyle.style)
+    }
+    if (componentBaseStyle?.className && componentBaseStyle?.style) {
+      cssObject[`.${componentBaseStyle.className}`] = parseStyle(componentBaseStyle.style)
+    }
   }
📝 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
if (materialsOptions.useBaseStyle) {
cssObject = {
...cssObject,
[`.${materialsOptions.blockBaseStyle.className}`]: parseStyle(materialsOptions.blockBaseStyle.style),
[`.${materialsOptions.componentBaseStyle.className}`]: parseStyle(materialsOptions.componentBaseStyle.style)
}
}
if (materialsOptions.useBaseStyle) {
const { blockBaseStyle, componentBaseStyle } = materialsOptions
if (blockBaseStyle?.className && blockBaseStyle?.style) {
cssObject[`.${blockBaseStyle.className}`] = parseStyle(blockBaseStyle.style)
}
if (componentBaseStyle?.className && componentBaseStyle?.style) {
cssObject[`.${componentBaseStyle.className}`] = parseStyle(componentBaseStyle.style)
}
}
🤖 Prompt for AI Agents
In `@packages/plugins/page/src/composable/usePage.ts` around lines 134 - 140, When
materialsOptions.useBaseStyle is true the code accesses
materialsOptions.blockBaseStyle and materialsOptions.componentBaseStyle without
null checks; add guards so you only reference .className and .style when
blockBaseStyle/componentBaseStyle are defined. Update the block that builds
cssObject (the parseStyle calls and computed keys) to check existence of
materialsOptions.blockBaseStyle and materialsOptions.componentBaseStyle (and
their .className/.style) before adding those entries to cssObject, falling back
to skipping the entry if missing. Keep parseStyle and cssObject merging logic
unchanged except for these presence checks.

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant