Skip to content

fix: page css miss atrule style#1783

Open
hexqi wants to merge 2 commits intoopentiny:developfrom
hexqi:fix/css
Open

fix: page css miss atrule style#1783
hexqi wants to merge 2 commits intoopentiny:developfrom
hexqi:fix/css

Conversation

@hexqi
Copy link
Collaborator

@hexqi hexqi commented Mar 10, 2026

English | 简体中文

PR

fix #1776

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

背景:
在v2.10版本中新增支持css 对象格式,系统将输入的全局 CSS 代码字符串解析并存储为 JSON 对象(cssObject)。保存时通过 parser 将 CSS 字符串转化格式并在必要时将其转化回字符串(objectCssToString)。

问题:
转换为 styleObject 的过程中没把包含 @keyframes@media 的在内的大部分 at-rules 囊括在内,直接导致这些代码在保存刷新后丢失。见 #1776

解决方法:
转化时增加对at-rules的支持,保存为 key,value格式

已处理的特殊场景:

  • 只有key,没有value, 如 @import
  • 顺序问题,保持原有顺序
  • 顺序提升:部分需要在顶部的规则进行提升,如 @import
  • 同名规则:使用数组格式保存

验证环境:https://hexqi.github.io/tiny-engine/?type=app&id=1&tenant=1&pageid=88

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Added a utility to parse CSS text into an ordered CSS object and emit top-level rules (like @charset/@import/@namespace) separately for correct output assembly.
  • Bug Fixes

    • Preserve editor source order for CSS rules.
    • Improved handling of at-rules so their blocks and ordering appear correctly in output.

@github-actions github-actions bot added the bug Something isn't working label Mar 10, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 10, 2026

Walkthrough

The parser now exposes buildCssObjectFromContent(content) to produce a source-ordered CSS object including at-rules; the component save flow uses it. Serialization (objectCssToString) was updated to emit top-level directives (@charset, @import, @namespace) before other rules.

Changes

Cohort / File(s) Summary
Component save flow
packages/settings/styles/src/components/classNamesContainer/index.vue
Replaced manual parsing/mapping with a direct call to buildCssObjectFromContent(content) when saving, delegating creation of the css object to the parser helper.
CSS parser
packages/settings/styles/src/js/parser.ts
Added export const buildCssObjectFromContent(content: string) that builds a CSS object preserving parseList source order, collects at-rule values (arrays when duplicated), and extended at-rule handling to mark hasBlock.
CSS serialization utils
packages/utils/src/utils/index.ts
Updated objectCssToString to collect and prepend top-level rules (@charset, @import, @namespace) into a topString, concatenating it before the remaining CSS output.

Sequence Diagram(s)

sequenceDiagram
    participant UI as ClassNamesContainer (component)
    participant Parser as parser.buildCssObjectFromContent
    participant Serializer as objectCssToString
    participant Store as Persistence/Storage

    UI->>Parser: save(content) -> buildCssObjectFromContent(content)
    Note right of Parser: parseList → cssObject\ninclude at-rules (arrays if dupes)
    Parser-->>UI: cssObject
    UI->>Serializer: objectCssToString(cssObject)
    Note left of Serializer: extract top-level directives\nprepend topString
    Serializer-->>UI: cssText
    UI->>Store: persist(cssText)
    Store-->>UI: confirm
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nibbled through CSS lines at night,

keyframes found their proper light,
top-rules first, then rules that play,
saved in order — hip hooray! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title directly addresses the main bug fix: enabling at-rules in CSS to be properly saved and persisted, matching the core problem statement in issue #1776.
Linked Issues check ✅ Passed The code changes implement the required functionality: parsing at-rules (like @keyframes) from CSS strings into a CSS object format, preserving rule order, and supporting array format for duplicate keys.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked issue requirements: adding at-rule handling in the parser and updating the CSS-to-object conversion to preserve these rules.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/settings/styles/src/components/classNamesContainer/index.vue`:
- Around line 462-465: The current logic in classNamesContainer that computes
rawValue/braceIdx/key/value re-parses item.style.value and splits on the first
'{', which misclassifies blockless at-rules containing '{' inside quoted URLs or
data URIs; instead, stop reparsing the raw rule: use item.style.value verbatim
(rawValue) for display/processing or, if structured data is needed, use the
parser-produced metadata (e.g., any at-rule fields produced in parser.ts) rather
than slicing on '{'. Concretely, remove the braceIdx/indexOf('{') branching that
sets key and value and either assign key = rawValue (or use
item.style.name/params if the parser exposes them) and keep value empty, or
consume the structured at-rule properties from the parser output so the
component never attempts to reparse the raw text.
- Around line 455-470: The current atrule handling in parseList merges later
occurrences into cssObject[key], which collapses multiple same-key at-rule
blocks and breaks source order; change the logic so each atrule occurrence gets
its own ordered slot instead of being merged — e.g., stop aggregating by key and
instead push an ordered entry (such as { key, value } or store values as
successive items in an array of entries like cssEntries) when item.type ===
'atrule' (use the existing variables item, rawValue, key, value), and update the
serializer (packages/utils/src/utils/index.ts where serialization reads
cssObject) to iterate these ordered entries so identical at-rule preludes remain
separate and round-trip in source order.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7a29d3b6-7f4c-4e71-be6b-5261c82612bc

📥 Commits

Reviewing files that changed from the base of the PR and between 7c4bdc0 and 0579932.

📒 Files selected for processing (2)
  • packages/settings/styles/src/components/classNamesContainer/index.vue
  • packages/utils/src/utils/index.ts

@hexqi hexqi changed the title fix: page css miss atrule style [WIP] fix: page css miss atrule style Mar 10, 2026
@github-actions github-actions bot removed the bug Something isn't working label Mar 10, 2026
@hexqi hexqi changed the title [WIP] fix: page css miss atrule style fix: page css miss atrule style Mar 10, 2026
@github-actions github-actions bot added the bug Something isn't working label Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐛 [Bug]: 在全局CSS中增加的 @keyframes不会保存

1 participant