code style solved, set input-default value to

pull/5239/head
asvsfs 5 years ago
parent 7818c9bc1d
commit 292ebdab19

@ -1,13 +1,13 @@
import Attribute from "../../../nodes/Attribute"; import Attribute from '../../../nodes/Attribute';
import Block from "../../Block"; import Block from '../../Block';
import fix_attribute_casing from "./fix_attribute_casing"; import fix_attribute_casing from './fix_attribute_casing';
import ElementWrapper from "./index"; import ElementWrapper from './index';
import { string_literal } from "../../../utils/stringify"; import { string_literal } from '../../../utils/stringify';
import { b, x } from "code-red"; import { b, x } from 'code-red';
import Expression from "../../../nodes/shared/Expression"; import Expression from '../../../nodes/shared/Expression';
import Text from "../../../nodes/Text"; import Text from '../../../nodes/Text';
import handle_select_value_binding from "./handle_select_value_binding"; import handle_select_value_binding from './handle_select_value_binding';
import { Identifier, Node } from "estree"; import { Identifier, Node } from 'estree';
export class BaseAttributeWrapper { export class BaseAttributeWrapper {
node: Attribute; node: Attribute;
@ -46,27 +46,22 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
if (node.dependencies.size > 0) { if (node.dependencies.size > 0) {
// special case — <option value={foo}> — see below // special case — <option value={foo}> — see below
if (this.parent.node.name === "option" && node.name === "value") { if (this.parent.node.name === 'option' && node.name === 'value') {
let select: ElementWrapper = this.parent; let select: ElementWrapper = this.parent;
while ( while (select && (select.node.type !== 'Element' || select.node.name !== 'select'))
select &&
(select.node.type !== "Element" || select.node.name !== "select")
)
// @ts-ignore todo: doublecheck this, but looks to be correct // @ts-ignore todo: doublecheck this, but looks to be correct
select = select.parent; select = select.parent;
if (select && select.select_binding_dependencies) { if (select && select.select_binding_dependencies) {
select.select_binding_dependencies.forEach((prop) => { select.select_binding_dependencies.forEach(prop => {
this.node.dependencies.forEach((dependency: string) => { this.node.dependencies.forEach((dependency: string) => {
this.parent.renderer.component.indirect_dependencies this.parent.renderer.component.indirect_dependencies.get(prop).add(dependency);
.get(prop)
.add(dependency);
}); });
}); });
} }
} }
if (node.name === "value") { if (node.name === 'value') {
handle_select_value_binding(this, node.dependencies); handle_select_value_binding(this, node.dependencies);
} }
} }
@ -75,38 +70,28 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
this.metadata = this.get_metadata(); this.metadata = this.get_metadata();
this.is_indirectly_bound_value = is_indirectly_bound_value(this); this.is_indirectly_bound_value = is_indirectly_bound_value(this);
this.property_name = this.is_indirectly_bound_value this.property_name = this.is_indirectly_bound_value
? "__value" ? '__value'
: this.metadata && this.metadata.property_name; : this.metadata && this.metadata.property_name;
this.is_src = this.name === "src"; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750 this.is_src = this.name === 'src'; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
this.is_select_value_attribute = this.is_select_value_attribute = this.name === 'value' && this.parent.node.name === 'select';
this.name === "value" && this.parent.node.name === "select"; this.is_input_value = this.name === 'value' && this.parent.node.name === 'input';
this.is_input_value =
this.name === "value" && this.parent.node.name === "input";
this.should_cache = should_cache(this); this.should_cache = should_cache(this);
} }
render(block: Block) { render(block: Block) {
const element = this.parent; const element = this.parent;
const { const { name, property_name, should_cache, is_indirectly_bound_value } = this;
name,
property_name,
should_cache,
is_indirectly_bound_value,
} = this;
// xlink is a special case... we could maybe extend this to generic // xlink is a special case... we could maybe extend this to generic
// namespaced attributes but I'm not sure that's applicable in // namespaced attributes but I'm not sure that's applicable in
// HTML5? // HTML5?
const method = /-/.test(element.node.name) const method = /-/.test(element.node.name)
? "@set_custom_element_data" ? '@set_custom_element_data'
: name.slice(0, 6) === "xlink:" : name.slice(0, 6) === 'xlink:'
? "@xlink_attr" ? '@xlink_attr'
: "@attr"; : '@attr';
const is_legacy_input_type = const is_legacy_input_type = element.renderer.component.compile_options.legacy && name === 'type' && this.parent.node.name === 'input';
element.renderer.component.compile_options.legacy &&
name === "type" &&
this.parent.node.name === "input";
const dependencies = this.get_dependencies(); const dependencies = this.get_dependencies();
const value = this.get_value(block); const value = this.get_value(block);
@ -114,27 +99,25 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
let updater; let updater;
const init = this.get_init(block, value); const init = this.get_init(block, value);
// Set inputs value default to '' if undefined
if (name == "value") {
block.chunks.mount.push(b`@set_input_value(${element.var}, ${value});`);
}
if (is_legacy_input_type) { if (is_legacy_input_type) {
block.chunks.hydrate.push(b`@set_input_type(${element.var}, ${init});`); block.chunks.hydrate.push(
updater = b`@set_input_type(${element.var}, ${ b`@set_input_type(${element.var}, ${init});`
should_cache ? this.last : value );
});`; updater = b`@set_input_type(${element.var}, ${should_cache ? this.last : value});`;
} else if (this.is_select_value_attribute) { } else if (this.is_select_value_attribute) {
// annoying special case // annoying special case
const is_multiple_select = element.node.get_static_attribute_value( const is_multiple_select = element.node.get_static_attribute_value('multiple');
"multiple"
);
if (is_multiple_select) { if (is_multiple_select) {
updater = b`@select_options(${element.var}, ${value});`; updater = b`@select_options(${element.var}, ${value});`;
} else { } else {
updater = b`@select_option(${element.var}, ${value});`; updater = b`@select_option(${element.var}, ${value});`;
} }
// Set inputs value default to '' if undefined
if (name == 'value') {
block.chunks.mount.push(b`@set_input_value(${element.var}, ${value});`);
}
block.chunks.mount.push(b` block.chunks.mount.push(b`
${updater} ${updater}
@ -143,25 +126,19 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
block.chunks.hydrate.push( block.chunks.hydrate.push(
b`if (${element.var}.src !== ${init}) ${method}(${element.var}, "${name}", ${this.last});` b`if (${element.var}.src !== ${init}) ${method}(${element.var}, "${name}", ${this.last});`
); );
updater = b`${method}(${element.var}, "${name}", ${ updater = b`${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
should_cache ? this.last : value
});`;
} else if (property_name) { } else if (property_name) {
block.chunks.hydrate.push(b`${element.var}.${property_name} = ${init};`); block.chunks.hydrate.push(
b`${element.var}.${property_name} = ${init};`
);
updater = block.renderer.options.dev updater = block.renderer.options.dev
? b`@prop_dev(${element.var}, "${property_name}", ${ ? b`@prop_dev(${element.var}, "${property_name}", ${should_cache ? this.last : value});`
should_cache ? this.last : value : b`${element.var}.${property_name} = ${should_cache ? this.last : value};`;
});`
: b`${element.var}.${property_name} = ${
should_cache ? this.last : value
};`;
} else { } else {
block.chunks.hydrate.push( block.chunks.hydrate.push(
b`${method}(${element.var}, "${name}", ${init});` b`${method}(${element.var}, "${name}", ${init});`
); );
updater = b`${method}(${element.var}, "${name}", ${ updater = b`${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
should_cache ? this.last : value
});`;
} }
if (is_indirectly_bound_value) { if (is_indirectly_bound_value) {
@ -175,10 +152,7 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
} }
if (dependencies.length > 0) { if (dependencies.length > 0) {
const condition = this.get_dom_update_conditions( const condition = this.get_dom_update_conditions(block, block.renderer.dirty(dependencies));
block,
block.renderer.dirty(dependencies)
);
block.chunks.update.push(b` block.chunks.update.push(b`
if (${condition}) { if (${condition}) {
@ -187,20 +161,15 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
} }
// special case autofocus. has to be handled in a bit of a weird way // special case autofocus. has to be handled in a bit of a weird way
if (this.node.is_true && name === "autofocus") { if (this.node.is_true && name === 'autofocus') {
block.autofocus = element.var; block.autofocus = element.var;
} }
} }
get_init(block: Block, value) { get_init(block: Block, value) {
this.last = this.last = this.should_cache && block.get_unique_name(
this.should_cache && `${this.parent.var.name}_${this.name.replace(/[^a-zA-Z_$]/g, '_')}_value`
block.get_unique_name( );
`${this.parent.var.name}_${this.name.replace(
/[^a-zA-Z_$]/g,
"_"
)}_value`
);
if (this.should_cache) block.add_variable(this.last); if (this.should_cache) block.add_variable(this.last);
@ -221,18 +190,10 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
} }
if (this.is_input_value) { if (this.is_input_value) {
const type = element.node.get_static_attribute_value("type"); const type = element.node.get_static_attribute_value('type');
if ( if (type === null || type === "" || type === "text" || type === "email" || type === "password") {
type === null || condition = x`${condition} && ${element.var}.${property_name} !== ${should_cache ? last : value}`;
type === "" ||
type === "text" ||
type === "email" ||
type === "password"
) {
condition = x`${condition} && ${element.var}.${property_name} !== ${
should_cache ? last : value
}`;
} }
} }
@ -248,11 +209,9 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
const dependencies = new Set(node_dependencies); const dependencies = new Set(node_dependencies);
node_dependencies.forEach((prop: string) => { node_dependencies.forEach((prop: string) => {
const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get( const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(prop);
prop
);
if (indirect_dependencies) { if (indirect_dependencies) {
indirect_dependencies.forEach((indirect_dependency) => { indirect_dependencies.forEach(indirect_dependency => {
dependencies.add(indirect_dependency); dependencies.add(indirect_dependency);
}); });
} }
@ -264,21 +223,13 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
get_metadata() { get_metadata() {
if (this.parent.node.namespace) return null; if (this.parent.node.namespace) return null;
const metadata = attribute_lookup[this.name]; const metadata = attribute_lookup[this.name];
if ( if (metadata && metadata.applies_to && !metadata.applies_to.includes(this.parent.node.name)) return null;
metadata &&
metadata.applies_to &&
!metadata.applies_to.includes(this.parent.node.name)
)
return null;
return metadata; return metadata;
} }
get_value(block) { get_value(block) {
if (this.node.is_true) { if (this.node.is_true) {
if ( if (this.metadata && boolean_attribute.has(this.metadata.property_name.toLowerCase())) {
this.metadata &&
boolean_attribute.has(this.metadata.property_name.toLowerCase())
) {
return x`true`; return x`true`;
} }
return x`""`; return x`""`;
@ -288,18 +239,17 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
// TODO some of this code is repeated in Tag.ts — would be good to // TODO some of this code is repeated in Tag.ts — would be good to
// DRY it out if that's possible without introducing crazy indirection // DRY it out if that's possible without introducing crazy indirection
if (this.node.chunks.length === 1) { if (this.node.chunks.length === 1) {
return this.node.chunks[0].type === "Text" return this.node.chunks[0].type === 'Text'
? string_literal((this.node.chunks[0] as Text).data) ? string_literal((this.node.chunks[0] as Text).data)
: (this.node.chunks[0] as Expression).manipulate(block); : (this.node.chunks[0] as Expression).manipulate(block);
} }
let value = let value = this.node.name === 'class'
this.node.name === "class" ? this.get_class_name_text(block)
? this.get_class_name_text(block) : this.render_chunks(block).reduce((lhs, rhs) => x`${lhs} + ${rhs}`);
: this.render_chunks(block).reduce((lhs, rhs) => x`${lhs} + ${rhs}`);
// '{foo} {bar}' — treat as string concatenation // '{foo} {bar}' — treat as string concatenation
if (this.node.chunks[0].type !== "Text") { if (this.node.chunks[0].type !== 'Text') {
value = x`"" + ${value}`; value = x`"" + ${value}`;
} }
@ -320,7 +270,7 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
render_chunks(block: Block) { render_chunks(block: Block) {
return this.node.chunks.map((chunk) => { return this.node.chunks.map((chunk) => {
if (chunk.type === "Text") { if (chunk.type === 'Text') {
return string_literal(chunk.data); return string_literal(chunk.data);
} }
@ -329,114 +279,104 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
} }
stringify() { stringify() {
if (this.node.is_true) return ""; if (this.node.is_true) return '';
const value = this.node.chunks; const value = this.node.chunks;
if (value.length === 0) return `=""`; if (value.length === 0) return `=""`;
return `="${value return `="${value.map(chunk => {
.map((chunk) => { return chunk.type === 'Text'
return chunk.type === "Text" ? chunk.data.replace(/"/g, '\\"')
? chunk.data.replace(/"/g, '\\"') : `\${${chunk.manipulate()}}`;
: `\${${chunk.manipulate()}}`; }).join('')}"`;
})
.join("")}"`;
} }
} }
// source: https://html.spec.whatwg.org/multipage/indices.html // source: https://html.spec.whatwg.org/multipage/indices.html
const attribute_lookup = { const attribute_lookup = {
allowfullscreen: { property_name: "allowFullscreen", applies_to: ["iframe"] }, allowfullscreen: { property_name: 'allowFullscreen', applies_to: ['iframe'] },
allowpaymentrequest: { allowpaymentrequest: { property_name: 'allowPaymentRequest', applies_to: ['iframe'] },
property_name: "allowPaymentRequest", async: { applies_to: ['script'] },
applies_to: ["iframe"], autofocus: { applies_to: ['button', 'input', 'keygen', 'select', 'textarea'] },
}, autoplay: { applies_to: ['audio', 'video'] },
async: { applies_to: ["script"] }, checked: { applies_to: ['input'] },
autofocus: { controls: { applies_to: ['audio', 'video'] },
applies_to: ["button", "input", "keygen", "select", "textarea"], default: { applies_to: ['track'] },
}, defer: { applies_to: ['script'] },
autoplay: { applies_to: ["audio", "video"] },
checked: { applies_to: ["input"] },
controls: { applies_to: ["audio", "video"] },
default: { applies_to: ["track"] },
defer: { applies_to: ["script"] },
disabled: { disabled: {
applies_to: [ applies_to: [
"button", 'button',
"fieldset", 'fieldset',
"input", 'input',
"keygen", 'keygen',
"optgroup", 'optgroup',
"option", 'option',
"select", 'select',
"textarea", 'textarea'
], ]
},
formnovalidate: {
property_name: "formNoValidate",
applies_to: ["button", "input"],
}, },
formnovalidate: { property_name: 'formNoValidate', applies_to: ['button', 'input'] },
hidden: {}, hidden: {},
indeterminate: { applies_to: ["input"] }, indeterminate: { applies_to: ['input'] },
ismap: { property_name: "isMap", applies_to: ["img"] }, ismap: { property_name: 'isMap', applies_to: ['img'] },
loop: { applies_to: ["audio", "bgsound", "video"] }, loop: { applies_to: ['audio', 'bgsound', 'video'] },
multiple: { applies_to: ["input", "select"] }, multiple: { applies_to: ['input', 'select'] },
muted: { applies_to: ["audio", "video"] }, muted: { applies_to: ['audio', 'video'] },
nomodule: { property_name: "noModule", applies_to: ["script"] }, nomodule: { property_name: 'noModule', applies_to: ['script'] },
novalidate: { property_name: "noValidate", applies_to: ["form"] }, novalidate: { property_name: 'noValidate', applies_to: ['form'] },
open: { applies_to: ["details", "dialog"] }, open: { applies_to: ['details', 'dialog'] },
playsinline: { property_name: "playsInline", applies_to: ["video"] }, playsinline: { property_name: 'playsInline', applies_to: ['video'] },
readonly: { property_name: "readOnly", applies_to: ["input", "textarea"] }, readonly: { property_name: 'readOnly', applies_to: ['input', 'textarea'] },
required: { applies_to: ["input", "select", "textarea"] }, required: { applies_to: ['input', 'select', 'textarea'] },
reversed: { applies_to: ["ol"] }, reversed: { applies_to: ['ol'] },
selected: { applies_to: ["option"] }, selected: { applies_to: ['option'] },
value: { value: {
applies_to: [ applies_to: [
"button", 'button',
"option", 'option',
"input", 'input',
"li", 'li',
"meter", 'meter',
"progress", 'progress',
"param", 'param',
"select", 'select',
"textarea", 'textarea'
], ]
}, }
}; };
Object.keys(attribute_lookup).forEach((name) => { Object.keys(attribute_lookup).forEach(name => {
const metadata = attribute_lookup[name]; const metadata = attribute_lookup[name];
if (!metadata.property_name) metadata.property_name = name; if (!metadata.property_name) metadata.property_name = name;
}); });
// source: https://html.spec.whatwg.org/multipage/indices.html // source: https://html.spec.whatwg.org/multipage/indices.html
const boolean_attribute = new Set([ const boolean_attribute = new Set([
"allowfullscreen", 'allowfullscreen',
"allowpaymentrequest", 'allowpaymentrequest',
"async", 'async',
"autofocus", 'autofocus',
"autoplay", 'autoplay',
"checked", 'checked',
"controls", 'controls',
"default", 'default',
"defer", 'defer',
"disabled", 'disabled',
"formnovalidate", 'formnovalidate',
"hidden", 'hidden',
"ismap", 'ismap',
"itemscope", 'itemscope',
"loop", 'loop',
"multiple", 'multiple',
"muted", 'muted',
"nomodule", 'nomodule',
"novalidate", 'novalidate',
"open", 'open',
"playsinline", 'playsinline',
"readonly", 'readonly',
"required", 'required',
"reversed", 'reversed',
"selected", 'selected'
]); ]);
function should_cache(attribute: AttributeWrapper) { function should_cache(attribute: AttributeWrapper) {
@ -445,12 +385,11 @@ function should_cache(attribute: AttributeWrapper) {
function is_indirectly_bound_value(attribute: AttributeWrapper) { function is_indirectly_bound_value(attribute: AttributeWrapper) {
const element = attribute.parent; const element = attribute.parent;
return ( return attribute.name === 'value' &&
attribute.name === "value" && (element.node.name === 'option' || // TODO check it's actually bound
(element.node.name === "option" || // TODO check it's actually bound (element.node.name === 'input' &&
(element.node.name === "input" && element.node.bindings.some(
element.node.bindings.some((binding) => (binding) =>
/checked|group/.test(binding.name) /checked|group/.test(binding.name)
))) )));
); }
}
Loading…
Cancel
Save