pull/4444/head
tanhauhau 5 years ago
parent 3707b9abf9
commit bb6fac8fbc

@ -374,7 +374,7 @@ export default class ElementWrapper extends Wrapper {
get_claim_statement(nodes: Identifier) {
const attributes = this.attributes
.filter((attr) => !(attr instanceof SpreadAttributeWrapper) && !attr.property_name)
.map((attr) => p`${fix_attribute_casing(attr.node.name)}: true`);
.map((attr) => p`${attr.name}: true`);
const name = this.node.namespace
? this.node.name

@ -51,11 +51,12 @@ export default class RawMustacheTagWrapper extends Tag {
const update_anchor = needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
block.chunks.create.push(b`${html_tag} = new @HtmlTag(${update_anchor});`);
block.chunks.create.push(b`${html_tag} = new @HtmlTag();`);
if (this.renderer.options.hydratable) {
block.chunks.claim.push(b`${html_tag} = @claim_html_tag(${update_anchor}, ${_parent_nodes});`);
block.chunks.claim.push(b`${html_tag} = @claim_html_tag(${_parent_nodes});`);
}
block.chunks.mount.push(b`${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : 'anchor'});`);
block.chunks.hydrate.push(b`${html_tag}.a = ${update_anchor};`);
block.chunks.mount.push(b`${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`);
if (needs_anchor) {
block.add_element(html_anchor, x`@empty()`, x`@empty()`, parent_node);

@ -7,6 +7,7 @@ import { x } from 'code-red';
import Expression from '../../nodes/shared/Expression';
import remove_whitespace_children from './utils/remove_whitespace_children';
import fix_attribute_casing from '../../render_dom/wrappers/Element/fix_attribute_casing';
import { namespaces } from '../../../utils/namespaces';
export default function(node: Element, renderer: Renderer, options: RenderOptions) {
@ -42,20 +43,21 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
if (attribute.is_spread) {
args.push(attribute.expression.node);
} else {
const attr_name = node.namespace === namespaces.foreign ? attribute.name : fix_attribute_casing(attribute.name);
const name = attribute.name.toLowerCase();
if (name === 'value' && node.name.toLowerCase() === 'textarea') {
node_contents = get_attribute_value(attribute);
} else if (attribute.is_true) {
args.push(x`{ ${fix_attribute_casing(attribute.name)}: true }`);
args.push(x`{ ${attr_name}: true }`);
} else if (
boolean_attributes.has(name) &&
attribute.chunks.length === 1 &&
attribute.chunks[0].type !== 'Text'
) {
// a boolean attribute with one non-Text chunk
args.push(x`{ ${fix_attribute_casing(attribute.name)}: ${(attribute.chunks[0] as Expression).node} || null }`);
args.push(x`{ ${attr_name}: ${(attribute.chunks[0] as Expression).node} || null }`);
} else {
args.push(x`{ ${fix_attribute_casing(attribute.name)}: ${get_attribute_value(attribute)} }`);
args.push(x`{ ${attr_name}: ${get_attribute_value(attribute)} }`);
}
}
});
@ -65,10 +67,11 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
let add_class_attribute = !!class_expression;
node.attributes.forEach(attribute => {
const name = attribute.name.toLowerCase();
const attr_name = node.namespace === namespaces.foreign ? attribute.name : fix_attribute_casing(attribute.name);
if (name === 'value' && node.name.toLowerCase() === 'textarea') {
node_contents = get_attribute_value(attribute);
} else if (attribute.is_true) {
renderer.add_string(` ${fix_attribute_casing(attribute.name)}`);
renderer.add_string(` ${attr_name}`);
} else if (
boolean_attributes.has(name) &&
attribute.chunks.length === 1 &&
@ -76,17 +79,17 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
) {
// a boolean attribute with one non-Text chunk
renderer.add_string(' ');
renderer.add_expression(x`${(attribute.chunks[0] as Expression).node} ? "${fix_attribute_casing(attribute.name)}" : ""`);
renderer.add_expression(x`${(attribute.chunks[0] as Expression).node} ? "${attr_name}" : ""`);
} else if (name === 'class' && class_expression) {
add_class_attribute = false;
renderer.add_string(` ${fix_attribute_casing(attribute.name)}="`);
renderer.add_string(` ${attr_name}="`);
renderer.add_expression(x`[${get_class_attribute_value(attribute)}, ${class_expression}].join(' ').trim()`);
renderer.add_string('"');
} else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') {
const snippet = (attribute.chunks[0] as Expression).node;
renderer.add_expression(x`@add_attribute("${fix_attribute_casing(attribute.name)}", ${snippet}, ${boolean_attributes.has(name) ? 1 : 0})`);
renderer.add_expression(x`@add_attribute("${attr_name}", ${snippet}, ${boolean_attributes.has(name) ? 1 : 0})`);
} else {
renderer.add_string(` ${fix_attribute_casing(attribute.name)}="`);
renderer.add_string(` ${attr_name}="`);
renderer.add_expression((name === 'class' ? get_class_attribute_value : get_attribute_value)(attribute));
renderer.add_string('"');
}

@ -201,17 +201,17 @@ function find_comment(nodes, text, start) {
return nodes.length;
}
export function claim_html_tag(update_anchor, nodes) {
export function claim_html_tag(nodes) {
// find html opening tag
const start_index = find_comment(nodes, 'HTML_TAG_START', 0);
const end_index = find_comment(nodes, 'HTML_TAG_END', start_index);
if (start_index === end_index) {
return new HtmlTag(update_anchor);
return new HtmlTag();
}
const html_tag_nodes = nodes.splice(start_index, end_index + 1);
detach(html_tag_nodes[0]);
detach(html_tag_nodes[html_tag_nodes.length - 1]);
return new HtmlTag(update_anchor, html_tag_nodes.slice(1, html_tag_nodes.length - 1));
return new HtmlTag(html_tag_nodes.slice(1, html_tag_nodes.length - 1));
}
export function set_data(text, data) {
@ -352,8 +352,7 @@ export class HtmlTag {
// anchor
a: HTMLElement;
constructor(anchor: HTMLElement = null, claimed_nodes?: ChildNode[]) {
this.a = anchor;
constructor(claimed_nodes?: ChildNode[]) {
this.e = this.n = null;
this.l = claimed_nodes;
}

@ -52,9 +52,9 @@ function create_each_block(ctx) {
t4 = text(t4_value);
t5 = text(" ago:");
t6 = space();
html_tag = new HtmlTag(raw_value);
html_tag = new HtmlTag();
attr(span, "class", "meta");
html_tag = new HtmlTag(null);
html_tag.a = null;
attr(div, "class", "comment");
},
m(target, anchor) {

@ -56,6 +56,7 @@ describe('runtime', () => {
const solo = config.solo || /\.solo/.test(dir);
if (hydrate && config.skip_if_hydrate) return;
if (hydrate && from_ssr_html && config.skip_if_hydrate_from_ssr) return;
if (solo && process.env.CI) {
throw new Error('Forgot to remove `solo: true` from test');
@ -160,6 +161,8 @@ describe('runtime', () => {
const { html } = SsrSvelteComponent.render(config.props);
target.innerHTML = html;
delete compileOptions.generate;
} else {
target.innerHTML = '';
}
if (config.before_test) config.before_test();

@ -11,6 +11,7 @@ export default {
options: {
hydrate: false // Hydration test will fail as case sensitivity is only handled for svg elements.
},
skip_if_hydrate_from_ssr: true,
compileOptions: {
namespace: 'foreign'
},

@ -9,6 +9,7 @@ export default {
options: {
hydrate: false // Hydration test will fail as case sensitivity is only handled for svg elements.
},
skip_if_hydrate_from_ssr: true,
test({ assert, target }) {
const attr = sel => target.querySelector(sel).attributes[0].name;

@ -7,7 +7,7 @@ export default {
props: {
callback
},
after_test() {
before_test() {
calls = [];
},
async test({ assert, component, target }) {

@ -9,6 +9,10 @@ export default {
}
},
before_test() {
count = 0;
},
html: `
<div>foo</div>
<div>foo</div>

@ -8,5 +8,6 @@ export default {
assert.ok(!span.previousSibling);
component.raw = '<span>bar</span>';
assert.htmlEqual(target.innerHTML, '<div><span>bar</span></div>');
}
};

@ -9,6 +9,9 @@ export default {
props: {
callback
},
before_test() {
called = 0;
},
async test({ assert, component, target, window }) {
assert.equal(called, 1);

@ -3,11 +3,13 @@ import { count } from './store.js';
export default {
html: '<p>count: 0</p>',
before_test() {
count.set(0);
},
async test({ assert, component, target }) {
await component.increment();
assert.htmlEqual(target.innerHTML, '<p>count: 1</p>');
count.set(0);
}
};

Loading…
Cancel
Save