import { is_void } from '../../utils/names'; import Node from './shared/Node'; import Attribute from './Attribute'; import Binding from './Binding'; import EventHandler from './EventHandler'; import Transition from './Transition'; import Animation from './Animation'; import Action from './Action'; import Class from './Class'; import Text from './Text'; import { namespaces } from '../../utils/namespaces'; import map_children from './shared/map_children'; import { dimensions } from '../../utils/patterns'; import fuzzymatch from '../../utils/fuzzymatch'; import list from '../../utils/list'; import Let from './Let'; import TemplateScope from './shared/TemplateScope'; import { INode } from './interfaces'; const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/; const aria_attributes = 'activedescendant atomic autocomplete busy checked colindex controls current describedby details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowindex selected setsize sort valuemax valuemin valuenow valuetext'.split(' '); const aria_attribute_set = new Set(aria_attributes); const aria_roles = 'alert alertdialog application article banner button cell checkbox columnheader combobox command complementary composite contentinfo definition dialog directory document feed figure form grid gridcell group heading img input landmark link list listbox listitem log main marquee math menu menubar menuitem menuitemcheckbox menuitemradio navigation none note option presentation progressbar radio radiogroup range region roletype row rowgroup rowheader scrollbar search searchbox section sectionhead select separator slider spinbutton status structure switch tab table tablist tabpanel term textbox timer toolbar tooltip tree treegrid treeitem widget window'.split(' '); const aria_role_set = new Set(aria_roles); const a11y_required_attributes = { a: ['href'], area: ['alt', 'aria-label', 'aria-labelledby'], // html-has-lang html: ['lang'], // iframe-has-title iframe: ['title'], img: ['alt'], object: ['title', 'aria-label', 'aria-labelledby'] }; const a11y_distracting_elements = new Set([ 'blink', 'marquee' ]); const a11y_required_content = new Set([ // anchor-has-content 'a', // heading-has-content 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ]); const invisible_elements = new Set(['meta', 'html', 'script', 'style']); const valid_modifiers = new Set([ 'preventDefault', 'stopPropagation', 'capture', 'once', 'passive' ]); const passive_events = new Set([ 'wheel', 'touchstart', 'touchmove', 'touchend', 'touchcancel' ]); function get_namespace(parent: Element, element: Element, explicit_namespace: string) { const parent_element = parent.find_nearest(/^Element/); if (!parent_element) { return explicit_namespace || (svg.test(element.name) ? namespaces.svg : null); } if (element.name.toLowerCase() === 'svg') return namespaces.svg; if (parent_element.name.toLowerCase() === 'foreignobject') return null; return parent_element.namespace; } export default class Element extends Node { type: 'Element'; name: string; scope: TemplateScope; attributes: Attribute[] = []; actions: Action[] = []; bindings: Binding[] = []; classes: Class[] = []; handlers: EventHandler[] = []; lets: Let[] = []; intro?: Transition = null; outro?: Transition = null; animation?: Animation = null; children: INode[]; namespace: string; constructor(component, parent, scope, info: any) { super(component, parent, scope, info); this.name = info.name; this.namespace = get_namespace(parent, this, component.namespace); if (this.name === 'textarea') { if (info.children.length > 0) { const value_attribute = info.attributes.find(node => node.name === 'value'); if (value_attribute) { component.error(value_attribute, { code: `textarea-duplicate-value`, message: `A