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

Serialize shadow DOM for use in javascript disabled user agents #788

Closed
mildred opened this issue Jan 30, 2019 · 9 comments
Closed

Serialize shadow DOM for use in javascript disabled user agents #788

mildred opened this issue Jan 30, 2019 · 9 comments

Comments

@mildred
Copy link

mildred commented Jan 30, 2019

Web components are great, but unfortunately, they makes the web unusable with user agents with javascript disabled. Mostly because custom elements and their behaviour is defined with Javascript.

In some applications where the web components are mostly static (components that defines layouts, or that are templating static data) it makes sense to allow user agents with javascript disabled to access the content.

To be able to render webcomponents user-agents with javascript enabled or disabled (both) we need a way to attach a shadow tree (computed from server-side) to a custom element in pure HTML that does not conflict with javascript-enabled user-agents.

Would it be possible to imagine something like that:

<custom-element>
  <template shadow-dom>
    <p>Hello <slot name="name"></slot></p>
  </template>
  <span slot="name">World</span>
</custom-element>

If the custom-element is not declared via javascript, the user-agent knows that custom-element is a webcomponent (because it is multi-word) and can attach the shadow-dom template to it, without a line of javascript.

Instead, if the user-agents declares the custom-element through javascript, it can redefine the shadow DOM for that element, and it can continue to work as usual.

@mildred
Copy link
Author

mildred commented Jan 30, 2019

Well, this is basically #731...

@caridy
Copy link

caridy commented Jan 31, 2019

Yeah, but we keep pushing for it... if you have concrete use-cases, make sure you add them there @mildred.

@rniwa
Copy link
Collaborator

rniwa commented Feb 1, 2019

This is a duplicate of #71 but we can keep this open since that one is closed.

Here's the current proposal:
https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Declarative-Shadow-DOM.md

@andyearnshaw
Copy link

andyearnshaw commented Feb 2, 2019

@rniwa that's an interesting proposal, but I have to say I'm not really a fan of it. I don't like that it is declared as an element but does not appear in the resulting child nodes, I find most of the defined behaviour pretty surprising. The resulting DOM structure could have any of:

  • Nothing
  • HTMLUnknownElement
  • HTMLShadowRootElement

CSS interactions aren't mentioned, nth-child, shadowroot + span, etc. I assume that because the element isn't treated as a real element after parsing, then they wouldn't be counted in nth-child and the combinators would not apply. That is (potentially) a breaking change on current behaviour, although it's unlikely that websites would be currently using an element called <shadowroot>.

Fragments and unconnected documents aren't mentioned anywhere either,

let frag = (new Range()).createContextualFragment(`
    <shadowroot mode="closed"></shadowroot>
    <span>Hello</span>
`);
console.log(frag.childNodes);

What happens in this case? I guess it would be the same as when it's found inside a template element, where it is a HTMLShadowRootElement, but the proposal should make that explicitly clear.

host.appendChild(document.createElement('shadowroot')) does append HTMLUnknownElement

This means <shadowroot> is not really an element tag, even though it looks like one. No other element tag works this way, and even <!DOCTYPE> and comments result in traversable DOM nodes. I think it would be a mistake to use a normal element tag notation but adopt this behaviour.

It should have mode attribute equal to open or closed, otherwise it is processed as HTMLUnknownElement

In addition to the previous point, this is a surprising rule that means a small mistake, e.g. typo in the attribute name or value, can result in a drastic change the style and behaviours associated sibling elements. See above regarding the CSS rules, do those combinators and nth-child selectors now count the element? Now there's more children, so JS code relying on a specific structure or node sequence could break. In this case, it may be better to default to one mode or the other.

I'm aware of the immutable nature of the parser, which is most likely the main reason this is proposed as a new element rather than a new node type. However, I think that the resulting DOM tree needs to be consistent in all cases.

The suggestion of extending the <template> element fits this scenario perfectly because its contents aren't parsed as its children, which is entirely the goal here too.

@rniwa
Copy link
Collaborator

rniwa commented Feb 3, 2019

Yeah, those are all issues that arise from a parser macro. We can probably define shadow element's "behavior" to only take effect when it has a parent element, and only when the parser encounters it but it's bizarre thing at best.

@gildas-lormeau
Copy link

gildas-lormeau commented Apr 26, 2019

I'm the author of SingleFile which is an extension to save web pages. I also wish this issue could be fixed very soon since Twitter, for example, uses web components in production to embed tweets. Today, I must include a bootstrap script in saved pages and I'm not really happy with that since SingleFile remove scripts by default. Moreover, the Chrome-specification of MHTML already "standardized" a way to serialize shadow DOMs via the "shadowmode" attribute, cf. "Save shadow DOM contents" here https://docs.google.com/document/d/1FvmYUC0S0BkdkR7wZsg0hLdKc_qjGnGahBwwa0CdnHE/edit. I don't see why HTML would not.

@rektide
Copy link

rektide commented Jan 18, 2020

A short related story from tonight: my tab situation has gotten out of control on a number of my devices. I thought I could just save chrome://history/syncedTabs - a page which lists all my open tabs on all my devices - to a file & clear my tabs on some of my devices, knowing I'd have a saved off html file that listed all my open tabs.

Alas if I look at the html file from that saved-off page, all I see is <history-app></history-app>.

Thankfully there was another way I could save my page ("single file" save, mhtml) that serialized out the shadow dom in an interesting manner! Still I think there's room for improvement here, and work to benefit no-script users might also flow through & help those trying to save the page get useful content back. [Edit: removed a lot of further belly-aching in post.]

@rniwa
Copy link
Collaborator

rniwa commented Apr 20, 2023

We've solved this problem by adding declarative shadow DOM to the platform.

@rniwa rniwa closed this as completed Apr 20, 2023
@mfreed7
Copy link

mfreed7 commented Apr 20, 2023

whatwg/html#8867 discusses serialization specifically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants