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

jarle

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jarle - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0

esm/transform/ImportTransformer.d.ts

6

esm/Provider.d.ts

@@ -31,2 +31,6 @@ import { PrismTheme } from 'prism-react-renderer';

code: string;
/**
* The named export of the code that JARLE should attempt to render if present
*/
exportToRender?: string;
/** A context object of values automatically available for use in editor code */

@@ -83,2 +87,2 @@ scope?: TScope;

*/
export default function Provider<TScope extends {} = {}>({ scope, children, code: rawCode, language, theme, showImports, renderAsComponent, resolveImports, }: Props<TScope>): JSX.Element;
export default function Provider<TScope extends {} = {}>({ scope, children, code: rawCode, language, theme, exportToRender, showImports, renderAsComponent, resolveImports, }: Props<TScope>): JSX.Element;

146

esm/Provider.js

@@ -9,6 +9,9 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }

import useMounted from '@restart/hooks/useMounted';
import React, { useContext, useEffect, useMemo, useState, isValidElement, createElement } from 'react';
import { isValidElementType } from 'react-is';
import { decode } from 'sourcemap-codec';
import transpile, { parseImports } from './transpile';
import React, { useContext, useEffect, useMemo, useState, isValidElement, createElement, useCallback } from 'react';
import { isValidElementType } from 'react-is'; // import { decode } from 'sourcemap-codec';
import { transform } from './transform'; // try and match render() calls with arguments to avoid false positives with class components
const hasRenderCall = code => !!code.match(/render\((?!\s*\))/gm);
const prettierComment = /(\{\s*\/\*\s+prettier-ignore\s+\*\/\s*\})|(\/\/\s+prettier-ignore)/gim;

@@ -35,7 +38,3 @@ const hooks = {};

const wrapAsComponent = ctx => {
return `return React.createElement(function StateContainer() {\n${ctx}\n})`;
};
function handleError(err, result, fn) {
function handleError(err, fn) {
const fnStr = fn.toString(); // account for the function chrome lines

@@ -66,30 +65,22 @@

if (!pos) return err;
if (!pos) return err; // if (result.map) {
// const decoded = decode(result.map.mappings);
// const line = pos.line - offset;
// const mapping = decoded[line]?.find(([col]) => col === pos.column);
// if (mapping) {
// err.location = { line: mapping[2], column: mapping[3] };
// }
// }
if (result.map) {
var _decoded$line;
const decoded = decode(result.map.mappings);
const line = pos.line - offset;
const mapping = (_decoded$line = decoded[line]) === null || _decoded$line === void 0 ? void 0 : _decoded$line.find(([col]) => col === pos.column);
if (mapping) {
err.location = {
line: mapping[2],
column: mapping[3]
};
}
}
return err;
}
function codeToComponent(code, {
function codeToComponent(compiledCode, {
scope,
preample,
isTypeScript,
exportToRender,
renderAsComponent = false
}) {
return new Promise((resolve, reject) => {
const isInline = !code.match(/render\S*\(\S*</);
const isInline = !hasRenderCall(compiledCode);

@@ -100,8 +91,2 @@ if (renderAsComponent && !isInline) {

const result = transpile(code, {
inline: isInline,
isTypeScript,
wrapper: renderAsComponent ? wrapAsComponent : undefined
});
const render = element => {

@@ -120,5 +105,11 @@ if (element === undefined) {

const args = ['React', 'render'].concat(Object.keys(finalScope));
const values = [React, render].concat(Object.values(finalScope));
let body = result.code;
const exports = {};
const args = ['React', 'render', 'exports'].concat(Object.keys(finalScope));
const values = [React, render, exports].concat(Object.values(finalScope));
let body = compiledCode;
if (renderAsComponent) {
body = `return React.createElement(function StateContainer() {\n${body}\n})`;
}
if (preample) body = `${preample}\n\n${body}`; // eslint-disable-next-line no-new-func

@@ -132,10 +123,23 @@

} catch (err) {
reject(handleError(err, result, fn));
reject(handleError(err, fn));
return;
}
if (!isInline) return;
const exportedValues = Object.values(exports);
if ('default' in exports) {
var _exports$default;
element = (_exports$default = exports.default) !== null && _exports$default !== void 0 ? _exports$default : element;
} else if (exportedValues.length) {
var _ref, _exports;
element = (_ref = (_exports = exports[exportToRender]) !== null && _exports !== void 0 ? _exports : exportedValues[0]) !== null && _ref !== void 0 ? _ref : element;
}
if (element === undefined) {
reject(new SyntaxError('The code did not return a JSX element'));
if (isInline) {
reject(new SyntaxError('The code did not return a JSX element'));
}
return;

@@ -147,3 +151,3 @@ }

element = /*#__PURE__*/createElement(element);
} else {
} else if (isInline) {
reject(new SyntaxError('The code did not return a valid React element or element type'));

@@ -173,15 +177,40 @@ }

function useNormalizedCode(code, showImports, isTypeScript, setError) {
return useMemo(() => {
const nextCode = code.replace(prettierComment, '').trim();
if (showImports) return [nextCode, [], ''];
function useCompiledCode(consumerCode, showImports, isTypeScript, setError) {
const compile = useCallback(nextCode => {
const isInline = !hasRenderCall(nextCode);
nextCode = nextCode.replace(prettierComment, '').trim();
try {
const result = parseImports(nextCode, true, isTypeScript);
return [result.code, result.imports, result.imports.map(i => i.code).join('\n').trimStart()];
return transform(nextCode, {
compiledFilename: 'compiled.js',
filename: 'example.js',
wrapLastExpression: isInline,
syntax: isTypeScript ? 'typescript' : 'js',
transforms: isTypeScript ? ['typescript', 'imports', 'jsx'] : ['imports', 'jsx']
});
} catch (err) {
setError(err);
return [code, [], ''];
return {
code: nextCode,
imports: []
};
}
}, [code, showImports]);
}, [isTypeScript, setError]);
const initialResult = useMemo(() => {
const nextCode = consumerCode.replace(prettierComment, '').trim();
return !showImports ? transform(nextCode, {
syntax: isTypeScript ? 'typescript' : 'js',
compiledFilename: 'compiled.js',
filename: 'example.js',
removeImports: true,
transforms: []
}) : {
code: nextCode,
imports: []
};
}, [consumerCode, compile, showImports]);
return [{
compiledCode: showImports ? initialResult.code : initialResult.code.trimStart(),
removedImports: showImports ? [] : initialResult.imports
}, compile];
}

@@ -200,2 +229,3 @@ /**

theme,
exportToRender,
showImports = true,

@@ -213,3 +243,4 @@ renderAsComponent = false,

const isTypeScript = isTypeScriptEnabled(language);
const [cleanCode, ogImports, ogImportBlock] = useNormalizedCode(rawCode, showImports, isTypeScript, setError);
const [initialResult, compile] = useCompiledCode(rawCode, showImports, isTypeScript, setError);
const initialCompiledCode = initialResult.compiledCode;
const handleChange = useEventCallback(nextCode => {

@@ -220,9 +251,10 @@ try {

imports
} = parseImports(nextCode, false, isTypeScript);
const sources = Array.from(new Set([...ogImports, ...imports].map(i => i.source)));
} = compile(nextCode);
const sources = Array.from(new Set([...initialResult.removedImports, ...imports].map(i => i.source)));
Promise.resolve(resolveImports(sources)).then(results => Array.isArray(results) ? objectZip(sources, results) : results).then(fetchedImports => codeToComponent(compiledCode, {
renderAsComponent,
isTypeScript,
exportToRender,
// also include the orginal imports if they were removed
preample: ogImportBlock,
preample: initialResult.removedImports.map(i => i.code).join('\n').trimStart(),
scope: _objectSpread(_objectSpread({}, scope), {}, {

@@ -246,4 +278,4 @@ require: getRequire(fetchedImports)

useEffect(() => {
handleChange(cleanCode);
}, [cleanCode, scope, handleChange]);
handleChange(initialCompiledCode);
}, [initialCompiledCode, scope, handleChange]);
const context = useMemo(() => ({

@@ -254,6 +286,6 @@ theme,

language,
code: cleanCode,
code: initialCompiledCode,
onError: setError,
onChange: handleChange
}), [cleanCode, element, error, handleChange, language, theme]);
}), [initialCompiledCode, element, error, handleChange, language, theme]);
return /*#__PURE__*/React.createElement(Context.Provider, {

@@ -260,0 +292,0 @@ value: context

import { Transform } from 'sucrase/dist/Options';
export declare type Import = {
code: string;
source: string;
base: null | string;
keys: Array<{
local: string;
imported: string;
}>;
};
import { Import } from './ImportTransformer';
export type { Import };
export interface Options {

@@ -22,3 +15,2 @@ removeImports?: boolean;

imports: Import[];
map: import("sucrase/dist/computeSourceMap").RawSourceMap;
};

@@ -1,209 +0,68 @@

import { TokenProcessor, parse, tt, HelperManager, NameManager, CJSImportProcessor, transform as sucraseTransform, getNonTypeIdentifiers, computeSourceMap } from './parser';
let FN = 'require';
let num = 0;
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
const getIdentifier = src => `${src.split('/').pop().replace(/\W/g, '_')}$${num++}`;
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function buildImport(path, {
importProcessor,
isTypeName
}) {
// @ts-ignore
if (!importProcessor.importInfoByPath.has(path)) {
return null;
}
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const {
defaultNames,
wildcardNames,
namedImports,
hasBareImport
} = // @ts-ignore
importProcessor.importInfoByPath.get(path);
const req = `${FN}('${path}');`;
const tmp = getIdentifier(path);
const named = [];
const details = {
base: null,
source: path,
keys: [],
code: ''
};
namedImports.forEach(s => {
if (isTypeName(s.localName)) {
return;
}
import ImportRemoverTransformer from './ImportTransformer';
import { getSucraseContext, RootTransformer } from './parser';
import wrapLastExpression from './wrapLastExpression';
named.push(s.localName === s.importedName ? s.localName : `${s.importedName}: ${s.localName}`);
details.keys.push({
local: s.localName,
imported: s.importedName
});
});
class JarleRootTransformer extends RootTransformer {
constructor(context, options, parsingTransforms) {
var _options$transforms;
if (defaultNames.length || wildcardNames.length) {
const name = defaultNames[0] || wildcardNames[0];
super(context, (_options$transforms = options.transforms) !== null && _options$transforms !== void 0 ? _options$transforms : [], false, _objectSpread({}, options));
if (!isTypeName(name)) {
details.base = name; // intentionally use `var` so that conflcits with Jarle provider scope get resolved naturally
// with the import overriding the scoped identifier
_defineProperty(this, "importTransformer", void 0);
if (wildcardNames.length) {
details.code = `var ${name} = ${req}`;
} else {
details.code = `var ${tmp} = ${req} var ${name} = ${tmp}.default;`;
}
}
}
_defineProperty(this, "wrapLastExpression", void 0);
if (named.length) {
details.code += ` var { ${named.join(', ')} } = ${details.code ? `${tmp};` : req}`;
}
this.importTransformer = new ImportRemoverTransformer(context, options); // @ts-ignore
if (hasBareImport) {
details.code = req;
this.transformers.unshift(this.importTransformer);
this.wrapLastExpression = options.wrapLastExpression ? result => {
return wrapLastExpression(getSucraseContext(result, _objectSpread(_objectSpread({}, options), {}, {
transforms: parsingTransforms
})));
} : result => result;
}
details.code = details.code.trim();
return details;
}
function processImports(tokens, ctx, {
removeImports
}) {
if (!tokens.matches1(tt._import)) return false; // dynamic import
if (tokens.matches2(tt._import, tt.parenL)) {
return true;
get imports() {
return this.importTransformer.imports;
}
tokens.removeInitialToken();
while (!tokens.matches1(tt.string)) {
tokens.removeToken();
transform() {
let result = super.transform();
result = result.replace('"use strict";', '').replace('exports. default =', 'exports.default =').replace('Object.defineProperty(exports, "__esModule", {value: true});', '');
return this.wrapLastExpression(result);
}
const path = tokens.stringValue();
const detail = buildImport(path, ctx);
if (detail !== null && detail !== void 0 && detail.code) {
ctx.imports.push(detail);
tokens.replaceTokenTrimmingLeftWhitespace(removeImports ? '' : detail.code);
} else {
tokens.removeToken();
}
if (tokens.matches1(tt.semi)) {
tokens.removeToken();
}
return true;
}
function wrapLastExpression(tokens, lastExprIdx) {
if (tokens.currentIndex() !== lastExprIdx) {
return false;
}
let prev = tokens.currentIndex() - 1;
let lastWasSemi = prev >= 0 && !tokens.matches1AtIndex(prev, tt.semi);
if (tokens.matches2(tt._export, tt._default)) {
tokens.removeInitialToken();
tokens.replaceTokenTrimmingLeftWhitespace(lastWasSemi ? 'return' : '; return');
} else {
let code = `return ${tokens.currentTokenCode()}`;
if (lastWasSemi) {
code = `;${code}`;
}
tokens.replaceTokenTrimmingLeftWhitespace(code);
}
return true;
}
function getContext(code, transforms, isTypescriptEnabled) {
const {
tokens
} = parse(code, true, isTypescriptEnabled, false);
const nameManager = new NameManager(code, tokens);
const helperManager = new HelperManager(nameManager);
const tokenProcessor = new TokenProcessor(code, tokens, false, true, helperManager);
const nonTypeIdents = isTypescriptEnabled ? getNonTypeIdentifiers(tokenProcessor, {
transforms: []
}) : null;
const importProcessor = new CJSImportProcessor(nameManager, tokenProcessor, false, {
transforms
}, isTypescriptEnabled, //
helperManager);
const imports = [];
return {
tokenProcessor,
importProcessor,
imports,
isTypeName: name => isTypescriptEnabled && !nonTypeIdents.has(name)
};
}
export function transform(code, options = {}) {
const transforms = options.transforms || [];
const isTypescriptEnabled = options.syntax == null ? transforms.includes('typescript') : options.syntax === 'typescript';
const parsingTransforms = ['imports', 'jsx'];
const isTypeScriptEnabled = options.syntax === 'typescript' || transforms.includes('typescript');
if (options.transforms) {
code = sucraseTransform(code, {
transforms
}).code;
if (isTypeScriptEnabled) {
parsingTransforms.push('typescript');
}
const ctx = getContext(code, transforms, isTypescriptEnabled);
const lastExprIdx = options.wrapLastExpression ? findLastExpression(ctx.tokenProcessor) : null;
ctx.importProcessor.preprocessTokens();
num = 0;
const sucraseOptions = _objectSpread(_objectSpread({}, options), {}, {
transforms,
preserveDynamicImport: true,
enableLegacyBabel5ModuleInterop: false,
enableLegacyTypeScriptModuleInterop: true,
jsxRuntime: 'classic'
});
while (!ctx.tokenProcessor.isAtEnd()) {
let wasProcessed = processImports(ctx.tokenProcessor, ctx, options);
if (!wasProcessed && lastExprIdx !== null) {
// console.log('HERE', lastExprIdx);
wasProcessed = wrapLastExpression(ctx.tokenProcessor, lastExprIdx);
}
if (!wasProcessed) {
ctx.tokenProcessor.copyToken();
}
}
const result = ctx.tokenProcessor.finish();
const map = computeSourceMap(result, options.filename, {
compiledFilename: options.compiledFilename
});
const ctx = getSucraseContext(code, _objectSpread(_objectSpread({}, sucraseOptions), {}, {
transforms: parsingTransforms
}));
const transformer = new JarleRootTransformer(ctx, sucraseOptions, parsingTransforms);
return {
code: result,
imports: ctx.imports,
map
code: transformer.transform(),
imports: transformer.imports
};
}
function findLastExpression(tokens) {
let lastExprIdx = null;
for (let i = 0; i < tokens.tokens.length; i++) {
if (tokens.matches2AtIndex(i, tt._export, tt._default)) {
lastExprIdx = i;
break;
}
if (tokens.tokens[i].isTopLevel) {
if (tokens.matches1AtIndex(i, tt._return)) {
lastExprIdx = null;
break;
}
lastExprIdx = i;
}
}
return lastExprIdx;
}

@@ -1,9 +0,14 @@

export { default as TokenProcessor } from 'sucrase/dist/TokenProcessor';
export { parse } from 'sucrase/dist/parser';
import { Options, SucraseContext } from 'sucrase/';
export { default as TokenProcessor } from 'sucrase/dist/types/TokenProcessor';
export { default as RootTransformer } from 'sucrase/dist/types/transformers/RootTransformer';
export { parse } from 'sucrase/dist/types/parser';
export { transform } from 'sucrase/';
export { TokenType as tt } from 'sucrase/dist/parser/tokenizer/types';
export { HelperManager } from 'sucrase/dist/HelperManager';
export { default as NameManager } from 'sucrase/dist/NameManager';
export { default as CJSImportProcessor } from 'sucrase/dist/CJSImportProcessor';
export { default as computeSourceMap } from 'sucrase/dist/computeSourceMap';
export { getNonTypeIdentifiers } from 'sucrase/dist/util/getNonTypeIdentifiers';
export { TokenType as tt } from 'sucrase/dist/types/parser/tokenizer/types';
export { default as CJSImportProcessor } from 'sucrase/dist/types/CJSImportProcessor';
export { default as computeSourceMap } from 'sucrase/dist/types/computeSourceMap';
export function getSucraseContext(
code: string,
options: Options
): SucraseContext;
import { Import } from './transform';
export declare function parseImports(input: string, remove: boolean, isTypeScript: boolean): {
code: string;
imports: Import[];
map: import("sucrase/dist/computeSourceMap").RawSourceMap;
leadingWhitespace: string;
};
export declare type Options = {
inline?: boolean;
isTypeScript?: boolean;
showImports?: boolean;
wrapper?: (code: string) => string;
};
declare const _default: (input: string, { inline, wrapper, isTypeScript }?: Options) => {
declare const _default: (input: string, { inline, isTypeScript, showImports }?: Options) => {
code: string;
imports: Import[];
map: import("sucrase/dist/computeSourceMap").RawSourceMap;
};
export default _default;

@@ -1,47 +0,38 @@

import { transform } from './transform';
import { transform } from './transform'; // function extractLeadingWhitespace(code: string): [string, string] {
// let leadingWhitespace = '';
// let lines = code.split(/\n/);
// for (const [idx, line] of lines.entries()) {
// if (!line.trim().length) {
// leadingWhitespace += '\n';
// } else {
// return [leadingWhitespace, lines.slice(idx).join('\n')];
// }
// }
// return [leadingWhitespace, code];
// }
// export function parseImports(
// input: string,
// remove: boolean,
// isTypeScript: boolean
// ) {
// const { code, imports, map } = transform(input, {
// removeImports: remove,
// syntax: isTypeScript ? 'typescript' : 'js',
// compiledFilename: 'compiled.js',
// filename: 'example.js',
// });
// const [leadingWhitespace, trailing] = extractLeadingWhitespace(code);
// return { code: trailing, imports, map, leadingWhitespace };
// }
function extractLeadingWhitespace(code) {
let leadingWhitespace = '';
let lines = code.split(/\n/);
for (const [idx, line] of lines.entries()) {
if (!line.trim().length) {
leadingWhitespace += '\n';
} else {
return [leadingWhitespace, lines.slice(idx).join('\n')];
}
}
return [leadingWhitespace, code];
}
export function parseImports(input, remove, isTypeScript) {
const {
code,
imports,
map
} = transform(input, {
removeImports: remove,
syntax: isTypeScript ? 'typescript' : 'js',
compiledFilename: 'compiled.js',
filename: 'example.js'
});
const [leadingWhitespace, trailing] = extractLeadingWhitespace(code);
return {
code: trailing,
imports,
map,
leadingWhitespace
};
}
export default ((input, {
inline: _inline = false,
wrapper,
isTypeScript
isTypeScript,
showImports
} = {}) => {
let {
code,
imports,
map
imports
} = transform(input, {
removeImports: !showImports,
wrapLastExpression: _inline,

@@ -52,8 +43,6 @@ transforms: isTypeScript ? ['typescript', 'jsx'] : ['jsx'],

});
if (wrapper) code = wrapper(code);
return {
code,
imports,
map
imports
};
});

@@ -31,2 +31,6 @@ import { PrismTheme } from 'prism-react-renderer';

code: string;
/**
* The named export of the code that JARLE should attempt to render if present
*/
exportToRender?: string;
/** A context object of values automatically available for use in editor code */

@@ -83,2 +87,2 @@ scope?: TScope;

*/
export default function Provider<TScope extends {} = {}>({ scope, children, code: rawCode, language, theme, showImports, renderAsComponent, resolveImports, }: Props<TScope>): JSX.Element;
export default function Provider<TScope extends {} = {}>({ scope, children, code: rawCode, language, theme, exportToRender, showImports, renderAsComponent, resolveImports, }: Props<TScope>): JSX.Element;

@@ -21,6 +21,4 @@ "use strict";

var _sourcemapCodec = require("sourcemap-codec");
var _transform = require("./transform");
var _transpile = _interopRequireWildcard(require("./transpile"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

@@ -38,2 +36,5 @@

// try and match render() calls with arguments to avoid false positives with class components
const hasRenderCall = code => !!code.match(/render\((?!\s*\))/gm);
const prettierComment = /(\{\s*\/\*\s+prettier-ignore\s+\*\/\s*\})|(\/\/\s+prettier-ignore)/gim;

@@ -66,7 +67,3 @@ const hooks = {};

const wrapAsComponent = ctx => {
return `return React.createElement(function StateContainer() {\n${ctx}\n})`;
};
function handleError(err, result, fn) {
function handleError(err, fn) {
const fnStr = fn.toString(); // account for the function chrome lines

@@ -97,30 +94,22 @@

if (!pos) return err;
if (!pos) return err; // if (result.map) {
// const decoded = decode(result.map.mappings);
// const line = pos.line - offset;
// const mapping = decoded[line]?.find(([col]) => col === pos.column);
// if (mapping) {
// err.location = { line: mapping[2], column: mapping[3] };
// }
// }
if (result.map) {
var _decoded$line;
const decoded = (0, _sourcemapCodec.decode)(result.map.mappings);
const line = pos.line - offset;
const mapping = (_decoded$line = decoded[line]) === null || _decoded$line === void 0 ? void 0 : _decoded$line.find(([col]) => col === pos.column);
if (mapping) {
err.location = {
line: mapping[2],
column: mapping[3]
};
}
}
return err;
}
function codeToComponent(code, {
function codeToComponent(compiledCode, {
scope,
preample,
isTypeScript,
exportToRender,
renderAsComponent = false
}) {
return new Promise((resolve, reject) => {
const isInline = !code.match(/render\S*\(\S*</);
const isInline = !hasRenderCall(compiledCode);

@@ -131,8 +120,2 @@ if (renderAsComponent && !isInline) {

const result = (0, _transpile.default)(code, {
inline: isInline,
isTypeScript,
wrapper: renderAsComponent ? wrapAsComponent : undefined
});
const render = element => {

@@ -151,5 +134,11 @@ if (element === undefined) {

const args = ['React', 'render'].concat(Object.keys(finalScope));
const values = [_react.default, render].concat(Object.values(finalScope));
let body = result.code;
const exports = {};
const args = ['React', 'render', 'exports'].concat(Object.keys(finalScope));
const values = [_react.default, render, exports].concat(Object.values(finalScope));
let body = compiledCode;
if (renderAsComponent) {
body = `return React.createElement(function StateContainer() {\n${body}\n})`;
}
if (preample) body = `${preample}\n\n${body}`; // eslint-disable-next-line no-new-func

@@ -163,10 +152,23 @@

} catch (err) {
reject(handleError(err, result, fn));
reject(handleError(err, fn));
return;
}
if (!isInline) return;
const exportedValues = Object.values(exports);
if ('default' in exports) {
var _exports$default;
element = (_exports$default = exports.default) !== null && _exports$default !== void 0 ? _exports$default : element;
} else if (exportedValues.length) {
var _ref, _exports;
element = (_ref = (_exports = exports[exportToRender]) !== null && _exports !== void 0 ? _exports : exportedValues[0]) !== null && _ref !== void 0 ? _ref : element;
}
if (element === undefined) {
reject(new SyntaxError('The code did not return a JSX element'));
if (isInline) {
reject(new SyntaxError('The code did not return a JSX element'));
}
return;

@@ -178,3 +180,3 @@ }

element = /*#__PURE__*/(0, _react.createElement)(element);
} else {
} else if (isInline) {
reject(new SyntaxError('The code did not return a valid React element or element type'));

@@ -209,15 +211,40 @@ }

function useNormalizedCode(code, showImports, isTypeScript, setError) {
return (0, _react.useMemo)(() => {
const nextCode = code.replace(prettierComment, '').trim();
if (showImports) return [nextCode, [], ''];
function useCompiledCode(consumerCode, showImports, isTypeScript, setError) {
const compile = (0, _react.useCallback)(nextCode => {
const isInline = !hasRenderCall(nextCode);
nextCode = nextCode.replace(prettierComment, '').trim();
try {
const result = (0, _transpile.parseImports)(nextCode, true, isTypeScript);
return [result.code, result.imports, result.imports.map(i => i.code).join('\n').trimStart()];
return (0, _transform.transform)(nextCode, {
compiledFilename: 'compiled.js',
filename: 'example.js',
wrapLastExpression: isInline,
syntax: isTypeScript ? 'typescript' : 'js',
transforms: isTypeScript ? ['typescript', 'imports', 'jsx'] : ['imports', 'jsx']
});
} catch (err) {
setError(err);
return [code, [], ''];
return {
code: nextCode,
imports: []
};
}
}, [code, showImports]);
}, [isTypeScript, setError]);
const initialResult = (0, _react.useMemo)(() => {
const nextCode = consumerCode.replace(prettierComment, '').trim();
return !showImports ? (0, _transform.transform)(nextCode, {
syntax: isTypeScript ? 'typescript' : 'js',
compiledFilename: 'compiled.js',
filename: 'example.js',
removeImports: true,
transforms: []
}) : {
code: nextCode,
imports: []
};
}, [consumerCode, compile, showImports]);
return [{
compiledCode: showImports ? initialResult.code : initialResult.code.trimStart(),
removedImports: showImports ? [] : initialResult.imports
}, compile];
}

@@ -236,2 +263,3 @@ /**

theme,
exportToRender,
showImports = true,

@@ -249,3 +277,4 @@ renderAsComponent = false,

const isTypeScript = isTypeScriptEnabled(language);
const [cleanCode, ogImports, ogImportBlock] = useNormalizedCode(rawCode, showImports, isTypeScript, setError);
const [initialResult, compile] = useCompiledCode(rawCode, showImports, isTypeScript, setError);
const initialCompiledCode = initialResult.compiledCode;
const handleChange = (0, _useEventCallback.default)(nextCode => {

@@ -256,9 +285,10 @@ try {

imports
} = (0, _transpile.parseImports)(nextCode, false, isTypeScript);
const sources = Array.from(new Set([...ogImports, ...imports].map(i => i.source)));
} = compile(nextCode);
const sources = Array.from(new Set([...initialResult.removedImports, ...imports].map(i => i.source)));
Promise.resolve(resolveImports(sources)).then(results => Array.isArray(results) ? objectZip(sources, results) : results).then(fetchedImports => codeToComponent(compiledCode, {
renderAsComponent,
isTypeScript,
exportToRender,
// also include the orginal imports if they were removed
preample: ogImportBlock,
preample: initialResult.removedImports.map(i => i.code).join('\n').trimStart(),
scope: _objectSpread(_objectSpread({}, scope), {}, {

@@ -282,4 +312,4 @@ require: getRequire(fetchedImports)

(0, _react.useEffect)(() => {
handleChange(cleanCode);
}, [cleanCode, scope, handleChange]);
handleChange(initialCompiledCode);
}, [initialCompiledCode, scope, handleChange]);
const context = (0, _react.useMemo)(() => ({

@@ -290,6 +320,6 @@ theme,

language,
code: cleanCode,
code: initialCompiledCode,
onError: setError,
onChange: handleChange
}), [cleanCode, element, error, handleChange, language, theme]);
}), [initialCompiledCode, element, error, handleChange, language, theme]);
return /*#__PURE__*/_react.default.createElement(Context.Provider, {

@@ -296,0 +326,0 @@ value: context

import { Transform } from 'sucrase/dist/Options';
export declare type Import = {
code: string;
source: string;
base: null | string;
keys: Array<{
local: string;
imported: string;
}>;
};
import { Import } from './ImportTransformer';
export type { Import };
export interface Options {

@@ -22,3 +15,2 @@ removeImports?: boolean;

imports: Import[];
map: import("sucrase/dist/computeSourceMap").RawSourceMap;
};

@@ -8,211 +8,73 @@ "use strict";

var _ImportTransformer = _interopRequireDefault(require("./ImportTransformer"));
var _parser = require("./parser");
let FN = 'require';
let num = 0;
var _wrapLastExpression = _interopRequireDefault(require("./wrapLastExpression"));
const getIdentifier = src => `${src.split('/').pop().replace(/\W/g, '_')}$${num++}`;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function buildImport(path, {
importProcessor,
isTypeName
}) {
// @ts-ignore
if (!importProcessor.importInfoByPath.has(path)) {
return null;
}
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
const {
defaultNames,
wildcardNames,
namedImports,
hasBareImport
} = // @ts-ignore
importProcessor.importInfoByPath.get(path);
const req = `${FN}('${path}');`;
const tmp = getIdentifier(path);
const named = [];
const details = {
base: null,
source: path,
keys: [],
code: ''
};
namedImports.forEach(s => {
if (isTypeName(s.localName)) {
return;
}
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
named.push(s.localName === s.importedName ? s.localName : `${s.importedName}: ${s.localName}`);
details.keys.push({
local: s.localName,
imported: s.importedName
});
});
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
if (defaultNames.length || wildcardNames.length) {
const name = defaultNames[0] || wildcardNames[0];
class JarleRootTransformer extends _parser.RootTransformer {
constructor(context, options, parsingTransforms) {
var _options$transforms;
if (!isTypeName(name)) {
details.base = name; // intentionally use `var` so that conflcits with Jarle provider scope get resolved naturally
// with the import overriding the scoped identifier
super(context, (_options$transforms = options.transforms) !== null && _options$transforms !== void 0 ? _options$transforms : [], false, _objectSpread({}, options));
if (wildcardNames.length) {
details.code = `var ${name} = ${req}`;
} else {
details.code = `var ${tmp} = ${req} var ${name} = ${tmp}.default;`;
}
}
}
_defineProperty(this, "importTransformer", void 0);
if (named.length) {
details.code += ` var { ${named.join(', ')} } = ${details.code ? `${tmp};` : req}`;
}
_defineProperty(this, "wrapLastExpression", void 0);
if (hasBareImport) {
details.code = req;
}
this.importTransformer = new _ImportTransformer.default(context, options); // @ts-ignore
details.code = details.code.trim();
return details;
}
function processImports(tokens, ctx, {
removeImports
}) {
if (!tokens.matches1(_parser.tt._import)) return false; // dynamic import
if (tokens.matches2(_parser.tt._import, _parser.tt.parenL)) {
return true;
this.transformers.unshift(this.importTransformer);
this.wrapLastExpression = options.wrapLastExpression ? result => {
return (0, _wrapLastExpression.default)((0, _parser.getSucraseContext)(result, _objectSpread(_objectSpread({}, options), {}, {
transforms: parsingTransforms
})));
} : result => result;
}
tokens.removeInitialToken();
while (!tokens.matches1(_parser.tt.string)) {
tokens.removeToken();
get imports() {
return this.importTransformer.imports;
}
const path = tokens.stringValue();
const detail = buildImport(path, ctx);
if (detail !== null && detail !== void 0 && detail.code) {
ctx.imports.push(detail);
tokens.replaceTokenTrimmingLeftWhitespace(removeImports ? '' : detail.code);
} else {
tokens.removeToken();
transform() {
let result = super.transform();
result = result.replace('"use strict";', '').replace('exports. default =', 'exports.default =').replace('Object.defineProperty(exports, "__esModule", {value: true});', '');
return this.wrapLastExpression(result);
}
if (tokens.matches1(_parser.tt.semi)) {
tokens.removeToken();
}
return true;
}
function wrapLastExpression(tokens, lastExprIdx) {
if (tokens.currentIndex() !== lastExprIdx) {
return false;
}
let prev = tokens.currentIndex() - 1;
let lastWasSemi = prev >= 0 && !tokens.matches1AtIndex(prev, _parser.tt.semi);
if (tokens.matches2(_parser.tt._export, _parser.tt._default)) {
tokens.removeInitialToken();
tokens.replaceTokenTrimmingLeftWhitespace(lastWasSemi ? 'return' : '; return');
} else {
let code = `return ${tokens.currentTokenCode()}`;
if (lastWasSemi) {
code = `;${code}`;
}
tokens.replaceTokenTrimmingLeftWhitespace(code);
}
return true;
}
function getContext(code, transforms, isTypescriptEnabled) {
const {
tokens
} = (0, _parser.parse)(code, true, isTypescriptEnabled, false);
const nameManager = new _parser.NameManager(code, tokens);
const helperManager = new _parser.HelperManager(nameManager);
const tokenProcessor = new _parser.TokenProcessor(code, tokens, false, true, helperManager);
const nonTypeIdents = isTypescriptEnabled ? (0, _parser.getNonTypeIdentifiers)(tokenProcessor, {
transforms: []
}) : null;
const importProcessor = new _parser.CJSImportProcessor(nameManager, tokenProcessor, false, {
transforms
}, isTypescriptEnabled, //
helperManager);
const imports = [];
return {
tokenProcessor,
importProcessor,
imports,
isTypeName: name => isTypescriptEnabled && !nonTypeIdents.has(name)
};
}
function transform(code, options = {}) {
const transforms = options.transforms || [];
const isTypescriptEnabled = options.syntax == null ? transforms.includes('typescript') : options.syntax === 'typescript';
const parsingTransforms = ['imports', 'jsx'];
const isTypeScriptEnabled = options.syntax === 'typescript' || transforms.includes('typescript');
if (options.transforms) {
code = (0, _parser.transform)(code, {
transforms
}).code;
if (isTypeScriptEnabled) {
parsingTransforms.push('typescript');
}
const ctx = getContext(code, transforms, isTypescriptEnabled);
const lastExprIdx = options.wrapLastExpression ? findLastExpression(ctx.tokenProcessor) : null;
ctx.importProcessor.preprocessTokens();
num = 0;
const sucraseOptions = _objectSpread(_objectSpread({}, options), {}, {
transforms,
preserveDynamicImport: true,
enableLegacyBabel5ModuleInterop: false,
enableLegacyTypeScriptModuleInterop: true,
jsxRuntime: 'classic'
});
while (!ctx.tokenProcessor.isAtEnd()) {
let wasProcessed = processImports(ctx.tokenProcessor, ctx, options);
if (!wasProcessed && lastExprIdx !== null) {
// console.log('HERE', lastExprIdx);
wasProcessed = wrapLastExpression(ctx.tokenProcessor, lastExprIdx);
}
if (!wasProcessed) {
ctx.tokenProcessor.copyToken();
}
}
const result = ctx.tokenProcessor.finish();
const map = (0, _parser.computeSourceMap)(result, options.filename, {
compiledFilename: options.compiledFilename
});
const ctx = (0, _parser.getSucraseContext)(code, _objectSpread(_objectSpread({}, sucraseOptions), {}, {
transforms: parsingTransforms
}));
const transformer = new JarleRootTransformer(ctx, sucraseOptions, parsingTransforms);
return {
code: result,
imports: ctx.imports,
map
code: transformer.transform(),
imports: transformer.imports
};
}
function findLastExpression(tokens) {
let lastExprIdx = null;
for (let i = 0; i < tokens.tokens.length; i++) {
if (tokens.matches2AtIndex(i, _parser.tt._export, _parser.tt._default)) {
lastExprIdx = i;
break;
}
if (tokens.tokens[i].isTopLevel) {
if (tokens.matches1AtIndex(i, _parser.tt._return)) {
lastExprIdx = null;
break;
}
lastExprIdx = i;
}
}
return lastExprIdx;
}

@@ -1,9 +0,14 @@

export { default as TokenProcessor } from 'sucrase/dist/TokenProcessor';
export { parse } from 'sucrase/dist/parser';
import { Options, SucraseContext } from 'sucrase/';
export { default as TokenProcessor } from 'sucrase/dist/types/TokenProcessor';
export { default as RootTransformer } from 'sucrase/dist/types/transformers/RootTransformer';
export { parse } from 'sucrase/dist/types/parser';
export { transform } from 'sucrase/';
export { TokenType as tt } from 'sucrase/dist/parser/tokenizer/types';
export { HelperManager } from 'sucrase/dist/HelperManager';
export { default as NameManager } from 'sucrase/dist/NameManager';
export { default as CJSImportProcessor } from 'sucrase/dist/CJSImportProcessor';
export { default as computeSourceMap } from 'sucrase/dist/computeSourceMap';
export { getNonTypeIdentifiers } from 'sucrase/dist/util/getNonTypeIdentifiers';
export { TokenType as tt } from 'sucrase/dist/types/parser/tokenizer/types';
export { default as CJSImportProcessor } from 'sucrase/dist/types/CJSImportProcessor';
export { default as computeSourceMap } from 'sucrase/dist/types/computeSourceMap';
export function getSucraseContext(
code: string,
options: Options
): SucraseContext;
import { Import } from './transform';
export declare function parseImports(input: string, remove: boolean, isTypeScript: boolean): {
code: string;
imports: Import[];
map: import("sucrase/dist/computeSourceMap").RawSourceMap;
leadingWhitespace: string;
};
export declare type Options = {
inline?: boolean;
isTypeScript?: boolean;
showImports?: boolean;
wrapper?: (code: string) => string;
};
declare const _default: (input: string, { inline, wrapper, isTypeScript }?: Options) => {
declare const _default: (input: string, { inline, isTypeScript, showImports }?: Options) => {
code: string;
imports: Import[];
map: import("sucrase/dist/computeSourceMap").RawSourceMap;
};
export default _default;

@@ -7,51 +7,15 @@ "use strict";

exports.default = void 0;
exports.parseImports = parseImports;
var _transform = require("./transform");
function extractLeadingWhitespace(code) {
let leadingWhitespace = '';
let lines = code.split(/\n/);
for (const [idx, line] of lines.entries()) {
if (!line.trim().length) {
leadingWhitespace += '\n';
} else {
return [leadingWhitespace, lines.slice(idx).join('\n')];
}
}
return [leadingWhitespace, code];
}
function parseImports(input, remove, isTypeScript) {
const {
code,
imports,
map
} = (0, _transform.transform)(input, {
removeImports: remove,
syntax: isTypeScript ? 'typescript' : 'js',
compiledFilename: 'compiled.js',
filename: 'example.js'
});
const [leadingWhitespace, trailing] = extractLeadingWhitespace(code);
return {
code: trailing,
imports,
map,
leadingWhitespace
};
}
var _default = (input, {
inline: _inline = false,
wrapper,
isTypeScript
isTypeScript,
showImports
} = {}) => {
let {
code,
imports,
map
imports
} = (0, _transform.transform)(input, {
removeImports: !showImports,
wrapLastExpression: _inline,

@@ -62,7 +26,5 @@ transforms: isTypeScript ? ['typescript', 'jsx'] : ['jsx'],

});
if (wrapper) code = wrapper(code);
return {
code,
imports,
map
imports
};

@@ -69,0 +31,0 @@ };

{
"name": "jarle",
"version": "2.0.0",
"version": "2.1.0",
"main": "lib/index.js",

@@ -17,2 +17,3 @@ "module": "esm/index.js",

"prepublishOnly": "yarn run build",
"release": "4c release",
"tdd": "jest --watch",

@@ -67,4 +68,4 @@ "test": "jest"

"rollup": "^2.59.0",
"sucrase": "^3.20.3",
"rollup-plugin-dts": "^4.0.1"
"rollup-plugin-dts": "^4.0.1",
"sucrase": "^3.29.0"
},

@@ -71,0 +72,0 @@ "dependencies": {

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

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