Use full hierarchy when determining the browser default styles
IDisposable opened this issue · comments
Use case: description, code
Per the original reported problem of #95, and the discoveries made while moving towards a solution in #104, we know that the only reasonable way to get the full defaults of a particular element is to generate a matching DOM element hierarchy in the sandbox such that (for example) a TD
in a TR
in a TBODY
in a TABLE
in a DIV
in BODY
would need all the intervening elements created in the sandbox and then we could insert the element we need now to determine its in-situ default styles.
Expected behavior
Insert a TD
and see the default 1px
style that would have been driven by the fact that it's nested in a TABLE
with a TBODY
with a TR
Actual behavior (stack traces, console logs etc.)
On Chrome, they default style of a bare TD
inserted as a direct descendent of BODY
lies and says that its padding is 0px
instead of what would actually be a 1px
padding due to the table-cell
display.
Library version
2.13.1 and 3.0.0
Browsers
- Chrome 49+
- Firefox 45+
The proposed solution is mentioned in #104 (comment)
and basically means we need to create a matching root-to-child hierarchy in the sandbox. Because this is kind of complex, we might want to leave the sandbox "live" longer, but that will need some validation.
I think we should be limiting that effort to reach up.
Maybe we could chunk the element's prototype name and see if the element is "similar" to its parent:
- get the prototype name of each element (
Object.getPrototypeOf(...).constructor.name
) - get the first word and remove it from the string - it can either be
HTML
SVG
or/^[A-Z][^A-Z]*/
- get the second word - it'll be
HTML
SVG
or/^[A-Z][^A-Z]*/
again.
(For any table elements and ruby elements it'll beHTML
, thenTable
orElement
- we can exploit that!)
Is that better than just doing a concatenation of the tagName
of each element going up to the first thing that has a display: block
or display: table
as the default display
style? This would result in TD.TR.TBODY.TABLE (stopped by TABLE's default style of table
) or IMG.SPAN.P.DIV (stopped by DIV's default style of block
)... or even just white-list the elements based on the CSS default values spec... then the cached default styles would be keyed by the resulting string.
It wouldn't work for the RT
tag in RUBY
, which is rendered as block
and CSS hasn't implemented yet (so another styling pice owned by Layout in Blink):
ポケットモンスター (see the ruby > rt
style declaring display: block
here 😩)
The W3Schools list is also missing SVG elements which is an avenue of weirdness all unto its own.
My solution wouldn't work for <ul>
and <li>
FWIW.
Your suggestion would be a start. I personally think we could cache default styles without accounting for hierarchy e.g TD.TR.TBODY.TABLE getting cached as TD
I'll admit that I never really attempted to target RUBY
so I've got full-on-ignorance about the topic... I'll dig some into that and likely spin up a different issue for what I grok.
In the meantime, I'm going to make a trial to see if I can resolve the original issue this way, and then optimize down to the simplest solution that works. :)
Looks like the best canonical list of stop tags is Block Level elements... for RUBY
looks like we should just treat them like any other Phrasing content and keep crawling up...
That list, if we add <svg>
, is something we could hardcode fairly. This means getDefaultStyle
will not reach up from body
head
and html
also. Which is okay.
POC works! See https://jsfiddle.net/ae1m6b5v/4/ (which has the updated source embedded)