Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

CSS: add support for :is(), :where() and :not() pseudoclasses, fix CSS cascade, and other fixes #552

Merged
merged 11 commits into from
Jan 14, 2024

Conversation

poire-z
Copy link
Contributor

@poire-z poire-z commented Jan 12, 2024

Fix getToc() not cached on initial loading

getToc() is usually called once and cached by frontend, but cre.cpp's footnote popup feature may call it multiple times to check if a link is a footnote candidate, which could be expensive if not cached if the ToC is huge.
See koreader/koreader#11254 (comment)
Should allow closing koreader/koreader#11254.

CSS: add support for forgotten border-style: hidden

Just so it is not ignored and we get no border displayed.
Should behave as none (except on table, where it still behave as none but gets a higher priority than table cells' border when table collapse - that we don't ensure).
(border-style: hidden is actually used in our html5.css.)

CSS: fix parsing of div :something and div [attr]

Fix very old oversight, since when we added support for attribute check and pseudoclasses, not having them working with ancestor rules (we were properly handling div .something and div #something).

CSS: fix checking E[foo~="value"]

It wouldn't check other "words" in the attribute: p[class~=foo] didn't match <p class="fooz foo">.
Similar logic as for checking classname in a5c046c.

CSS: order rules as written when building a selector

Keep consecutive current node check rules ordered as written when building a selector, instead of putting them always at start (only parent/ancestor/sibling checks need to put the following rule at start).
The stylesheet author may intuitively write them with quicker checks first, and complex ones last, ie.:
table.mytab[rules]:not([rules="none"]

CSS: fix useragent vs. author stylesheet CSS cascade

Introduce another stylesheet object in the document to hold the useragent sheet, to be applied before the author stylesheets. Per-CSS-specs, these are 2 "origins", and selectors shouldn't be mixed and ordered by relative specificity.
Ie, this high specificity selector in the useragent sheet:
table[align="right"] { float: right; }
shouldn't result in such tables floating when an author stylesheet has one of these lower specificity selectors:
table { float: none; } or * { float: none; }
More details in #551 (comment).
Reference: https://www.w3.org/TR/css-cascade-3/#cascading

CSS: pass useragent_sheet flag all along parse() code

So we can if needed support some private CSS syntax only for the useragent stylesheet and user style tweaks.

CSS: add private selector syntax to match against text

Allows classic attribute selectors (ie. [foo*=value i]), when the attribute name is _ (ie. [_*="some text" i]), to match against the node full inner text.
Only allow this syntax when parsing the useragent stylesheet, to avoid unexpected results with author stylesheets.
Might be handy with style tweaks, when the book has not enough classes distinctions to target what we want.
Proposed at koreader/koreader#11323, see some screenshots showing what this new trick could allow..

CSS: add support for :is(), :where() and :not() pseudoclasses

Reference: https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes#functional_pseudo-classes
(No support for :has(), which would be a lot more complicated.)

EPUB: don't ignore any <spine> item

We were only accepting <spine> items which are declared with media-type="application/xhtml+xml.
Assume all items in the <spine> are content and should have a <DocFragment>, even if unsupported or if parsing failed.
Also add support for SVG items in the spine.
Bump DOM_VERSION_CURRENT to 20240114 to have this change only done on new books, so old xpointers are not messed up.
See koreader/koreader#11268 (comment)
Should allow closing koreader/koreader#11268.

bump CACHE_FILE_FORMAT_VERSION

Necessary with the previous commits.
Also add to the hardcoded element lists some tag names that can be seen in HTML standard and Firefox stylesheets.


This change is Reviewable

@@ -2755,6 +2755,7 @@ static const char * css_lsp_names[] =
static const char * css_bst_names[]={
"", // css_border_inherit
"none",
"hidden",
Copy link
Member

Choose a reason for hiding this comment

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

So if I understand correctly this property is in principle only relevant in tables?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Relevant everywhere (if written by the CSS author, is should behave as none), but only possibly different than "none" with tables.

https://developer.mozilla.org/en-US/docs/Web/CSS/border-style

hidden
Like the none keyword, displays no border. Unless a background-image is set, the computed value of the same side's border-width will be 0, even if the specified value is something else. In the case of table cell and border collapsing, the hidden value has the highest priority: if any other conflicting border is set, it won't be displayed.

It will now not be considered invalid, and will be handled as "none".

Copy link
Member

Choose a reason for hiding this comment

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

It's just a bit confusing that it sounds the same as visibility: hidden (but that'd be border-color: transparent).

@poire-z
Copy link
Contributor Author

poire-z commented Jan 12, 2024

Pinging @bbshelper for info/quick review.

  • CSS: order rules as written when building a selector tweaks/renames insertRuleAtStart()
  • CSS: add support for :is(), :where() and :not() pseudoclasses uses some LVRef() like you did recently.

getToc() is usually called once and cached by frontend,
but cre.cpp's footnote popup feature may call it multiple
times to check if a link is a footnote candidate, which
could be expensive if not cached if the ToC is huge.
Just so it is not ignored and we get no border displayed.
Should behave as "none" (except on table, where it still
behave as "none" but gets a higher priority than table
cells' border when table collapse - that we don't ensure).
Fix very old oversight, since when we added support for
attribute check and pseudoclasses, not having them
working with ancestor rules (we were properly handling
'div .something' and 'div #something').
It wouldn't check other "words" in the attribute:
p[class~=foo] didn't match <p class="fooz foo">.
Similar logic as for checking classname in a5c046c.
Keep consecutive current node check rules ordered as written
when building a selector, instead of putting them always at
start (only parent/ancestor/sibling checks need to put the
following rule at start).
The stylesheet author may intuitively write them with
quicker checks first, and complex ones last, ie.:
  table.mytab[rules]:not([rules="none"]
Introduce another stylesheet object in the document to
hold the useragent sheet, to be applied before the author
stylesheets. Per-CSS-specs, these are 2 "origins", and
selectors shouldn't be mixed and ordered by relative
specificity.
Ie, this high specificity selector in the useragent sheet:
  table[align="right"] { float: right; }
shouldn't result in such tables floating when an author
stylesheet has one of these lower specificity selectors:
  table { float: none; }  or * { float: none; }
So we can if needed support some private CSS syntax only
for the useragent stylesheet and user style tweaks.
(Non-essential follow-up to previous commit.)
Allows classic attribute selectors (ie. [foo*=value i]), when
the attribute name is '_' (ie. [_*="some text" i]), to match
against the node full inner text.
Only allow this syntax when parsing the useragent stylesheet,
to avoid unexpected results with author stylesheets.
Might be handy with style tweaks, when the book has not enough
classes distinctions to target what we want.
(No support for :has(), which would be a lot more complicated.)
We were only accepting <spine> items which are declared
with media-type="application/xhtml+xml.
Assume all items in the <spine> are content and should have
a <DocFragment>, even if unsupported or if parsing failed.
Also add support for SVG items in the spine.
Bump DOM_VERSION_CURRENT to 20240114 to have this change
only done on new books, so old xpointers are not messed up.
Necessary with the previous commits.
Also add to the hardcoded element lists some tag names that
can be seen in HTML standard and Firefox stylesheets.
@poire-z poire-z merged commit b5f97c4 into koreader:master Jan 14, 2024
1 check passed
@poire-z poire-z deleted the is_where_not_and_more branch January 14, 2024 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants