Socket
Socket
Sign inDemoInstall

sveltedoc-parser

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sveltedoc-parser - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0

8

CHANGELOG.md

@@ -6,2 +6,10 @@ # Change Log

## [2.1.0] 09.08.2019
- [Added] Svelte V3: Implement support for property binding parsing (`bind:proprty={...}`)
- [Added] Svelte V3: Implement support for event parsing which dispatched from code (`dispatch(...)`)
- [Added] Svelte V3: Implement support for event parsing which dispatched from markup expressions (`<button on:click="{() => dispatch(....)}">`)
- [Added] Svelte V3: Implement support for ref parsing (`bind:this={...}`)
- [Fixed] Spec: Property `SvelteDataItem.let` changed to `SvelteDateItem.kind`, that was named as `let` by mistake
## [2.0.0] 05.08.2019

@@ -8,0 +16,0 @@

41

index.js

@@ -64,2 +64,35 @@ const { loadFileStructureFromOptions } = require('./lib/helpers');

function convertVisibilityToLevel(visibility) {
switch (visibility) {
case 'public':
return 3;
case 'protected':
return 2;
case 'private':
return 1;
}
return 0;
}
function mergeItems(currentItem, newItem) {
if (convertVisibilityToLevel(currentItem.visibility) < convertVisibilityToLevel(newItem.visibility)) {
currentItem.visibility = newItem.visibility;
}
if (!currentItem.description && newItem.description) {
currentItem.description = newItem;
}
if (!currentItem.keywords && newItem.keywords) {
currentItem.keywords = newItem.keywords;
}
if (!currentItem.bind && newItem.bind) {
currentItem.bind = newItem.bind;
}
return currentItem;
}
function subscribeOnParserEvents(parser, options, version, resolve, reject) {

@@ -94,3 +127,9 @@ const component = {

} else {
component[feature][itemIndex] = value;
// Use merge logic of items information for specific features
if (['data'].includes(feature)) {
const currentItem = component[feature][itemIndex];
component[feature][itemIndex] = mergeItems(currentItem, value);
} else {
component[feature][itemIndex] = value;
}
}

@@ -97,0 +136,0 @@ });

16

lib/utils.js

@@ -70,13 +70,15 @@ const RE_VISIBILITY = /(public|protected|private)/;

const getComment = (property, defaultVisibility = DEFAULT_VISIBILITY, features) => {
const getComment = (property, defaultVisibility = DEFAULT_VISIBILITY, features, useLeading = true, useTrailing = true) => {
let lastComment = null;
if (property.leadingComments) {
lastComment = property.leadingComments.pop().value;
if (property) {
if (useLeading && property.leadingComments && property.leadingComments.length > 0) {
lastComment = property.leadingComments[property.leadingComments.length - 1].value;
}
if (useTrailing && property.trailingComments && property.trailingComments.length > 0) {
lastComment = property.trailingComments[property.trailingComments.length - 1].value;
}
}
if (property.trailingComments) {
lastComment = property.trailingComments.pop().value;
}
if (lastComment) {

@@ -83,0 +85,0 @@ return parseComment(lastComment, defaultVisibility, features);

@@ -17,12 +17,13 @@ const EventEmitter = require('events');

'methods',
// 'actions',
// 'helpers',
'components',
// 'description',
'description',
'events',
'slots',
// 'transitions',
// 'store'
'refs'
];
const SCOPE_DEFAULT = 'default';
const SCOPE_STATIC = 'static';
const SCOPE_MARKUP = 'markup';
class Parser extends EventEmitter {

@@ -44,2 +45,5 @@ constructor(structure, options) {

this.imports = {};
this.dispatcherConstructorNames = [];
this.dispatcherNames = [];
}

@@ -105,7 +109,9 @@

emitDataItem(variable, isStaticScope, defaultVisibility) {
const item = Object.assign({}, utils.getComment(variable.node, defaultVisibility), {
emitDataItem(variable, scopeType, defaultVisibility, parentComment) {
const comment = parentComment || utils.getComment(variable.node, defaultVisibility);
const item = Object.assign({}, comment, {
name: variable.name,
kind: variable.kind,
static: isStaticScope,
static: scopeType === SCOPE_STATIC,
readonly: variable.kind === 'const',

@@ -120,7 +126,9 @@ type: jsdoc.DEFAULT_TYPE

emitMethodItem(method, isStaticScope, defaultVisibility) {
const item = Object.assign({}, utils.getComment(method.node, defaultVisibility), {
emitMethodItem(method, scopeType, defaultVisibility, parentComment) {
const comment = parentComment || utils.getComment(method.node, defaultVisibility);
const item = Object.assign({}, comment, {
name: method.name,
args: method.args,
static: isStaticScope
static: scopeType === SCOPE_STATIC
});

@@ -131,6 +139,6 @@

emitComputedItem(computed, isStaticScope, defaultVisibility) {
emitComputedItem(computed, scopeType, defaultVisibility) {
const item = Object.assign({}, utils.getComment(computed.node, defaultVisibility), {
name: computed.name,
static: isStaticScope,
static: scopeType === SCOPE_STATIC,
type: jsdoc.DEFAULT_TYPE

@@ -144,2 +152,18 @@ });

emitEventItem(event) {
const item = Object.assign({}, utils.getComment(event.node, 'public'), {
name: event.name
});
this.emit('event', item);
}
emitRefItem(ref) {
const item = Object.assign({}, ref, {
visibility: 'private'
});
this.emit('ref', item);
}
emitImportedComponentItem(importNode, name, path) {

@@ -154,20 +178,58 @@ const item = Object.assign({}, utils.getComment(importNode, 'private'), {

parseScriptBlock(scriptBlock) {
const ast = espree.parse(scriptBlock.content, {
attachComment: true,
tokens: true,
ecmaVersion: 9,
sourceType: 'module',
ecmaFeatures: {
experimentalObjectRestSpread: true
parseBodyRecursively(rootNode, scopeType, level) {
const nodes = rootNode.body
? rootNode.body
: (rootNode.length > 0 ? rootNode : [rootNode]);
nodes.forEach(node => {
if (node.type === 'ExpressionStatement') {
const expressionNode = node.expression;
if (expressionNode.type === 'CallExpression') {
const callee = expressionNode.callee;
if (callee.type === 'Identifier' && this.dispatcherNames.indexOf(callee.name) >= 0) {
const eventItem = this.parseEvenDeclaration(expressionNode);
this.emitEventItem(eventItem);
return;
}
}
if (expressionNode.type === 'ArrowFunctionExpression') {
if (expressionNode.body) {
this.parseBodyRecursively(expressionNode.body, scopeType, level + 1);
return;
}
}
}
});
const isStaticScope = /\sscope=('module'|"module")/gi.test(scriptBlock.attributes)
if (node.type === 'CallExpression') {
const callee = node.callee;
if (callee.type === 'Identifier' && this.dispatcherNames.indexOf(callee.name) >= 0) {
const eventItem = this.parseEvenDeclaration(node);
this.emitEventItem(eventItem);
return;
}
}
ast.body.forEach(node => {
if (node.type === 'VariableDeclaration') {
if (node.type === 'VariableDeclaration' && scopeType !== SCOPE_MARKUP) {
const variables = this.parseVariableDeclaration(node);
variables.forEach(variable => {
this.emitDataItem(variable, isStaticScope, 'private');
if (level === 0) {
this.emitDataItem(variable, scopeType, 'private');
}
if (variable.declarator.init) {
const initNode = variable.declarator.init;
if (initNode.type === 'CallExpression') {
const callee = initNode.callee;
if (callee.type === 'Identifier' && this.dispatcherConstructorNames.indexOf(callee.name) >= 0) {
this.dispatcherNames.push(variable.name);
}
} else if (initNode.type === 'ArrowFunctionExpression') {
if (initNode.body) {
this.parseBodyRecursively(initNode.body, scopeType, level + 1);
}
}
}
});

@@ -179,14 +241,19 @@

if (node.type === 'FunctionDeclaration') {
this.emitMethodItem(this.parseFunctionDeclaration(node), isStaticScope, 'private');
this.emitMethodItem(this.parseFunctionDeclaration(node), scopeType, 'private');
if (node.body) {
this.parseBodyRecursively(node.body, scopeType, level + 1);
}
return;
}
if (node.type === 'ExportNamedDeclaration') {
if (node.type === 'ExportNamedDeclaration' && level === 0 && scopeType !== SCOPE_MARKUP) {
const declaration = node.declaration;
if (declaration) {
const exportNodeComment = utils.getComment(node, 'public', this.features, true, false);
if (declaration.type === 'VariableDeclaration') {
const variables = this.parseVariableDeclaration(declaration);
variables.forEach(variable => {
this.emitDataItem(variable, isStaticScope, 'public');
this.emitDataItem(variable, scopeType, 'public', exportNodeComment);
});

@@ -198,3 +265,5 @@

if (declaration.type === 'FunctionDeclaration') {
this.emitMethodItem(this.parseFunctionDeclaration(declaration), isStaticScope, 'public');
const func = this.parseFunctionDeclaration(declaration);
this.emitMethodItem(func, scopeType, 'public', exportNodeComment);
return;

@@ -205,3 +274,3 @@ }

if (node.type === 'LabeledStatement') {
if (node.type === 'LabeledStatement' && level === 0 && scopeType !== SCOPE_MARKUP) {
const idNode = node.label;

@@ -217,3 +286,3 @@ if (idNode && idNode.type === 'Identifier' && idNode.name === '$') {

node: node
}, isStaticScope, 'private');
}, scopeType, 'private');

@@ -227,3 +296,3 @@ return;

if (node.type === 'ImportDeclaration') {
if (node.type === 'ImportDeclaration' && level === 0 && scopeType !== SCOPE_MARKUP) {
const specifier = node.specifiers[0];

@@ -252,3 +321,3 @@

kind: 'const'
}, isStaticScope, 'private');
}, scopeType, 'private');
}

@@ -265,12 +334,84 @@ }

kind: 'const'
}, isStaticScope, 'private');
}, scopeType, 'private');
}
});
// Import svelte API functions
if (node.source.type === 'Literal' && node.source.value === 'svelte') {
// Dispatcher constructors
node.specifiers
.filter(specifier => specifier.imported.name === 'createEventDispatcher')
.forEach(specifier => {
this.dispatcherConstructorNames.push(specifier.local.name);
});
}
}
}
//console.log(util.inspect(node, false, null, true));
// console.log(util.inspect(node, false, null, true));
if (node.body) {
this.parseBodyRecursively(node.body, scopeType, level + 1);
}
});
}
getAstParsingOptions() {
return {
attachComment: true,
tokens: true,
ecmaVersion: 9,
sourceType: 'module',
ecmaFeatures: {
experimentalObjectRestSpread: true
}
};
}
parseScriptBlock(scriptBlock) {
const ast = espree.parse(
scriptBlock.content,
this.getAstParsingOptions()
);
const isStaticScope = /\sscope=('module'|"module")/gi.test(scriptBlock.attributes)
this.parseBodyRecursively(
ast,
isStaticScope
? SCOPE_STATIC
: SCOPE_DEFAULT,
0
);
}
parseMarkupExpressionBlock(expression) {
const ast = espree.parse(
expression,
this.getAstParsingOptions()
);
this.parseBodyRecursively(ast, SCOPE_MARKUP, 0);
}
parseEvenDeclaration(node) {
if (node.type !== 'CallExpression') {
throw new Error('Node should have a CallExpressionType, but is ' + node.type);
}
const args = node.arguments;
if (!args && args.length < 1) {
return null;
}
const nameNode = args[0];
return {
name: nameNode.type === 'Literal'
? nameNode.value
: undefined,
node: node
};
}
parseVariableDeclaration(node) {

@@ -289,3 +430,4 @@ if (node.type !== 'VariableDeclaration') {

kind: node.kind,
node: node
node: node,
declarator: declarator
});

@@ -299,3 +441,4 @@ } else if (idNode.type === 'ObjectPattern') {

kind: node.kind,
node: node
node: node,
declarator: declarator
});

@@ -444,2 +587,66 @@ }

}
if (this.features.includes('data')) {
const bindProperties = Object.keys(attrs)
.filter(name => name.length > 5 && name.indexOf('bind:') === 0)
.filter(name => name !== 'bind:this')
.map(name => {
const sourcePropertyName = name.substr(5);
let targetPropertyName = sourcePropertyName;
const attributeValue = attrs[name];
if (attributeValue && attributeValue.length > 2 && attributeValue.charAt(0) === '{' && attributeValue.charAt(attributeValue.length - 1) === '}') {
targetPropertyName = attributeValue.substr(1, attributeValue.length - 2);
}
return {
sourcePropertyName: sourcePropertyName,
targetPropertyName: targetPropertyName,
parent: tagName,
loc: this.includeSourceLocations && lastAttributeLocations.hasOwnProperty(name)
? lastAttributeLocations[name]
: null
};
});
bindProperties.forEach(bindProperty => {
const dataItem = {
name: bindProperty.targetPropertyName,
kind: 'let',
bind: {
source: bindProperty.parent,
property: bindProperty.sourcePropertyName
},
loc: bindProperty.loc,
visibility: 'private',
static: false,
readonly: false
};
this.emit('data', dataItem);
});
}
if (this.features.includes('refs')) {
if (attrs.hasOwnProperty('bind:this') && attrs['bind:this']) {
const value = 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,
loc: this.includeSourceLocations && lastAttributeLocations.hasOwnProperty('bind:this')
? lastAttributeLocations[name]
: null
});
}
}
}
// Parse event handlers
Object.keys(attrs)
.filter(name => name.length > 3 && name.indexOf('on:') === 0 && attrs[name])
.forEach(name => {
this.parseMarkupExpressionBlock(attrs[name]);
});
}

@@ -446,0 +653,0 @@ }

{
"name": "sveltedoc-parser",
"version": "2.0.0",
"version": "2.1.0",
"description": "Generate a JSON documentation for a Svelte file",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -27,6 +27,11 @@ # The sveltedoc parser

- Extract list of references that attached to components or HTML elements
- Extract all fired events
- Extract information about events
- Events that propogated from child component or HTML elements `<button on:click>...</button>`
- Parse event modificators `... on:click|once`
- Extract all fired events (_Svelte 2 only_)
- Events that fired by this component by `fire(...)` method
- Events that propogated from child component or HTML elements
- Custom event handlers with `private` visibility scope
- Extract all dispatched events (_Svelte 3_)
- Events that dispatched from script block by user-created dispatcher
- Events that dispatched from markup expressions by user-created dispatcher
- Extract list of used default and named `slots`

@@ -39,5 +44,5 @@ - Extract component methods

- Identify default values for optional parameters (`@param [parameter=Default value]`)
- Extract component helpers
- Extract component actions
- Extract component transitions
- Extract component helpers (_Svelte 2 only_)
- Extract component actions (_Svelte 2 only_)
- Extract component transitions (_Svelte 2 only_)
- Extract source locations for component symbols

@@ -60,3 +65,3 @@ - data

| **includeSourceLocations** | Flag, which indicates that source locations should be provided for component symbols. | `false` |
| **version** | Optional. Use 2 or 3 to specify which svelte syntax should be used. | `undefined` |
| **version** | Optional. Use `2` or `3` to specify which svelte syntax should be used. When that is not provided, parser try to detect version of the syntax. | `undefined` |
| **defaultVersion** | Optional. Specify default version of svelte syntax, if auto-detector can't indetify correct version. | `undefined` |

@@ -66,14 +71,14 @@

- `'name'` - Extract the component name.
- `'data'` - Extract and parse the list of component data properties.
- `'computed'` - Extract and parse the list of component computed properties.
- `'methods'` - Extract the list of component methods.
- `'actions'` - Extract the list of component actions.
- `'helpers'` - Extract the list of component helpers.
- `'components'` - Extract the list of imported components.
- `'description'` - Extract the component description.
- `'events'` - Extract the list of events that fired by this component.
- `'slots'` - Extract the list of slots provided by this component.
- `'transitions'` - Extract the list of transitions used by this component.
- `'refs'` - Extract the list of references used by this component.
- `'name'` - Extract the component name (_Supported by Svelte 2 and Svelte 3_).
- `'data'` - Extract and parse the list of component data properties (_Supported by Svelte 2 and Svelte 3_).
- `'computed'` - Extract and parse the list of component computed properties (_Supported by Svelte 2 and Svelte 3_).
- `'methods'` - Extract the list of component methods (_Supported by Svelte 2 and Svelte 3_).
- `'actions'` - Extract the list of component actions (_Supported by Svelte 2_).
- `'helpers'` - Extract the list of component helpers (_Supported by Svelte 2_).
- `'components'` - Extract the list of imported components (_Supported by Svelte 2 and Svelte 3_).
- `'description'` - Extract the component description (_Supported by Svelte 2 and Svelte 3_).
- `'events'` - Extract the list of events that fired by this component (_Supported by Svelte 2 and Svelte 3_).
- `'slots'` - Extract the list of slots provided by this component (_Supported by Svelte 2 and Svelte 3_).
- `'transitions'` - Extract the list of transitions used by this component (_Supported by Svelte 2_).
- `'refs'` - Extract the list of references used by this component (_Supported by Svelte 2 and Svelte 3_).

@@ -84,3 +89,3 @@ ## Output format

See example of output [here](/test/overall/overall.main.doc.json) presented in JSON format for [this component](/test/overall/main.svelte).
See example of output for Svelte 2 component [here](/test/svelte2/integration/overall/overall.main.doc.json) presented in JSON format for [this component](/test/svelte2/integration/overall/main.svelte).

@@ -87,0 +92,0 @@ ## Usage

@@ -79,2 +79,14 @@ /**

export interface SvelteDataBindMapping {
/**
* The parent component name or DOM element from which are was binded.
*/
source: string;
/**
* The name of the property which are was binded.
*/
property: string;
}
export interface SvelteDataItem extends ISvelteItem {

@@ -90,4 +102,10 @@ /**

*/
let?: 'var'|'let'|'const';
kind?: 'var'|'let'|'const';
/**
* Provides information about property binding.
* @since Svelte V3
* @since {2.1.0}
*/
bind?: SvelteDataBindMapping;
/**
* Indicates that this data item of component located in static context.

@@ -271,2 +289,9 @@ * Variable should be declared in `<script scope="module" />` block.

transitions?: SvelteMethodItem[];
/**
* The list of event dispatchers that was created in this component.
* @since Svelte V3
* @since {2.1.0}
*/
dispatchers?: SvelteMethodItem[];
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc