From fc7ed7b8781260eb58e372d2637ba694f6ecc380 Mon Sep 17 00:00:00 2001 From: "Alexey Mulyukin (alexprey)" Date: Tue, 25 Aug 2020 12:46:45 +0300 Subject: [PATCH] Fix issue #28: Inline event handlers in markup cause errors when used without quotes --- CHANGELOG.md | 13 +++-- README.md | 5 ++ examples/Alert.svelte | 2 +- lib/parser.js | 2 +- lib/v3/parser.js | 53 +++++++++---------- package.json | 4 +- test/svelte3/integration/bind/bind.spec.js | 4 +- ...markup.dispatcher.customConstructor.svelte | 4 ++ ....markup.dispatcher.default.function.svelte | 4 ++ .../svelte3/integration/events/events.spec.js | 30 +++++++---- 10 files changed, 73 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a8cd7e..ff4fe94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,15 +3,20 @@ All notable changes to the "svelte-intellisense" extension will be documented in Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. +## [3.0.3] 25.08.2020 + +- 🛠 **[Fixed]** Fix [issue #28](https://github.com/alexprey/sveltedoc-parser/issues/28) (Inline event handlers in markup cause errors when used without quotes) + - Change dependency from `htmlparser2` to [htmlparser2-svelte](https://www.npmjs.com/package/htmlparser2-svelte) special fork of [htmlparser2](https://www.npmjs.com/package/htmlparser2) to handle Svelte specific cases to parse markup + ## [3.0.2] 24.08.2020 -- 🛠 [Fixed] Fix issue #6 (Build a correct component name from a file name) +- 🛠 **[Fixed]** Fix issue #6 (Build a correct component name from a file name) ``` round.button.svelte -> RoundButton ``` -- 🛠 [Fixed] Fix issue #27 (Events is not exposed from exported functions and arrow functions) -- 🛠 [Fixed] Fix issue #31 (Propogated events in markup should be parsed even it was before handled) -- 🛠 [Fixed] Fix issue #32 (Event is not registered when dispatched from functions used as a parameters of another functions) +- 🛠 **[Fixed]** Fix [issue #27](https://github.com/alexprey/sveltedoc-parser/issues/27) (Events is not exposed from exported functions and arrow functions) +- 🛠 **[Fixed]** Fix [issue #31](https://github.com/alexprey/sveltedoc-parser/issues/31) (Propogated events in markup should be parsed even it was before handled) +- 🛠 **[Fixed]** Fix [issue #32](https://github.com/alexprey/sveltedoc-parser/issues/32) (Event is not registered when dispatched from functions used as a parameters of another functions) ## [3.0.1] 17.08.2020 diff --git a/README.md b/README.md index 949bf73..751aa20 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,11 @@ Generate a JSON documentation for a Svelte file ## Changelog +### [3.0.3] 25.08.2020 + +- 🛠 **[Fixed]** Fix [issue #28](https://github.com/alexprey/sveltedoc-parser/issues/28) (Inline event handlers in markup cause errors when used without quotes) + - Change dependency from `htmlparser2` to [htmlparser2-svelte](https://www.npmjs.com/package/htmlparser2-svelte) special fork of [htmlparser2](https://www.npmjs.com/package/htmlparser2) to handle Svelte specific cases to parse markup + ### [3.0.2] 24.08.2020 - 🛠 **[Fixed]** Fix issue #6 (Build a correct component name from a file name) diff --git a/examples/Alert.svelte b/examples/Alert.svelte index 38bfc17..3fce1a6 100644 --- a/examples/Alert.svelte +++ b/examples/Alert.svelte @@ -27,7 +27,7 @@ The `close` event fired when user click to X button in the panel. @event CloseEvent#close --> - + {/if} \ No newline at end of file diff --git a/lib/parser.js b/lib/parser.js index 7553374..67a53ad 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -1,7 +1,7 @@ const EventEmitter = require('events'); const espree = require('espree'); const eslint = require('eslint'); -const HtmlParser = require('htmlparser2').Parser; +const HtmlParser = require('htmlparser2-svelte').Parser; const path = require('path'); const utils = require('./utils'); const jsdoc = require('./jsdoc'); diff --git a/lib/v3/parser.js b/lib/v3/parser.js index 26fbcf1..c658aa5 100644 --- a/lib/v3/parser.js +++ b/lib/v3/parser.js @@ -3,7 +3,7 @@ const path = require('path'); const espree = require('espree'); const eslint = require('eslint'); -const HtmlParser = require('htmlparser2').Parser; +const HtmlParser = require('htmlparser2-svelte').Parser; const utils = require('./../utils'); const jsdoc = require('./../jsdoc'); @@ -573,10 +573,15 @@ class Parser extends EventEmitter { parseMarkupExpressionBlock(expression, offset) { // Add name for anonymous functions to prevent parser error - const regex = /^{\s*function\s+\(/i; + const regex = /^{?\s*function\s+\(/i; - expression = expression.replace(regex, function () { - return '{function a('; + expression = expression.replace(regex, function (m) { + // When quotes in attributes used curcly braces are provided here, so we should handle it separatly + if (m.startsWith('{')) { + return '{function a('; + } + + return 'function a('; }); const ast = espree.parse( @@ -724,8 +729,6 @@ class Parser extends EventEmitter { } }, onattribute: (name, value) => { - console.log('onattribute', name, value); - if (this.includeSourceLocations && parser.startIndex >= 0 && parser.endIndex >= parser.startIndex) { lastAttributeLocations[name] = { start: lastAttributeIndex, @@ -783,14 +786,11 @@ class Parser extends EventEmitter { } }, onopentagname: (tagName) => { - console.log('onopentagname', tagName); lastTagName = tagName; lastAttributeIndex = parser._tokenizer._index; lastAttributeLocations = {}; }, onopentag: (tagName, attrs) => { - console.log('onopentag', tagName, attrs); - const isNotStyleOrScript = !['style', 'script'].includes(tagName); const isTopLevelElement = parser._stack.length === 1; @@ -845,8 +845,8 @@ class Parser extends EventEmitter { const attributeValue = attrs[name]; - if (attributeValue && attributeValue.length > 2 && attributeValue.charAt(0) === '{' && attributeValue.charAt(attributeValue.length - 1) === '}') { - targetPropertyName = attributeValue.substr(1, attributeValue.length - 2); + if (attributeValue && attributeValue.length > 0) { + targetPropertyName = attributeValue; } return { @@ -885,30 +885,27 @@ class Parser extends EventEmitter { if (this.features.includes('refs')) { if (hasOwnProperty(attrs, 'bind:this') && attrs['bind:this']) { - const value = attrs['bind:this']; + const bindedVariableName = attrs['bind:this']; - if (value.length > 2 && value.charAt(0) === '{' && value.charAt(value.length - 1) === '}') { - const bindedVariableName = value.substr(1, value.length - 2); - - this.emitRefItem({ - name: bindedVariableName, - parent: tagName, - locations: this.includeSourceLocations && hasOwnProperty(lastAttributeLocations, 'bind:this') - ? [lastAttributeLocations['bind:this']] - : null, - // TODO: Reprication, remove this property with 3.* - loc: this.includeSourceLocations && hasOwnProperty(lastAttributeLocations, 'bind:this') - ? lastAttributeLocations['bind:this'] - : null - }); - } + this.emitRefItem({ + name: bindedVariableName, + parent: tagName, + locations: this.includeSourceLocations && hasOwnProperty(lastAttributeLocations, 'bind:this') + ? [lastAttributeLocations['bind:this']] + : null, + // TODO: Reprication, remove this property with 3.* + loc: this.includeSourceLocations && hasOwnProperty(lastAttributeLocations, 'bind:this') + ? lastAttributeLocations['bind:this'] + : null + }); } } } } }, { lowerCaseTags: false, - lowerCaseAttributeNames: false + lowerCaseAttributeNames: false, + curlyBracesInAttributes: true }); parser.write(this.structure.template); diff --git a/package.json b/package.json index 483964f..51128de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sveltedoc-parser", - "version": "3.0.2", + "version": "3.0.3", "description": "Generate a JSON documentation for a Svelte file", "main": "index.js", "scripts": { @@ -38,7 +38,7 @@ "dependencies": { "espree": "7.2.0", "eslint": "7.6.0", - "htmlparser2": "3.9.2" + "htmlparser2-svelte": "4.1.0" }, "devDependencies": { "chai": "4.1.2", diff --git a/test/svelte3/integration/bind/bind.spec.js b/test/svelte3/integration/bind/bind.spec.js index 8b27abf..6807d21 100644 --- a/test/svelte3/integration/bind/bind.spec.js +++ b/test/svelte3/integration/bind/bind.spec.js @@ -43,7 +43,7 @@ describe('SvelteDoc v3 - Bind', () => { expect(doc, 'Document should be provided').to.exist; expect(doc.data, 'Document data should be parsed').to.exist; - expect(doc.data.length).to.equal(1); + expect(doc.data.length, 'Found following data items - ' + doc.data.map(d => d.name).join(', ')).to.equal(1); const item = doc.data[0]; expect(item, 'Bind item should be a valid entity').to.exist; @@ -98,7 +98,7 @@ describe('SvelteDoc v3 - Bind', () => { expect(doc, 'Document should be provided').to.exist; expect(doc.data, 'Document data should be parsed').to.exist; - expect(doc.data.length).to.equal(1); + expect(doc.data.length, 'Found following data items - ' + doc.data.map(d => d.name).join(', ')).to.equal(1); const item = doc.data[0]; expect(item, 'Bind item should be a valid entity').to.exist; diff --git a/test/svelte3/integration/events/event.markup.dispatcher.customConstructor.svelte b/test/svelte3/integration/events/event.markup.dispatcher.customConstructor.svelte index 977d36d..81a4597 100644 --- a/test/svelte3/integration/events/event.markup.dispatcher.customConstructor.svelte +++ b/test/svelte3/integration/events/event.markup.dispatcher.customConstructor.svelte @@ -6,4 +6,8 @@ + + \ No newline at end of file diff --git a/test/svelte3/integration/events/event.markup.dispatcher.default.function.svelte b/test/svelte3/integration/events/event.markup.dispatcher.default.function.svelte index 37d119f..36c23f0 100644 --- a/test/svelte3/integration/events/event.markup.dispatcher.default.function.svelte +++ b/test/svelte3/integration/events/event.markup.dispatcher.default.function.svelte @@ -6,4 +6,8 @@ + + \ No newline at end of file diff --git a/test/svelte3/integration/events/events.spec.js b/test/svelte3/integration/events/events.spec.js index 3b4c700..6eb194b 100644 --- a/test/svelte3/integration/events/events.spec.js +++ b/test/svelte3/integration/events/events.spec.js @@ -147,12 +147,17 @@ describe('SvelteDoc v3 - Events', () => { expect(doc, 'Document should be provided').to.exist; expect(doc.events, 'Document events should be parsed').to.exist; - expect(doc.events.length).to.equal(1); - const event = doc.events[0]; + const event1 = doc.events.find(e => e.name === 'notify'); - expect(event, 'Event should be a valid entity').to.exist; - expect(event.name).to.equal('notify'); - expect(event.visibility).to.equal('public'); + expect(event1, 'Event should be a valid entity').to.exist; + expect(event1.name).to.equal('notify'); + expect(event1.visibility).to.equal('public'); + + const event2 = doc.events.find(e => e.name === 'notify2'); + + expect(event2, 'Event should be a valid entity').to.exist; + expect(event2.name).to.equal('notify2'); + expect(event2.visibility).to.equal('public'); done(); }).catch(e => { @@ -279,12 +284,17 @@ describe('SvelteDoc v3 - Events', () => { expect(doc, 'Document should be provided').to.exist; expect(doc.events, 'Document events should be parsed').to.exist; - expect(doc.events.length).to.equal(1); - const event = doc.events[0]; + const event1 = doc.events.find(e => e.name === 'notify'); - expect(event, 'Event should be a valid entity').to.exist; - expect(event.name).to.equal('notify'); - expect(event.visibility).to.equal('public'); + expect(event1, 'Event should be a valid entity').to.exist; + expect(event1.name).to.equal('notify'); + expect(event1.visibility).to.equal('public'); + + const event2 = doc.events.find(e => e.name === 'notify2'); + + expect(event2, 'Event should be a valid entity').to.exist; + expect(event2.name).to.equal('notify2'); + expect(event2.visibility).to.equal('public'); done(); }).catch(e => {