From 342389863e6856515fa002fc9d8c0b5cfe23faa9 Mon Sep 17 00:00:00 2001 From: Benjamin Milde Date: Sun, 5 May 2019 19:33:00 +0200 Subject: [PATCH] Allow multiple event listeners on a single node --- src/parse/state/tag.ts | 25 ++--- .../input.svelte | 1 + .../output.json | 96 +++++++++++++++++++ 3 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 test/parser/samples/non-unique-attribute-event-handler/input.svelte create mode 100644 test/parser/samples/non-unique-attribute-event-handler/output.json diff --git a/src/parse/state/tag.ts b/src/parse/state/tag.ts index 3747d2d482..f02eed037c 100644 --- a/src/parse/state/tag.ts +++ b/src/parse/state/tag.ts @@ -131,8 +131,8 @@ export default function tag(parser: Parser) { const type = meta_tags.has(name) ? meta_tags.get(name) : (/[A-Z]/.test(name[0]) || name === 'svelte:self' || name === 'svelte:component') ? 'InlineComponent' - : name === 'title' && parent_is_head(parser.stack) ? 'Title' - : name === 'slot' && !parser.customElement ? 'Slot' : 'Element'; + : name === 'title' && parent_is_head(parser.stack) ? 'Title' + : name === 'slot' && !parser.customElement ? 'Slot' : 'Element'; const element: Node = { start, @@ -360,14 +360,6 @@ function read_attribute(parser: Parser, unique_names: Set) { let name = parser.read_until(/(\s|=|\/|>)/); if (!name) return null; - if (unique_names.has(name)) { - parser.error({ - code: `duplicate-attribute`, - message: 'Attributes need to be unique' - }, start); - } - - unique_names.add(name); let end = parser.index; @@ -376,6 +368,15 @@ function read_attribute(parser: Parser, unique_names: Set) { const colon_index = name.indexOf(':'); const type = colon_index !== -1 && get_directive_type(name.slice(0, colon_index)); + if (unique_names.has(name) && type != "EventHandler") { + parser.error({ + code: `duplicate-attribute`, + message: 'Attributes need to be unique' + }, start); + } + + unique_names.add(name); + let value: any[] | true = true; if (parser.eat('=')) { value = read_attribute_value(parser); @@ -453,8 +454,8 @@ function read_attribute_value(parser: Parser) { const regex = ( quote_mark === `'` ? /'/ : - quote_mark === `"` ? /"/ : - /(\/>|[\s"'=<>`])/ + quote_mark === `"` ? /"/ : + /(\/>|[\s"'=<>`])/ ); const value = read_sequence(parser, () => !!parser.match_regex(regex)); diff --git a/test/parser/samples/non-unique-attribute-event-handler/input.svelte b/test/parser/samples/non-unique-attribute-event-handler/input.svelte new file mode 100644 index 0000000000..b13403f77d --- /dev/null +++ b/test/parser/samples/non-unique-attribute-event-handler/input.svelte @@ -0,0 +1 @@ + diff --git a/test/parser/samples/non-unique-attribute-event-handler/output.json b/test/parser/samples/non-unique-attribute-event-handler/output.json new file mode 100644 index 0000000000..9579fe5b4c --- /dev/null +++ b/test/parser/samples/non-unique-attribute-event-handler/output.json @@ -0,0 +1,96 @@ +{ + "html": { + "start": 0, + "end": 87, + "type": "Fragment", + "children": [ + { + "start": 0, + "end": 87, + "type": "Element", + "name": "button", + "attributes": [ + { + "start": 8, + "end": 45, + "type": "EventHandler", + "name": "click", + "modifiers": [], + "expression": { + "type": "ArrowFunctionExpression", + "start": 19, + "end": 43, + "id": null, + "expression": true, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "AssignmentExpression", + "start": 25, + "end": 43, + "operator": "=", + "left": { + "type": "Identifier", + "start": 25, + "end": 32, + "name": "visible" + }, + "right": { + "type": "UnaryExpression", + "start": 35, + "end": 43, + "operator": "!", + "prefix": true, + "argument": { + "type": "Identifier", + "start": 36, + "end": 43, + "name": "visible" + } + } + } + } + }, + { + "start": 46, + "end": 77, + "type": "EventHandler", + "name": "click", + "modifiers": [], + "expression": { + "type": "ArrowFunctionExpression", + "start": 57, + "end": 75, + "id": null, + "expression": true, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "AssignmentExpression", + "start": 63, + "end": 75, + "operator": "=", + "left": { + "type": "Identifier", + "start": 63, + "end": 67, + "name": "ajax" + }, + "right": { + "type": "Literal", + "start": 70, + "end": 75, + "value": false, + "raw": "false" + } + } + } + } + ], + "children": [] + } + ] + } +}