UNPKG

cst

Version:

JavaScript CST Implementation

296 lines (253 loc) 10.9 kB
/** * @typedef {Object} CSTParserOptions * @property {String} sourceType Type of parsed code: "module" or "script". * @property {Boolean} strictMode * @property {Boolean} allowHashBang * @property {Number} ecmaVersion * @property {CSTParserExperimentalFeatureOptions} experimentalFeatures * @property {CSTParserLanguageExtensionsOptions} languageExtensions */ /** * @typedef {Object} CSTParserLanguageExtensionsOptions * @property {Boolean} jsx * @property {Boolean} flow */ /** * @typedef {Object} CSTParserExperimentalFeatureOptions * @property {Boolean} 'es7.asyncFunctions' * @property {Boolean} 'es7.classProperties' * @property {Boolean} 'es7.comprehensions' * @property {Boolean} 'es7.decorators' * @property {Boolean} 'es7.doExpressions' * @property {Boolean} 'es7.exponentiationOperator' * @property {Boolean} 'es7.exportExtensions' * @property {Boolean} 'es7.functionBind' * @property {Boolean} 'es7.objectRestSpread' * @property {Boolean} 'es7.trailingFunctionCommas' */ // https://developer.apple.com/library/watchos/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/UIAutomation.html 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _babylon = require('babylon'); var _elementTree = require('./elementTree'); var DIRECTIVE_APPLE_INSTRUMENTATION = { type: 'AppleInstrumentationDirective', regexp: /^#([^\n]+)/gm }; // https://www.chromium.org/developers/web-development-style-guide var DIRECTIVE_GRIT = { type: 'GritDirective', regexp: /^\s*<(\/?\s*(?:if|include)(?!\w)[^]*?)>/gim }; // checking for the options passed to the babel parse method /** * CST Parser. */ var Parser = (function () { /** * @param {CSTParserOptions} options */ function Parser(options) { _classCallCheck(this, Parser); this._options = { sourceType: 'module', strictMode: true, allowHashBang: true, ecmaVersion: Infinity, experimentalFeatures: { 'es7.asyncFunctions': true, 'es7.classProperties': true, 'es7.comprehensions': true, 'es7.decorators': true, 'es7.doExpressions': true, 'es7.exponentiationOperator': true, 'es7.exportExtensions': true, 'es7.functionBind': true, 'es7.objectRestSpread': true, 'es7.trailingFunctionCommas': true }, languageExtensions: { jsx: true, flow: true }, plugins: [] }; if (options) { this.setOptions(options); } } _createClass(Parser, [{ key: 'getOptions', /** * @returns {CSTParserOptions} */ value: function getOptions() { return this._options; } /** * @param {CSTParserOptions} newOptions */ }, { key: 'setOptions', value: function setOptions(newOptions) { var currentOptions = this._options; var currentExperimentalFeatures = currentOptions.experimentalFeatures; var currentLanguageExtensions = currentOptions.languageExtensions; var newExperimentalFeatures = newOptions.experimentalFeatures; var newLanguageExtensions = newOptions.languageExtensions; this._options = _extends({}, currentOptions, newOptions, { experimentalFeatures: _extends({}, currentExperimentalFeatures, newExperimentalFeatures), languageExtensions: _extends({}, currentLanguageExtensions, newLanguageExtensions) }); } }, { key: 'parse', value: function parse(code) { var ast = this._parseAst(code); var tokens = this._processTokens(ast, code); var program = (0, _elementTree.buildElementTree)(ast, tokens); var programPlugins = {}; var plugins = this._options.plugins; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = plugins[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var plugin = _step.value; var api = plugin.createApiForProgram(program); if (api) { if (plugin.pluginName in programPlugins) { throw new Error('Plugin "' + plugin.pluginName + '" was already registered.'); } else { programPlugins[plugin.pluginName] = api; } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } program._acceptPlugins(programPlugins); return program; } }, { key: '_parseAst', value: function _parseAst(code) { var options = this._options; var languageExtensions = options.languageExtensions; var directiveInstances = {}; var hasDirectives = false; var directiveTypes = []; if (languageExtensions.appleInstrumentationDirectives) { directiveTypes.push(DIRECTIVE_APPLE_INSTRUMENTATION); } if (languageExtensions.gritDirectives) { directiveTypes.push(DIRECTIVE_GRIT); } var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { var _loop = function () { var directive = _step2.value; code = code.replace(directive.regexp, function (str, value, pos) { hasDirectives = true; directiveInstances[pos] = { type: directive.type, value: value }; // Cut 4 characters to save correct line/column info for surrounding code return '/*' + str.slice(4) + '*/'; }); }; for (var _iterator2 = directiveTypes[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { _loop(); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2['return']) { _iterator2['return'](); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } var ast = (0, _babylon.parse)(code, { sourceType: options.sourceType, strictMode: options.strictMode, ecmaVersion: options.ecmaVersion, allowHashBang: options.allowHashBang, features: options.experimentalFeatures, plugins: { jsx: languageExtensions.jsx, flow: languageExtensions.flow } }); var program = ast.program; program.tokens = ast.tokens; if (hasDirectives) { var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = program.tokens[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var token = _step3.value; var directiveInstance = directiveInstances[token.start]; if (directiveInstances[token.start]) { token.type = directiveInstance.type; token.value = directiveInstance.value; } } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3['return']) { _iterator3['return'](); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } } if (options.allowHashBang) { if (code.substr(0, 2) === '#!') { program.tokens[0].type = 'Hashbang'; } } return program; } }, { key: '_processTokens', value: function _processTokens(ast, code) { return (0, _elementTree.buildTokenList)(ast.tokens, code); } }]); return Parser; })(); exports['default'] = Parser; module.exports = exports['default']; // allowReturnOutsideFunction: boolean, // allowImportExportEverywhere: boolean,