Socket
Socket
Sign inDemoInstall

vue-component-analyzer

Package Overview
Dependencies
50
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.0 to 0.1.1

src/VueComponentAnalyzerPlugin.js

2

package.json
{
"name": "vue-component-analyzer",
"description": "Analyze dependencies, inheritance and some other useful info of Vue components in static code.",
"version": "0.1.0",
"version": "0.1.1",
"author": "Rainfore <rainforest92@126.com>",

@@ -6,0 +6,0 @@ "scripts": {

@@ -0,1 +1,2 @@

const fs = require('fs-extra');
const path = require('path');

@@ -18,2 +19,9 @@ const babel = require('babel-core');

purge(files) {
files.forEach((file) => Object.keys(this.caches).forEach((key) => {
if (key.startsWith(file))
delete this.caches[key];
}));
}
build() {

@@ -29,24 +37,19 @@ // @TODO

else {
return new Promise((resolve, reject) => {
this.loader.fs.readFile(fullPath, (err, content) => {
if (err)
return reject(err);
return fs.readFile(fullPath).then((content) => {
content = content.toString();
const isVue = fullPath.endsWith('.vue');
if (isVue) {
const found = content.match(/<script>([\s\S]+)<\/script>/);
content = found ? found[1] : '';
}
content = content.toString();
const isVue = fullPath.endsWith('.vue');
if (isVue) {
const found = content.match(/<script>([\s\S]+)<\/script>/);
content = found ? found[1] : '';
}
const jsFile = new JSFile({
fullPath,
content,
babelResult: babel.transform(content),
isVue,
});
const jsFile = new JSFile({
fullPath,
content,
babelResult: babel.transform(content),
isVue,
});
this.caches[fullPath] = jsFile;
return resolve(jsFile);
});
this.caches[fullPath] = jsFile;
return jsFile;
});

@@ -65,11 +68,7 @@ }

return new Promise((resolve, reject) => {
this.loader.resolve(path.dirname(fullPath), sourcePath, (err, importPath) => {
if (err)
return reject(err);
if (importPath.endsWith('.vue') && this.loader.fs.statSync(importPath).isDirectory())
importPath += '/index.js';
return resolve(this.loadJSFile(importPath)
.then((jsFile) => this.findVueObject(jsFile, identifier, true, true)));
});
let importPath = this.resolve(sourcePath, path.dirname(fullPath));
if (importPath.endsWith('.vue') && fs.statSync(importPath).isDirectory())
importPath += '/index.js';
return resolve(this.loadJSFile(importPath)
.then((jsFile) => this.findVueObject(jsFile, 'export', identifier, true)));
});

@@ -82,11 +81,34 @@ }

* @param {*} identifier
* @param {*} exported - find from exports
* @param {FromType} from - 'local' or 'export' - find from local or exports;
* @param {*} recursive
* @return { objectExpression, jsFile, identifier }
*
* @examples
* e-1. export default {}
* e-2. export default ID [local]-> e-5, e-6, i-7, i-8, i-9, v-10, v-11
* e-3. export { A as ID } [local]-> e-5, e-6, i-7, i-8, i-9, v-10, v-11
* e-4. export * from
* e-5. export const ID = {}
* e-6. export const A = ID [local]->
* i-7. import ID from [export]-> e-1, e-2
* i-8. import { A as ID } from [export]-> e-3, e-4, e-5, e-6
* i-9. import * from from [export]-> e-3, e-4, e-5, e-6
* v-10. const ID
* v-11. const A = ID [local]->
*
* 3 types:
* from export default
* from export
* from local
*/
findVueObject(jsFile, identifier = 'default', exported = false, recursive = false) {
findVueObject(jsFile, from = 'export', identifier = 'default', recursive = false, beforeNode) {
if (!identifier)
throw new Error('Argument identifier is required!');
return Promise.resolve(jsFile).then((jsFile) => {
const babelResult = jsFile.babelResult;
if (identifier === 'default') {
if (from !== 'export' && identifier === 'default')
throw new Error('Identifier `default` is reserved word! Please set `from` as `export`');
else if (from === 'export' && identifier === 'default') { // Find from export default, ignore 'from' param for easy way
const exportDefault = babelResult.ast.program.body.find((node) => node.type === 'ExportDefaultDeclaration');

@@ -99,2 +121,3 @@ if (!exportDefault)

objectExpression: exportDefault.declaration,
objectDeclaration: exportDefault,
jsFile,

@@ -105,6 +128,8 @@ identifier,

const exportDefaultName = exportDefault.declaration.name;
return this.findVueObject(jsFile, exportDefaultName);
}
return this.findVueObject(jsFile, 'local', exportDefaultName, recursive);
} else
return null;
} else {
if (exported) {
// Find from exports
if (from === 'export') {
const exportsNode = babelResult.metadata.modules.exports;

@@ -120,6 +145,6 @@ const externalAllSpecifiers = [];

if (exportSpecifier)
identifier = exportSpecifier.local;
identifier = exportSpecifier.local; // Change identifier to local
else if (recursive)
return Promise.all(externalAllSpecifiers.map((specifier) => this.importVueObject(jsFile.fullPath, specifier.source, identifier)))
.then((results) => results.find((result) => !!result.objectExpression));
.then((results) => results.find((result) => !!result));
else

@@ -130,3 +155,3 @@ throw new Error('Cannot find identifier in exports: ' + identifier);

if (recursive) {
// find in imports
// Find from imports
let importSpecifier;

@@ -144,21 +169,31 @@ const importsNode = babelResult.metadata.modules.imports.find((impt) => impt.specifiers.some((specifier) => {

// find in body
let objectExpression;
babelResult.ast.program.body.some((node) => {
if (node.type !== 'VariableDeclaration')
return false;
return node.declarations.some((declaration) => {
if (declaration.id.name === identifier && declaration.init.type === 'ObjectExpression') {
objectExpression = declaration.init;
return true;
} else
return false;
});
});
// Find from local
for (const node of babelResult.ast.program.body) {
if (node === beforeNode) // 必须在 beforeNode 声明之前
return null;
return {
objectExpression,
jsFile,
identifier,
};
let declarations;
if (node.type === 'VariableDeclaration')
declarations = node.declarations;
else if (node.type === 'ExportNamedDeclaration')
declarations = node.declaration.declarations;
else
continue;
for (const declarator of declarations) {
if (declarator.type !== 'VariableDeclarator' || declarator.id.name !== identifier)
continue;
if (declarator.init.type === 'ObjectExpression') {
return {
objectExpression: declarator.init,
objectDeclaration: node,
jsFile,
identifier,
};
} else if (declarator.init.type === 'Identifier')
return this.findVueObject(jsFile, 'local', declarator.init.name, recursive, node);
}
}
return null;
}

@@ -169,16 +204,23 @@ });

findSuper(jsFile) {
return this.findVueObject(jsFile, 'default').then(({ objectExpression, jsFile, identifier }) => {
if (jsFile.extends) // Cached
return jsFile.extends;
return this.findVueObject(jsFile).then((vueResult) => {
// this.loader.addDependency(jsFile.fullPath);
const extendsName = objectExpression ? this.findExtendsName(objectExpression) : identifier;
if (!vueResult)
throw new Error('Cannot find vue object!');
if (vueResult.jsFile.extends) // Cached
return vueResult.jsFile.extends;
const extendsName = vueResult.objectExpression ? this.findExtendsName(vueResult.objectExpression) : vueResult.identifier;
if (!extendsName)
throw new Error('Cannot find extends name');
throw new Error('Cannot find extends name!');
return this.findVueObject(jsFile, extendsName, false, true).then((result) => {
if (!result.objectExpression)
throw new Error('Cannot find vue object');
return this.findVueObject(vueResult.jsFile, 'local', extendsName, true, vueResult.objectDeclaration).then((extendsResult) => {
// this.loader.addDependency(vueResult.jsFile.fullPath);
jsFile.extends = result.jsFile;
return result.jsFile;
if (!extendsResult.objectExpression)
throw new Error('Cannot find vue object!');
vueResult.jsFile.extends = extendsResult.jsFile;
return extendsResult.jsFile;
});

@@ -185,0 +227,0 @@ });

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc