|
|
|
@ -17,120 +17,7 @@ export default function validateElement(
|
|
|
|
|
elementStack: Node[]
|
|
|
|
|
) {
|
|
|
|
|
node.attributes.forEach((attribute: Node) => {
|
|
|
|
|
if (attribute.type === 'Binding') {
|
|
|
|
|
const { name } = attribute;
|
|
|
|
|
|
|
|
|
|
if (name === 'value') {
|
|
|
|
|
if (
|
|
|
|
|
node.name !== 'input' &&
|
|
|
|
|
node.name !== 'textarea' &&
|
|
|
|
|
node.name !== 'select'
|
|
|
|
|
) {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: `invalid-binding`,
|
|
|
|
|
message: `'value' is not a valid binding on <${node.name}> elements`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (node.name === 'select') {
|
|
|
|
|
const attribute = node.attributes.find(
|
|
|
|
|
(attribute: Node) => attribute.name === 'multiple'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (attribute && isDynamic(attribute)) {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: `dynamic-multiple-attribute`,
|
|
|
|
|
message: `'multiple' attribute cannot be dynamic if select uses two-way binding`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
checkTypeAttribute(component, node);
|
|
|
|
|
}
|
|
|
|
|
} else if (name === 'checked' || name === 'indeterminate') {
|
|
|
|
|
if (node.name !== 'input') {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: `invalid-binding`,
|
|
|
|
|
message: `'${name}' is not a valid binding on <${node.name}> elements`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (checkTypeAttribute(component, node) !== 'checkbox') {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: `invalid-binding`,
|
|
|
|
|
message: `'${name}' binding can only be used with <input type="checkbox">`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else if (name === 'group') {
|
|
|
|
|
if (node.name !== 'input') {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: `invalid-binding`,
|
|
|
|
|
message: `'group' is not a valid binding on <${node.name}> elements`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const type = checkTypeAttribute(component, node);
|
|
|
|
|
|
|
|
|
|
if (type !== 'checkbox' && type !== 'radio') {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: `invalid-binding`,
|
|
|
|
|
message: `'checked' binding can only be used with <input type="checkbox"> or <input type="radio">`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else if (name == 'files') {
|
|
|
|
|
if (node.name !== 'input') {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: `invalid-binding`,
|
|
|
|
|
message: `'files' binding acn only be used with <input type="file">`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const type = checkTypeAttribute(component, node);
|
|
|
|
|
|
|
|
|
|
if (type !== 'file') {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: `invalid-binding`,
|
|
|
|
|
message: `'files' binding can only be used with <input type="file">`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else if (
|
|
|
|
|
name === 'currentTime' ||
|
|
|
|
|
name === 'duration' ||
|
|
|
|
|
name === 'paused' ||
|
|
|
|
|
name === 'buffered' ||
|
|
|
|
|
name === 'seekable' ||
|
|
|
|
|
name === 'played' ||
|
|
|
|
|
name === 'volume'
|
|
|
|
|
) {
|
|
|
|
|
if (node.name !== 'audio' && node.name !== 'video') {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: `invalid-binding`,
|
|
|
|
|
message: `'${name}' binding can only be used with <audio> or <video>`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else if (dimensions.test(name)) {
|
|
|
|
|
if (node.name === 'svg' && (name === 'offsetWidth' || name === 'offsetHeight')) {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: 'invalid-binding',
|
|
|
|
|
message: `'${attribute.name}' is not a valid binding on <svg>. Use '${name.replace('offset', 'client')}' instead`
|
|
|
|
|
});
|
|
|
|
|
} else if (svg.test(node.name)) {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: 'invalid-binding',
|
|
|
|
|
message: `'${attribute.name}' is not a valid binding on SVG elements`
|
|
|
|
|
});
|
|
|
|
|
} else if (isVoidElementName(node.name)) {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: 'invalid-binding',
|
|
|
|
|
message: `'${attribute.name}' is not a valid binding on void elements like <${node.name}>. Use a wrapper element instead`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|
code: `invalid-binding`,
|
|
|
|
|
message: `'${attribute.name}' is not a valid binding`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else if (attribute.type === 'Attribute') {
|
|
|
|
|
if (attribute.type === 'Attribute') {
|
|
|
|
|
if (attribute.name === 'value' && node.name === 'textarea') {
|
|
|
|
|
if (node.children.length) {
|
|
|
|
|
component.error(attribute, {
|
|
|
|
|