-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Add option to make usage of shadow dom configurable #2516
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
Changes from 10 commits
1d495c8
f3d0d29
9e55be0
c599d6b
c435703
2c8228a
fa5124a
b7efcbe
711fd92
0df811f
6ddad99
0dc6825
c785c0b
dc9ca80
3d9d3a0
46b1843
a197bc6
a5d6210
c598bc6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,14 +21,15 @@ const valid_options = [ | |
'hydratable', | ||
'legacy', | ||
'customElement', | ||
'shadowDom', | ||
'tag', | ||
'css', | ||
'preserveComments', | ||
'preserveWhitespace' | ||
]; | ||
|
||
function validate_options(options: CompileOptions, warnings: Warning[]) { | ||
const { name, filename } = options; | ||
const { name, filename, shadowDom, customElement } = options; | ||
|
||
Object.keys(options).forEach(key => { | ||
if (valid_options.indexOf(key) === -1) { | ||
|
@@ -53,6 +54,10 @@ function validate_options(options: CompileOptions, warnings: Warning[]) { | |
toString: () => message, | ||
}); | ||
} | ||
|
||
if (!customElement && shadowDom) { | ||
throw new Error(`options.shadowDom cannot be true if options.customElement is false`) | ||
} | ||
} | ||
|
||
function get_name(filename) { | ||
|
@@ -74,7 +79,7 @@ function get_name(filename) { | |
} | ||
|
||
export default function compile(source: string, options: CompileOptions = {}) { | ||
options = assign({ generate: 'dom', dev: false }, options); | ||
options = assign({ generate: 'dom', dev: false, shadowDom: options.customElement }, options); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This defaults |
||
|
||
const stats = new Stats(); | ||
const warnings = []; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,12 +31,13 @@ export default function dom( | |
builder.add_line(`const ${renderer.file_var} = ${JSON.stringify(component.file)};`); | ||
} | ||
|
||
const css = component.stylesheet.render(options.filename, !options.customElement); | ||
|
||
const css = component.stylesheet.render(options.filename, !options.shadowDom); | ||
const styles = component.stylesheet.has_styles && stringify(options.dev ? | ||
`${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */` : | ||
css.code, { only_escape_at_symbol: true }); | ||
|
||
if (styles && component.compile_options.css !== false && !options.customElement) { | ||
if (styles && component.compile_options.css !== false && !options.shadowDom) { | ||
builder.add_block(deindent` | ||
function @add_css() { | ||
var style = @element("style"); | ||
|
@@ -64,7 +65,7 @@ export default function dom( | |
// TODO injecting CSS this way is kinda dirty. Maybe it should be an | ||
// explicit opt-in, or something? | ||
const should_add_css = ( | ||
!options.customElement && | ||
!options.shadowDom && | ||
component.stylesheet.has_styles && | ||
options.css !== false | ||
); | ||
|
@@ -443,11 +444,12 @@ export default function dom( | |
builder.add_block(deindent` | ||
class ${name} extends @SvelteElement { | ||
constructor(options) { | ||
super(); | ||
super(${options.shadowDom ? '' : '{ use_shadow_dom: false }'}); | ||
|
||
${css.code && `this.shadowRoot.innerHTML = \`<style>${escape(css.code, { only_escape_at_symbol: true }).replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`} | ||
${css.code && options.shadowDom && `this.shadowRoot.innerHTML = \`<style>${escape(css.code, { only_escape_at_symbol: true }).replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`} | ||
${should_add_css && `if (!document.getElementById("${component.stylesheet.id}-style")) @add_css();`} | ||
|
||
@init(this, { target: this.shadowRoot }, ${definition}, create_fragment, ${not_equal}, ${prop_names}); | ||
@init(this, { target: this${options.shadowDom ? '.shadowRoot' : ''} }, ${definition}, create_fragment, ${not_equal}, ${prop_names}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't guess I'm 100% confident about this. It makes the target itself... I assume it's okay? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hello. Yes this should work. I just had to modify the javascript generated by Svelte: set "this"as the target in the init() method of the component, and remove "this.attachShadow({ mode: 'open' });" from SvelteElement constructor() method. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ldumaine, If the shadowDom option is disabled then the target will be |
||
|
||
${dev_props_check} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,7 +132,7 @@ export default function tag(parser: Parser) { | |
? meta_tags.get(name) | ||
: (/[A-Z]/.test(name[0]) || name === 'svelte:self' || name === 'svelte:component') ? 'InlineComponent' | ||
: name === 'title' && parent_is_head(parser.stack) ? 'Title' | ||
: name === 'slot' && !parser.customElement ? 'Slot' : 'Element'; | ||
: name === 'slot' && !parser.shadowDom ? 'Slot' : 'Element'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another area I wasn't 100% sure on. From my reading |
||
|
||
const element: Node = { | ||
start, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export default { | ||
customElement: true, | ||
shadowDom: false | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<svelte:options tag="custom-element"/> | ||
|
||
<h1>Hello world!</h1> | ||
|
||
<style> | ||
h1 { | ||
color: blue; | ||
} | ||
</style> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import * as assert from 'assert'; | ||
import CustomElement from './main.svelte'; | ||
|
||
export default function (target) { | ||
new CustomElement({ | ||
target | ||
}); | ||
|
||
assert.equal(target.innerHTML, '<custom-element><h1 class="svelte-619mm8">Hello world!</h1></custom-element>'); | ||
|
||
const el = target.querySelector('custom-element'); | ||
const h1 = el.querySelector('h1'); | ||
const { color } = getComputedStyle(h1); | ||
|
||
assert.equal(h1.textContent, 'Hello world!'); | ||
assert.equal(color, 'rgb(0, 0, 255)'); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export default { | ||
options: { | ||
customElement: true, | ||
shadowDom: false | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* generated by Svelte vX.Y.Z */ | ||
import { | ||
SvelteElement, | ||
append, | ||
detach, | ||
element, | ||
init, | ||
insert, | ||
noop, | ||
safe_not_equal | ||
} from "svelte/internal"; | ||
|
||
function add_css() { | ||
var style = element("style"); | ||
style.id = 'svelte-pbe34-style'; | ||
style.textContent = "h1.svelte-pbe34{color:blue}"; | ||
append(document.head, style); | ||
} | ||
|
||
function create_fragment(ctx) { | ||
var h1; | ||
|
||
return { | ||
c() { | ||
h1 = element("h1"); | ||
h1.textContent = "Hello world"; | ||
this.c = noop; | ||
h1.className = "svelte-pbe34"; | ||
}, | ||
|
||
m(target, anchor) { | ||
insert(target, h1, anchor); | ||
}, | ||
|
||
p: noop, | ||
i: noop, | ||
o: noop, | ||
|
||
d(detaching) { | ||
if (detaching) { | ||
detach(h1); | ||
} | ||
} | ||
}; | ||
} | ||
|
||
class Component extends SvelteElement { | ||
constructor(options) { | ||
super({ use_shadow_dom: false }); | ||
if (!document.getElementById("svelte-pbe34-style")) add_css(); | ||
|
||
init(this, { target: this }, null, create_fragment, safe_not_equal, []); | ||
|
||
if (options) { | ||
if (options.target) { | ||
insert(options.target, this, options.anchor); | ||
} | ||
} | ||
} | ||
} | ||
|
||
customElements.define("custom-element", Component); | ||
|
||
export default Component; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<svelte:options tag="custom-element"/> | ||
|
||
<h1>Hello world</h1> | ||
|
||
<style> | ||
h1 { | ||
color: blue; | ||
} | ||
</style> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a little sanity check to save us from an invalid state.