UNPKG

sucrase

Version:

Super-fast alternative to Babel for when you can target modern JS runtimes

107 lines (106 loc) 4.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const sucrase_babylon_1 = require("../sucrase-babylon"); const JSXTransformer_1 = require("./transformers/JSXTransformer"); const TokenProcessor_1 = require("./TokenProcessor"); const ImportTransformer_1 = require("./transformers/ImportTransformer"); const augmentTokenContext_1 = require("./augmentTokenContext"); const ImportProcessor_1 = require("./ImportProcessor"); const NameManager_1 = require("./NameManager"); const ReactDisplayNameTransformer_1 = require("./transformers/ReactDisplayNameTransformer"); const DEFAULT_BABYLON_PLUGINS = ['jsx', 'objectRestSpread']; function transform(code, options = {}) { const babylonPlugins = options.babylonPlugins || DEFAULT_BABYLON_PLUGINS; const transforms = options.transforms || ['jsx']; let tokens = sucrase_babylon_1.getTokens(code, { tokens: true, sourceType: 'module', plugins: babylonPlugins }); tokens = tokens.filter((token) => token.type !== 'CommentLine' && token.type !== 'CommentBlock'); augmentTokenContext_1.default(tokens); const tokenProcessor = new TokenProcessor_1.default(code, tokens); return new RootTransformer(tokenProcessor, transforms).transform(); } exports.transform = transform; class RootTransformer { constructor(tokens, transforms) { this.tokens = tokens; this.transformers = []; const nameManager = new NameManager_1.NameManager(tokens); const importProcessor = transforms.includes('imports') ? new ImportProcessor_1.ImportProcessor(nameManager, tokens) : null; const identifierReplacer = importProcessor ? importProcessor : { getIdentifierReplacement: () => null }; if (transforms.includes('jsx')) { this.transformers.push(new JSXTransformer_1.default(this, tokens, identifierReplacer)); } // react-display-name must come before imports since otherwise imports will // claim a normal `React` name token. if (transforms.includes('react-display-name')) { this.transformers.push(new ReactDisplayNameTransformer_1.default(this, tokens, identifierReplacer)); } if (transforms.includes('imports')) { const shouldAddModuleExports = transforms.includes('add-module-exports'); this.transformers.push(new ImportTransformer_1.default(this, tokens, nameManager, importProcessor, shouldAddModuleExports)); } } transform() { this.tokens.reset(); for (const transformer of this.transformers) { transformer.preprocess(); } this.processBalancedCode(); let prefix = ''; for (const transformer of this.transformers) { prefix += transformer.getPrefixCode(); } let suffix = ''; for (const transformer of this.transformers) { suffix += transformer.getSuffixCode(); } return prefix + this.tokens.finish() + suffix; } processBalancedCode() { let braceDepth = 0; let parenDepth = 0; while (!this.tokens.isAtEnd()) { let wasProcessed = false; for (const transformer of this.transformers) { wasProcessed = transformer.process(); if (wasProcessed) { break; } } if (!wasProcessed) { if (this.tokens.matches(['{']) || this.tokens.matches(['${'])) { braceDepth++; } else if (this.tokens.matches(['}'])) { if (braceDepth === 0) { return; } braceDepth--; } if (this.tokens.matches(['('])) { parenDepth++; } else if (this.tokens.matches([')'])) { if (parenDepth === 0) { return; } parenDepth--; } this.tokens.copyToken(); } } } processToken() { for (const transformer of this.transformers) { const wasProcessed = transformer.process(); if (wasProcessed) { return; } } this.tokens.copyToken(); } } exports.RootTransformer = RootTransformer;