Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
'use strict';
/** Imports */
import Parser, { plugins } from 'babylon/lib/parser';
import { TokenType, types as tt } from 'babylon/lib/tokenizer/types';
/** Constants */
const CHAR_CODES = '|>'.split('').map((c) => c.charCodeAt(0));
const PLUGIN_NAME = 'pipeline';
const beforeExpr = true;
/** Types */
tt.pipeline = new TokenType('|>', { beforeExpr, binop: 12 });
/** Parser */
const pp = Parser.prototype;
pp.readToken_pipeline = function readToken_pipeline(code) { // eslint-disable-line camelcase
return this.finishOp(tt.pipeline, 2);
};
/** Plugin */
function plugin(instance) {
instance.extend('readToken', (inner) => function readToken(code) {
const next = this.input.charCodeAt(this.state.pos + 1);
if (!(code === CHAR_CODES[0] && next === CHAR_CODES[1])) {
export default function patch() {
let Parser;
let tt;
try {
Parser = require('babylon/lib/parser').default;
tt = require('babylon/lib/tokenizer/types').types;
} catch(e) {
console.error('Install `babylon` as a top-level package.');
throw e;
}
// HACK: Monkey patching to parse parameter decorators.
// Based on the compiled output of babel-core 6.0.14.
Parser.prototype.parseBindingList = function (close, allowEmpty, allowTrailingComma) {
let elts = [];
let first = true;
while (!this.eat(close)) {
if (first) {
first = false;
} else {
this.expect(tt.comma);
}
export default function patch() {
let Parser;
let tt;
try {
Parser = require('babylon/lib/parser').default;
tt = require('babylon/lib/tokenizer/types').types;
} catch(e) {
console.error('Install `babylon` as a top-level package.');
throw e;
}
// HACK: Monkey patching to parse parameter decorators.
// Based on the compiled output of babel-core 6.0.14.
Parser.prototype.parseBindingList = function (close, allowEmpty, allowTrailingComma) {
let elts = [];
let first = true;
while (!this.eat(close)) {
if (first) {
first = false;
} else {
this.expect(tt.comma);
import Parser, { plugins } from 'babylon/lib/parser';
import { TokenType, types as tt } from 'babylon/lib/tokenizer/types';
/** Constants */
const CHAR_CODES = '|>'.split('').map((c) => c.charCodeAt(0));
const PLUGIN_NAME = 'pipeline';
const beforeExpr = true;
/** Types */
tt.pipeline = new TokenType('|>', { beforeExpr, binop: 12 });
/** Parser */
const pp = Parser.prototype;
pp.readToken_pipeline = function readToken_pipeline(code) { // eslint-disable-line camelcase
return this.finishOp(tt.pipeline, 2);
};
/** Plugin */
function plugin(instance) {
instance.extend('readToken', (inner) => function readToken(code) {
const next = this.input.charCodeAt(this.state.pos + 1);
if (!(code === CHAR_CODES[0] && next === CHAR_CODES[1])) {
return inner.call(this, code);
}
return this.readToken_pipeline(code);
export default function(instance, pluginOptions) {
instance.whitespaceState = new TokenizerState();
instance.whitespaceState.init({}, instance.state.input);
instance.whitespaceState.type = tokenTypes.whitespace;
instance.cstState = {
format: pluginOptions.format || {}
};
instance.extend("skipSpace", function(/*inner*/ /*complete override*/) {
return function skipSpace() {
this.startWhitespace();
loop: while (this.state.pos < this.input.length) {
let ch = this.input.charCodeAt(this.state.pos);
switch (ch) {
case 32: case 160: // ' '
this.whitespaceState.value += String.fromCharCode(ch);
++this.state.pos;
// Babylon currently has...abysmal support for typescript. We need to transpile
// it with the standard typescript library first.
// TODO: When Typescript support lands in Babylon, remove this: https://github.com/babel/babylon/issues/320
if (path.parse(template.identifier).ext === ".tsx") {
let wat = typescript.transpileModule(template.data, {
compilerOptions: {
module: typescript.ModuleKind.ES2015,
jsx: typescript.JsxEmit.Preserve,
target: typescript.ScriptTarget.Latest,
},
});
template.data = wat.outputText;
}
analysis.template.ast = some(babylon.parse(template.data, this.options.parserOptions));
} catch (e) {
process.chdir(oldDir);
throw new JSXParseError(`Error parsing '${template.identifier}'\n${e.message}\n\n${template.data}: ${e.message}`, { filename: template.identifier });
}
// The blocks importer will insert a promise that resolves to a `ResolvedBlock`
// for each CSS Blocks import it encounters. Every new `tsx` or `jsx` file discovered
// will kick of another `Analyzer.parse()` for that file.
let blockPromises: Promise[] = [];
let childTemplatePromises: Promise[] = [];
traverse(unwrap(analysis.template.ast), importVisitor(template, this, analysis, blockPromises, childTemplatePromises, this.options));
// Once all blocks this file is waiting for resolve, resolve with the File object.
// After import traversal, it is safe to move back to our old working directory.
process.chdir(oldDir);
// Read the content of the file as a string.
const content = fs.readFileSync(filename, 'utf-8');
// Now we try to figure out which files this file depends on. We can do that
// by looking at its content for import strings. However, this is a pretty
// clunky approach, so instead, we will use a JavaScript parser.
//
// JavaScript parsers are tools that can read and understand JavaScript code.
// They generate a more abstract model called an AST (abstract syntax tree).
// I strongly suggest that you look at AST Explorer (https://astexplorer.net)
// to see how an AST looks like.
//
// The AST contains a lot of information about our code. We can query it to
// understand what our code is trying to do.
const ast = babylon.parse(content, {
sourceType: 'module',
});
// This array will hold the relative paths of modules this module depends on.
const dependencies = [];
// We traverse the AST to try and understand which modules this module depends
// on. To do that, we check every import declaration in the AST.
traverse(ast, {
// EcmaScript modules are fairly easy because they are static. This means
// that you can't import a variable, or conditionally import another module.
// Every time we see an import statement we can just count its value as a
// dependency.
ImportDeclaration: ({node}) => {
// We push the value that we import into the dependencies array.
dependencies.push(node.source.value);
}
switch (ext) {
case '.mjs':
try {
return babylon.parse(code, { sourceType: 'module' });
} catch (e) { /* ignore */ }
try {
return babylon.parse(code);
} catch (e) { /* ignore */ }
break;
case '.js':
try {
return babylon.parse(code);
} catch (e) { /* ignore */ }
try {
return babylon.parse(code, { sourceType: 'module' });
} catch (e) { /* ignore */ }
break;
}
return 'unparsed';
}
"classConstructorCall",
"classProperties",
"decorators",
"doExpressions",
"exponentiationOperator",
"exportExtensions",
"functionBind",
"functionSent",
"objectRestSpread",
"trailingFunctionCommas"
]
};
var ast;
try {
ast = parse(code, opts);
} catch (err) {
if (err instanceof SyntaxError) {
err.lineNumber = err.loc.line;
err.column = err.loc.column + 1;
// remove trailing "(LINE:COLUMN)" acorn message and add in esprima syntax error message start
err.message = "Line " + err.lineNumber + ": " + err.message.replace(/ \((\d+):(\d+)\)$/, "");
}
throw err;
}
// remove EOF token, eslint doesn't use this for anything and it interferes with some rules
// see https://github.com/babel/babel-eslint/issues/2 for more info
// todo: find a more elegant way to do this
ast.tokens.pop();
if (locale === pseudoLocale) {
pluralRules = plurals["en"]
}
const compiledMessages = R.keys(messages).map(key => {
let translation = messages[key] || (!strict ? key : "")
if (locale === pseudoLocale) {
translation = pseudoLocalize(translation)
}
return t.objectProperty(t.stringLiteral(key), compile(translation))
})
const languageData = [
t.objectProperty(
t.stringLiteral("plurals"),
parseExpression(pluralRules.toString())
)
]
const ast = buildExportStatement(
t.objectExpression([
// language data
t.objectProperty(
t.identifier("languageData"),
t.objectExpression(languageData)
),
// messages
t.objectProperty(
t.identifier("messages"),
t.objectExpression(compiledMessages)
)
]),