import validateEventHandler from './validateEventHandler'; import { Validator } from '../index'; import { Node } from '../../interfaces'; export default function validateElement(validator: Validator, node: Node, refs: Map, refCallees: Node[]) { const isComponent = node.name === ':Self' || validator.components.has(node.name); if (!isComponent && /^[A-Z]/.test(node.name[0])) { // TODO upgrade to validator.error in v2 validator.warn(`${node.name} component is not defined`, node.start); } if (node.name === 'slot') { const nameAttribute = node.attributes.find((attribute: Node) => attribute.name === 'name'); if (nameAttribute) { if (nameAttribute.value.length !== 1 || nameAttribute.value[0].type !== 'Text') { validator.error(` name cannot be dynamic`, nameAttribute.start); } const slotName = nameAttribute.value[0].data; if (slotName === 'default') { validator.error(`default is a reserved word — it cannot be used as a slot name`, nameAttribute.start); } // TODO should duplicate slots be disallowed? Feels like it's more likely to be a // bug than anything. Perhaps it should be a warning // if (validator.slots.has(slotName)) { // validator.error(`duplicate '${slotName}' element`, nameAttribute.start); // } // validator.slots.add(slotName); } else { // if (validator.slots.has('default')) { // validator.error(`duplicate default element`, node.start); // } // validator.slots.add('default'); } } let hasIntro: boolean; let hasOutro: boolean; let hasTransition: boolean; node.attributes.forEach((attribute: Node) => { if (attribute.type === 'Ref') { if (!refs.has(attribute.name)) refs.set(attribute.name, []); refs.get(attribute.name).push(node); } if (!isComponent && attribute.type === 'Binding') { const { name } = attribute; if (name === 'value') { if ( node.name !== 'input' && node.name !== 'textarea' && node.name !== 'select' ) { validator.error( `'value' is not a valid binding on <${node.name}> elements`, attribute.start ); } checkTypeAttribute(validator, node); } else if (name === 'checked') { if (node.name !== 'input') { validator.error( `'checked' is not a valid binding on <${node.name}> elements`, attribute.start ); } if (checkTypeAttribute(validator, node) !== 'checkbox') { validator.error( `'checked' binding can only be used with `, attribute.start ); } } else if (name === 'group') { if (node.name !== 'input') { validator.error( `'group' is not a valid binding on <${node.name}> elements`, attribute.start ); } const type = checkTypeAttribute(validator, node); if (type !== 'checkbox' && type !== 'radio') { validator.error( `'checked' binding can only be used with or `, attribute.start ); } } else if ( name === 'currentTime' || name === 'duration' || name === 'paused' ) { if (node.name !== 'audio' && node.name !== 'video') { validator.error( `'${name}' binding can only be used with