webpack-extjs-loader
Version:
A ExtJs project module loader for webpack
301 lines (296 loc) • 10.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _bluebird = _interopRequireDefault(require("bluebird"));
var _esprima = require("esprima");
var _commentParser = require("comment-parser");
var _colors = _interopRequireDefault(require("colors"));
var _parseTag = _interopRequireDefault(require("./parseTag"));
var _esquery = _interopRequireDefault(require("esquery"));
var _util = _interopRequireDefault(require("util"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// let Promise = require('bluebird');
const readFile = _bluebird.default.promisify(_fs.default.readFile);
const nameTags = ['define'];
const requireTags = ['require', 'mixins'];
const overrideTags = ['override'];
/**
*
* @property Array names
* @property Array requires
* @property Array override
*/
class FileParser {
constructor(options = {}) {
this.names = [];
this.requires = [];
this.override = "";
this.filesRequires = {};
this.files = [];
this.aliases = {};
this.ignoreOverrides = options.ignoreOverrides || false;
}
async parse(src) {
const content = await this.loadFile(src);
const AST = this.generateAST(content);
// console.dir(JSON.stringify(AST, null, 2))
// const comments = await this.extractComments(AST);
// const groupedTags = await this.groupComments(comments);
// const parsedTags = await this.parseTags(groupedTags);
// console.dir(parsedTags)
this.extractCode(AST);
}
async parseContent(content) {
// console.log(content)
const AST = this.generateAST(content);
// console.dir(JSON.stringify(AST, null, 2))
// const comments = await this.extractComments(AST);
// const groupedTags = await this.groupComments(comments);
// const parsedTags = await this.parseTags(groupedTags);
// console.dir(parsedTags)
this.extractCode(AST);
}
generateAST(content) {
// console.dir(Esprima)
// return Esprima.parse(content.toString(), {
return (0, _esprima.parseScript)(content.toString(), {
tolerant: true,
comment: false,
tokens: false,
range: false,
loc: true,
jsx: false
});
}
/**
* Loads a file and returns with the jsDoc comments
*
* @param src String
*/
async loadFile(src) {
this.src = src;
const content = await readFile(_path.default.resolve(src));
return content.toString();
}
addAlternateClassName() {}
extractCode(AST) {
let me = this;
// let esquery = require('esquery');
const validDefines = `[expression.callee.object.name = 'Ext'][expression.callee.property.name = define][expression.arguments.0.value!='null']`;
let requires = {};
let matches = _esquery.default.match(AST, _esquery.default.parse(validDefines));
if (matches && matches[0] && matches[0].expression.arguments) {
me.addName(matches[0].expression.arguments[0].value);
}
matches = _esquery.default.match(AST, _esquery.default.parse(`${validDefines} ObjectExpression > Property[key.name=alternateClassName]`));
if (matches && matches[0] && matches[0].value) {
let node = matches[0].value;
if (node.type === "Literal") {
// me.addName(node.value);
requires.alternateClassName = [node.value];
} else if (node.type === "ArrayExpression") {
requires.alternateClassName = [];
node.elements.forEach(element => {
// me.addName(element.value);
requires.alternateClassName.push(element.value);
});
}
}
matches = _esquery.default.match(AST, _esquery.default.parse('ObjectExpression > Property[key.name=model]'));
if (matches && matches[0] && matches[0].value) {
let node = matches[0].value;
if (node.type === 'Literal') {
requires.model = node.value;
}
}
matches = _esquery.default.match(AST, _esquery.default.parse(`ObjectExpression > Property[key.name=controllers]`));
if (matches && matches[0] && matches[0].value) {
let node = matches[0].value;
if (node.type === "Literal") {
// console.log('controllers', node.value)
// me.addRequire(node.value);
requires.controllers = [node.value];
} else {
if (node.type === "ArrayExpression") {
// console.dir('controllers' + node.elements.toString())
requires.controllers = [];
node.elements.forEach(element => {
// me.addRequire(element.value);
requires.controllers.push(element.value);
});
}
}
}
matches = _esquery.default.match(AST, _esquery.default.parse(`ObjectExpression > Property[key.name=controller]`));
if (matches && matches[0] && matches[0].value) {
let node = matches[0].value;
if (node.type === "Literal") {
// console.log('controller', node.value)
// me.addRequire(node.value);
requires.controller = node.value;
} else {
// if (node.type === "ArrayExpression") {
// node.elements.forEach((element) => {
// me.addRequire(element.value);
// });
// }
}
}
matches = _esquery.default.match(AST, _esquery.default.parse(`ObjectExpression > Property[key.name=requires]`));
if (matches && matches[0] && matches[0].value) {
let node = matches[0].value;
if (node.type === "Literal") {
// me.addRequire(node.value);
requires.requires = [node.value];
} else if (node.type === "ArrayExpression") {
requires.requires = [];
node.elements.forEach(element => {
// me.addRequire(element.value);
requires.requires.push(element.value);
});
}
}
matches = _esquery.default.match(AST, _esquery.default.parse(`ObjectExpression > Property[key.name=mixins]`));
if (matches && matches[0] && matches[0].value) {
let node = matches[0].value;
if (node.type === "Literal") {
// me.addRequire(node.value);
requires.mixins = [node.value];
} else if (node.type === "ArrayExpression") {
requires.mixins = [];
node.elements.forEach(element => {
// me.addRequire(element.value);
requires.mixins.push(element.value);
});
}
}
if (!this.ignoreOverrides) {
matches = _esquery.default.match(AST, _esquery.default.parse(`${validDefines} ObjectExpression > Property[key.name=override]`));
if (matches && matches[0] && matches[0].value) {
let node = matches[0].value;
if (node.type === "Literal") {
// me.addOverride(node.value);
me.override = node.value;
} else {
//console.log('found alternateClassName but not literal',matches);
}
}
}
matches = _esquery.default.match(AST, _esquery.default.parse(`ObjectExpression > Property[key.name=extend]`));
if (matches && matches[0] && matches[0].value) {
let node = matches[0].value;
if (node.type === "Literal") {
// me.addRequire(node.value);
requires.extend = node.value;
} else {
//console.log('found alternateClassName but not literal',matches);
}
}
// console.dir(JSON.stringify(esquery.parse(`MemberExpression > Property[key.name=require]`)))
// matches = esquery.match(AST, esquery.parse(`CallExpression > MemberExpression > .property[name='require']`));//> Property[key.name=Ext] CallExpression > .arguments
// matches = esquery.match(AST, esquery.parse(`CallExpression[callee.name='require']`))// > Property[key.name=require]
matches = (0, _esquery.default)(AST, 'CallExpression[callee.property.name=\'require\']');
// console.dir(JSON.stringify(matches))
// if(this.src === 'app/Application.js') console.dir(JSON.stringify(matches))
if (matches) {
matches.forEach(node => {
node.arguments.forEach(arg => {
// console.dir(arg)
if (arg.type === 'Literal') {
// me.addRequire(arg.value)
if (!requires.require) requires.require = [];
requires.require.push(arg.value);
}
if (arg.type === 'Identifier') {
// console.log(colors.red(arg.name))
// console.log(JSON.stringify(AST))
}
});
});
}
if (this.src) {
requires.file = this.src;
this.filesRequires[this.src] = requires;
this.files.push(this.src);
} else {
this.filesRequires['content'] = requires;
}
// if(this.src === 'app/Application.js')
// console.dir(requires)
}
/**
* Return an
*
* @param AST
* @returns {Array} Array of comment blocks
*/
extractComments(AST) {
if (!AST.comments) console.warn('no comments...');
return AST.comments.map(comment => {
let value = comment.value;
if (comment.type === 'Line') {
value = `*${comment.value}`;
}
return (0, _commentParser.parse)(`/*${value}*/`)[0];
}).filter(Boolean);
}
/**
* Gathers the tags from comment block and returns with the combined array of tags
*
* @param {Object[]} comments Array which contains the extracted comments
* @param {String} comments[].tags Array of tags
* @return Promise
*/
groupComments(comments) {
return comments.reduce((ret, comment) => [...ret, ...comment.tags], []);
}
parseTags(tags) {
// let tagParser = require('./parseTag');
tags.forEach(tag => {
this.parseTag(new _parseTag.default(tag));
});
}
parseTag(tag) {
if (tag.tag === "class" && (tag.name === "Ext" || tag.name === "Ext.Widget")) {
if (this.src.indexOf('Ext.js') == -1) {
return _bluebird.default.resolve();
}
}
if (nameTags.includes(tag.tag)) {
this.addName(tag.name);
}
if (requireTags.includes(tag.tag)) {
this.addRequire(tag.name);
}
if (overrideTags.includes(tag.tag)) {
this.addOverride(tag.name);
}
/* if (tag.tag.indexOf('cmd-auto-dependency') > -1) {
if (tag.type.defaultType && tag.type.defaultType.indexOf('Ext.') > -1) {
console.log('Adding defaultType',tag.type.defaultType);
this.addRequire(tag.type.defaultType);
}
}*/
return _bluebird.default.resolve();
}
addName(name) {
if (name && name != "" && !this.names.includes(name)) {
this.names.push(name);
}
}
addRequire(require) {
if (require) {
this.requires.push(require);
}
}
addOverride(override) {
if (override) {
this.override = override;
}
}
}
exports.default = FileParser;