diff --git a/CHANGELOG.md b/CHANGELOG.md
index 23c02a2..57f9eb8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,11 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
## UNRELEASED
+## [3.0.1] 17.08.2020
+
+- [Fixed] Solve issue #26, support `export { variables as var }` statement.
+- [Added] now interface `SvelteDataItem` provides a new property `localName` with information about internal name of component property.
+
## [3.0.0] 08.08.2020
- [Fixed] Solve vulnerability issues:
diff --git a/README.md b/README.md
index f1bfdda..7b0f76f 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,11 @@ Generate a JSON documentation for a Svelte file
## Changelog
+### [3.0.1] 17.08.2020
+
+- [Fixed] Solve issue #26, support `export { variables as var }` statement.
+- [Added] now interface `SvelteDataItem` provides a new property `localName` with information about internal name of component property.
+
### [3.0.0] 08.08.2020
- [Fixed] Solve vulnerability issues:
diff --git a/index.js b/index.js
index e52445f..939c621 100644
--- a/index.js
+++ b/index.js
@@ -74,24 +74,32 @@ function convertVisibilityToLevel(visibility) {
return 0;
}
-function mergeItems(itemType, currentItem, newItem) {
+function mergeItems(itemType, currentItem, newItem, ignoreLocations) {
if (convertVisibilityToLevel(currentItem.visibility) < convertVisibilityToLevel(newItem.visibility)) {
currentItem.visibility = newItem.visibility;
}
if (!currentItem.description && newItem.description) {
- currentItem.description = newItem;
+ currentItem.description = newItem.description;
+ }
+
+ if (!currentItem.type || currentItem.type.type === 'any') {
+ if (newItem.type && newItem.type.type !== 'any') {
+ currentItem.type = newItem.type;
+ }
}
if (!currentItem.keywords && newItem.keywords) {
currentItem.keywords = newItem.keywords;
}
- if (newItem.locations && newItem.locations.length > 0) {
- if (currentItem.locations) {
- currentItem.locations.push(...newItem.locations);
- } else {
- currentItem.locations = [...newItem.locations];
+ if (!ignoreLocations) {
+ if (newItem.locations && newItem.locations.length > 0) {
+ if (currentItem.locations) {
+ currentItem.locations.push(...newItem.locations);
+ } else {
+ currentItem.locations = [...newItem.locations];
+ }
}
}
@@ -134,6 +142,14 @@ function subscribeOnParserEvents(parser, options, version, resolve, reject) {
parser.on(eventName, (value) => {
const itemIndex = component[feature].findIndex(item => item.name === value.name);
+ if (value.localName) {
+ const localItem = component[feature].find(item => item.name === value.localName);
+
+ if (localItem) {
+ value = mergeItems(feature, value, localItem, true);
+ }
+ }
+
if (itemIndex < 0) {
component[feature].push(value);
} else {
diff --git a/lib/v3/parser.js b/lib/v3/parser.js
index 9cf1ae1..3b25d80 100644
--- a/lib/v3/parser.js
+++ b/lib/v3/parser.js
@@ -121,6 +121,7 @@ class Parser extends EventEmitter {
type: utils.inferTypeFromVariableDeclaration(variable),
importPath: variable.importPath,
originalName: variable.originalName,
+ localName: variable.localName
});
if (variable.declarator && variable.declarator.init) {
@@ -330,6 +331,7 @@ class Parser extends EventEmitter {
if (node.type === 'ExportNamedDeclaration' && level === 0 && parseContext.scopeType !== SCOPE_MARKUP) {
const declaration = node.declaration;
+ const specifiers = node.specifiers;
if (declaration) {
const exportNodeComment = utils.getCommentFromSourceCode(node, parseContext.sourceCode, { defaultVisibility: 'public', useLeading: true, useTrailing: false });
@@ -352,6 +354,27 @@ class Parser extends EventEmitter {
return;
}
}
+
+ if (specifiers) {
+ specifiers.forEach(specifier => {
+ if (specifier.type === 'ExportSpecifier') {
+ const exportedOrLocalName = specifier.exported
+ ? specifier.exported.name
+ : specifier.local.name;
+
+ this.emitDataItem({
+ node: specifier,
+ name: exportedOrLocalName,
+ localName: specifier.local.name,
+ kind: 'const',
+ location: {
+ start: specifier.exported ? specifier.exported.start : specifier.local.start,
+ end: specifier.exported ? specifier.exported.end : specifier.local.end
+ }
+ }, parseContext, 'public');
+ }
+ });
+ }
}
if (node.type === 'LabeledStatement' && level === 0 && parseContext.scopeType !== SCOPE_MARKUP) {
diff --git a/package.json b/package.json
index 8d22a7c..596d5f6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "sveltedoc-parser",
- "version": "3.0.0",
+ "version": "3.0.1",
"description": "Generate a JSON documentation for a Svelte file",
"main": "index.js",
"scripts": {
diff --git a/test/svelte3/integration/data/data.export.aliace.svelte b/test/svelte3/integration/data/data.export.aliace.svelte
new file mode 100644
index 0000000..0e3fc1f
--- /dev/null
+++ b/test/svelte3/integration/data/data.export.aliace.svelte
@@ -0,0 +1,11 @@
+
\ No newline at end of file
diff --git a/test/svelte3/integration/data/data.export.many.svelte b/test/svelte3/integration/data/data.export.many.svelte
new file mode 100644
index 0000000..9d21030
--- /dev/null
+++ b/test/svelte3/integration/data/data.export.many.svelte
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/test/svelte3/integration/data/data.spec.js b/test/svelte3/integration/data/data.spec.js
index bd0c5cc..54ea4c8 100644
--- a/test/svelte3/integration/data/data.spec.js
+++ b/test/svelte3/integration/data/data.spec.js
@@ -247,4 +247,78 @@ describe('SvelteDoc v3 - Props', () => {
done(e);
});
});
+
+ it('Export object statement with multiple variables should be parsed as public props', done => {
+ parser.parse({
+ version: 3,
+ filename: path.resolve(__dirname, 'data.export.many.svelte'),
+ features: ['data'],
+ includeSourceLocations: true,
+ ignoredVisibilities: []
+ }).then((doc) => {
+ expect(doc, 'Document should be provided').to.exist;
+ expect(doc.data, 'Document data should be parsed').to.exist;
+
+ expect(doc.data.length).to.equal(2);
+
+ const prop1 = doc.data.find(d => d.name === 'a');
+
+ expect(prop1.name).to.equal('a');
+ expect(prop1.visibility).to.equal('public');
+ expect(prop1.static).to.be.false;
+ expect(prop1.description).to.be.equal('The `a` variable description');
+ expect(prop1.type).to.eql({ kind: 'type', type: 'number', text: 'number' });
+
+ expect(prop1.locations, 'Code location should be parsed').to.be.exist;
+ expect(prop1.locations[0]).is.deep.equals({ start: 58, end: 59 });
+ expect(prop1.locations[1]).is.deep.equals({ start: 102, end: 103 });
+
+ const prop2 = doc.data.find(d => d.name === 'b');
+
+ expect(prop2.name).to.equal('b');
+ expect(prop2.visibility).to.equal('public');
+ expect(prop2.static).to.be.false;
+ expect(prop2.type).to.eql({ kind: 'type', type: 'string', text: 'string' });
+
+ done();
+ }).catch(e => {
+ done(e);
+ });
+ });
+
+ it('Export object statement with variable and aliace for that should be parsed as public prop', done => {
+ parser.parse({
+ version: 3,
+ filename: path.resolve(__dirname, 'data.export.aliace.svelte'),
+ features: ['data'],
+ includeSourceLocations: true,
+ ignoredVisibilities: []
+ }).then((doc) => {
+ expect(doc, 'Document should be provided').to.exist;
+ expect(doc.data, 'Document data should be parsed').to.exist;
+
+ expect(doc.data.length).to.equal(2);
+
+ const prop = doc.data.find(d => d.name === 'class');
+
+ expect(prop).to.exist;
+ expect(prop.name, 'Aliace name must be exposed instead of original name').to.equal('class');
+ expect(prop.localName, 'Local name must be stored').to.equal('classes');
+ expect(prop.visibility).to.equal('public');
+ expect(prop.static).to.be.false;
+ expect(prop.description).to.be.equal('Description for variable that must be exported later');
+ expect(prop.type).to.eql({ kind: 'type', type: 'Array', text: 'Array' });
+
+ expect(prop.locations, 'Code location should be parsed').to.be.exist;
+ expect(prop.locations[0]).is.deep.equals({ start: 189, end: 194 });
+
+ const localProp = doc.data.find(d => d.name === 'classes');
+
+ expect(localProp, 'Local prop definition also must be provided').to.exist;
+
+ done();
+ }).catch(e => {
+ done(e);
+ });
+ });
});
diff --git a/typings.d.ts b/typings.d.ts
index 65c1422..2486d71 100644
--- a/typings.d.ts
+++ b/typings.d.ts
@@ -137,6 +137,20 @@ export interface SvelteDataItem extends ISvelteItem {
* @since {2.2.0}
*/
originalName?: string;
+
+ /**
+ * The local name of the prop that was exported with aliace statement
+ * @example
+ * ```js
+ * const local = 1;
+ * export { local as public };
+ * // `name` of this item will be `'public'`
+ * // `localName` of this item will be `'local'`
+ * ```
+ * @since {3.0.1}
+ */
+ localName?: string;
+
/**
* The relative path of importing of this object.
* When not defined, so variable is not provided.