Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Use textContent of stylesheet if available #61

Merged
merged 3 commits into from
Feb 3, 2025
Merged

Use textContent of stylesheet if available #61

merged 3 commits into from
Feb 3, 2025

Conversation

trotzig
Copy link
Contributor

@trotzig trotzig commented Feb 3, 2025

This will fix a bug where our style collection would not work if the stylesheet was using this pattern:

font: var(--some-var);
font-weight: var(--some-other-var);

Iterating over cssRules here would mean we collected styles that looked something like:

font-style: ;
font-variant-ligatures: ;
font-variant-caps: ;
font-variant-numeric: ;
font-variant-east-asian: ;
font-variant-alternates: ;
font-variant-position: ;
font-variant-emoji: ;
font-stretch: ;
font-size: ;
line-height: ;
font-family: ;
font-optical-sizing: ;
font-size-adjust: ;
font-kerning: ;
font-feature-settings: ;
font-variation-settings: ;
font-weight: var(--some-other-var);

Notice how properties are expanded and left with no content.

To fix this, we can use textContent of the style element instead. And if that isn't available, we fall back to sheet.cssRules.

The only potential issue this could introduce is if you mix text content styles and dynamically injected ones (using e.g. insertRule). I doubt that's a common way to create styling however.

This will fix a bug where our style collection would not work if the
stylesheet was using this pattern:

  font: var(--some-var);
  font-weight: var(--some-other-var);

Iterating over cssRules here would mean we collected styles that looked
something like:

  font-style: ;
  font-variant-ligatures: ;
  font-variant-caps: ;
  font-variant-numeric: ;
  font-variant-east-asian: ;
  font-variant-alternates: ;
  font-variant-position: ;
  font-variant-emoji: ;
  font-stretch: ;
  font-size: ;
  line-height: ;
  font-family: ;
  font-optical-sizing: ;
  font-size-adjust: ;
  font-kerning: ;
  font-feature-settings: ;
  font-variation-settings: ;
  font-weight: var(--some-other-var);

Notice how properties are expanded and left with no content.

To fix this, we can use `textContent` of the style element instead. And
if that isn't available, we fall back to `sheet.cssRules`.

The only potential issue this could introduce is if you mix text content
styles and dynamically injected ones (using e.g. `insertRule`). I doubt
that's a common way to create styling however.
@trotzig trotzig requested a review from lencioni February 3, 2025 13:50
.split('\n')
.map((line) => line.trim())
.filter((line) => line && !COMMENT_PATTERN.test(line))
.join(' ');
Copy link
Contributor

Choose a reason for hiding this comment

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

On line 16 we join with \n. Should we do the same here?

Comment on lines 44 to 45
? stripComments(element.textContent)
: getContentFromStyleSheet(element.sheet);
Copy link
Contributor

Choose a reason for hiding this comment

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

The naming of these functions seems a bit off to me. Also, I think perhaps it should be refactored a bit where here and below we would call getContentFromStyleSheet(element) and then that function would be this:

function getContentFromStyleSheet(element) {
  const lines = element.textContent
    ? element.textContent.split('\n').map(line => line.trim())
    : element.sheet.map((rule) => rule.cssText);

  return lines
    .filter((line) => line && !COMMENT_PATTERN.test(line))
    .join('\n');
}

That sorts out the naming and avoids duplicating/forking logic.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh it looks like adoptedStyleSheets will need slightly different logic.

Copy link
Contributor

Choose a reason for hiding this comment

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

I updated this PR

Comment on lines 66 to 67
expect(snapshot.cssBlocks[0].content).toMatch(/font-weight: 400;/);
expect(snapshot.cssBlocks[0].content).toMatch(/font: 400 1rem/);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we do something here to make it more obvious that these are the variables? We could use names that don't match the styles exactly, and also maybe include the leading -- in the assertions?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good.

@trotzig
Copy link
Contributor Author

trotzig commented Feb 3, 2025

I'll make some small changes here.

lencioni and others added 2 commits February 3, 2025 09:27
I found the naming here to be a bit off, and I didn't like that the
logic was duplicated and different. This commit attempts to refactor
this code to have better naming and logical flow.
We had to make some small updates because we're no longer one-lining
everything. I also took the time to name the custom vars better so that
the assertions are easier to make.
@lencioni lencioni merged commit 1a9499b into main Feb 3, 2025
5 checks passed
@lencioni lencioni deleted the css-rules branch February 3, 2025 16:19
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants