Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@chialab/estransform

Package Overview
Dependencies
Maintainers
2
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@chialab/estransform - npm Package Compare versions

Comparing version 0.10.4 to 0.11.0

lib/helpers.js

355

lib/index.js

@@ -1,351 +0,4 @@

import { readFile } from 'fs/promises';
import path from 'path';
import MagicString from 'magic-string';
import esbuild from 'esbuild';
import { Parser as AcornParser } from 'acorn';
import jsx from 'acorn-jsx';
import { simple as walk } from 'acorn-walk';
const SOURCEMAP_REGEX = /(?:(\/\*+\s*?sourceMappingURL\s*=)([\s\S]*?)(\*\/))|(?:(\/\/\s*?sourceMappingURL\s*=)(.*?)([\r\n]))/;
const Parser = AcornParser.extend(/** @type {*} */ (jsx()));
export { walk };
/**
* @param {string} contents
*/
export function parse(contents) {
return Parser.parse(contents, {
ecmaVersion: 'latest',
sourceType: 'module',
locations: true,
});
}
/**
* @param {string} code
* @param {number} line
* @param {number} column
*/
export function getOffsetFromLocation(code, line, column) {
let offest = 0;
const lines = code.split('\n');
for (let i = 0; i < line; i++) {
if (i === line - 1) {
offest += column;
return offest;
}
offest += lines[i].length + 1;
}
return -1;
}
/**
* @typedef {Object} SourceMap
* @property {number} [version]
* @property {string[]} sources
* @property {string[]} names
* @property {string} [sourceRoot]
* @property {string[]} [sourcesContent]
* @property {string} mappings
* @property {string} [file]
*/
/**
* @param {string} map
* @return {SourceMap}
*/
export function parseSourcemap(map) {
return JSON.parse(map);
}
/**
* @param {string} code
* @param {string} [filePath]
*/
export async function loadSourcemap(code, filePath) {
const match = code.match(SOURCEMAP_REGEX);
if (match) {
const mapUrl = match[2] || match[5];
try {
let content;
if (mapUrl.startsWith('data:')) {
content = Buffer.from(mapUrl.split(',')[1]).toString('base64');
return parseSourcemap(content);
}
if (filePath) {
content = await readFile(path.resolve(path.dirname(filePath), mapUrl), 'utf-8');
return parseSourcemap(content);
}
} catch {
//
}
}
return null;
}
/**
* @param {SourceMap[]} sourceMaps
*/
export async function mergeSourcemaps(sourceMaps) {
if (sourceMaps.length === 1) {
return {
version: 3,
...sourceMaps[0],
};
}
const { default: { default: SourceMapNode } } = await import('@parcel/source-map');
const sourceMap = sourceMaps.reduce(
/**
* @param {InstanceType<SourceMapNode>|null} sourceMap
* @param {SourceMap} map
* @return {InstanceType<SourceMapNode>}
*/
(sourceMap, map) => {
const mergedMap = new SourceMapNode();
mergedMap.addVLQMap(map);
if (sourceMap) {
mergedMap.extends(sourceMap.toBuffer());
}
return mergedMap;
},
null
);
if (!sourceMap) {
return null;
}
return {
version: 3,
...sourceMap.toVLQ(),
};
}
/**
* @typedef {Object} TransformOptions
* @property {string} [source] The source filename.
* @property {'inline'|boolean} [sourcemap] Should include sourcemap.
* @property {boolean} [sourcesContent] Should include source content in sourcemaps.
*/
/**
* @typedef {Object} TransformResult
* @property {string} [code]
* @property {SourceMap|null} [map]
* @property {import('esbuild').Loader} [loader]
* @property {string} [target]
*/
/**
* @typedef {(data: { ast: acorn.Node, magicCode: MagicString, code: string }, options: TransformOptions) => Promise<TransformResult|void>|TransformResult|void} TransformCallack
*/
/**
* @param {string} contents
* @param {TransformOptions} options
* @param {TransformCallack} callback
* @return {Promise<TransformResult>}
*/
export async function transform(contents, options, callback) {
/**
* @type {MagicString|undefined}
*/
let magicCode;
/**
* @type {acorn.Node|undefined}
*/
let ast;
return await callback({
code: contents,
get ast() {
if (!ast) {
ast = parse(contents);
}
return ast;
},
get magicCode() {
if (!magicCode) {
magicCode = new MagicString(contents);
}
return magicCode;
},
}, options) || {
code: magicCode ? magicCode.toString() : undefined,
map: options.sourcemap && magicCode ? parseSourcemap(
magicCode.generateMap({
hires: true,
source: options.source,
includeContent: options.sourcesContent,
}).toString()
) : undefined,
};
}
export const TARGETS = {
unknown: 'unknown',
typescript: 'typescript',
es2020: 'es2020',
es2019: 'es2019',
es2018: 'es2018',
es2017: 'es2017',
es2016: 'es2016',
es2015: 'es2015',
es5: 'es5',
};
/**
* Transpile entry to standard js.
* @param {import('esbuild').TransformOptions} [config]
* @return {TransformCallack}
*/
export function createTypeScriptTransform(config = {}) {
return async function transpileTypescript({ code }, options) {
const { code: finalCode, map } = await esbuild.transform(code, {
tsconfigRaw: {},
sourcemap: true,
format: 'esm',
target: TARGETS.es2020,
sourcefile: options.source,
loader: config.loader,
jsxFactory: config.jsxFactory,
jsxFragment: config.jsxFragment,
});
return {
code: finalCode,
map: parseSourcemap(map),
target: TARGETS.es2020,
loader: 'js',
};
};
}
/**
* @typedef {Object} Pipeline
* @property {string} contents
* @property {string} code
* @property {SourceMap[]|null} sourceMaps
* @property {string} target
* @property {import('esbuild').Loader} loader
*/
/**
* @param {string} contents
* @param {{ sourcemap?: boolean, source?: string }} [options]
*/
export async function createPipeline(contents, { sourcemap = true, source } = {}) {
const sourceMaps = [];
if (sourcemap) {
const map = await loadSourcemap(contents, source);
if (map) {
sourceMaps.push(map);
}
}
const target = source && source.match(/\.tsx?$/) ? TARGETS.typescript : TARGETS.unknown;
const loader = source && source.match(/\.ts$/) ? 'ts' : 'tsx';
/**
* @type {Pipeline}
*/
const pipeline = {
contents,
code: contents,
sourceMaps: sourcemap ? sourceMaps : null,
target,
loader,
};
return pipeline;
}
/**
* @param {Pipeline} pipeline
* @param {TransformOptions} options
* @param {TransformCallack} callback
*/
export async function pipe(pipeline, options, callback) {
const { code, map, loader, target } = await transform(pipeline.code, {
sourcemap: !!pipeline.sourceMaps,
...options,
}, callback);
if (code) {
if (pipeline.sourceMaps && map && code !== pipeline.code) {
pipeline.sourceMaps.push(map);
}
pipeline.code = code;
}
if (loader) {
pipeline.loader = loader;
}
if (target) {
pipeline.target = target;
}
}
/**
* @param {string} code
* @param {SourceMap} sourceMap
*/
export function inlineSourcemap(code, sourceMap) {
const match = code.match(SOURCEMAP_REGEX);
const url = `data:application/json;base64,${Buffer.from(JSON.stringify(sourceMap)).toString('base64')}`;
if (!match) {
return `${code}\n//# sourceMappingURL=${url}\n`;
}
return code.replace(SOURCEMAP_REGEX, (full, arg1, arg2, arg3, arg4, arg5, arg6) => `${arg1 || arg4}${url}${arg3 || arg6}`);
}
/**
* @param {Pipeline} pipeline
* @param {TransformOptions} options
* @return {Promise<TransformResult>}
*/
export async function finalize(pipeline, { source, sourcemap = true, sourcesContent = true }) {
if (!pipeline.sourceMaps || !pipeline.sourceMaps.length || pipeline.code === pipeline.contents || !sourcemap) {
return {
code: pipeline.code,
map: null,
loader: pipeline.loader,
};
}
const finalMap = await mergeSourcemaps(pipeline.sourceMaps);
if (!finalMap) {
return {
code: pipeline.code,
map: null,
loader: pipeline.loader,
};
}
if (source) {
finalMap.file = source;
} else {
delete finalMap.file;
}
if (!sourcesContent) {
delete finalMap.sourcesContent;
}
return {
code: sourcemap === 'inline' ? inlineSourcemap(pipeline.code, finalMap) : pipeline.code,
map: finalMap,
loader: pipeline.loader,
};
}
export * from './parser.js';
export * from './sourcemaps.js';
export * from './transform.js';
export * from './helpers.js';
{
"name": "@chialab/estransform",
"type": "module",
"version": "0.10.4",
"version": "0.11.0",
"description": "Execute multiple transformations on JavaScript sources with full sourcemaps support.",

@@ -44,5 +44,5 @@ "main": "lib/index.js",

"devDependencies": {
"typescript": "^4.2.3"
"typescript": "^4.3.0"
},
"gitHead": "7f174e0680356966c7cce4b50f2cf2bc58492c5a"
"gitHead": "2113318a74e860b8962591325c65a58bdd1db16f"
}

@@ -1,160 +0,4 @@

/**
* @param {string} contents
*/
export function parse(contents: string): import("acorn").Node;
/**
* @param {string} code
* @param {number} line
* @param {number} column
*/
export function getOffsetFromLocation(code: string, line: number, column: number): number;
/**
* @typedef {Object} SourceMap
* @property {number} [version]
* @property {string[]} sources
* @property {string[]} names
* @property {string} [sourceRoot]
* @property {string[]} [sourcesContent]
* @property {string} mappings
* @property {string} [file]
*/
/**
* @param {string} map
* @return {SourceMap}
*/
export function parseSourcemap(map: string): SourceMap;
/**
* @param {string} code
* @param {string} [filePath]
*/
export function loadSourcemap(code: string, filePath?: string | undefined): Promise<SourceMap | null>;
/**
* @param {SourceMap[]} sourceMaps
*/
export function mergeSourcemaps(sourceMaps: SourceMap[]): Promise<{
version: number;
sources: string[];
names: string[];
sourceRoot?: string | undefined;
sourcesContent?: string[] | undefined;
mappings: string;
file?: string | undefined;
} | null>;
/**
* @typedef {Object} TransformOptions
* @property {string} [source] The source filename.
* @property {'inline'|boolean} [sourcemap] Should include sourcemap.
* @property {boolean} [sourcesContent] Should include source content in sourcemaps.
*/
/**
* @typedef {Object} TransformResult
* @property {string} [code]
* @property {SourceMap|null} [map]
* @property {import('esbuild').Loader} [loader]
* @property {string} [target]
*/
/**
* @typedef {(data: { ast: acorn.Node, magicCode: MagicString, code: string }, options: TransformOptions) => Promise<TransformResult|void>|TransformResult|void} TransformCallack
*/
/**
* @param {string} contents
* @param {TransformOptions} options
* @param {TransformCallack} callback
* @return {Promise<TransformResult>}
*/
export function transform(contents: string, options: TransformOptions, callback: TransformCallack): Promise<TransformResult>;
/**
* Transpile entry to standard js.
* @param {import('esbuild').TransformOptions} [config]
* @return {TransformCallack}
*/
export function createTypeScriptTransform(config?: esbuild.TransformOptions | undefined): TransformCallack;
/**
* @typedef {Object} Pipeline
* @property {string} contents
* @property {string} code
* @property {SourceMap[]|null} sourceMaps
* @property {string} target
* @property {import('esbuild').Loader} loader
*/
/**
* @param {string} contents
* @param {{ sourcemap?: boolean, source?: string }} [options]
*/
export function createPipeline(contents: string, { sourcemap, source }?: {
sourcemap?: boolean | undefined;
source?: string | undefined;
} | undefined): Promise<Pipeline>;
/**
* @param {Pipeline} pipeline
* @param {TransformOptions} options
* @param {TransformCallack} callback
*/
export function pipe(pipeline: Pipeline, options: TransformOptions, callback: TransformCallack): Promise<void>;
/**
* @param {string} code
* @param {SourceMap} sourceMap
*/
export function inlineSourcemap(code: string, sourceMap: SourceMap): string;
/**
* @param {Pipeline} pipeline
* @param {TransformOptions} options
* @return {Promise<TransformResult>}
*/
export function finalize(pipeline: Pipeline, { source, sourcemap, sourcesContent }: TransformOptions): Promise<TransformResult>;
export { walk };
export namespace TARGETS {
const unknown: string;
const typescript: string;
const es2020: string;
const es2019: string;
const es2018: string;
const es2017: string;
const es2016: string;
const es2015: string;
const es5: string;
}
export type SourceMap = {
version?: number | undefined;
sources: string[];
names: string[];
sourceRoot?: string | undefined;
sourcesContent?: string[] | undefined;
mappings: string;
file?: string | undefined;
};
export type TransformOptions = {
/**
* The source filename.
*/
source?: string | undefined;
/**
* Should include sourcemap.
*/
sourcemap?: boolean | "inline" | undefined;
/**
* Should include source content in sourcemaps.
*/
sourcesContent?: boolean | undefined;
};
export type TransformResult = {
code?: string | undefined;
map?: SourceMap | null | undefined;
loader?: esbuild.Loader | undefined;
target?: string | undefined;
};
export type TransformCallack = (data: {
ast: acorn.Node;
magicCode: MagicString;
code: string;
}, options: TransformOptions) => Promise<TransformResult | void> | TransformResult | void;
export type Pipeline = {
contents: string;
code: string;
sourceMaps: SourceMap[] | null;
target: string;
loader: import('esbuild').Loader;
};
import esbuild from "esbuild";
import { simple as walk } from "acorn-walk";
import MagicString from "magic-string";
export * from "./parser.js";
export * from "./sourcemaps.js";
export * from "./transform.js";
export * from "./helpers.js";
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc