bug: mock-doc splits inline style at `;` inside url(), corrupting data-URI backgrounds
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- css, html, javascript, node.js, typescript
Research direction
Start in packages/mock-doc/src/css-style-declaration.ts at the set cssText setter, where cssText.split(';') runs unconditionally before the existing slice(1).join(':') rejoin for values. Run the repro script from the issue (MockDocument + parseHtmlToFragment from @stencil/core/mock-doc) first to see the truncation, then look at the existing mock-doc spec tests for css-style-declaration to match their style. Done means declarations split only at top-level semicolons outside parentheses and quotes, so the three expected outputs in the issue (innerHTML round-trip, style.backgroundImage, and parseHtmlToFragment round-trip) all hold.
Written by the indexing model from the issue text.
Description
Prerequisites
- I have read the Contributing Guidelines.
- I agree to follow the Code of Conduct.
- I have searched for existing issues that already report this problem, without success.
Stencil Version
4.45.3 (also reproduced on main at f4fe940 and 5.0.0-rc.1 / v5 at 1ed1c6c)
Current Behavior
MockCSSStyleDeclaration's cssText setter splits declarations with cssText.split(';'), so a semicolon inside url(...) (such as ;base64, in a data URI) or inside quotes terminates the declaration early. The remainder of the data URI is dropped (or misparsed as the next property if it contains :), leaving an unclosed url( or quote in the serialized style attribute.
This affects:
renderToString()when hydrating HTML that contains inline data-URI styles (<div style="background: url(data:image/gif;base64,...) no-repeat; color: red">), emitting<div style="background: url(data:image/gif; color: red;">where the unclosedurl(also invalidatescolor: redin browsers.el.setAttribute('style', ...)andel.style.cssText = ...in components running under SSR ornewSpecPage().toEqualHtml()in spec tests: JSXstyle={{ backgroundImage: 'url(data:image/png;base64,...)' }}usesstyle.setProperty()and serializes intact on the live element, whereasparseHtmlToFragment()re-parses the expected HTML string throughcssTextand truncates it, sotoEqualHtml()fails even against the element's ownouterHTML.
Expected Behavior
MockCSSStyleDeclaration.cssText only splits declarations at top-level semicolons (outside parentheses and quotes), matching browser CSSStyleDeclaration behavior and CSS Syntax Module Level 3:
doc.body.innerHTMLpreserves<div style="background: url(data:image/gif;base64,R0lGOD==) no-repeat; color: red;">x</div>.div.style.backgroundImageisurl('data:image/png;base64,iVBORw0KGgo=')anddiv.getAttribute('style')isbackground-image: url('data:image/png;base64,iVBORw0KGgo='); color: red;.parseHtmlToFragment(rendered.outerHTML)round-tripsbackground-image: url(data:image/png;base64,iVBORw0KGgo=); color: blue;unchanged.
System Info
System: node 26.13.0
Platform: linux (6.1.0-54-cloud-amd64)
CPU Model: Intel(R) Xeon(R) CPU @ 2.80GHz (64 cpus)
Stencil: 4.45.3
TypeScript: 5.8.3
Rollup: 4.44.0
Parse5: 7.2.1
jQuery: 4.0.0-pre
Terser: 5.37.0
Steps to Reproduce
Run npm install @stencil/[email protected] && node stencil-core-tslib.repro.mjs:
// stencil-core-tslib.repro.mjs
import { MockDocument, parseHtmlToFragment } from "@stencil/core/mock-doc";
const doc = new MockDocument(
'<div style="background: url(data:image/gif;base64,R0lGOD==) no-repeat; color: red">x</div>'
);
console.log(doc.body.innerHTML);
const div = doc.createElement("div");
div.setAttribute("style", "background-image: url('data:image/png;base64,iVBORw0KGgo='); color: red");
console.log(div.getAttribute("style"));
console.log(div.style.backgroundImage);
const rendered = doc.createElement("div");
rendered.style.setProperty("background-image", "url(data:image/png;base64,iVBORw0KGgo=)");
rendered.style.setProperty("color", "blue");
console.log("before parse:", rendered.outerHTML);
console.log("after parse: ", parseHtmlToFragment(rendered.outerHTML).firstElementChild.outerHTML);
Actual output:
<div style="background: url(data:image/gif; color: red;">x</div>
background-image: url('data:image/png; color: red;
url('data:image/png
before parse: <div style="background-image: url(data:image/png;base64,iVBORw0KGgo=); color: blue;"></div>
after parse: <div style="background-image: url(data:image/png; color: blue;"></div>
Code Reproduction URL
https://gist.github.com/trackoor/624030cdd797e27d114e86126108b278
Additional Information
In src/mock-doc/css-style-declaration.ts (packages/mock-doc/src/css-style-declaration.ts on v5), set cssText already rejoins : segments via splt.slice(1).join(':') so URLs with schemes survive, while the outer cssText.split(';') splits unconditionally.
Credit: https://ucsbplse.github.io/
- Dominant language
- TypeScript
- Stars
- 13.2k
- Forks
- 865
- Avg merge
- 2d 16h
- Merged PRs (30d)
- 29
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from stenciljs/core
-
bug(mock-doc): `Element.toggleAttribute()` is missing, so components that use it fail during SSROpentriage
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Stencil FOUC styles should use @layer to avoid cascade conflicts with React 19Possibly taken @johnjenkins claimed this 230 days ago. OpenStencil v5
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 45/100
stenciljs/core#7016 · 1 reaction ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 22/100
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 35/100
Maintainers usually reply within 1 day
Similar issues
-
[BUG]: Duplicate preposition in heading and unformatted feedback text on Strengthen Argument pageOpenbug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
AOSSIE-Org/DebateAI#801 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
agents area: runtime automation chore cli consistency dependencies developer-experience difficulty: easy documentation enhancement good first issue help wanted hygiene json-output priority: P3 starters tests
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Add: BOM CineOpenapproved check:passed streams:add
Difficulty 1/5 Under an hour Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
area:claude-code-web bug has repro platform:linux platform:web
Difficulty 1/5 Under an hour Newbie friendliness 66/100
anthropics/claude-code#110168 ·