New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@teleporthq/teleport-code-generators

Package Overview
Dependencies
Maintainers
4
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@teleporthq/teleport-code-generators - npm Package Compare versions

Comparing version 0.3.0 to 0.3.1

.all-contributorsrc

6

__tests__/unit/index.ts

@@ -9,3 +9,3 @@ import componentUIDL from '../../examples/uidl-samples/component-author-card.json'

const { ReactComponentFlavors } = ComponentGeneratorTypes
const { ReactComponentStylingFlavors } = ComponentGeneratorTypes

@@ -15,3 +15,3 @@ describe('React Component Generator', () => {

const generator = createReactComponentGenerator({
variation: ReactComponentFlavors.CSSModules,
variation: ReactComponentStylingFlavors.CSSModules,
})

@@ -30,3 +30,3 @@

const generator = createReactComponentGenerator({
variation: ReactComponentFlavors.InlineStyles,
variation: ReactComponentStylingFlavors.InlineStyles,
customMapping: { container: { type: 'fakediv' } },

@@ -33,0 +33,0 @@ })

{
"arrowParens": "always",
"parser": "typescript",
"printWidth": 99,
"printWidth": 100,
"semi": false,

@@ -6,0 +6,0 @@ "singleQuote": true,

@@ -1,11 +0,12 @@

import { ComponentPlugin, ComponentStructure } from '../../types';
import { ComponentPlugin, ComponentStructure, ChunkDefinition } from '../../types';
import { ComponentUIDL } from '../../../uidl-definitions/types';
export default class ComponentAssemblyLine {
export default class AssemblyLine {
private plugins;
constructor(plugins?: ComponentPlugin[]);
run(uidl: ComponentUIDL, initialStructure?: ComponentStructure): Promise<{
chunks: import("../../types").ChunkDefinition[];
chunks: ChunkDefinition[];
dependencies: Record<string, import("../../../uidl-definitions/types").ComponentDependency>;
}>;
addPlugin(plugin: ComponentPlugin): void;
groupChunksByFileId(chunks: ChunkDefinition[]): Record<string, ChunkDefinition[]>;
}

@@ -38,8 +38,8 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var ComponentAssemblyLine = /** @class */ (function () {
function ComponentAssemblyLine(plugins) {
var AssemblyLine = /** @class */ (function () {
function AssemblyLine(plugins) {
if (plugins === void 0) { plugins = []; }
this.plugins = plugins;
}
ComponentAssemblyLine.prototype.run = function (uidl, initialStructure) {
AssemblyLine.prototype.run = function (uidl, initialStructure) {
if (initialStructure === void 0) { initialStructure = {

@@ -79,8 +79,18 @@ uidl: uidl,

};
ComponentAssemblyLine.prototype.addPlugin = function (plugin) {
AssemblyLine.prototype.addPlugin = function (plugin) {
this.plugins.push(plugin);
};
return ComponentAssemblyLine;
AssemblyLine.prototype.groupChunksByFileId = function (chunks) {
return chunks.reduce(function (chunksByFileId, chunk) {
var fileId = (chunk.meta && chunk.meta.fileId) || 'default';
if (!chunksByFileId[fileId]) {
chunksByFileId[fileId] = [];
}
chunksByFileId[fileId].push(chunk);
return chunksByFileId;
}, {});
};
return AssemblyLine;
}());
exports.default = ComponentAssemblyLine;
exports.default = AssemblyLine;
//# sourceMappingURL=index.js.map

@@ -5,15 +5,2 @@ "use strict";

var html_to_string_1 = require("./generators/html-to-string");
var removeItemsInArray = function (arrayToRemoveFrom, itemsToRemove) {
return arrayToRemoveFrom.filter(function (item) {
return itemsToRemove.indexOf(item) === -1;
});
};
var removeChildDependency = function (children, targetChunkName) {
return children.reduce(function (acc, child) {
if (child.chunkName !== targetChunkName) {
acc.push(child);
}
return acc;
}, []);
};
var Builder = /** @class */ (function () {

@@ -212,2 +199,15 @@ function Builder(chunkDefinitions) {

exports.default = Builder;
var removeItemsInArray = function (arrayToRemoveFrom, itemsToRemove) {
return arrayToRemoveFrom.filter(function (item) {
return itemsToRemove.indexOf(item) === -1;
});
};
var removeChildDependency = function (children, targetChunkName) {
return children.reduce(function (acc, child) {
if (child.chunkName !== targetChunkName) {
acc.push(child);
}
return acc;
}, []);
};
//# sourceMappingURL=index.js.map

@@ -1,3 +0,3 @@

export { default as ComponentAssemblyLine } from './assembly-line';
export { default as AssemblyLine } from './assembly-line';
export { default as Builder } from './builder';
export { default as Resolver } from './resolver';
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var assembly_line_1 = require("./assembly-line");
exports.ComponentAssemblyLine = assembly_line_1.default;
exports.AssemblyLine = assembly_line_1.default;
var builder_1 = require("./builder");

@@ -6,0 +6,0 @@ exports.Builder = builder_1.default;

@@ -14,4 +14,81 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var uidl_utils_1 = require("../../utils/uidl-utils");
var constants_1 = require("../../constants");
var STYLE_PROPERTIES_WITH_URL = ['background', 'backgroundImage'];
var ATTRIBUTES_WITH_URL = ['url', 'srcset'];
exports.resolveContentNode = function (node, elementsMapping, localDependenciesPrefix, assetsPrefix) {
var mappedElement = elementsMapping[node.type] || { type: node.type };
node.type = mappedElement.type;
// If the mapping contains children, insert that structure into the UIDL
if (mappedElement.children) {
var originalNodeChildren = node.children || [];
var originalAttrs = node.attrs || {};
var replacingNode = __assign({}, node, { children: JSON.parse(JSON.stringify(mappedElement.children)) });
insertChildrenIntoNode(replacingNode, originalNodeChildren, originalAttrs);
node.children = replacingNode.children;
}
// Resolve dependency with the UIDL having priority
if (node.dependency || mappedElement.dependency) {
node.dependency = resolveDependency(mappedElement, node.dependency, localDependenciesPrefix);
}
// Resolve assets prefix inside style (ex: background-image)
if (node.styles && assetsPrefix) {
node.styles = prefixAssetURLs(node.styles, assetsPrefix);
}
// Prefix the attributes which may point to local assets
if (node.attrs && assetsPrefix) {
ATTRIBUTES_WITH_URL.forEach(function (attribute) {
if (node.attrs[attribute]) {
node.attrs[attribute] = uidl_utils_1.prefixPlaygroundAssetsURL(assetsPrefix, node.attrs[attribute]);
}
});
}
// Merge UIDL attributes to the attributes coming from the mapping object
if (mappedElement.attrs) {
node.attrs = mergeAttributes(mappedElement, node.attrs);
}
// The UIDL has priority over the mapping repeat
var repeatStructure = node.repeat || mappedElement.repeat;
if (repeatStructure) {
var dataSource = repeatStructure.dataSource, content = repeatStructure.content;
// Data source might be preset on a referenced attribute in the uidl node
// ex: attrs[options] in case of a dropdown primitive with select/options
if (typeof dataSource === 'string' && dataSource.startsWith('$attrs.') && node.attrs) {
var nodeDataSourceAttr = dataSource.replace('$attrs.', '');
repeatStructure.dataSource = node.attrs[nodeDataSourceAttr];
}
// The content inside the repeat must also be mapped like any regular content node
repeatStructure.content = exports.resolveContentNode(content, elementsMapping, localDependenciesPrefix, assetsPrefix);
node.repeat = repeatStructure;
}
// If the node has multiple state branches, each content needs to be resolved
if (node.type === 'state' && node.states) {
node.states = node.states.map(function (stateBranch) {
if (typeof stateBranch.content === 'string') {
return stateBranch;
}
else {
return __assign({}, stateBranch, { content: exports.resolveContentNode(stateBranch.content, elementsMapping, localDependenciesPrefix, assetsPrefix) });
}
});
}
// Traverse the UIDL
if (node.children) {
node.children = node.children.map(function (child) {
if (typeof child === 'string') {
return child;
}
else {
return exports.resolveContentNode(child, elementsMapping, localDependenciesPrefix, assetsPrefix);
}
});
}
return node;
};
/**
* Prefixes all urls inside the style object with the assetsPrefix
* @param styles the style object on the current node
* @param assetsPrefix a string representing the asset prefix
*/
var prefixAssetURLs = function (styles, assetsPrefix) {
var whitelistStyleProperties = ['background', 'backgroundImage'];
// iterate through all the style keys

@@ -31,8 +108,8 @@ return Object.keys(styles).reduce(function (acc, styleKey) {

// only whitelisted style properties are checked
if (whitelistStyleProperties.includes(styleKey) && styleValue.includes('url("')) {
// position index after the double quotes to introduce the url prefix before
var startIndex = styleValue.indexOf('url("') + 5;
if (STYLE_PROPERTIES_WITH_URL.includes(styleKey) && styleValue.includes(constants_1.ASSETS_IDENTIFIER)) {
// split the string at the beginning of the ASSETS_IDENTIFIER string
var startIndex = styleValue.indexOf(constants_1.ASSETS_IDENTIFIER);
acc[styleKey] =
styleValue.slice(0, startIndex) +
prefixRelativeURL(assetsPrefix, styleValue.slice(startIndex, styleValue.length - 1));
uidl_utils_1.prefixPlaygroundAssetsURL(assetsPrefix, styleValue.slice(startIndex, styleValue.length));
}

@@ -45,17 +122,3 @@ else {

};
/**
* Concatenates the prefix to the URL string.
* If the url starts with 'http', the return value will be the 'originalString'
* If the url does not start with a '/' it also appends that
*/
var prefixRelativeURL = function (prefix, originalString) {
if (originalString.startsWith('http')) {
return originalString;
}
if (originalString.startsWith('/')) {
return prefix + originalString;
}
return prefix + "/" + originalString;
};
var mergeAttributes = function (mappedElement, uidlAttrs, assetsPrefix) {
var mergeAttributes = function (mappedElement, uidlAttrs) {
// We gather the results here uniting the mapped attributes and the uidl attributes.

@@ -79,6 +142,3 @@ var resolvedAttrs = {};

if (uidlAttrs && uidlAttrs[uidlAttributeKey]) {
resolvedAttrs[key] =
key === 'src' && assetsPrefix
? prefixRelativeURL(assetsPrefix, uidlAttrs[uidlAttributeKey])
: uidlAttrs[uidlAttributeKey];
resolvedAttrs[key] = uidlAttrs[uidlAttributeKey];
mappedAttributes.push(uidlAttributeKey);

@@ -114,3 +174,16 @@ }

// Traverses the mapped elements children and inserts the original children of the node being mapped.
var insertChildrenIntoNode = function (node, originalChildren) {
var insertChildrenIntoNode = function (node, originalChildren, originalAttrs) {
// The same kind of referencing that is done in the mergeAttributes function
// TODO: Extract duplicate code and apply in both instances (merge attributes and solving children nodes)
// Explained here: https://github.com/teleporthq/teleport-code-generators/issues/44
// Object.keys(node.attrs).forEach((attrKey) => {
// if (typeof node.attrs[attrKey] === 'string' && node.attrs[attrKey].startsWith('$attrs.')) {
// const referencedAttributeKey = node.attrs[attrKey].replace('$attrs.', '')
// if (originalAttrs[referencedAttributeKey]) {
// node.attrs[attrKey] = originalAttrs[referencedAttributeKey]
// // since the attribute is mapped in the children, we assume it is not longer needed on the root node
// delete originalAttrs[referencedAttributeKey]
// }
// }
// })
if (!node.children) {

@@ -132,3 +205,3 @@ return;

// The child node is pushed after the $children token was replaced
insertChildrenIntoNode(child, originalChildren);
insertChildrenIntoNode(child, originalChildren, originalAttrs);
acc.push(child);

@@ -138,62 +211,2 @@ return acc;

};
exports.resolveContentNode = function (node, elementsMapping, localDependenciesPrefix, assetsPrefix) {
var mappedElement = elementsMapping[node.type] || { type: node.type };
node.type = mappedElement.type;
// Resolve dependency with the UIDL having priority
if (node.dependency || mappedElement.dependency) {
node.dependency = resolveDependency(mappedElement, node.dependency, localDependenciesPrefix);
}
// Resolve assets prefix inside style (ex: background-image)
if (node.styles && assetsPrefix) {
node.styles = prefixAssetURLs(node.styles, assetsPrefix);
}
// Merge UIDL attributes to the attributes coming from the mapping object
if (mappedElement.attrs) {
node.attrs = mergeAttributes(mappedElement, node.attrs, assetsPrefix);
}
// If the mapping contains children, insert that structure into the UIDL
if (mappedElement.children) {
var originalNodeChildren = node.children || [];
var replacingNode = __assign({}, node, { children: JSON.parse(JSON.stringify(mappedElement.children)) });
insertChildrenIntoNode(replacingNode, originalNodeChildren);
node.children = replacingNode.children;
}
// The UIDL has priority over the mapping repeat
var repeatStructure = node.repeat || mappedElement.repeat;
if (repeatStructure) {
var dataSource = repeatStructure.dataSource, content = repeatStructure.content;
// Data source might be preset on a referenced attribute in the uidl node
// ex: attrs[options] in case of a dropdown primitive with select/options
if (typeof dataSource === 'string' && dataSource.startsWith('$attrs.') && node.attrs) {
var nodeDataSourceAttr = dataSource.replace('$attrs.', '');
repeatStructure.dataSource = node.attrs[nodeDataSourceAttr];
}
// The content inside the repeat must also be mapped like any regular content node
repeatStructure.content = exports.resolveContentNode(content, elementsMapping, localDependenciesPrefix, assetsPrefix);
node.repeat = repeatStructure;
}
// If the node has multiple state branches, each content needs to be resolved
if (node.type === 'state' && node.states) {
node.states = node.states.map(function (stateBranch) {
if (typeof stateBranch.content === 'string') {
return stateBranch;
}
else {
return __assign({}, stateBranch, { content: exports.resolveContentNode(stateBranch.content, elementsMapping, localDependenciesPrefix, assetsPrefix) });
}
});
}
// Traverse the UIDL
if (node.children) {
node.children = node.children.map(function (child) {
if (typeof child === 'string') {
return child;
}
else {
return exports.resolveContentNode(child, elementsMapping, localDependenciesPrefix, assetsPrefix);
}
});
}
return node;
};
//# sourceMappingURL=utils.js.map

@@ -40,2 +40,20 @@ "use strict";

var js_ast_1 = require("../../utils/js-ast");
exports.createPlugin = function (config) {
var _a = config || {}, _b = _a.importLibsChunkName, importLibsChunkName = _b === void 0 ? 'import-libs' : _b, _c = _a.importPackagesChunkName, importPackagesChunkName = _c === void 0 ? 'import-packages' : _c, _d = _a.importLocalsChunkName, importLocalsChunkName = _d === void 0 ? 'import-local' : _d, _e = _a.fileId, fileId = _e === void 0 ? null : _e;
var importPlugin = function (structure) { return __awaiter(_this, void 0, void 0, function () {
var dependencies, libraryDependencies, packageDependencies, localDependencies;
return __generator(this, function (_a) {
dependencies = structure.dependencies;
libraryDependencies = groupDependenciesByPackage(dependencies, 'library');
packageDependencies = groupDependenciesByPackage(dependencies, 'package');
localDependencies = groupDependenciesByPackage(dependencies, 'local');
addImportChunk(structure.chunks, libraryDependencies, importLibsChunkName, fileId);
addImportChunk(structure.chunks, packageDependencies, importPackagesChunkName, fileId);
addImportChunk(structure.chunks, localDependencies, importLocalsChunkName, fileId);
return [2 /*return*/, structure];
});
}); };
return importPlugin;
};
exports.default = exports.createPlugin();
var groupDependenciesByPackage = function (dependencies, packageType) {

@@ -77,20 +95,2 @@ var result = {};

};
exports.createPlugin = function (config) {
var _a = config || {}, _b = _a.importLibsChunkName, importLibsChunkName = _b === void 0 ? 'import-libs' : _b, _c = _a.importPackagesChunkName, importPackagesChunkName = _c === void 0 ? 'import-packages' : _c, _d = _a.importLocalsChunkName, importLocalsChunkName = _d === void 0 ? 'import-local' : _d, _e = _a.fileId, fileId = _e === void 0 ? null : _e;
var importPlugin = function (structure) { return __awaiter(_this, void 0, void 0, function () {
var dependencies, libraryDependencies, packageDependencies, localDependencies;
return __generator(this, function (_a) {
dependencies = structure.dependencies;
libraryDependencies = groupDependenciesByPackage(dependencies, 'library');
packageDependencies = groupDependenciesByPackage(dependencies, 'package');
localDependencies = groupDependenciesByPackage(dependencies, 'local');
addImportChunk(structure.chunks, libraryDependencies, importLibsChunkName, fileId);
addImportChunk(structure.chunks, packageDependencies, importPackagesChunkName, fileId);
addImportChunk(structure.chunks, localDependencies, importLocalsChunkName, fileId);
return [2 /*return*/, structure];
});
}); };
return importPlugin;
};
exports.default = exports.createPlugin();
//# sourceMappingURL=import-statements.js.map

@@ -15,3 +15,3 @@ "use strict";

path: 'react',
version: '16.6.3',
version: '16.8.3',
};

@@ -21,3 +21,3 @@ dependencies.ReactDOM = {

path: 'react-dom',
version: '16.6.3',
version: '16.8.3',
};

@@ -24,0 +24,0 @@ dependencies.Router = {

@@ -1,5 +0,2 @@

import * as t from '@babel/types';
import { ComponentPlugin, ComponentPluginFactory, StateIdentifier } from '../../../types';
import { ContentNode, PropDefinition, ComponentDependency } from '../../../../uidl-definitions/types';
export declare const generateTreeStructure: (content: ContentNode, propDefinitions: Record<string, PropDefinition>, stateIdentifiers: Record<string, StateIdentifier>, nodesLookup: Record<string, t.JSXElement>, dependencies: Record<string, ComponentDependency>) => t.JSXElement;
import { ComponentPlugin, ComponentPluginFactory } from '../../../types';
interface JSXConfig {

@@ -6,0 +3,0 @@ componentChunkName: string;

@@ -54,103 +54,2 @@ "use strict";

var helpers_1 = require("../../../utils/helpers");
/**
*
* @param tag the ref to the AST tag under construction
* @param key the key of the attribute that should be added on the current AST node
* @param value the value(string, number, bool) of the attribute that should be added on the current AST node
*/
var addAttributeToTag = function (tag, key, value) {
if (typeof value !== 'string') {
jsx_ast_1.addAttributeToJSXTag(tag, { name: key, value: value });
return;
}
if (value.startsWith('$props.')) {
var dynamicPropValue = value.replace('$props.', '');
jsx_ast_1.addDynamicPropOnJsxOpeningTag(tag, key, dynamicPropValue, 'props');
}
else if (value.startsWith('$state.')) {
var dynamicPropValue = value.replace('$state.', '');
jsx_ast_1.addDynamicPropOnJsxOpeningTag(tag, key, dynamicPropValue);
}
else if (value === '$item' || value === '$index') {
jsx_ast_1.addDynamicPropOnJsxOpeningTag(tag, key, value.slice(1));
}
else {
jsx_ast_1.addAttributeToJSXTag(tag, { name: key, value: value });
}
};
var addTextElementToTag = function (tag, text) {
if (text.startsWith('$props.') && !text.endsWith('$props.')) {
jsx_ast_1.addDynamicChild(tag, text.replace('$props.', ''), 'props');
}
else if (text.startsWith('$state.') && !text.endsWith('$state.')) {
jsx_ast_1.addDynamicChild(tag, text.replace('$state.', ''));
}
else if (text === '$item' || text === '$index') {
jsx_ast_1.addDynamicChild(tag, text.slice(1));
}
else {
jsx_ast_1.addChildJSXText(tag, text);
}
};
exports.generateTreeStructure = function (content, propDefinitions, stateIdentifiers, nodesLookup, dependencies) {
var type = content.type, children = content.children, key = content.key, attrs = content.attrs, dependency = content.dependency, events = content.events, repeat = content.repeat;
var mainTag = jsx_ast_1.generateASTDefinitionForJSXTag(type);
if (attrs) {
Object.keys(attrs).forEach(function (attrKey) {
addAttributeToTag(mainTag, attrKey, attrs[attrKey]);
});
}
if (dependency) {
// Make a copy to avoid reference leaking
dependencies[type] = __assign({}, dependency);
}
if (events) {
Object.keys(events).forEach(function (eventKey) {
utils_1.addEventHandlerToTag(mainTag, eventKey, events[eventKey], stateIdentifiers, propDefinitions);
});
}
if (repeat) {
var repeatContent = repeat.content, dataSource = repeat.dataSource, meta = repeat.meta;
var contentAST = exports.generateTreeStructure(repeatContent, propDefinitions, stateIdentifiers, nodesLookup, dependencies);
addAttributeToTag(contentAST, 'key', '$item');
var repeatAST = utils_1.makeRepeatStructureWithMap(dataSource, contentAST, meta);
mainTag.children.push(repeatAST);
}
if (children) {
children.forEach(function (child) {
if (!child) {
return;
}
if (typeof child === 'string') {
addTextElementToTag(mainTag, child);
return;
}
if (child.type === 'state') {
var _a = child.states, states = _a === void 0 ? [] : _a, stateKey_1 = child.key;
states.forEach(function (stateBranch) {
var stateContent = stateBranch.content;
var stateIdentifier = stateIdentifiers[stateKey_1];
if (!stateIdentifier) {
return;
}
if (typeof stateContent === 'string') {
var jsxExpression = jsx_ast_1.createConditionalJSXExpression(stateContent, stateBranch.value, stateIdentifier);
mainTag.children.push(jsxExpression);
}
else {
var stateChildSubTree = exports.generateTreeStructure(stateContent, propDefinitions, stateIdentifiers, nodesLookup, dependencies);
var jsxExpression = jsx_ast_1.createConditionalJSXExpression(stateChildSubTree, stateBranch.value, stateIdentifier);
mainTag.children.push(jsxExpression);
}
});
return;
}
var childTag = exports.generateTreeStructure(child, propDefinitions, stateIdentifiers, nodesLookup, dependencies);
jsx_ast_1.addChildJSXTag(mainTag, childTag);
});
}
// UIDL name should be unique
nodesLookup[key] = mainTag;
return mainTag;
};
exports.createPlugin = function (config) {

@@ -165,2 +64,3 @@ var _a = config || {}, _b = _a.componentChunkName, componentChunkName = _b === void 0 ? 'react-component' : _b, _c = _a.exportChunkName, exportChunkName = _c === void 0 ? 'export' : _c, _d = _a.importChunkName, importChunkName = _d === void 0 ? 'import' : _d;

path: 'react',
version: '16.8.3',
};

@@ -172,2 +72,3 @@ stateIdentifiers = {};

path: 'react',
version: '16.8.3',
meta: {

@@ -189,3 +90,3 @@ namedImport: true,

nodesLookup = {};
jsxTagStructure = exports.generateTreeStructure(uidl.content, uidl.propDefinitions || {}, stateIdentifiers, nodesLookup, dependencies);
jsxTagStructure = generateTreeStructure(uidl.content, uidl.propDefinitions || {}, stateIdentifiers, nodesLookup, dependencies);
pureComponent = utils_1.makePureComponent(uidl.name, stateIdentifiers, jsxTagStructure);

@@ -217,2 +118,63 @@ structure.chunks.push({

exports.default = exports.createPlugin();
var generateTreeStructure = function (content, propDefinitions, stateIdentifiers, nodesLookup, dependencies) {
var type = content.type, children = content.children, key = content.key, attrs = content.attrs, dependency = content.dependency, events = content.events, repeat = content.repeat;
var mainTag = jsx_ast_1.generateASTDefinitionForJSXTag(type);
if (attrs) {
Object.keys(attrs).forEach(function (attrKey) {
utils_1.addAttributeToTag(mainTag, attrKey, attrs[attrKey]);
});
}
if (dependency) {
// Make a copy to avoid reference leaking
dependencies[type] = __assign({}, dependency);
}
if (events) {
Object.keys(events).forEach(function (eventKey) {
utils_1.addEventHandlerToTag(mainTag, eventKey, events[eventKey], stateIdentifiers, propDefinitions);
});
}
if (repeat) {
var repeatContent = repeat.content, dataSource = repeat.dataSource, meta = repeat.meta;
var contentAST = generateTreeStructure(repeatContent, propDefinitions, stateIdentifiers, nodesLookup, dependencies);
utils_1.addAttributeToTag(contentAST, 'key', '$item');
var repeatAST = utils_1.makeRepeatStructureWithMap(dataSource, contentAST, meta);
mainTag.children.push(repeatAST);
}
if (children) {
children.forEach(function (child) {
if (!child) {
return;
}
if (typeof child === 'string') {
utils_1.addTextElementToTag(mainTag, child);
return;
}
if (child.type === 'state') {
var _a = child.states, states = _a === void 0 ? [] : _a, stateKey_1 = child.key;
states.forEach(function (stateBranch) {
var stateContent = stateBranch.content;
var stateIdentifier = stateIdentifiers[stateKey_1];
if (!stateIdentifier) {
return;
}
if (typeof stateContent === 'string') {
var jsxExpression = jsx_ast_1.createConditionalJSXExpression(stateContent, stateBranch.value, stateIdentifier);
mainTag.children.push(jsxExpression);
}
else {
var stateChildSubTree = generateTreeStructure(stateContent, propDefinitions, stateIdentifiers, nodesLookup, dependencies);
var jsxExpression = jsx_ast_1.createConditionalJSXExpression(stateChildSubTree, stateBranch.value, stateIdentifier);
mainTag.children.push(jsxExpression);
}
});
return;
}
var childTag = generateTreeStructure(child, propDefinitions, stateIdentifiers, nodesLookup, dependencies);
jsx_ast_1.addChildJSXTag(mainTag, childTag);
});
}
// UIDL name should be unique
nodesLookup[key] = mainTag;
return mainTag;
};
//# sourceMappingURL=index.js.map

@@ -11,1 +11,9 @@ import * as types from '@babel/types';

export declare const makeRepeatStructureWithMap: (dataSource: string | any[], content: types.JSXElement, meta?: any, t?: typeof types) => types.JSXExpressionContainer;
/**
*
* @param tag the ref to the AST tag under construction
* @param key the key of the attribute that should be added on the current AST node
* @param value the value(string, number, bool) of the attribute that should be added on the current AST node
*/
export declare const addAttributeToTag: (tag: types.JSXElement, key: string, value: any) => void;
export declare const addTextElementToTag: (tag: types.JSXElement, text: string) => void;

@@ -12,33 +12,3 @@ "use strict";

var js_ast_1 = require("../../../utils/js-ast");
var createStateChangeStatement = function (eventHandlerStatement, stateIdentifiers, t) {
if (t === void 0) { t = types; }
if (!eventHandlerStatement.modifies) {
console.warn("No state identifier referenced under the \"modifies\" field");
return null;
}
var stateKey = eventHandlerStatement.modifies;
var stateIdentifier = stateIdentifiers[stateKey];
if (!stateIdentifier) {
console.warn("No state hook was found for \"" + stateKey + "\"");
return null;
}
var stateSetterArgument = eventHandlerStatement.newState === '$toggle'
? t.unaryExpression('!', t.identifier(stateIdentifier.key))
: js_ast_1.convertValueToLiteral(eventHandlerStatement.newState, stateIdentifier.type);
return t.expressionStatement(t.callExpression(t.identifier(stateIdentifier.setter), [stateSetterArgument]));
};
var createPropCallStatement = function (eventHandlerStatement, propDefinitions, t) {
if (t === void 0) { t = types; }
var propFunctionKey = eventHandlerStatement.calls, _a = eventHandlerStatement.args, args = _a === void 0 ? [] : _a;
if (!propFunctionKey) {
console.warn("No prop definition referenced under the \"calls\" field");
return null;
}
var propDefinition = propDefinitions[propFunctionKey];
if (!propDefinition || propDefinition.type !== 'func') {
console.warn("No prop definition was found for \"" + propFunctionKey + "\"");
return null;
}
return t.expressionStatement(t.callExpression(t.identifier('props.' + propFunctionKey), args.map(function (arg) { return js_ast_1.convertValueToLiteral(arg); }).slice()));
};
var jsx_ast_1 = require("../../../utils/jsx-ast");
// Adds all the event handlers and all the instructions for each event handler

@@ -77,2 +47,33 @@ // in case there is more than one specified in the UIDL

};
var createPropCallStatement = function (eventHandlerStatement, propDefinitions, t) {
if (t === void 0) { t = types; }
var propFunctionKey = eventHandlerStatement.calls, _a = eventHandlerStatement.args, args = _a === void 0 ? [] : _a;
if (!propFunctionKey) {
console.warn("No prop definition referenced under the \"calls\" field");
return null;
}
var propDefinition = propDefinitions[propFunctionKey];
if (!propDefinition || propDefinition.type !== 'func') {
console.warn("No prop definition was found for \"" + propFunctionKey + "\"");
return null;
}
return t.expressionStatement(t.callExpression(t.identifier('props.' + propFunctionKey), args.map(function (arg) { return js_ast_1.convertValueToLiteral(arg); }).slice()));
};
var createStateChangeStatement = function (eventHandlerStatement, stateIdentifiers, t) {
if (t === void 0) { t = types; }
if (!eventHandlerStatement.modifies) {
console.warn("No state identifier referenced under the \"modifies\" field");
return null;
}
var stateKey = eventHandlerStatement.modifies;
var stateIdentifier = stateIdentifiers[stateKey];
if (!stateIdentifier) {
console.warn("No state hook was found for \"" + stateKey + "\"");
return null;
}
var stateSetterArgument = eventHandlerStatement.newState === '$toggle'
? t.unaryExpression('!', t.identifier(stateIdentifier.key))
: js_ast_1.convertValueToLiteral(eventHandlerStatement.newState, stateIdentifier.type);
return t.expressionStatement(t.callExpression(t.identifier(stateIdentifier.setter), [stateSetterArgument]));
};
exports.makePureComponent = function (name, stateIdentifiers, jsxTagTree, t) {

@@ -113,2 +114,42 @@ if (t === void 0) { t = types; }

};
/**
*
* @param tag the ref to the AST tag under construction
* @param key the key of the attribute that should be added on the current AST node
* @param value the value(string, number, bool) of the attribute that should be added on the current AST node
*/
exports.addAttributeToTag = function (tag, key, value) {
if (typeof value !== 'string') {
jsx_ast_1.addAttributeToJSXTag(tag, { name: key, value: value });
return;
}
if (value.startsWith('$props.')) {
var dynamicPropValue = value.replace('$props.', '');
jsx_ast_1.addDynamicPropOnJsxOpeningTag(tag, key, dynamicPropValue, 'props');
}
else if (value.startsWith('$state.')) {
var dynamicPropValue = value.replace('$state.', '');
jsx_ast_1.addDynamicPropOnJsxOpeningTag(tag, key, dynamicPropValue);
}
else if (value === '$item' || value === '$index') {
jsx_ast_1.addDynamicPropOnJsxOpeningTag(tag, key, value.slice(1));
}
else {
jsx_ast_1.addAttributeToJSXTag(tag, { name: key, value: value });
}
};
exports.addTextElementToTag = function (tag, text) {
if (text.startsWith('$props.') && !text.endsWith('$props.')) {
jsx_ast_1.addDynamicChild(tag, text.replace('$props.', ''), 'props');
}
else if (text.startsWith('$state.') && !text.endsWith('$state.')) {
jsx_ast_1.addDynamicChild(tag, text.replace('$state.', ''));
}
else if (text === '$item' || text === '$index') {
jsx_ast_1.addDynamicChild(tag, text.slice(1));
}
else {
jsx_ast_1.addChildJSXText(tag, text);
}
};
//# sourceMappingURL=utils.js.map

@@ -49,2 +49,25 @@ "use strict";

var js_ast_1 = require("../../utils/js-ast");
exports.createPlugin = function (config) {
var _a = (config || {}).componentChunkName, componentChunkName = _a === void 0 ? 'react-component' : _a;
/**
* Generate the inlines stlye definition as a AST block which will represent the
* defined styles of this component in UIDL
*
* @param structure : ComponentStructure
*/
var reactInlineStyleComponentPlugin = function (structure) { return __awaiter(_this, void 0, void 0, function () {
var uidl, chunks, componentChunk;
return __generator(this, function (_a) {
uidl = structure.uidl, chunks = structure.chunks;
componentChunk = chunks.find(function (chunk) { return chunk.name === componentChunkName; });
if (!componentChunk) {
return [2 /*return*/, structure];
}
enhanceJSXWithStyles(uidl.content, componentChunk.meta.nodesLookup);
return [2 /*return*/, structure];
});
}); };
return reactInlineStyleComponentPlugin;
};
exports.default = exports.createPlugin();
var prepareDynamicProps = function (styles) {

@@ -91,25 +114,2 @@ return Object.keys(styles).reduce(function (acc, key) {

};
exports.createPlugin = function (config) {
var _a = (config || {}).componentChunkName, componentChunkName = _a === void 0 ? 'react-component' : _a;
/**
* Generate the inlines stlye definition as a AST block which will represent the
* defined styles of this component in UIDL
*
* @param structure : ComponentStructure
*/
var reactInlineStyleComponentPlugin = function (structure) { return __awaiter(_this, void 0, void 0, function () {
var uidl, chunks, componentChunk;
return __generator(this, function (_a) {
uidl = structure.uidl, chunks = structure.chunks;
componentChunk = chunks.find(function (chunk) { return chunk.name === componentChunkName; });
if (!componentChunk) {
return [2 /*return*/, structure];
}
enhanceJSXWithStyles(uidl.content, componentChunk.meta.nodesLookup);
return [2 /*return*/, structure];
});
}); };
return reactInlineStyleComponentPlugin;
};
exports.default = exports.createPlugin();
//# sourceMappingURL=react-inline-styles.js.map

@@ -61,40 +61,2 @@ "use strict";

var helpers_1 = require("../../utils/helpers");
var prepareDynamicProps = function (styles) {
return Object.keys(styles).reduce(function (acc, key) {
var value = styles[key];
if (typeof value === 'string' && value.startsWith('$props.')) {
acc[key] = new js_ast_1.ParsedASTNode(t.arrowFunctionExpression([t.identifier('props')], t.memberExpression(t.identifier('props'), t.identifier(value.replace('$props.', '')))));
}
else {
acc[key] = styles[key];
}
return acc;
}, {});
};
var generateStyleTagStrings = function (content, nodesLookup) {
var accumulator = {};
var styles = content.styles, children = content.children, key = content.key, repeat = content.repeat;
if (styles) {
var root = nodesLookup[key];
var className = helpers_1.cammelCaseToDashCase(key);
accumulator[className] = prepareDynamicProps(styles);
// addClassStringOnJSXTag(root.node, className)
jsx_ast_1.addDynamicPropOnJsxOpeningTag(root, 'className', "classes['" + className + "']", 'props');
}
if (repeat) {
var items = generateStyleTagStrings(repeat.content, nodesLookup);
accumulator = __assign({}, accumulator, items);
}
if (children) {
children.forEach(function (child) {
if (typeof child === 'string') {
return;
}
// only call on children if they are not strings
var items = generateStyleTagStrings(child, nodesLookup);
accumulator = __assign({}, accumulator, items);
});
}
return accumulator;
};
exports.createPlugin = function (config) {

@@ -158,2 +120,40 @@ var _a = config || {}, _b = _a.componentChunkName, componentChunkName = _b === void 0 ? 'react-component' : _b, _c = _a.importChunkName, importChunkName = _c === void 0 ? 'import' : _c, _d = _a.styleChunkName, styleChunkName = _d === void 0 ? 'jss-style-definition' : _d, _e = _a.exportChunkName, exportChunkName = _e === void 0 ? 'export' : _e, _f = _a.jssDeclarationName, jssDeclarationName = _f === void 0 ? 'style' : _f;

exports.default = exports.createPlugin();
var prepareDynamicProps = function (styles) {
return Object.keys(styles).reduce(function (acc, key) {
var value = styles[key];
if (typeof value === 'string' && value.startsWith('$props.')) {
acc[key] = new js_ast_1.ParsedASTNode(t.arrowFunctionExpression([t.identifier('props')], t.memberExpression(t.identifier('props'), t.identifier(value.replace('$props.', '')))));
}
else {
acc[key] = styles[key];
}
return acc;
}, {});
};
var generateStyleTagStrings = function (content, nodesLookup) {
var accumulator = {};
var styles = content.styles, children = content.children, key = content.key, repeat = content.repeat;
if (styles) {
var root = nodesLookup[key];
var className = helpers_1.cammelCaseToDashCase(key);
accumulator[className] = prepareDynamicProps(styles);
// addClassStringOnJSXTag(root.node, className)
jsx_ast_1.addDynamicPropOnJsxOpeningTag(root, 'className', "classes['" + className + "']", 'props');
}
if (repeat) {
var items = generateStyleTagStrings(repeat.content, nodesLookup);
accumulator = __assign({}, accumulator, items);
}
if (children) {
children.forEach(function (child) {
if (typeof child === 'string') {
return;
}
// only call on children if they are not strings
var items = generateStyleTagStrings(child, nodesLookup);
accumulator = __assign({}, accumulator, items);
});
}
return accumulator;
};
//# sourceMappingURL=react-jss.js.map

@@ -63,2 +63,3 @@ "use strict";

path: 'prop-types',
version: '15.7.2',
};

@@ -65,0 +66,0 @@ chunks.push({

@@ -47,2 +47,30 @@ "use strict";

var helpers_1 = require("../../utils/helpers");
exports.createPlugin = function (config) {
var _a = (config || {}).componentChunkName, componentChunkName = _a === void 0 ? 'react-component' : _a;
var reactStyledJSXChunkPlugin = function (structure) { return __awaiter(_this, void 0, void 0, function () {
var uidl, chunks, content, componentChunk, jsxNodesLookup, styleJSXString, jsxASTNodeReference, rootJSXNode;
return __generator(this, function (_a) {
uidl = structure.uidl, chunks = structure.chunks;
content = uidl.content;
componentChunk = chunks.find(function (chunk) { return chunk.name === componentChunkName; });
if (!componentChunk) {
return [2 /*return*/, structure];
}
jsxNodesLookup = componentChunk.meta.nodesLookup;
styleJSXString = generateStyledJSXString(content, jsxNodesLookup);
if (!styleJSXString || !styleJSXString.length) {
return [2 /*return*/, structure];
}
jsxASTNodeReference = jsx_ast_1.generateStyledJSXTag(styleJSXString.join('\n'));
rootJSXNode = jsxNodesLookup[content.key];
// We have the ability to insert the tag into the existig JSX structure, or do something else with it.
// Here we take the JSX <style> tag and we insert it as the last child of the JSX structure
// inside the React Component
rootJSXNode.children.push(jsxASTNodeReference);
return [2 /*return*/, structure];
});
}); };
return reactStyledJSXChunkPlugin;
};
exports.default = exports.createPlugin();
var prepareDynamicProps = function (styles) {

@@ -103,30 +131,2 @@ return Object.keys(styles).reduce(function (acc, key) {

};
exports.createPlugin = function (config) {
var _a = (config || {}).componentChunkName, componentChunkName = _a === void 0 ? 'react-component' : _a;
var reactStyledJSXChunkPlugin = function (structure) { return __awaiter(_this, void 0, void 0, function () {
var uidl, chunks, content, componentChunk, jsxNodesLookup, styleJSXString, jsxASTNodeReference, rootJSXNode;
return __generator(this, function (_a) {
uidl = structure.uidl, chunks = structure.chunks;
content = uidl.content;
componentChunk = chunks.find(function (chunk) { return chunk.name === componentChunkName; });
if (!componentChunk) {
return [2 /*return*/, structure];
}
jsxNodesLookup = componentChunk.meta.nodesLookup;
styleJSXString = generateStyledJSXString(content, jsxNodesLookup);
if (!styleJSXString || !styleJSXString.length) {
return [2 /*return*/, structure];
}
jsxASTNodeReference = jsx_ast_1.generateStyledJSXTag(styleJSXString.join('\n'));
rootJSXNode = jsxNodesLookup[content.key];
// We have the ability to insert the tag into the existig JSX structure, or do something else with it.
// Here we take the JSX <style> tag and we insert it as the last child of the JSX structure
// inside the React Component
rootJSXNode.children.push(jsxASTNodeReference);
return [2 /*return*/, structure];
});
}); };
return reactStyledJSXChunkPlugin;
};
exports.default = exports.createPlugin();
//# sourceMappingURL=react-styled-jsx.js.map

@@ -46,2 +46,31 @@ "use strict";

var helpers_1 = require("../../utils/helpers");
exports.createPlugin = function (config) {
var _a = config || {}, _b = _a.chunkName, chunkName = _b === void 0 ? 'vue-component-style-chunk' : _b, _c = _a.vueTemplateChunk, vueTemplateChunk = _c === void 0 ? 'vue-component-template-chunk' : _c, _d = _a.styleFileId, styleFileId = _d === void 0 ? null : _d;
var vueComponentStyleChunkPlugin = function (structure) { return __awaiter(_this, void 0, void 0, function () {
var uidl, chunks, content, templateChunk, templateLookup, jssStylesArray;
return __generator(this, function (_a) {
uidl = structure.uidl, chunks = structure.chunks;
content = uidl.content;
templateChunk = chunks.filter(function (chunk) { return chunk.name === vueTemplateChunk; })[0];
templateLookup = templateChunk.meta.lookup;
jssStylesArray = generateStyleTagStrings(content, templateLookup);
chunks.push({
type: 'string',
name: chunkName,
meta: {
fileId: styleFileId,
},
wrap: styleFileId
? undefined
: function (generatedContent) {
return "<style>\n" + generatedContent + "</style>";
},
content: jssStylesArray.join('\n'),
});
return [2 /*return*/, structure];
});
}); };
return vueComponentStyleChunkPlugin;
};
exports.default = exports.createPlugin();
var filterOutDynamicStyles = function (styles) {

@@ -98,31 +127,2 @@ if (!styles) {

};
exports.createPlugin = function (config) {
var _a = config || {}, _b = _a.chunkName, chunkName = _b === void 0 ? 'vue-component-style-chunk' : _b, _c = _a.vueTemplateChunk, vueTemplateChunk = _c === void 0 ? 'vue-component-template-chunk' : _c, _d = _a.styleFileId, styleFileId = _d === void 0 ? null : _d;
var vueComponentStyleChunkPlugin = function (structure) { return __awaiter(_this, void 0, void 0, function () {
var uidl, chunks, content, templateChunk, templateLookup, jssStylesArray;
return __generator(this, function (_a) {
uidl = structure.uidl, chunks = structure.chunks;
content = uidl.content;
templateChunk = chunks.filter(function (chunk) { return chunk.name === vueTemplateChunk; })[0];
templateLookup = templateChunk.meta.lookup;
jssStylesArray = generateStyleTagStrings(content, templateLookup);
chunks.push({
type: 'string',
name: chunkName,
meta: {
fileId: styleFileId,
},
wrap: styleFileId
? undefined
: function (generatedContent) {
return "<style>\n" + generatedContent + "</style>";
},
content: jssStylesArray.join('\n'),
});
return [2 /*return*/, structure];
});
}); };
return vueComponentStyleChunkPlugin;
};
exports.default = exports.createPlugin();
//# sourceMappingURL=vue-style-chunk.js.map

@@ -51,4 +51,5 @@ "use strict";

};
Object.defineProperty(exports, "__esModule", { value: true });
var _a;
var _this = this;
Object.defineProperty(exports, "__esModule", { value: true });
var pipeline_1 = require("../pipeline");

@@ -63,4 +64,4 @@ var react_base_component_1 = require("../plugins/react/react-base-component");

var html_mapping_json_1 = __importDefault(require("../../uidl-definitions/elements-mapping/html-mapping.json"));
var elements_mapping_json_1 = __importDefault(require("./elements-mapping.json"));
var utils_1 = require("./utils");
var react_mapping_json_1 = __importDefault(require("./react-mapping.json"));
var types_1 = require("../types");
var configuredReactJSX = react_base_component_1.createPlugin({

@@ -91,8 +92,8 @@ componentChunkName: 'react-component',

});
var stylePlugins = {
InlineStyles: configuredReactInlineStyles,
StyledJSX: configuredReactStyledJSX,
JSS: configuredReactJSS,
CSSModules: configuredReactCSSModules,
};
var stylePlugins = (_a = {},
_a[types_1.ReactComponentStylingFlavors.InlineStyles] = configuredReactInlineStyles,
_a[types_1.ReactComponentStylingFlavors.StyledJSX] = configuredReactStyledJSX,
_a[types_1.ReactComponentStylingFlavors.JSS] = configuredReactJSS,
_a[types_1.ReactComponentStylingFlavors.CSSModules] = configuredReactCSSModules,
_a);
/**

@@ -113,4 +114,4 @@ * Runs a component pipeline and generates all the necessary parts (ex: js, css) as well as the list of dependencies

stylePlugin = stylePlugins[variation];
resolver = new pipeline_1.Resolver(__assign({}, html_mapping_json_1.default, elements_mapping_json_1.default, customMapping));
assemblyLine = new pipeline_1.ComponentAssemblyLine([
resolver = new pipeline_1.Resolver(__assign({}, html_mapping_json_1.default, react_mapping_json_1.default, customMapping));
assemblyLine = new pipeline_1.AssemblyLine([
configuredReactJSX,

@@ -126,3 +127,3 @@ stylePlugin,

result = _a.sent();
chunksByFileId = utils_1.groupChunksByFileId(result.chunks);
chunksByFileId = assemblyLine.groupChunksByFileId(result.chunks);
code = chunksLinker.link(chunksByFileId.default);

@@ -129,0 +130,0 @@ css = chunksLinker.link(chunksByFileId['component-styles']);

@@ -1,5 +0,5 @@

import { ReactComponentFlavors, ComponentGenerator } from '../types';
import { ReactComponentStylingFlavors, ComponentGenerator } from '../types';
import { ElementsMapping } from '../../uidl-definitions/types';
interface ReactGeneratorFactoryParams {
variation?: ReactComponentFlavors;
variation?: ReactComponentStylingFlavors;
customMapping?: ElementsMapping;

@@ -6,0 +6,0 @@ }

@@ -52,34 +52,11 @@ "use strict";

var html_mapping_json_1 = __importDefault(require("../../uidl-definitions/elements-mapping/html-mapping.json"));
var elements_mapping_json_1 = __importDefault(require("./elements-mapping.json"));
var utils_1 = require("./utils");
var chooseStylePlugin = function (variation) {
switch (variation) {
case types_1.ReactComponentFlavors.CSSModules:
return react_css_modules_1.createPlugin({
componentChunkName: 'react-component',
});
case types_1.ReactComponentFlavors.InlineStyles:
return react_inline_styles_1.createPlugin({
componentChunkName: 'react-component',
});
case types_1.ReactComponentFlavors.JSS:
return react_jss_1.createPlugin({
componentChunkName: 'react-component',
importChunkName: 'import',
exportChunkName: 'export',
});
case types_1.ReactComponentFlavors.StyledJSX:
return react_styled_jsx_1.createPlugin({
componentChunkName: 'react-component',
});
}
};
var react_mapping_json_1 = __importDefault(require("./react-mapping.json"));
var createReactGenerator = function (params) {
if (params === void 0) { params = {}; }
var _a = params.variation, variation = _a === void 0 ? types_1.ReactComponentFlavors.CSSModules : _a, _b = params.customMapping, customMapping = _b === void 0 ? {} : _b;
var _a = params.variation, variation = _a === void 0 ? types_1.ReactComponentStylingFlavors.InlineStyles : _a, _b = params.customMapping, customMapping = _b === void 0 ? {} : _b;
var resolver = new pipeline_1.Resolver();
resolver.addMapping(html_mapping_json_1.default);
resolver.addMapping(elements_mapping_json_1.default);
resolver.addMapping(react_mapping_json_1.default);
resolver.addMapping(customMapping);
var assemblyLine = new pipeline_1.ComponentAssemblyLine();
var assemblyLine = new pipeline_1.AssemblyLine();
assemblyLine.addPlugin(react_base_component_1.createPlugin({

@@ -109,3 +86,3 @@ componentChunkName: 'react-component',

result = _a.sent();
chunksByFileId = utils_1.groupChunksByFileId(result.chunks);
chunksByFileId = assemblyLine.groupChunksByFileId(result.chunks);
code = chunksLinker.link(chunksByFileId.default);

@@ -129,3 +106,29 @@ externalCSS = chunksLinker.link(chunksByFileId['component-styles']);

};
var chooseStylePlugin = function (variation) {
switch (variation) {
case types_1.ReactComponentStylingFlavors.CSSModules:
return react_css_modules_1.createPlugin({
componentChunkName: 'react-component',
});
case types_1.ReactComponentStylingFlavors.InlineStyles:
return react_inline_styles_1.createPlugin({
componentChunkName: 'react-component',
});
case types_1.ReactComponentStylingFlavors.JSS:
return react_jss_1.createPlugin({
componentChunkName: 'react-component',
importChunkName: 'import',
exportChunkName: 'export',
});
case types_1.ReactComponentStylingFlavors.StyledJSX:
return react_styled_jsx_1.createPlugin({
componentChunkName: 'react-component',
});
default:
return react_inline_styles_1.createPlugin({
componentChunkName: 'react-component',
});
}
};
exports.default = createReactGenerator;
//# sourceMappingURL=react-component.js.map

@@ -57,5 +57,5 @@ "use strict";

var html_mapping_json_1 = __importDefault(require("../../uidl-definitions/elements-mapping/html-mapping.json"));
var elements_mapping_json_1 = __importDefault(require("./elements-mapping.json"));
var react_mapping_json_1 = __importDefault(require("./react-mapping.json"));
var createRouterComponentGenerator = function () {
var resolver = new pipeline_1.Resolver(__assign({}, html_mapping_json_1.default, elements_mapping_json_1.default));
var resolver = new pipeline_1.Resolver(__assign({}, html_mapping_json_1.default, react_mapping_json_1.default));
var configureAppRouterComponent = react_app_routing_1.createPlugin({

@@ -69,6 +69,3 @@ componentChunkName: 'app-router-component',

});
var assemblyLine = new pipeline_1.ComponentAssemblyLine([
configureAppRouterComponent,
configureImportStatements,
]);
var assemblyLine = new pipeline_1.AssemblyLine([configureAppRouterComponent, configureImportStatements]);
var chunksLinker = new pipeline_1.Builder();

@@ -75,0 +72,0 @@ var generateComponent = function (uidl) { return __awaiter(_this, void 0, void 0, function () {

@@ -94,2 +94,14 @@ "use strict";

};
exports.addAttributeToJSXTag = function (jsxNode, attribute, t) {
if (t === void 0) { t = types; }
var nameOfAttribute = t.jsxIdentifier(attribute.name);
var attributeDefinition;
if (typeof attribute.value === 'boolean') {
attributeDefinition = t.jsxAttribute(nameOfAttribute);
}
else {
attributeDefinition = t.jsxAttribute(nameOfAttribute, getProperAttributeValueAssignment(attribute.value));
}
jsxNode.openingElement.attributes.push(attributeDefinition);
};
/**

@@ -118,14 +130,2 @@ * node must be a AST node element of type JSXElement (babel-types) or

};
exports.addAttributeToJSXTag = function (jsxNode, attribute, t) {
if (t === void 0) { t = types; }
var nameOfAttribute = t.jsxIdentifier(attribute.name);
var attributeDefinition;
if (typeof attribute.value === 'boolean') {
attributeDefinition = t.jsxAttribute(nameOfAttribute);
}
else {
attributeDefinition = t.jsxAttribute(nameOfAttribute, getProperAttributeValueAssignment(attribute.value));
}
jsxNode.openingElement.attributes.push(attributeDefinition);
};
/**

@@ -132,0 +132,0 @@ * Generates the AST definiton (without start/end position) for a JSX tag

@@ -15,1 +15,2 @@ import { StateDefinition } from '../../uidl-definitions/types';

};
export declare const prefixPlaygroundAssetsURL: (prefix: string, originalString: string) => string;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var constants_1 = require("../constants");
/**

@@ -36,2 +37,11 @@ * A couple of different cases which need to be handled

};
exports.prefixPlaygroundAssetsURL = function (prefix, originalString) {
if (!originalString || !originalString.startsWith(constants_1.ASSETS_IDENTIFIER)) {
return originalString;
}
if (originalString.startsWith('/')) {
return prefix + originalString;
}
return prefix + "/" + originalString;
};
//# sourceMappingURL=uidl-utils.js.map

@@ -58,7 +58,7 @@ "use strict";

var html_mapping_json_1 = __importDefault(require("../../uidl-definitions/elements-mapping/html-mapping.json"));
var elements_mapping_json_1 = __importDefault(require("./elements-mapping.json"));
var vue_mapping_json_1 = __importDefault(require("./vue-mapping.json"));
var createVueGenerator = function (_a) {
var customMapping = (_a === void 0 ? { customMapping: {} } : _a).customMapping;
var resolver = new pipeline_1.Resolver(__assign({}, html_mapping_json_1.default, elements_mapping_json_1.default, customMapping));
var assemblyLine = new pipeline_1.ComponentAssemblyLine([
var resolver = new pipeline_1.Resolver(__assign({}, html_mapping_json_1.default, vue_mapping_json_1.default, customMapping));
var assemblyLine = new pipeline_1.AssemblyLine([
vue_base_component_1.createPlugin({

@@ -65,0 +65,0 @@ jsFileId: 'vuejs',

@@ -57,7 +57,7 @@ "use strict";

var html_mapping_json_1 = __importDefault(require("../../uidl-definitions/elements-mapping/html-mapping.json"));
var elements_mapping_json_1 = __importDefault(require("./elements-mapping.json"));
var vue_mapping_json_1 = __importDefault(require("./vue-mapping.json"));
var createVuePipeline = function (_a) {
var customMapping = (_a === void 0 ? {} : _a).customMapping;
var resolver = new pipeline_1.Resolver(__assign({}, html_mapping_json_1.default, elements_mapping_json_1.default, customMapping));
var assemblyLine = new pipeline_1.ComponentAssemblyLine([
var resolver = new pipeline_1.Resolver(__assign({}, html_mapping_json_1.default, vue_mapping_json_1.default, customMapping));
var assemblyLine = new pipeline_1.AssemblyLine([
vue_router_1.createPlugin({

@@ -64,0 +64,0 @@ codeChunkName: 'vue-router',

@@ -53,3 +53,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var elements_mapping_json_1 = __importDefault(require("./elements-mapping.json"));
var react_project_mapping_json_1 = __importDefault(require("./react-project-mapping.json"));
var react_router_1 = __importDefault(require("../../component-generators/react/react-router"));

@@ -61,6 +61,7 @@ var react_component_1 = __importDefault(require("../../component-generators/react/react-component"));

var utils_1 = require("./utils");
var constants_1 = require("./constants");
exports.default = (function (uidl, options) {
if (options === void 0) { options = {}; }
return __awaiter(_this, void 0, void 0, function () {
var reactGenerator, routingComponentGenerator, componentsFolder, pagesFolder, staticFolder, srcFolder, distFolder, allDependencies, _a, components, root, states, stateDefinitions, assetsPrefix, result, routerDefinitions, manifestJSON, manifestFile, htmlIndexContent, htmlFile, rootCopy, routingComponent, sourcePackageJson, externalDep, packageFile;
var reactGenerator, routingComponentGenerator, componentsFolder, pagesFolder, staticFolder, srcFolder, distFolder, allDependencies, _a, components, root, states, stateDefinitions, result, routerDefinitions, manifestJSON, manifestFile, htmlIndexContent, htmlFile, rootCopy, routingComponent, sourcePackageJson, packageJSON, packageFile;
var _this = this;

@@ -71,3 +72,3 @@ return __generator(this, function (_b) {

reactGenerator = react_component_1.default({
variation: types_1.ReactComponentFlavors.CSSModules,
variation: types_1.ReactComponentStylingFlavors.CSSModules,
});

@@ -96,3 +97,3 @@ routingComponentGenerator = react_router_1.default();

distFolder = {
name: options.distPath || 'dist',
name: options.distPath || constants_1.DEFAULT_OUTPUT_FOLDER,
files: [],

@@ -102,3 +103,3 @@ subFolders: [srcFolder],

// Step 2: Initialization with project specific mappings and of other data structures
reactGenerator.addMapping(elements_mapping_json_1.default);
reactGenerator.addMapping(react_project_mapping_json_1.default);
if (options.customMapping) {

@@ -111,6 +112,5 @@ reactGenerator.addMapping(options.customMapping);

stateDefinitions = root.stateDefinitions;
assetsPrefix = '/static';
result = {
outputFolder: distFolder,
assetsPath: assetsPrefix,
assetsPath: 'src' + constants_1.ASSETS_PREFIX,
};

@@ -126,3 +126,3 @@ if (!states || !stateDefinitions) {

if (uidl.globals.manifest) {
manifestJSON = generator_utils_1.createManifestJSON(uidl.globals.manifest, uidl.name);
manifestJSON = generator_utils_1.createManifestJSON(uidl.globals.manifest, uidl.name, constants_1.ASSETS_PREFIX);
manifestFile = {

@@ -174,2 +174,3 @@ name: 'manifest',

localDependenciesPrefix: '../components/',
assetsPrefix: constants_1.ASSETS_PREFIX,
})];

@@ -210,3 +211,5 @@ case 1:

component = components[componentName];
return [4 /*yield*/, reactGenerator.generateComponent(component)];
return [4 /*yield*/, reactGenerator.generateComponent(component, {
assetsPrefix: constants_1.ASSETS_PREFIX,
})];
case 1:

@@ -240,12 +243,11 @@ compiledComponent = _a.sent();

sourcePackageJson = options.sourcePackageJson;
if (sourcePackageJson) {
externalDep = generator_utils_1.extractExternalDependencies(allDependencies);
sourcePackageJson.dependencies = __assign({}, sourcePackageJson.dependencies, externalDep);
packageFile = {
name: 'package',
extension: '.json',
content: JSON.stringify(sourcePackageJson, null, 2),
};
distFolder.files.push(packageFile);
}
packageJSON = generator_utils_1.createPackageJSON(sourcePackageJson || constants_1.DEFAULT_PACKAGE_JSON, allDependencies, {
projectName: uidl.name,
});
packageFile = {
name: 'package',
extension: '.json',
content: JSON.stringify(packageJSON, null, 2),
};
distFolder.files.push(packageFile);
return [2 /*return*/, result];

@@ -252,0 +254,0 @@ }

@@ -5,2 +5,4 @@ "use strict";

var xml_1 = require("../../component-generators/utils/xml");
var constants_1 = require("./constants");
var uidl_utils_1 = require("../../component-generators/utils/uidl-utils");
exports.createHtmlIndexFile = function (uidl) {

@@ -34,3 +36,4 @@ var _a = uidl.globals, settings = _a.settings, meta = _a.meta, assets = _a.assets, manifest = _a.manifest;

Object.keys(metaItem).forEach(function (key) {
metaTag.attr(key, metaItem[key]);
var prefixedURL = uidl_utils_1.prefixPlaygroundAssetsURL(constants_1.ASSETS_PREFIX, metaItem[key]);
metaTag.attr(key, prefixedURL);
});

@@ -40,7 +43,8 @@ headNode.append(metaTag);

assets.forEach(function (asset) {
var assetPath = uidl_utils_1.prefixPlaygroundAssetsURL(constants_1.ASSETS_PREFIX, asset.path);
// link stylesheet (external css, font)
if ((asset.type === 'style' || asset.type === 'font') && asset.path) {
if ((asset.type === 'style' || asset.type === 'font') && assetPath) {
var linkTag = xml_1.createXMLNode('link', { selfClosing: true });
linkTag.attr('rel', 'stylesheet');
linkTag.attr('href', asset.path);
linkTag.attr('href', assetPath);
headNode.append(linkTag);

@@ -60,4 +64,4 @@ }

scriptTag.attr('type', 'text/javascript');
if (asset.path) {
scriptTag.attr('src', asset.path);
if (assetPath) {
scriptTag.attr('src', assetPath);
if (asset.meta && asset.meta.defer) {

@@ -81,6 +85,6 @@ scriptTag.attr('defer', true);

// icon
if (asset.type === 'icon' && asset.path) {
if (asset.type === 'icon' && assetPath) {
var iconTag_1 = xml_1.createXMLNode('link', { selfClosing: true });
iconTag_1.attr('rel', 'shortcut icon');
iconTag_1.attr('href', asset.path);
iconTag_1.attr('href', assetPath);
if (typeof asset.meta === 'object') {

@@ -87,0 +91,0 @@ var assetMeta_1 = asset.meta;

@@ -58,7 +58,8 @@ "use strict";

var utils_1 = require("./utils");
var elements_mapping_json_1 = __importDefault(require("./elements-mapping.json"));
var next_mapping_json_1 = __importDefault(require("./next-mapping.json"));
var constants_1 = require("./constants");
exports.default = (function (uidl, options) {
if (options === void 0) { options = {}; }
return __awaiter(_this, void 0, void 0, function () {
var reactGenerator, pagesFolder, componentsFolder, staticFolder, distFolder, allDependencies, assetsPrefix, components, root, states, stateDefinitions, result, routerDefinitions, manifestJSON, manifestFile, documentComponent, file, sourcePackageJson, externalDep, packageFile;
var reactGenerator, pagesFolder, componentsFolder, staticFolder, distFolder, allDependencies, components, root, states, stateDefinitions, result, routerDefinitions, manifestJSON, manifestFile, documentComponent, file, sourcePackageJson, packageJSON, packageFile;
var _this = this;

@@ -69,4 +70,4 @@ return __generator(this, function (_a) {

reactGenerator = react_component_1.default({
variation: types_1.ReactComponentFlavors.StyledJSX,
customMapping: elements_mapping_json_1.default,
variation: types_1.ReactComponentStylingFlavors.StyledJSX,
customMapping: next_mapping_json_1.default,
});

@@ -89,3 +90,3 @@ pagesFolder = {

distFolder = {
name: options.distPath || 'dist',
name: options.distPath || constants_1.DEFAULT_OUTPUT_FOLDER,
files: [],

@@ -95,3 +96,3 @@ subFolders: [pagesFolder, componentsFolder, staticFolder],

// Step 2: Initialization with project specific mappings and of other data structures
reactGenerator.addMapping(elements_mapping_json_1.default);
reactGenerator.addMapping(next_mapping_json_1.default);
if (options.customMapping) {

@@ -101,3 +102,2 @@ reactGenerator.addMapping(options.customMapping);

allDependencies = {};
assetsPrefix = '/static';
components = uidl.components, root = uidl.root;

@@ -108,3 +108,3 @@ states = root.content.states;

outputFolder: distFolder,
assetsPath: assetsPrefix,
assetsPath: constants_1.ASSETS_PREFIX.slice(1),
};

@@ -120,3 +120,3 @@ if (!states || !stateDefinitions) {

if (uidl.globals.manifest) {
manifestJSON = generator_utils_1.createManifestJSON(uidl.globals.manifest, uidl.name);
manifestJSON = generator_utils_1.createManifestJSON(uidl.globals.manifest, uidl.name, constants_1.ASSETS_PREFIX);
manifestFile = {

@@ -162,3 +162,3 @@ name: 'manifest',

localDependenciesPrefix: '../components/',
assetsPrefix: assetsPrefix,
assetsPrefix: constants_1.ASSETS_PREFIX,
})];

@@ -199,3 +199,3 @@ case 2:

return [4 /*yield*/, reactGenerator.generateComponent(component, {
assetsPrefix: assetsPrefix,
assetsPrefix: constants_1.ASSETS_PREFIX,
})];

@@ -225,12 +225,11 @@ case 2:

sourcePackageJson = options.sourcePackageJson;
if (sourcePackageJson) {
externalDep = generator_utils_1.extractExternalDependencies(allDependencies);
sourcePackageJson.dependencies = __assign({}, sourcePackageJson.dependencies, externalDep);
packageFile = {
name: 'package',
extension: '.json',
content: JSON.stringify(sourcePackageJson, null, 2),
};
distFolder.files.push(packageFile);
}
packageJSON = generator_utils_1.createPackageJSON(sourcePackageJson || constants_1.DEFAULT_PACKAGE_JSON, allDependencies, {
projectName: uidl.name,
});
packageFile = {
name: 'package',
extension: '.json',
content: JSON.stringify(packageJSON, null, 2),
};
distFolder.files.push(packageFile);
return [2 /*return*/, result];

@@ -237,0 +236,0 @@ }

@@ -13,2 +13,4 @@ "use strict";

var types = __importStar(require("@babel/types"));
var constants_1 = require("./constants");
var uidl_utils_1 = require("../../component-generators/utils/uidl-utils");
exports.createDocumentComponent = function (uidl, t) {

@@ -43,3 +45,4 @@ if (t === void 0) { t = types; }

Object.keys(metaItem).forEach(function (key) {
jsx_ast_1.addAttributeToJSXTag(metaTag, { name: key, value: metaItem[key] });
var metaValue = uidl_utils_1.prefixPlaygroundAssetsURL(constants_1.ASSETS_PREFIX, metaItem[key]);
jsx_ast_1.addAttributeToJSXTag(metaTag, { name: key, value: metaValue });
});

@@ -49,7 +52,8 @@ jsx_ast_1.addChildJSXTag(headNode, metaTag);

assets.forEach(function (asset) {
var assetPath = uidl_utils_1.prefixPlaygroundAssetsURL(constants_1.ASSETS_PREFIX, asset.path);
// link stylesheet (external css, font)
if ((asset.type === 'style' || asset.type === 'font') && asset.path) {
if ((asset.type === 'style' || asset.type === 'font') && assetPath) {
var linkTag = jsx_ast_1.generateASTDefinitionForJSXTag('link');
jsx_ast_1.addAttributeToJSXTag(linkTag, { name: 'rel', value: 'stylesheet' });
jsx_ast_1.addAttributeToJSXTag(linkTag, { name: 'href', value: asset.path });
jsx_ast_1.addAttributeToJSXTag(linkTag, { name: 'href', value: assetPath });
jsx_ast_1.addChildJSXTag(headNode, linkTag);

@@ -70,4 +74,4 @@ }

jsx_ast_1.addAttributeToJSXTag(scriptTag, { name: 'type', value: 'text/javascript' });
if (asset.path) {
jsx_ast_1.addAttributeToJSXTag(scriptTag, { name: 'src', value: asset.path });
if (assetPath) {
jsx_ast_1.addAttributeToJSXTag(scriptTag, { name: 'src', value: assetPath });
if (asset.meta && asset.meta.defer) {

@@ -94,6 +98,6 @@ jsx_ast_1.addAttributeToJSXTag(scriptTag, { name: 'defer', value: true });

// icon
if (asset.type === 'icon' && asset.path) {
if (asset.type === 'icon' && assetPath) {
var iconTag_1 = jsx_ast_1.generateASTDefinitionForJSXTag('link');
jsx_ast_1.addAttributeToJSXTag(iconTag_1, { name: 'rel', value: 'shortcut icon' });
jsx_ast_1.addAttributeToJSXTag(iconTag_1, { name: 'href', value: asset.path });
jsx_ast_1.addAttributeToJSXTag(iconTag_1, { name: 'href', value: assetPath });
if (typeof asset.meta === 'object') {

@@ -100,0 +104,0 @@ var assetMeta_1 = asset.meta;

@@ -13,3 +13,3 @@ import { ProjectUIDL, ElementsMapping } from '../../uidl-definitions/types';

export interface ProjectGeneratorOptions {
sourcePackageJson?: Record<string, any>;
sourcePackageJson?: PackageJSON;
distPath?: string;

@@ -22,1 +22,11 @@ customMapping?: ElementsMapping;

}>;
export interface PackageJSON {
name: string;
description: string;
version: string;
main: string;
author: string;
license: string;
scripts?: Record<string, string>;
dependencies?: Record<string, string>;
}
import { ComponentDependency, WebManifest } from '../../uidl-definitions/types';
import { PackageJSON } from '../../project-generators/types';
export declare const extractExternalDependencies: (dependencies: Record<string, ComponentDependency>) => any;
export declare const createManifestJSON: (manifest: WebManifest, projectName?: string) => {
short_name?: string;
name?: string;
icons?: {
export declare const createManifestJSON: (manifest: WebManifest, projectName: string, assetsPrefix?: string) => {
icons: {
src: string;

@@ -11,2 +10,4 @@ type: string;

}[];
short_name?: string;
name?: string;
start_url?: string;

@@ -19,1 +20,4 @@ background_color?: string;

};
export declare const createPackageJSON: (packageJSONTemplate: PackageJSON, dependencies: Record<string, ComponentDependency>, overwrites: {
projectName: string;
}) => PackageJSON;

@@ -14,3 +14,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
// Only package dependencies are needed for the package.json file
var uidl_utils_1 = require("../../component-generators/utils/uidl-utils");
exports.extractExternalDependencies = function (dependencies) {

@@ -30,3 +30,3 @@ return Object.keys(dependencies)

// Creates a manifest json with the UIDL having priority over the default values
exports.createManifestJSON = function (manifest, projectName) {
exports.createManifestJSON = function (manifest, projectName, assetsPrefix) {
var defaultManifest = {

@@ -38,4 +38,13 @@ short_name: projectName,

};
return __assign({}, defaultManifest, manifest);
var icons = manifest.icons.map(function (icon) {
var src = uidl_utils_1.prefixPlaygroundAssetsURL(assetsPrefix, icon.src);
return __assign({}, icon, { src: src });
});
return __assign({}, defaultManifest, manifest, { icons: icons });
};
exports.createPackageJSON = function (packageJSONTemplate, dependencies, overwrites) {
var projectName = overwrites.projectName;
var externalDep = exports.extractExternalDependencies(dependencies);
return __assign({}, packageJSONTemplate, { name: projectName, dependencies: __assign({}, packageJSONTemplate.dependencies, externalDep) });
};
//# sourceMappingURL=generator-utils.js.map

@@ -57,3 +57,3 @@ "use strict";

var generator_utils_1 = require("../utils/generator-utils");
var elements_mapping_json_1 = __importDefault(require("./elements-mapping.json"));
var vue_project_mapping_json_1 = __importDefault(require("./vue-project-mapping.json"));
exports.default = (function (uidl, options) {

@@ -68,3 +68,3 @@ if (options === void 0) { options = {}; }

vueGenerator = vue_component_1.default({
customMapping: elements_mapping_json_1.default,
customMapping: vue_project_mapping_json_1.default,
});

@@ -71,0 +71,0 @@ vueRouterGenerator = vue_router_1.default();

@@ -56,3 +56,3 @@ "use strict";

var vue_component_1 = __importDefault(require("../../component-generators/vue/vue-component"));
var elements_mapping_json_1 = __importDefault(require("./elements-mapping.json"));
var nuxt_mapping_json_1 = __importDefault(require("./nuxt-mapping.json"));
exports.default = (function (uidl, options) {

@@ -67,3 +67,3 @@ if (options === void 0) { options = {}; }

vueGenerator = vue_component_1.default({
customMapping: __assign({}, elements_mapping_json_1.default),
customMapping: __assign({}, nuxt_mapping_json_1.default),
});

@@ -70,0 +70,0 @@ pagesFolder = {

@@ -141,7 +141,28 @@ {

"video": {
"type": "video"
"type": "video",
"children": [
"$children",
"This browser does not support the video formats given"
]
},
"audio": {
"type": "audio"
"type": "audio",
"children": [
"$children",
"This browser does not support the audio formats given"
]
},
"picture": {
"type": "picture",
"children": [
"$children",
"This browser does not support the image formats given"
]
},
"source": {
"type": "source",
"attrs": {
"src": "$attrs.url"
}
},
"svg": {

@@ -148,0 +169,0 @@ "type": "svg"

@@ -10,8 +10,3 @@ export interface ProjectUIDL {

meta: Array<Record<string, string>>;
assets: Array<{
type: string;
path?: string;
content?: string;
meta?: Record<string, any>;
}>;
assets: GlobalAsset[];
manifest?: WebManifest;

@@ -23,2 +18,8 @@ variables?: Record<string, string>;

}
export interface GlobalAsset {
type: string;
path?: string;
content?: string;
meta?: Record<string, any>;
}
export interface ComponentUIDL {

@@ -25,0 +26,0 @@ $schema?: string;

@@ -11,25 +11,25 @@ {

"author": "teleportHQ",
"license": "ISC",
"license": "MIT",
"dependencies": {
"@babel/core": "7.1.6",
"@babel/plugin-syntax-jsx": "7.0.0",
"@babel/plugin-transform-react-display-name": "7.0.0",
"@babel/plugin-transform-react-jsx": "7.1.6",
"@babel/preset-env": "7.1.6",
"react": "16.8.3",
"react-dom": "16.8.3",
"react-router-dom": "4.3.1"
},
"devDependencies": {
"@babel/core": "7.3.3",
"@babel/plugin-syntax-jsx": "7.2.0",
"@babel/plugin-transform-react-display-name": "7.2.0",
"@babel/plugin-transform-react-jsx": "7.3.0",
"@babel/preset-env": "7.3.1",
"babel": "6.23.0",
"babel-loader": "8.0.4",
"clean-webpack-plugin": "1.0.0",
"copy-webpack-plugin": "4.6.0",
"babel-loader": "8.0.5",
"clean-webpack-plugin": "1.0.1",
"copy-webpack-plugin": "5.0.0",
"html-webpack-plugin": "3.2.0",
"react": "16.8.1",
"react-dom": "16.8.1",
"react-router-dom": "4.3.1",
"webpack": "4.26.1"
},
"devDependencies": {
"css-loader": "2.0.0",
"css-loader": "2.1.0",
"style-loader": "0.23.1",
"webpack-cli": "3.1.2",
"webpack-dev-server": "3.1.10"
"webpack-cli": "3.2.3",
"webpack-dev-server": "3.2.0",
"webpack": "4.29.5"
}
}

@@ -10,9 +10,9 @@ {

"dependencies": {
"vue": "^2.5.17",
"vue-router": "^3.0.1"
"vue": "^2.6.7",
"vue-router": "^3.0.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.2.0",
"@vue/cli-service": "^3.2.0",
"vue-template-compiler": "^2.5.17"
"@vue/cli-plugin-babel": "^3.4.1",
"@vue/cli-service": "^3.4.1",
"vue-template-compiler": "^2.6.7"
},

@@ -19,0 +19,0 @@ "postcss": {

@@ -15,10 +15,10 @@ {

"cross-env": "^5.2.0",
"nuxt": "^2.0.0"
"nuxt": "^2.4.3"
},
"devDependencies": {
"nodemon": "^1.11.0",
"eslint-config-prettier": "^3.1.0",
"eslint-plugin-prettier": "2.6.2",
"prettier": "1.14.3"
"nodemon": "^1.18.10",
"eslint-config-prettier": "^4.0.0",
"eslint-plugin-prettier": "3.0.1",
"prettier": "1.16.4"
}
}
{
"$schema": "https://raw.githubusercontent.com/teleporthq/uidl-definitions/master/component.json",
"$schema": "https://raw.githubusercontent.com/teleporthq/teleport-code-generators/master/src/uidl-definitions/schemas/component.json",
"name": "AuthorCard",

@@ -4,0 +4,0 @@ "propDefinitions": {

{
"$schema": "https://raw.githubusercontent.com/teleporthq/uidl-definitions/master/component.json",
"$schema": "https://raw.githubusercontent.com/teleporthq/teleport-code-generators/master/src/uidl-definitions/schemas/component.json",
"name": "Cards",

@@ -4,0 +4,0 @@ "propDefinitions": {

{
"$schema": "https://raw.githubusercontent.com/teleporthq/uidl-definitions/master/component.json",
"$schema": "https://raw.githubusercontent.com/teleporthq/teleport-code-generators/master/src/uidl-definitions/schemas/component.json",
"name": "TabSelector",

@@ -4,0 +4,0 @@ "stateDefinitions": {

{
"$schema": "https://raw.githubusercontent.com/teleporthq/uidl-definitions/master/project.json",
"$schema": "https://raw.githubusercontent.com/teleporthq/teleport-code-generators/master/src/uidl-definitions/schemas/project.json",
"name": "myVueProject",

@@ -4,0 +4,0 @@ "globals": {

{
"$schema": "https://raw.githubusercontent.com/teleporthq/uidl-definitions/master/project.json",
"$schema": "https://raw.githubusercontent.com/teleporthq/teleport-code-generators/master/src/uidl-definitions/schemas/project.json",
"name": "Teleport Project",

@@ -7,3 +7,3 @@ "globals": {

"language": "en",
"title": "TeleportHQ"
"title": "teleportHQ"
},

@@ -14,3 +14,4 @@ "meta" : [

{ "name": "viewport", "content": "width=device-width, initial-scale=1.0" },
{ "property": "og:title", "content": "Free Web tutorials" }
{ "property": "og:title", "content": "Free Web tutorials" },
{ "property": "og:url", "content": "/playground_assets/asdasd.png" }
],

@@ -20,3 +21,3 @@ "manifest": {

{
"src": "/static/icons-192.png",
"src": "/playground_assets/icons-192.png",
"type": "image/png",

@@ -26,3 +27,3 @@ "sizes": "192x192"

{
"src": "/static/icons-512.png",
"src": "/playground_assets/icons-512.png",
"type": "image/png",

@@ -67,3 +68,3 @@ "sizes": "512x512"

"type": "icon",
"path": "/static/favicon-32x32.png",
"path": "/playground_assets/favicon-32x32.png",
"meta": {

@@ -109,2 +110,27 @@ "type": "image/png",

{
"type": "video",
"key": "video",
"attrs": {
"autoPlay": true
},
"children": [
{
"type": "source",
"key": "mp4-source",
"attrs": {
"type": "video/mp4",
"url": "https://www.quirksmode.org/html5/videos/big_buck_bunny.mp4"
}
},
{
"type": "source",
"key": "webm-source",
"attrs": {
"type": "video/webm",
"url": "https://www.quirksmode.org/html5/videos/big_buck_bunny.webm"
}
}
]
},
{
"type": "container",

@@ -590,16 +616,2 @@ "key": "accordions",

{
"type": "image",
"key": "image",
"attrs": {
"url": "/playground_assets/image.jpg"
}
},
{
"type": "container",
"key": "container",
"styles": {
"background": "#ffffff url(\"/playground_assets/image.png\") no-repeat right top;"
}
},
{
"type": "button",

@@ -606,0 +618,0 @@ "key": "close",

{
"$schema": "https://raw.githubusercontent.com/teleporthq/uidl-definitions/master/project.json",
"$schema": "https://raw.githubusercontent.com/teleporthq/teleport-code-generators/master/src/uidl-definitions/schemas/project.json",
"name": "myVueProject",

@@ -4,0 +4,0 @@ "root": {

{
"name": "@teleporthq/teleport-code-generators",
"version": "0.3.0",
"version": "0.3.1",
"description": "Code generators and UIDL definition library",

@@ -17,2 +17,3 @@ "main": "dist/index.js",

"prepare": "npm run build",
"add-contributor": "all-contributors add",
"create-react-next": "ts-node --project tsconfig.json ./examples/project-exporters/react-next/index.ts",

@@ -36,5 +37,6 @@ "create-react-basic": "ts-node --project tsconfig.json ./examples/project-exporters/react-basic/index.ts",

"devDependencies": {
"@types/cheerio": "^0.22.10",
"@types/jest": "^24.0.6",
"@types/cheerio": "^0.22.10",
"@types/node": "^11.9.4",
"all-contributors-cli": "^6.1.2",
"codecov": "^3.2.0",

@@ -45,4 +47,4 @@ "husky": "^1.3.1",

"rimraf": "^2.6.3",
"ts-jest": "^24.0.0",
"ts-node": "^8.0.2",
"ts-jest": "^24.0.0",
"tslint": "^5.12.1",

@@ -49,0 +51,0 @@ "tslint-config-prettier": "^1.18.0",

@@ -1,31 +0,56 @@

## TeleportHQ Code Generators 0.3 - Alpha!
<p align="center">
<img src="https://raw.githubusercontent.com/teleporthq/teleport-lib-js/master/logo50.png" width="250"/>
</p>
[![npm]()]()
[![Build Status](https://travis-ci.org/teleporthq/teleport-code-generators.svg?branch=master)](https://travis-ci.org/teleporthq/teleport-code-generators)
[![Codecov]()]()
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
<h2 align="center">Code Generators v0.3 - Alpha!</h2>
This is a **WIP prototype** containing all our project and component generators, as well as the UIDL schemas and validators. While we have some working examples, it should not be considered production ready by any means! Do not hesitate to give us feedback and contribute back!
<h3 align="center">
<a href="#what">What</a>
<span> · </span>
<a href="#quick-setup">Quick Setup</a>
<span> · </span>
<a href="#features">Features</a>
<span> · </span>
<a href="#development">Development</a>
<span> · </span>
<a href="#planning">Planning</a>
<span> · </span>
<a href="#contributions">Contributions</a>
</h3>
## What is this?
The **code generators** are a part of the **TeleportHQ** ecosystem, which we are actively building, in an effort to streamline website and design generation. You can read more about our inception in [this article](https://teleporthq.io/blog/we-believe-in-AI-powered-code-generation/).
<p align="center">
<a target="_blank" href="https://www.npmjs.com/package/@teleporthq/teleport-code-generators"><img src="https://img.shields.io/npm/v/@teleporthq/teleport-code-generators.svg" /></a>
<a target="_blank" href="https://travis-ci.org/teleporthq/teleport-code-generators"><img src="https://travis-ci.org/teleporthq/teleport-code-generators.svg?branch=master" /></a>
<a target="_blank" href="https://codecov.io/gh/teleporthq/teleport-code-generators"><img src="https://codecov.io/gh/teleporthq/teleport-code-generators/branch/master/graph/badge.svg" /></a>
<a target="_blank" href="https://github.com/prettier/prettier"><img src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg" /></a>
<img src="https://img.shields.io/npm/l/@teleporthq/teleport-code-generators.svg" />
<a target="_blank" href="https://bundlephobia.com/result?p=@teleporthq/teleport-code-generators"><img src="https://img.shields.io/bundlephobia/minzip/@teleporthq/teleport-code-generators.svg" /></a>
<a target="_blank" href="https://twitter.com/teleporthqio"><img src="https://img.shields.io/twitter/follow/teleporthqio.svg" /></a>
</p>
The code generators are used by our online visual editor (coming soon), a tool which lets you build websites via a familiar design tool interface. The glue between our different tools and systems and the code generators is the [UIDL Standard](todo: blog link). The **UIDL** allows us to define **user interfaces** in an **abstract** way, independent of any framework or even the web platform itself, which then allows us to convert that abstraction into different flavors of coding (ex: React, Vue, etc.)
This is a **WIP prototype** containing all of our project and component generators, as well as the **UIDL** schemas and validators. While we have some working examples, it shouldn't be considered production ready by any means! Don't hesitate to give us feedback and feel free to contribute in any way!
<h2 id="what">🤔 What is this?</h2>
The **code generators** are a part of the **teleportHQ** ecosystem, which we're actively building in an effort to streamline the creation of web and mobile applications. You can read more about our inception in [this article](https://teleporthq.io/blog/we-believe-in-AI-powered-code-generation/).
The code generators are used by our online **visual editor** (coming soon), a platform that lets you build applications via a familiar design tool interface. The glue between our platform and the code generators is the [**UIDL Standard**](link coming soon). The UIDL allows us to define **user interfaces** in an **abstract** way, independent of any framework or even the web platform itself, which then allows us to convert that abstraction into different flavors of coding (e.g. React, Vue, etc.).
Our philosophy behind the code generators is:
* User interfaces are decomposed into **components**, hence our focus on component generation
* What can be built with `React`, can also be built with `Vue` or on top of the `Web Components` standard, we support multiple targets
* What can be built with `React`, can also be built with `Vue` or on top of the `Web Components` standard - we support multiple targets
* A project built with the visual editor should have a **high standard of quality** (performance, security, accessibility included)
* Generated **code quality** should be as good as possible, so that any developer can pick up the work from there and enhance the project
* Generated **code quality** should be as high as possible, so that any developer could pick up the work from there on and enhance the project
* The code generation architecture is open and extendable, we invite everyone to contribute!
You can also read more about our [decision to open source our code generators](todo: blog link).
You can also read more on our [decision to open source our code generators](link coming soon).
Read more about the [UIDL Standard](todo: link).
Read more about the [UIDL Standard](link coming soon).
## Instalation and Basic Usage
While this will probably remain a [monorepo](https://danluu.com/monorepo/), we will publish different **npm** packages for various parts of our code generation ecosystem. For now, there's a single package published under `@teleporthq/teleport-generators`. So, let's integrate that into your project:
<h2 id="quick-setup">🚀 Quick Setup</h2>
While this will probably remain a [monorepo](https://danluu.com/monorepo/), we'll publish different **npm** packages for various parts of our code generation ecosystem. For now, there's a single package published under `@teleporthq/teleport-generators`. So, let's integrate that into your project:
```bash
npm install @teleporthq/teleport-generators
npm install @teleporthq/teleport-code-generators
```

@@ -51,3 +76,3 @@

The code output from this snippet would be
```
```jsx
import React from "react"

@@ -62,5 +87,9 @@

<h2 id="features">💼 Features</h2>
This repo contains multiple **modules** that will soon be available as individual `npm` **packages**. There are two types of generators available: component and project generators. Component generators take a simple **ComponentUIDL** input and return the **code** according to the specific generator flavors (e.g. React + StyledJSX, Vue, etc.). Project generators operate on **ProjectUIDL**s and will return a complete structure of `folders` and `files` which then can be written to disk or sent to servers for deployment. The aim of the project generators is to output a **working application**.
### Component Generators
We have **official** component generators for `React` and `Vue`, but we plan on supporting other frameworks and standards as soon as possible. Also, `React Native` is definitely on our minds, because we designed the UIDL in such a way that it is agnostic of the web platform.
We have **official** component generators for `React` and `Vue`, but we also plan on supporting other frameworks and standards as soon as possible. Also, `React Native` is definitely on our minds, since we've designed the UIDL in such a way that it's agnostic of the web platform.

@@ -75,3 +104,3 @@ There are two **factory functions** exported from our main module, for the React and Vue generators.

// Instantiate a generator, selecting the styled-jsx plugin for handling styles (other options: CSSModules, JSS, InlineStyles)
const reactGenerator = createReactComponentGenerator({ variation: ReactComponentFlavors.StyledJSX })
const reactGenerator = createReactComponentGenerator({ variation: "StyledJSX" })

@@ -84,8 +113,6 @@ // Calling the generate function will return the code as a string

Read more about [the API of the component generator](todo: doc link).
Read more about [the API of the component generator](link coming soon).
Read more about [mappings and resolvers](todo: doc link).
Read more about [mappings and resolvers](link coming soon).
TODO: More complex examples
#### Vue

@@ -105,8 +132,7 @@

TODO: More complex examples
#### Current capabilities
Here's a list of functionalities that the UIDL and the component generators support at the moment, besides the obvious presentational layer:
#### Advanced capabilities
Here's a list of functionalities that the UIDL and the component generators are supporting at the moment, besides the obvious presentational layer:
* Dynamic values (props, state) inside html nodes or at attribute level
* Type definitions for component props (PropTypes in React, props in Vue)
* External dependencies definition
* Simple component state (Hooks in React)

@@ -118,5 +144,5 @@ * Event Handlers (related to state changes)

We have **official** project generators for the two different frameworks we support so far. For `React`, we can generate a project based on a `React` and `React-Router` template, or we can generate a project with `Next.js`. For `Vue`, we have a standard `Vue` app, build with the `vue-cli` and a generator for `Nuxt`.
We have **official** project generators for the two different frameworks we're supporting so far. For `React`, we can generate a project based on a `React` and `React-Router` template, or we can generate a project on top of `Next.js`. For `Vue`, we have a standard `Vue` app, build with the `vue-cli` and a generator for `Nuxt`.
Project generators rely on the component generators and on the structure of the `ProjectUIDL` to figure out how many files to create and where. Each project generator has its own strategy, based on the particularities of that specific framework/tool.
Project generators rely on the component generators and on the structure of the `ProjectUIDL` to figure out how many files to create and where to create them. Each project generator has its own strategy, based on the particularities of that specific framework/tool.

@@ -139,5 +165,11 @@ #### React + React-Router

#### Advanced Capabilities
Besides the regular files and folders generated at the end of the process, project generators are also taking care of:
* Extracting all external dependencies and adding them to the `package.json`
* Creating the entry point for each application (it can be an `index.html` or something that is framework specific)
* Generating a web manifest for PWA support
### UIDL Validators
The package also exports a module that performs UIDL validations for any given JSON structure, based on the [JSON Schema](todo: link documentation).
The package also exports a module that performs UIDL validations for any given JSON structure, based on the [JSON Schema](link coming soon).

@@ -156,29 +188,76 @@ ```javascript

### Further Reading
A few useful links to get you up to speed with the **teleport** ecosystem:
* [Component](todo: link) and [Project](todo: link) JSON Schemas
* [Full Documentation](https://teleporthq.io/docs)
* [Introducing the new Generators](todo: link)
A few useful links to get you up to speed with the entire **teleport** ecosystem:
* [Component](link coming soon) and [Project](link coming soon) JSON Schemas
* [Full Documentation](link coming soon)
* [Introducing the new Generators](link coming soon)
* [Playground link](link coming soon)
## Development
<h2 id="development">💻 Development</h2>
This project is writen with **TypeScript**. The project setup is pretty standard. In order to give it a spin locally, you have to do:
This project is writen with **TypeScript** and has a pretty standard setup. In order to give it a spin locally, you have to:
```
npm install
```
Project generators are running locally in the `/examples` folder, where you'll find a number of UIDL samples as well as the code that writes the files and folders to disk.
To generate the projects locally, you can try one of these four examples:
```
npm run create-react-basic
npm run create-react-next
npm run create-vue-basic
npm run create-vue-nuxt
```
Project generators are running locally in the `/examples` folder, where you will find a number of UIDL samples as well as the code that write the files and folders to disk.
Files and folders for each template are generated after you run the corresponding npm task in `/examples/projects-exporters/<project-template>`.
todo: Write about tests
Running the test suite:
```
npm run test
npm run test:coverage
```
## Planning
todo: write about next steps
Please [open an issue](https://github.com/teleporthq/teleport-code-generators/issues) for any irregularity, potential bug that you find while running the codebase, or if you simply have any questions or curiosities about this project.
## Contributions
We would be super happy to have community involvment around this project. We strongly believe in the power of open source, so we want to build the best possible code generators together with the entire development community.
<h2 id="planning">🤖 Planning</h2>
todo: Contact links
It's not just our code that's open source, we're also planning the development of the code generators on GitHub. We already have [a number of issues](https://github.com/teleporthq/teleport-code-generators/issues) opened and we expect further contributions on this.
We're especially interested in opening discussions around the issues tagged with the [`proposal`](https://github.com/teleporthq/teleport-code-generators/issues?q=is%3Aissue+is%3Aopen+label%3Aproposal) label.
We also have a couple of milestone down the line:
### Beta Release
This is our immediately planned release for both the teleportHQ platform, as well as for the new generators and website. ETA for this release is mid April 2019, but this also depends on the release of other parts of the ecosystem.
### Official Release
Our official release will be a switch to version `1.0`. ETA for this is around May/June 2019. Hopefully, by then, we'll have more people contributing to the code generators.
<h2 id="contributions">💕 Contributions</h2>
We'd be super happy to have **community** involvement around this project. We strongly believe in the power of **open source**, so we're planning on building the best possible code generators, together with the entire development community.
We envision different types of involvement from this point on:
* Trying out the generators and reporting back any bugs and potential points of improvement
* Contributing to the existing issues, either on the core modules or on the existing generators and plugins
* Exploring and building new plugins for the existing generators
* Exploring and building new generators based on the existing architecture
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore -->
<table><tr><td align="center"><a href="https://medium.com/@alexnm"><img src="https://avatars0.githubusercontent.com/u/9945366?v=4" width="100px;" alt="Alex Moldovan"/><br /><sub><b>Alex Moldovan</b></sub></a><br /><a href="https://github.com/teleporthq/teleport-code-generators/commits?author=alexnm" title="Code">💻</a> <a href="https://github.com/teleporthq/teleport-code-generators/commits?author=alexnm" title="Documentation">📖</a> <a href="#ideas-alexnm" title="Ideas, Planning, & Feedback">🤔</a></td><td align="center"><a href="https://github.com/vladnicula"><img src="https://avatars3.githubusercontent.com/u/126038?v=4" width="100px;" alt="Vlad Nicula"/><br /><sub><b>Vlad Nicula</b></sub></a><br /><a href="https://github.com/teleporthq/teleport-code-generators/commits?author=vladnicula" title="Code">💻</a> <a href="#ideas-vladnicula" title="Ideas, Planning, & Feedback">🤔</a></td><td align="center"><a href="https://github.com/paulbrie"><img src="https://avatars2.githubusercontent.com/u/3997538?v=4" width="100px;" alt="Paul BRIE"/><br /><sub><b>Paul BRIE</b></sub></a><br /><a href="https://github.com/teleporthq/teleport-code-generators/issues?q=author%3Apaulbrie" title="Bug reports">🐛</a> <a href="https://github.com/teleporthq/teleport-code-generators/commits?author=paulbrie" title="Documentation">📖</a> <a href="#ideas-paulbrie" title="Ideas, Planning, & Feedback">🤔</a></td><td align="center"><a href="https://github.com/mihaitaba"><img src="https://avatars3.githubusercontent.com/u/45386599?v=4" width="100px;" alt="mihaitaba"/><br /><sub><b>mihaitaba</b></sub></a><br /><a href="#design-mihaitaba" title="Design">🎨</a> <a href="https://github.com/teleporthq/teleport-code-generators/commits?author=mihaitaba" title="Documentation">📖</a></td></tr></table>
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
<h2 id="contact">✍️ Contact</h2>
Reach out to us on any of these channels:
* 📧 [Write an Email](mailto:hello@teleporthq.io)
* 🐦 [Drop a message on twitter](https://twitter.com/teleporthqio)
* ℹ️ [Website](https://teleporthq.io/)

@@ -1,6 +0,6 @@

import { ComponentPlugin, ComponentStructure } from '../../types'
import { ComponentPlugin, ComponentStructure, ChunkDefinition } from '../../types'
import { ComponentUIDL } from '../../../uidl-definitions/types'
export default class ComponentAssemblyLine {
export default class AssemblyLine {
private plugins: ComponentPlugin[]

@@ -40,2 +40,13 @@

}
public groupChunksByFileId(chunks: ChunkDefinition[]): Record<string, ChunkDefinition[]> {
return chunks.reduce((chunksByFileId: Record<string, ChunkDefinition[]>, chunk) => {
const fileId = (chunk.meta && chunk.meta.fileId) || 'default'
if (!chunksByFileId[fileId]) {
chunksByFileId[fileId] = []
}
chunksByFileId[fileId].push(chunk)
return chunksByFileId
}, {})
}
}

@@ -6,23 +6,2 @@ import { ChunkDefinition, GeneratorFunction } from '../../types'

const removeItemsInArray = (arrayToRemoveFrom: string[], itemsToRemove: string[]) => {
return arrayToRemoveFrom.filter((item: string) => {
return itemsToRemove.indexOf(item) === -1
})
}
const removeChildDependency = (children: EmbedDependency[], targetChunkName: string) => {
return children.reduce((acc: EmbedDependency[], child) => {
if (child.chunkName !== targetChunkName) {
acc.push(child)
}
return acc
}, [])
}
interface EmbedDependency {
chunkName: string
slot: string
}
export default class Builder {

@@ -252,1 +231,22 @@ public chunkDefinitions: ChunkDefinition[] = []

}
const removeItemsInArray = (arrayToRemoveFrom: string[], itemsToRemove: string[]) => {
return arrayToRemoveFrom.filter((item: string) => {
return itemsToRemove.indexOf(item) === -1
})
}
const removeChildDependency = (children: EmbedDependency[], targetChunkName: string) => {
return children.reduce((acc: EmbedDependency[], child) => {
if (child.chunkName !== targetChunkName) {
acc.push(child)
}
return acc
}, [])
}
interface EmbedDependency {
chunkName: string
slot: string
}

@@ -1,3 +0,3 @@

export { default as ComponentAssemblyLine } from './assembly-line'
export { default as AssemblyLine } from './assembly-line'
export { default as Builder } from './builder'
export { default as Resolver } from './resolver'

@@ -9,5 +9,118 @@ import {

import { prefixPlaygroundAssetsURL } from '../../utils/uidl-utils'
import { ASSETS_IDENTIFIER } from '../../constants'
const STYLE_PROPERTIES_WITH_URL = ['background', 'backgroundImage']
const ATTRIBUTES_WITH_URL = ['url', 'srcset']
export const resolveContentNode = (
node: ContentNode,
elementsMapping: ElementsMapping,
localDependenciesPrefix: string,
assetsPrefix?: string
) => {
const mappedElement = elementsMapping[node.type] || { type: node.type }
node.type = mappedElement.type
// If the mapping contains children, insert that structure into the UIDL
if (mappedElement.children) {
const originalNodeChildren = node.children || []
const originalAttrs = node.attrs || {}
const replacingNode = {
...node,
children: JSON.parse(JSON.stringify(mappedElement.children)),
}
insertChildrenIntoNode(replacingNode, originalNodeChildren, originalAttrs)
node.children = replacingNode.children
}
// Resolve dependency with the UIDL having priority
if (node.dependency || mappedElement.dependency) {
node.dependency = resolveDependency(mappedElement, node.dependency, localDependenciesPrefix)
}
// Resolve assets prefix inside style (ex: background-image)
if (node.styles && assetsPrefix) {
node.styles = prefixAssetURLs(node.styles, assetsPrefix)
}
// Prefix the attributes which may point to local assets
if (node.attrs && assetsPrefix) {
ATTRIBUTES_WITH_URL.forEach((attribute) => {
if (node.attrs[attribute]) {
node.attrs[attribute] = prefixPlaygroundAssetsURL(assetsPrefix, node.attrs[attribute])
}
})
}
// Merge UIDL attributes to the attributes coming from the mapping object
if (mappedElement.attrs) {
node.attrs = mergeAttributes(mappedElement, node.attrs)
}
// The UIDL has priority over the mapping repeat
const repeatStructure = node.repeat || mappedElement.repeat
if (repeatStructure) {
const { dataSource, content } = repeatStructure
// Data source might be preset on a referenced attribute in the uidl node
// ex: attrs[options] in case of a dropdown primitive with select/options
if (typeof dataSource === 'string' && dataSource.startsWith('$attrs.') && node.attrs) {
const nodeDataSourceAttr = dataSource.replace('$attrs.', '')
repeatStructure.dataSource = node.attrs[nodeDataSourceAttr]
}
// The content inside the repeat must also be mapped like any regular content node
repeatStructure.content = resolveContentNode(
content,
elementsMapping,
localDependenciesPrefix,
assetsPrefix
)
node.repeat = repeatStructure
}
// If the node has multiple state branches, each content needs to be resolved
if (node.type === 'state' && node.states) {
node.states = node.states.map((stateBranch) => {
if (typeof stateBranch.content === 'string') {
return stateBranch
} else {
return {
...stateBranch,
content: resolveContentNode(
stateBranch.content,
elementsMapping,
localDependenciesPrefix,
assetsPrefix
),
}
}
})
}
// Traverse the UIDL
if (node.children) {
node.children = node.children.map((child) => {
if (typeof child === 'string') {
return child
} else {
return resolveContentNode(child, elementsMapping, localDependenciesPrefix, assetsPrefix)
}
})
}
return node
}
/**
* Prefixes all urls inside the style object with the assetsPrefix
* @param styles the style object on the current node
* @param assetsPrefix a string representing the asset prefix
*/
const prefixAssetURLs = (styles: StyleDefinitions, assetsPrefix: string): StyleDefinitions => {
const whitelistStyleProperties = ['background', 'backgroundImage']
// iterate through all the style keys

@@ -30,8 +143,8 @@ return Object.keys(styles).reduce((acc, styleKey) => {

// only whitelisted style properties are checked
if (whitelistStyleProperties.includes(styleKey) && styleValue.includes('url("')) {
// position index after the double quotes to introduce the url prefix before
const startIndex = styleValue.indexOf('url("') + 5
if (STYLE_PROPERTIES_WITH_URL.includes(styleKey) && styleValue.includes(ASSETS_IDENTIFIER)) {
// split the string at the beginning of the ASSETS_IDENTIFIER string
const startIndex = styleValue.indexOf(ASSETS_IDENTIFIER)
acc[styleKey] =
styleValue.slice(0, startIndex) +
prefixRelativeURL(assetsPrefix, styleValue.slice(startIndex, styleValue.length - 1))
prefixPlaygroundAssetsURL(assetsPrefix, styleValue.slice(startIndex, styleValue.length))
} else {

@@ -45,20 +158,3 @@ acc[styleKey] = styleValue

/**
* Concatenates the prefix to the URL string.
* If the url starts with 'http', the return value will be the 'originalString'
* If the url does not start with a '/' it also appends that
*/
const prefixRelativeURL = (prefix: string, originalString: string) => {
if (originalString.startsWith('http')) {
return originalString
}
if (originalString.startsWith('/')) {
return prefix + originalString
}
return `${prefix}/${originalString}`
}
const mergeAttributes = (mappedElement: ElementMapping, uidlAttrs: any, assetsPrefix?: string) => {
const mergeAttributes = (mappedElement: ElementMapping, uidlAttrs: any) => {
// We gather the results here uniting the mapped attributes and the uidl attributes.

@@ -85,7 +181,3 @@ const resolvedAttrs: Record<string, any> = {}

if (uidlAttrs && uidlAttrs[uidlAttributeKey]) {
resolvedAttrs[key] =
key === 'src' && assetsPrefix
? prefixRelativeURL(assetsPrefix, uidlAttrs[uidlAttributeKey])
: uidlAttrs[uidlAttributeKey]
resolvedAttrs[key] = uidlAttrs[uidlAttributeKey]
mappedAttributes.push(uidlAttributeKey)

@@ -133,4 +225,19 @@ }

node: ContentNode,
originalChildren: Array<ContentNode | string>
originalChildren: Array<ContentNode | string>,
originalAttrs: Record<string, any>
) => {
// The same kind of referencing that is done in the mergeAttributes function
// TODO: Extract duplicate code and apply in both instances (merge attributes and solving children nodes)
// Explained here: https://github.com/teleporthq/teleport-code-generators/issues/44
// Object.keys(node.attrs).forEach((attrKey) => {
// if (typeof node.attrs[attrKey] === 'string' && node.attrs[attrKey].startsWith('$attrs.')) {
// const referencedAttributeKey = node.attrs[attrKey].replace('$attrs.', '')
// if (originalAttrs[referencedAttributeKey]) {
// node.attrs[attrKey] = originalAttrs[referencedAttributeKey]
// // since the attribute is mapped in the children, we assume it is not longer needed on the root node
// delete originalAttrs[referencedAttributeKey]
// }
// }
// })
if (!node.children) {

@@ -155,3 +262,3 @@ return

// The child node is pushed after the $children token was replaced
insertChildrenIntoNode(child, originalChildren)
insertChildrenIntoNode(child, originalChildren, originalAttrs)
acc.push(child)

@@ -161,95 +268,1 @@ return acc

}
export const resolveContentNode = (
node: ContentNode,
elementsMapping: ElementsMapping,
localDependenciesPrefix: string,
assetsPrefix?: string
) => {
const mappedElement = elementsMapping[node.type] || { type: node.type }
node.type = mappedElement.type
// Resolve dependency with the UIDL having priority
if (node.dependency || mappedElement.dependency) {
node.dependency = resolveDependency(mappedElement, node.dependency, localDependenciesPrefix)
}
// Resolve assets prefix inside style (ex: background-image)
if (node.styles && assetsPrefix) {
node.styles = prefixAssetURLs(node.styles, assetsPrefix)
}
// Merge UIDL attributes to the attributes coming from the mapping object
if (mappedElement.attrs) {
node.attrs = mergeAttributes(mappedElement, node.attrs, assetsPrefix)
}
// If the mapping contains children, insert that structure into the UIDL
if (mappedElement.children) {
const originalNodeChildren = node.children || []
const replacingNode = {
...node,
children: JSON.parse(JSON.stringify(mappedElement.children)),
}
insertChildrenIntoNode(replacingNode, originalNodeChildren)
node.children = replacingNode.children
}
// The UIDL has priority over the mapping repeat
const repeatStructure = node.repeat || mappedElement.repeat
if (repeatStructure) {
const { dataSource, content } = repeatStructure
// Data source might be preset on a referenced attribute in the uidl node
// ex: attrs[options] in case of a dropdown primitive with select/options
if (typeof dataSource === 'string' && dataSource.startsWith('$attrs.') && node.attrs) {
const nodeDataSourceAttr = dataSource.replace('$attrs.', '')
repeatStructure.dataSource = node.attrs[nodeDataSourceAttr]
}
// The content inside the repeat must also be mapped like any regular content node
repeatStructure.content = resolveContentNode(
content,
elementsMapping,
localDependenciesPrefix,
assetsPrefix
)
node.repeat = repeatStructure
}
// If the node has multiple state branches, each content needs to be resolved
if (node.type === 'state' && node.states) {
node.states = node.states.map((stateBranch) => {
if (typeof stateBranch.content === 'string') {
return stateBranch
} else {
return {
...stateBranch,
content: resolveContentNode(
stateBranch.content,
elementsMapping,
localDependenciesPrefix,
assetsPrefix
),
}
}
})
}
// Traverse the UIDL
if (node.children) {
node.children = node.children.map((child) => {
if (typeof child === 'string') {
return child
} else {
return resolveContentNode(child, elementsMapping, localDependenciesPrefix, assetsPrefix)
}
})
}
return node
}

@@ -6,2 +6,33 @@ import { ComponentPlugin, ComponentPluginFactory, ChunkDefinition } from '../../types'

interface ImportPluginConfig {
importLibsChunkName?: string
importPackagesChunkName?: string
importLocalsChunkName?: string
}
export const createPlugin: ComponentPluginFactory<ImportPluginConfig> = (config) => {
const {
importLibsChunkName = 'import-libs',
importPackagesChunkName = 'import-packages',
importLocalsChunkName = 'import-local',
fileId = null,
} = config || {}
const importPlugin: ComponentPlugin = async (structure) => {
const { dependencies } = structure
const libraryDependencies = groupDependenciesByPackage(dependencies, 'library')
const packageDependencies = groupDependenciesByPackage(dependencies, 'package')
const localDependencies = groupDependenciesByPackage(dependencies, 'local')
addImportChunk(structure.chunks, libraryDependencies, importLibsChunkName, fileId)
addImportChunk(structure.chunks, packageDependencies, importPackagesChunkName, fileId)
addImportChunk(structure.chunks, localDependencies, importLocalsChunkName, fileId)
return structure
}
return importPlugin
}
export default createPlugin()
interface ImportDependency {

@@ -65,32 +96,1 @@ identifier: string

}
interface ImportPluginConfig {
importLibsChunkName?: string
importPackagesChunkName?: string
importLocalsChunkName?: string
}
export const createPlugin: ComponentPluginFactory<ImportPluginConfig> = (config) => {
const {
importLibsChunkName = 'import-libs',
importPackagesChunkName = 'import-packages',
importLocalsChunkName = 'import-local',
fileId = null,
} = config || {}
const importPlugin: ComponentPlugin = async (structure) => {
const { dependencies } = structure
const libraryDependencies = groupDependenciesByPackage(dependencies, 'library')
const packageDependencies = groupDependenciesByPackage(dependencies, 'package')
const localDependencies = groupDependenciesByPackage(dependencies, 'local')
addImportChunk(structure.chunks, libraryDependencies, importLibsChunkName, fileId)
addImportChunk(structure.chunks, packageDependencies, importPackagesChunkName, fileId)
addImportChunk(structure.chunks, localDependencies, importLocalsChunkName, fileId)
return structure
}
return importPlugin
}
export default createPlugin()

@@ -34,5 +34,3 @@ import * as t from '@babel/types'

if (typeof pageKey !== 'string' || typeof content === 'string') {
console.warn(
'Route not correctly specified. Value should be a string when defining routes'
)
console.warn('Route not correctly specified. Value should be a string when defining routes')
return null

@@ -39,0 +37,0 @@ }

@@ -8,3 +8,3 @@ import * as t from '@babel/types'

path: 'react',
version: '16.6.3',
version: '16.8.3',
}

@@ -15,3 +15,3 @@

path: 'react-dom',
version: '16.6.3',
version: '16.8.3',
}

@@ -18,0 +18,0 @@

@@ -5,7 +5,3 @@ import * as t from '@babel/types'

addChildJSXTag,
addChildJSXText,
addAttributeToJSXTag,
generateASTDefinitionForJSXTag,
addDynamicChild,
addDynamicPropOnJsxOpeningTag,
createConditionalJSXExpression,

@@ -15,3 +11,9 @@ } from '../../../utils/jsx-ast'

import { makeDefaultExport } from '../../../utils/js-ast'
import { addEventHandlerToTag, makePureComponent, makeRepeatStructureWithMap } from './utils'
import {
addEventHandlerToTag,
makePureComponent,
makeRepeatStructureWithMap,
addAttributeToTag,
addTextElementToTag,
} from './utils'

@@ -28,40 +30,95 @@ import { capitalize } from '../../../utils/helpers'

/**
*
* @param tag the ref to the AST tag under construction
* @param key the key of the attribute that should be added on the current AST node
* @param value the value(string, number, bool) of the attribute that should be added on the current AST node
*/
const addAttributeToTag = (tag: t.JSXElement, key: string, value: any) => {
if (typeof value !== 'string') {
addAttributeToJSXTag(tag, { name: key, value })
return
}
interface JSXConfig {
componentChunkName: string
exportChunkName: string
importChunkName: string
}
if (value.startsWith('$props.')) {
const dynamicPropValue = value.replace('$props.', '')
addDynamicPropOnJsxOpeningTag(tag, key, dynamicPropValue, 'props')
} else if (value.startsWith('$state.')) {
const dynamicPropValue = value.replace('$state.', '')
addDynamicPropOnJsxOpeningTag(tag, key, dynamicPropValue)
} else if (value === '$item' || value === '$index') {
addDynamicPropOnJsxOpeningTag(tag, key, value.slice(1))
} else {
addAttributeToJSXTag(tag, { name: key, value })
export const createPlugin: ComponentPluginFactory<JSXConfig> = (config) => {
const {
componentChunkName = 'react-component',
exportChunkName = 'export',
importChunkName = 'import',
} = config || {}
const reactComponentPlugin: ComponentPlugin = async (structure) => {
const { uidl, dependencies } = structure
dependencies.React = {
type: 'library',
path: 'react',
version: '16.8.3',
}
let stateIdentifiers: Record<string, StateIdentifier> = {}
if (uidl.stateDefinitions) {
dependencies.useState = {
type: 'library',
path: 'react',
version: '16.8.3',
meta: {
namedImport: true,
},
}
const stateDefinitions = uidl.stateDefinitions
stateIdentifiers = Object.keys(stateDefinitions).reduce(
(acc: Record<string, StateIdentifier>, stateKey: string) => {
acc[stateKey] = {
key: stateKey,
type: stateDefinitions[stateKey].type,
default: stateDefinitions[stateKey].defaultValue,
setter: 'set' + capitalize(stateKey),
}
return acc
},
{}
)
}
// We will keep a flat mapping object from each component identifier (from the UIDL) to its correspoding JSX AST Tag
// This will help us inject style or classes at a later stage in the pipeline, upon traversing the UIDL
// The structure will be populated as the AST is being created
const nodesLookup = {}
const jsxTagStructure = generateTreeStructure(
uidl.content,
uidl.propDefinitions || {},
stateIdentifiers,
nodesLookup,
dependencies
)
const pureComponent = makePureComponent(uidl.name, stateIdentifiers, jsxTagStructure)
structure.chunks.push({
type: 'js',
name: componentChunkName,
linker: {
after: [importChunkName],
},
meta: {
nodesLookup,
},
content: pureComponent,
})
structure.chunks.push({
type: 'js',
name: exportChunkName,
linker: {
after: [componentChunkName],
},
content: makeDefaultExport(uidl.name),
})
return structure
}
}
const addTextElementToTag = (tag: t.JSXElement, text: string) => {
if (text.startsWith('$props.') && !text.endsWith('$props.')) {
addDynamicChild(tag, text.replace('$props.', ''), 'props')
} else if (text.startsWith('$state.') && !text.endsWith('$state.')) {
addDynamicChild(tag, text.replace('$state.', ''))
} else if (text === '$item' || text === '$index') {
addDynamicChild(tag, text.slice(1))
} else {
addChildJSXText(tag, text)
}
return reactComponentPlugin
}
export const generateTreeStructure = (
export default createPlugin()
const generateTreeStructure = (
content: ContentNode,

@@ -176,91 +233,1 @@ propDefinitions: Record<string, PropDefinition>,

}
interface JSXConfig {
componentChunkName: string
exportChunkName: string
importChunkName: string
}
export const createPlugin: ComponentPluginFactory<JSXConfig> = (config) => {
const {
componentChunkName = 'react-component',
exportChunkName = 'export',
importChunkName = 'import',
} = config || {}
const reactComponentPlugin: ComponentPlugin = async (structure) => {
const { uidl, dependencies } = structure
dependencies.React = {
type: 'library',
path: 'react',
}
let stateIdentifiers: Record<string, StateIdentifier> = {}
if (uidl.stateDefinitions) {
dependencies.useState = {
type: 'library',
path: 'react',
meta: {
namedImport: true,
},
}
const stateDefinitions = uidl.stateDefinitions
stateIdentifiers = Object.keys(stateDefinitions).reduce(
(acc: Record<string, StateIdentifier>, stateKey: string) => {
acc[stateKey] = {
key: stateKey,
type: stateDefinitions[stateKey].type,
default: stateDefinitions[stateKey].defaultValue,
setter: 'set' + capitalize(stateKey),
}
return acc
},
{}
)
}
// We will keep a flat mapping object from each component identifier (from the UIDL) to its correspoding JSX AST Tag
// This will help us inject style or classes at a later stage in the pipeline, upon traversing the UIDL
// The structure will be populated as the AST is being created
const nodesLookup = {}
const jsxTagStructure = generateTreeStructure(
uidl.content,
uidl.propDefinitions || {},
stateIdentifiers,
nodesLookup,
dependencies
)
const pureComponent = makePureComponent(uidl.name, stateIdentifiers, jsxTagStructure)
structure.chunks.push({
type: 'js',
name: componentChunkName,
linker: {
after: [importChunkName],
},
meta: {
nodesLookup,
},
content: pureComponent,
})
structure.chunks.push({
type: 'js',
name: exportChunkName,
linker: {
after: [componentChunkName],
},
content: makeDefaultExport(uidl.name),
})
return structure
}
return reactComponentPlugin
}
export default createPlugin()
import * as types from '@babel/types'
import { StateIdentifier } from '../../../types'
import { convertValueToLiteral } from '../../../utils/js-ast'
import {
addChildJSXText,
addAttributeToJSXTag,
addDynamicChild,
addDynamicPropOnJsxOpeningTag,
} from '../../../utils/jsx-ast'
import { EventHandlerStatement, PropDefinition } from '../../../../uidl-definitions/types'
const createStateChangeStatement = (
eventHandlerStatement: EventHandlerStatement,
// Adds all the event handlers and all the instructions for each event handler
// in case there is more than one specified in the UIDL
export const addEventHandlerToTag = (
tag: types.JSXElement,
eventKey: string,
eventHandlerStatements: EventHandlerStatement[],
stateIdentifiers: Record<string, StateIdentifier>,
propDefinitions: Record<string, PropDefinition> = {},
t = types
) => {
if (!eventHandlerStatement.modifies) {
console.warn(`No state identifier referenced under the "modifies" field`)
return null
}
const eventHandlerASTStatements: types.ExpressionStatement[] = []
const stateKey = eventHandlerStatement.modifies
const stateIdentifier = stateIdentifiers[stateKey]
eventHandlerStatements.forEach((eventHandlerAction) => {
if (eventHandlerAction.type === 'stateChange') {
const handler = createStateChangeStatement(eventHandlerAction, stateIdentifiers)
if (handler) {
eventHandlerASTStatements.push(handler)
}
}
if (!stateIdentifier) {
console.warn(`No state hook was found for "${stateKey}"`)
return null
if (eventHandlerAction.type === 'propCall') {
const handler = createPropCallStatement(eventHandlerAction, propDefinitions)
if (handler) {
eventHandlerASTStatements.push(handler)
}
}
})
let expressionContent: types.ArrowFunctionExpression | types.Expression
if (eventHandlerASTStatements.length === 1) {
const expression = eventHandlerASTStatements[0].expression
expressionContent =
expression.type === 'CallExpression' && expression.arguments.length === 0
? expression.callee
: t.arrowFunctionExpression([], expression)
} else {
expressionContent = t.arrowFunctionExpression([], t.blockStatement(eventHandlerASTStatements))
}
const stateSetterArgument =
eventHandlerStatement.newState === '$toggle'
? t.unaryExpression('!', t.identifier(stateIdentifier.key))
: convertValueToLiteral(eventHandlerStatement.newState, stateIdentifier.type)
return t.expressionStatement(
t.callExpression(t.identifier(stateIdentifier.setter), [stateSetterArgument])
tag.openingElement.attributes.push(
t.jsxAttribute(t.jsxIdentifier(eventKey), t.jsxExpressionContainer(expressionContent))
)

@@ -60,44 +83,27 @@ }

// Adds all the event handlers and all the instructions for each event handler
// in case there is more than one specified in the UIDL
export const addEventHandlerToTag = (
tag: types.JSXElement,
eventKey: string,
eventHandlerStatements: EventHandlerStatement[],
const createStateChangeStatement = (
eventHandlerStatement: EventHandlerStatement,
stateIdentifiers: Record<string, StateIdentifier>,
propDefinitions: Record<string, PropDefinition> = {},
t = types
) => {
const eventHandlerASTStatements: types.ExpressionStatement[] = []
if (!eventHandlerStatement.modifies) {
console.warn(`No state identifier referenced under the "modifies" field`)
return null
}
eventHandlerStatements.forEach((eventHandlerAction) => {
if (eventHandlerAction.type === 'stateChange') {
const handler = createStateChangeStatement(eventHandlerAction, stateIdentifiers)
if (handler) {
eventHandlerASTStatements.push(handler)
}
}
const stateKey = eventHandlerStatement.modifies
const stateIdentifier = stateIdentifiers[stateKey]
if (eventHandlerAction.type === 'propCall') {
const handler = createPropCallStatement(eventHandlerAction, propDefinitions)
if (handler) {
eventHandlerASTStatements.push(handler)
}
}
})
if (!stateIdentifier) {
console.warn(`No state hook was found for "${stateKey}"`)
return null
}
let expressionContent: types.ArrowFunctionExpression | types.Expression
if (eventHandlerASTStatements.length === 1) {
const expression = eventHandlerASTStatements[0].expression
const stateSetterArgument =
eventHandlerStatement.newState === '$toggle'
? t.unaryExpression('!', t.identifier(stateIdentifier.key))
: convertValueToLiteral(eventHandlerStatement.newState, stateIdentifier.type)
expressionContent =
expression.type === 'CallExpression' && expression.arguments.length === 0
? expression.callee
: t.arrowFunctionExpression([], expression)
} else {
expressionContent = t.arrowFunctionExpression([], t.blockStatement(eventHandlerASTStatements))
}
tag.openingElement.attributes.push(
t.jsxAttribute(t.jsxIdentifier(eventKey), t.jsxExpressionContainer(expressionContent))
return t.expressionStatement(
t.callExpression(t.identifier(stateIdentifier.setter), [stateSetterArgument])
)

@@ -164,1 +170,38 @@ }

}
/**
*
* @param tag the ref to the AST tag under construction
* @param key the key of the attribute that should be added on the current AST node
* @param value the value(string, number, bool) of the attribute that should be added on the current AST node
*/
export const addAttributeToTag = (tag: types.JSXElement, key: string, value: any) => {
if (typeof value !== 'string') {
addAttributeToJSXTag(tag, { name: key, value })
return
}
if (value.startsWith('$props.')) {
const dynamicPropValue = value.replace('$props.', '')
addDynamicPropOnJsxOpeningTag(tag, key, dynamicPropValue, 'props')
} else if (value.startsWith('$state.')) {
const dynamicPropValue = value.replace('$state.', '')
addDynamicPropOnJsxOpeningTag(tag, key, dynamicPropValue)
} else if (value === '$item' || value === '$index') {
addDynamicPropOnJsxOpeningTag(tag, key, value.slice(1))
} else {
addAttributeToJSXTag(tag, { name: key, value })
}
}
export const addTextElementToTag = (tag: types.JSXElement, text: string) => {
if (text.startsWith('$props.') && !text.endsWith('$props.')) {
addDynamicChild(tag, text.replace('$props.', ''), 'props')
} else if (text.startsWith('$state.') && !text.endsWith('$state.')) {
addDynamicChild(tag, text.replace('$state.', ''))
} else if (text === '$item' || text === '$index') {
addDynamicChild(tag, text.slice(1))
} else {
addChildJSXText(tag, text)
}
}

@@ -9,2 +9,31 @@ import { ComponentPlugin, ComponentPluginFactory } from '../../types'

interface InlineStyleConfig {
componentChunkName: string
}
export const createPlugin: ComponentPluginFactory<InlineStyleConfig> = (config) => {
const { componentChunkName = 'react-component' } = config || {}
/**
* Generate the inlines stlye definition as a AST block which will represent the
* defined styles of this component in UIDL
*
* @param structure : ComponentStructure
*/
const reactInlineStyleComponentPlugin: ComponentPlugin = async (structure) => {
const { uidl, chunks } = structure
const componentChunk = chunks.find((chunk) => chunk.name === componentChunkName)
if (!componentChunk) {
return structure
}
enhanceJSXWithStyles(uidl.content, componentChunk.meta.nodesLookup)
return structure
}
return reactInlineStyleComponentPlugin
}
export default createPlugin()
const prepareDynamicProps = (styles: UIDLTypes.StyleDefinitions) => {

@@ -60,30 +89,1 @@ return Object.keys(styles).reduce((acc: any, key) => {

}
interface InlineStyleConfig {
componentChunkName: string
}
export const createPlugin: ComponentPluginFactory<InlineStyleConfig> = (config) => {
const { componentChunkName = 'react-component' } = config || {}
/**
* Generate the inlines stlye definition as a AST block which will represent the
* defined styles of this component in UIDL
*
* @param structure : ComponentStructure
*/
const reactInlineStyleComponentPlugin: ComponentPlugin = async (structure) => {
const { uidl, chunks } = structure
const componentChunk = chunks.find((chunk) => chunk.name === componentChunkName)
if (!componentChunk) {
return structure
}
enhanceJSXWithStyles(uidl.content, componentChunk.meta.nodesLookup)
return structure
}
return reactInlineStyleComponentPlugin
}
export default createPlugin()

@@ -15,60 +15,2 @@ import * as t from '@babel/types'

const prepareDynamicProps = (styles: StyleDefinitions) => {
return Object.keys(styles).reduce((acc: any, key) => {
const value = styles[key]
if (typeof value === 'string' && value.startsWith('$props.')) {
acc[key] = new ParsedASTNode(
t.arrowFunctionExpression(
[t.identifier('props')],
t.memberExpression(t.identifier('props'), t.identifier(value.replace('$props.', '')))
)
)
} else {
acc[key] = styles[key]
}
return acc
}, {})
}
const generateStyleTagStrings = (
content: ContentNode,
nodesLookup: Record<string, t.JSXElement>
) => {
let accumulator: { [key: string]: any } = {}
const { styles, children, key, repeat } = content
if (styles) {
const root = nodesLookup[key]
const className = cammelCaseToDashCase(key)
accumulator[className] = prepareDynamicProps(styles)
// addClassStringOnJSXTag(root.node, className)
addDynamicPropOnJsxOpeningTag(root, 'className', `classes['${className}']`, 'props')
}
if (repeat) {
const items = generateStyleTagStrings(repeat.content, nodesLookup)
accumulator = {
...accumulator,
...items,
}
}
if (children) {
children.forEach((child) => {
if (typeof child === 'string') {
return
}
// only call on children if they are not strings
const items = generateStyleTagStrings(child, nodesLookup)
accumulator = {
...accumulator,
...items,
}
})
}
return accumulator
}
interface JSSConfig {

@@ -154,1 +96,59 @@ styleChunkName?: string

export default createPlugin()
const prepareDynamicProps = (styles: StyleDefinitions) => {
return Object.keys(styles).reduce((acc: any, key) => {
const value = styles[key]
if (typeof value === 'string' && value.startsWith('$props.')) {
acc[key] = new ParsedASTNode(
t.arrowFunctionExpression(
[t.identifier('props')],
t.memberExpression(t.identifier('props'), t.identifier(value.replace('$props.', '')))
)
)
} else {
acc[key] = styles[key]
}
return acc
}, {})
}
const generateStyleTagStrings = (
content: ContentNode,
nodesLookup: Record<string, t.JSXElement>
) => {
let accumulator: { [key: string]: any } = {}
const { styles, children, key, repeat } = content
if (styles) {
const root = nodesLookup[key]
const className = cammelCaseToDashCase(key)
accumulator[className] = prepareDynamicProps(styles)
// addClassStringOnJSXTag(root.node, className)
addDynamicPropOnJsxOpeningTag(root, 'className', `classes['${className}']`, 'props')
}
if (repeat) {
const items = generateStyleTagStrings(repeat.content, nodesLookup)
accumulator = {
...accumulator,
...items,
}
}
if (children) {
children.forEach((child) => {
if (typeof child === 'string') {
return
}
// only call on children if they are not strings
const items = generateStyleTagStrings(child, nodesLookup)
accumulator = {
...accumulator,
...items,
}
})
}
return accumulator
}

@@ -47,2 +47,3 @@ import { ComponentPlugin, ComponentPluginFactory } from '../../../types'

path: 'prop-types',
version: '15.7.2',
}

@@ -49,0 +50,0 @@

@@ -14,2 +14,43 @@ import preset from 'jss-preset-default'

interface StyledJSXConfig {
componentChunkName: string
}
export const createPlugin: ComponentPluginFactory<StyledJSXConfig> = (config) => {
const { componentChunkName = 'react-component' } = config || {}
const reactStyledJSXChunkPlugin: ComponentPlugin = async (structure) => {
const { uidl, chunks } = structure
const { content } = uidl
const componentChunk = chunks.find((chunk) => chunk.name === componentChunkName)
if (!componentChunk) {
return structure
}
const jsxNodesLookup = componentChunk.meta.nodesLookup
const styleJSXString = generateStyledJSXString(content, jsxNodesLookup)
if (!styleJSXString || !styleJSXString.length) {
return structure
}
const jsxASTNodeReference = generateStyledJSXTag(styleJSXString.join('\n'))
const rootJSXNode = jsxNodesLookup[content.key]
// We have the ability to insert the tag into the existig JSX structure, or do something else with it.
// Here we take the JSX <style> tag and we insert it as the last child of the JSX structure
// inside the React Component
rootJSXNode.children.push(jsxASTNodeReference)
return structure
}
return reactStyledJSXChunkPlugin
}
export default createPlugin()
const prepareDynamicProps = (styles: StyleDefinitions) => {

@@ -85,41 +126,1 @@ return Object.keys(styles).reduce((acc: any, key) => {

}
interface StyledJSXConfig {
componentChunkName: string
}
export const createPlugin: ComponentPluginFactory<StyledJSXConfig> = (config) => {
const { componentChunkName = 'react-component' } = config || {}
const reactStyledJSXChunkPlugin: ComponentPlugin = async (structure) => {
const { uidl, chunks } = structure
const { content } = uidl
const componentChunk = chunks.find((chunk) => chunk.name === componentChunkName)
if (!componentChunk) {
return structure
}
const jsxNodesLookup = componentChunk.meta.nodesLookup
const styleJSXString = generateStyledJSXString(content, jsxNodesLookup)
if (!styleJSXString || !styleJSXString.length) {
return structure
}
const jsxASTNodeReference = generateStyledJSXTag(styleJSXString.join('\n'))
const rootJSXNode = jsxNodesLookup[content.key]
// We have the ability to insert the tag into the existig JSX structure, or do something else with it.
// Here we take the JSX <style> tag and we insert it as the last child of the JSX structure
// inside the React Component
rootJSXNode.children.push(jsxASTNodeReference)
return structure
}
return reactStyledJSXChunkPlugin
}
export default createPlugin()

@@ -9,2 +9,48 @@ import preset from 'jss-preset-default'

interface VueStyleChunkConfig {
chunkName: string
vueJSChunk: string
vueTemplateChunk: string
styleFileId: string
}
export const createPlugin: ComponentPluginFactory<VueStyleChunkConfig> = (config) => {
const {
chunkName = 'vue-component-style-chunk',
vueTemplateChunk = 'vue-component-template-chunk',
styleFileId = null,
} = config || {}
const vueComponentStyleChunkPlugin: ComponentPlugin = async (structure) => {
const { uidl, chunks } = structure
const { content } = uidl
const templateChunk = chunks.filter((chunk) => chunk.name === vueTemplateChunk)[0]
const templateLookup = templateChunk.meta.lookup
const jssStylesArray = generateStyleTagStrings(content, templateLookup)
chunks.push({
type: 'string',
name: chunkName,
meta: {
fileId: styleFileId,
},
wrap: styleFileId
? undefined
: (generatedContent) => {
return `<style>\n${generatedContent}</style>`
},
content: jssStylesArray.join('\n'),
})
return structure
}
return vueComponentStyleChunkPlugin
}
export default createPlugin()
const filterOutDynamicStyles = (styles: StyleDefinitions) => {

@@ -74,47 +120,1 @@ if (!styles) {

}
interface VueStyleChunkConfig {
chunkName: string
vueJSChunk: string
vueTemplateChunk: string
styleFileId: string
}
export const createPlugin: ComponentPluginFactory<VueStyleChunkConfig> = (config) => {
const {
chunkName = 'vue-component-style-chunk',
vueTemplateChunk = 'vue-component-template-chunk',
styleFileId = null,
} = config || {}
const vueComponentStyleChunkPlugin: ComponentPlugin = async (structure) => {
const { uidl, chunks } = structure
const { content } = uidl
const templateChunk = chunks.filter((chunk) => chunk.name === vueTemplateChunk)[0]
const templateLookup = templateChunk.meta.lookup
const jssStylesArray = generateStyleTagStrings(content, templateLookup)
chunks.push({
type: 'string',
name: chunkName,
meta: {
fileId: styleFileId,
},
wrap: styleFileId
? undefined
: (generatedContent) => {
return `<style>\n${generatedContent}</style>`
},
content: jssStylesArray.join('\n'),
})
return structure
}
return vueComponentStyleChunkPlugin
}
export default createPlugin()

@@ -1,2 +0,2 @@

import { ComponentAssemblyLine, Builder, Resolver } from '../pipeline'
import { AssemblyLine, Builder, Resolver } from '../pipeline'

@@ -12,5 +12,4 @@ import { createPlugin as reactComponent } from '../plugins/react/react-base-component'

import htmlMapping from '../../uidl-definitions/elements-mapping/html-mapping.json'
import reactMapping from './elements-mapping.json'
import { ComponentPlugin } from '../types'
import { groupChunksByFileId } from './utils'
import reactMapping from './react-mapping.json'
import { ComponentPlugin, ReactComponentStylingFlavors } from '../types'
import { ComponentUIDL, ElementsMapping } from '../../uidl-definitions/types'

@@ -51,6 +50,6 @@

const stylePlugins: Record<string, ComponentPlugin> = {
InlineStyles: configuredReactInlineStyles,
StyledJSX: configuredReactStyledJSX,
JSS: configuredReactJSS,
CSSModules: configuredReactCSSModules,
[ReactComponentStylingFlavors.InlineStyles]: configuredReactInlineStyles,
[ReactComponentStylingFlavors.StyledJSX]: configuredReactStyledJSX,
[ReactComponentStylingFlavors.JSS]: configuredReactJSS,
[ReactComponentStylingFlavors.CSSModules]: configuredReactCSSModules,
}

@@ -75,3 +74,3 @@

})
const assemblyLine = new ComponentAssemblyLine([
const assemblyLine = new AssemblyLine([
configuredReactJSX,

@@ -86,3 +85,3 @@ stylePlugin,

const result = await assemblyLine.run(resolvedUidl)
const chunksByFileId = groupChunksByFileId(result.chunks)
const chunksByFileId = assemblyLine.groupChunksByFileId(result.chunks)

@@ -89,0 +88,0 @@ const code = chunksLinker.link(chunksByFileId.default)

@@ -1,2 +0,2 @@

import { ComponentAssemblyLine, Builder, Resolver } from '../pipeline'
import { AssemblyLine, Builder, Resolver } from '../pipeline'

@@ -14,3 +14,3 @@ import { createPlugin as reactComponent } from '../plugins/react/react-base-component'

GeneratorOptions,
ReactComponentFlavors,
ReactComponentStylingFlavors,
ComponentGenerator,

@@ -22,35 +22,11 @@ CompiledComponent,

import htmlMapping from '../../uidl-definitions/elements-mapping/html-mapping.json'
import reactMapping from './elements-mapping.json'
import { groupChunksByFileId } from './utils'
import reactMapping from './react-mapping.json'
interface ReactGeneratorFactoryParams {
variation?: ReactComponentFlavors
variation?: ReactComponentStylingFlavors
customMapping?: ElementsMapping
}
const chooseStylePlugin = (variation: ReactComponentFlavors) => {
switch (variation) {
case ReactComponentFlavors.CSSModules:
return reactCSSModules({
componentChunkName: 'react-component',
})
case ReactComponentFlavors.InlineStyles:
return reactInlineStyles({
componentChunkName: 'react-component',
})
case ReactComponentFlavors.JSS:
return reactJSS({
componentChunkName: 'react-component',
importChunkName: 'import',
exportChunkName: 'export',
})
case ReactComponentFlavors.StyledJSX:
return reactStyledJSX({
componentChunkName: 'react-component',
})
}
}
const createReactGenerator = (params: ReactGeneratorFactoryParams = {}): ComponentGenerator => {
const { variation = ReactComponentFlavors.CSSModules, customMapping = {} } = params
const { variation = ReactComponentStylingFlavors.InlineStyles, customMapping = {} } = params

@@ -62,3 +38,3 @@ const resolver = new Resolver()

const assemblyLine = new ComponentAssemblyLine()
const assemblyLine = new AssemblyLine()
assemblyLine.addPlugin(

@@ -92,3 +68,3 @@ reactComponent({

const chunksByFileId = groupChunksByFileId(result.chunks)
const chunksByFileId = assemblyLine.groupChunksByFileId(result.chunks)

@@ -113,2 +89,29 @@ const code = chunksLinker.link(chunksByFileId.default)

const chooseStylePlugin = (variation: ReactComponentStylingFlavors) => {
switch (variation) {
case ReactComponentStylingFlavors.CSSModules:
return reactCSSModules({
componentChunkName: 'react-component',
})
case ReactComponentStylingFlavors.InlineStyles:
return reactInlineStyles({
componentChunkName: 'react-component',
})
case ReactComponentStylingFlavors.JSS:
return reactJSS({
componentChunkName: 'react-component',
importChunkName: 'import',
exportChunkName: 'export',
})
case ReactComponentStylingFlavors.StyledJSX:
return reactStyledJSX({
componentChunkName: 'react-component',
})
default:
return reactInlineStyles({
componentChunkName: 'react-component',
})
}
}
export default createReactGenerator
import { createPlugin as importStatements } from '../plugins/common/import-statements'
import { createPlugin as appRoutingPlugin } from '../plugins/react/react-app-routing'
import { ComponentAssemblyLine, Builder, Resolver } from '../pipeline'
import { AssemblyLine, Builder, Resolver } from '../pipeline'
import { ComponentUIDL } from '../../uidl-definitions/types'
import htmlMapping from '../../uidl-definitions/elements-mapping/html-mapping.json'
import reactMapping from './elements-mapping.json'
import reactMapping from './react-mapping.json'

@@ -25,6 +25,3 @@ const createRouterComponentGenerator = () => {

const assemblyLine = new ComponentAssemblyLine([
configureAppRouterComponent,
configureImportStatements,
])
const assemblyLine = new AssemblyLine([configureAppRouterComponent, configureImportStatements])
const chunksLinker = new Builder()

@@ -31,0 +28,0 @@

@@ -154,2 +154,20 @@ import * as types from '@babel/types'

export const addAttributeToJSXTag = (
jsxNode: types.JSXElement,
attribute: { name: string; value?: any },
t = types
) => {
const nameOfAttribute = t.jsxIdentifier(attribute.name)
let attributeDefinition
if (typeof attribute.value === 'boolean') {
attributeDefinition = t.jsxAttribute(nameOfAttribute)
} else {
attributeDefinition = t.jsxAttribute(
nameOfAttribute,
getProperAttributeValueAssignment(attribute.value)
)
}
jsxNode.openingElement.attributes.push(attributeDefinition)
}
/**

@@ -181,19 +199,2 @@ * node must be a AST node element of type JSXElement (babel-types) or

}
export const addAttributeToJSXTag = (
jsxNode: types.JSXElement,
attribute: { name: string; value?: any },
t = types
) => {
const nameOfAttribute = t.jsxIdentifier(attribute.name)
let attributeDefinition
if (typeof attribute.value === 'boolean') {
attributeDefinition = t.jsxAttribute(nameOfAttribute)
} else {
attributeDefinition = t.jsxAttribute(
nameOfAttribute,
getProperAttributeValueAssignment(attribute.value)
)
}
jsxNode.openingElement.attributes.push(attributeDefinition)
}

@@ -200,0 +201,0 @@ /**

import { StateDefinition } from '../../uidl-definitions/types'
import { ASSETS_IDENTIFIER } from '../constants'

@@ -43,1 +44,13 @@ /**

}
export const prefixPlaygroundAssetsURL = (prefix: string, originalString: string | undefined) => {
if (!originalString || !originalString.startsWith(ASSETS_IDENTIFIER)) {
return originalString
}
if (originalString.startsWith('/')) {
return prefix + originalString
}
return `${prefix}/${originalString}`
}
import cheerio from 'cheerio'
export const createXMLRoot = (
tagName: string,
options = { selfClosing: false }
): CheerioStatic => {
export const createXMLRoot = (tagName: string, options = { selfClosing: false }): CheerioStatic => {
const emptyDeclaration = options.selfClosing ? `<${tagName}/>` : `<${tagName}></${tagName}>`

@@ -8,0 +5,0 @@ let result

@@ -1,2 +0,2 @@

import { ComponentAssemblyLine, Builder, Resolver } from '../pipeline'
import { AssemblyLine, Builder, Resolver } from '../pipeline'

@@ -11,3 +11,3 @@ import { createPlugin as vueBaseComponent } from '../plugins/vue/vue-base-component'

import htmlMapping from '../../uidl-definitions/elements-mapping/html-mapping.json'
import vueMapping from './elements-mapping.json'
import vueMapping from './vue-mapping.json'

@@ -18,3 +18,3 @@ const createVueGenerator = (

const resolver = new Resolver({ ...htmlMapping, ...vueMapping, ...customMapping })
const assemblyLine = new ComponentAssemblyLine([
const assemblyLine = new AssemblyLine([
vueBaseComponent({

@@ -21,0 +21,0 @@ jsFileId: 'vuejs',

@@ -1,2 +0,2 @@

import { ComponentAssemblyLine, Builder, Resolver } from '../pipeline'
import { AssemblyLine, Builder, Resolver } from '../pipeline'

@@ -10,7 +10,7 @@ import { createPlugin as createRouterPlugin } from '../plugins/vue/vue-router'

import htmlMapping from '../../uidl-definitions/elements-mapping/html-mapping.json'
import vueMapping from './elements-mapping.json'
import vueMapping from './vue-mapping.json'
const createVuePipeline = ({ customMapping }: GeneratorOptions = {}) => {
const resolver = new Resolver({ ...htmlMapping, ...vueMapping, ...customMapping })
const assemblyLine = new ComponentAssemblyLine([
const assemblyLine = new AssemblyLine([
createRouterPlugin({

@@ -17,0 +17,0 @@ codeChunkName: 'vue-router',

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

import reactProjectMapping from './elements-mapping.json'
import reactProjectMapping from './react-project-mapping.json'
import createRouterComponentGenerator from '../../component-generators/react/react-router'
import createReactGenerator from '../../component-generators/react/react-component'
import { ReactComponentFlavors } from '../../component-generators/types'
import { ReactComponentStylingFlavors } from '../../component-generators/types'
import { extractPageMetadata } from '../../component-generators/utils/uidl-utils'
import { extractExternalDependencies, createManifestJSON } from '../utils/generator-utils'
import { createPackageJSON, createManifestJSON } from '../utils/generator-utils'

@@ -13,2 +13,3 @@ import { File, Folder, ProjectGeneratorOptions } from '../types'

import { createHtmlIndexFile } from './utils'
import { ASSETS_PREFIX, DEFAULT_OUTPUT_FOLDER, DEFAULT_PACKAGE_JSON } from './constants'

@@ -18,3 +19,3 @@ export default async (uidl: ProjectUIDL, options: ProjectGeneratorOptions = {}) => {

const reactGenerator = createReactGenerator({
variation: ReactComponentFlavors.CSSModules,
variation: ReactComponentStylingFlavors.CSSModules,
})

@@ -50,3 +51,3 @@

const distFolder: Folder = {
name: options.distPath || 'dist',
name: options.distPath || DEFAULT_OUTPUT_FOLDER,
files: [],

@@ -66,7 +67,6 @@ subFolders: [srcFolder],

const stateDefinitions = root.stateDefinitions
const assetsPrefix = '/static'
const result = {
outputFolder: distFolder,
assetsPath: assetsPrefix,
assetsPath: 'src' + ASSETS_PREFIX,
}

@@ -85,3 +85,3 @@

if (uidl.globals.manifest) {
const manifestJSON = createManifestJSON(uidl.globals.manifest, uidl.name)
const manifestJSON = createManifestJSON(uidl.globals.manifest, uidl.name, ASSETS_PREFIX)
const manifestFile: File = {

@@ -144,2 +144,3 @@ name: 'manifest',

localDependenciesPrefix: '../components/',
assetsPrefix: ASSETS_PREFIX,
})

@@ -177,3 +178,5 @@

const component = components[componentName]
const compiledComponent = await reactGenerator.generateComponent(component)
const compiledComponent = await reactGenerator.generateComponent(component, {
assetsPrefix: ASSETS_PREFIX,
})

@@ -208,20 +211,20 @@ let cssFile: File | null = null

const { sourcePackageJson } = options
if (sourcePackageJson) {
const externalDep = extractExternalDependencies(allDependencies)
sourcePackageJson.dependencies = {
...sourcePackageJson.dependencies,
...externalDep,
const packageJSON = createPackageJSON(
sourcePackageJson || DEFAULT_PACKAGE_JSON,
allDependencies,
{
projectName: uidl.name,
}
)
const packageFile: File = {
name: 'package',
extension: '.json',
content: JSON.stringify(sourcePackageJson, null, 2),
}
distFolder.files.push(packageFile)
const packageFile: File = {
name: 'package',
extension: '.json',
content: JSON.stringify(packageJSON, null, 2),
}
distFolder.files.push(packageFile)
return result
}
import { generator } from '../../component-generators/pipeline/builder/generators/html-to-string'
import { createXMLNode, createXMLRoot } from '../../component-generators/utils/xml'
import { ProjectUIDL } from '../../uidl-definitions/types'
import { ASSETS_PREFIX } from './constants'
import { prefixPlaygroundAssetsURL } from '../../component-generators/utils/uidl-utils'

@@ -39,3 +41,4 @@ export const createHtmlIndexFile = (uidl: ProjectUIDL) => {

Object.keys(metaItem).forEach((key) => {
metaTag.attr(key, metaItem[key])
const prefixedURL = prefixPlaygroundAssetsURL(ASSETS_PREFIX, metaItem[key])
metaTag.attr(key, prefixedURL)
})

@@ -46,7 +49,9 @@ headNode.append(metaTag)

assets.forEach((asset) => {
const assetPath = prefixPlaygroundAssetsURL(ASSETS_PREFIX, asset.path)
// link stylesheet (external css, font)
if ((asset.type === 'style' || asset.type === 'font') && asset.path) {
if ((asset.type === 'style' || asset.type === 'font') && assetPath) {
const linkTag = createXMLNode('link', { selfClosing: true })
linkTag.attr('rel', 'stylesheet')
linkTag.attr('href', asset.path)
linkTag.attr('href', assetPath)
headNode.append(linkTag)

@@ -68,4 +73,4 @@ }

scriptTag.attr('type', 'text/javascript')
if (asset.path) {
scriptTag.attr('src', asset.path)
if (assetPath) {
scriptTag.attr('src', assetPath)
if (asset.meta && asset.meta.defer) {

@@ -88,6 +93,6 @@ scriptTag.attr('defer', true)

// icon
if (asset.type === 'icon' && asset.path) {
if (asset.type === 'icon' && assetPath) {
const iconTag = createXMLNode('link', { selfClosing: true })
iconTag.attr('rel', 'shortcut icon')
iconTag.attr('href', asset.path)
iconTag.attr('href', assetPath)
if (typeof asset.meta === 'object') {

@@ -94,0 +99,0 @@ const assetMeta = asset.meta

import { Folder, File, ProjectGeneratorOptions } from '../types'
import { ReactComponentFlavors } from '../../component-generators/types'
import { ReactComponentStylingFlavors } from '../../component-generators/types'
import { ProjectUIDL, ComponentDependency, ComponentUIDL } from '../../uidl-definitions/types'
import { extractExternalDependencies, createManifestJSON } from '../utils/generator-utils'
import { createManifestJSON, createPackageJSON } from '../utils/generator-utils'

@@ -11,3 +11,4 @@ import createReactGenerator from '../../component-generators/react/react-component'

import { createDocumentComponent } from './utils'
import nextMapping from './elements-mapping.json'
import nextMapping from './next-mapping.json'
import { ASSETS_PREFIX, DEFAULT_OUTPUT_FOLDER, DEFAULT_PACKAGE_JSON } from './constants'

@@ -17,3 +18,3 @@ export default async (uidl: ProjectUIDL, options: ProjectGeneratorOptions = {}) => {

const reactGenerator = createReactGenerator({
variation: ReactComponentFlavors.StyledJSX,
variation: ReactComponentStylingFlavors.StyledJSX,
customMapping: nextMapping,

@@ -42,3 +43,3 @@ })

const distFolder: Folder = {
name: options.distPath || 'dist',
name: options.distPath || DEFAULT_OUTPUT_FOLDER,
files: [],

@@ -55,3 +56,2 @@ subFolders: [pagesFolder, componentsFolder, staticFolder],

let allDependencies: Record<string, ComponentDependency> = {}
const assetsPrefix = '/static'
const { components, root } = uidl

@@ -63,3 +63,3 @@ const states = root.content.states

outputFolder: distFolder,
assetsPath: assetsPrefix,
assetsPath: ASSETS_PREFIX.slice(1),
}

@@ -78,3 +78,3 @@

if (uidl.globals.manifest) {
const manifestJSON = createManifestJSON(uidl.globals.manifest, uidl.name)
const manifestJSON = createManifestJSON(uidl.globals.manifest, uidl.name, ASSETS_PREFIX)
const manifestFile: File = {

@@ -123,3 +123,3 @@ name: 'manifest',

localDependenciesPrefix: '../components/',
assetsPrefix,
assetsPrefix: ASSETS_PREFIX,
})

@@ -153,3 +153,3 @@

const compiledComponent = await reactGenerator.generateComponent(component, {
assetsPrefix,
assetsPrefix: ASSETS_PREFIX,
})

@@ -177,19 +177,20 @@ const file: File = {

const { sourcePackageJson } = options
if (sourcePackageJson) {
const externalDep = extractExternalDependencies(allDependencies)
sourcePackageJson.dependencies = {
...sourcePackageJson.dependencies,
...externalDep,
}
const packageFile: File = {
name: 'package',
extension: '.json',
content: JSON.stringify(sourcePackageJson, null, 2),
const packageJSON = createPackageJSON(
sourcePackageJson || DEFAULT_PACKAGE_JSON,
allDependencies,
{
projectName: uidl.name,
}
)
distFolder.files.push(packageFile)
const packageFile: File = {
name: 'package',
extension: '.json',
content: JSON.stringify(packageJSON, null, 2),
}
distFolder.files.push(packageFile)
return result
}

@@ -10,2 +10,4 @@ import { generator } from '../../component-generators/pipeline/builder/generators/js-ast-to-code'

import { ProjectUIDL } from '../../uidl-definitions/types'
import { ASSETS_PREFIX } from './constants'
import { prefixPlaygroundAssetsURL } from '../../component-generators/utils/uidl-utils'

@@ -47,3 +49,4 @@ export const createDocumentComponent = (uidl: ProjectUIDL, t = types) => {

Object.keys(metaItem).forEach((key) => {
addAttributeToJSXTag(metaTag, { name: key, value: metaItem[key] })
const metaValue = prefixPlaygroundAssetsURL(ASSETS_PREFIX, metaItem[key])
addAttributeToJSXTag(metaTag, { name: key, value: metaValue })
})

@@ -54,7 +57,9 @@ addChildJSXTag(headNode, metaTag)

assets.forEach((asset) => {
const assetPath = prefixPlaygroundAssetsURL(ASSETS_PREFIX, asset.path)
// link stylesheet (external css, font)
if ((asset.type === 'style' || asset.type === 'font') && asset.path) {
if ((asset.type === 'style' || asset.type === 'font') && assetPath) {
const linkTag = generateASTDefinitionForJSXTag('link')
addAttributeToJSXTag(linkTag, { name: 'rel', value: 'stylesheet' })
addAttributeToJSXTag(linkTag, { name: 'href', value: asset.path })
addAttributeToJSXTag(linkTag, { name: 'href', value: assetPath })
addChildJSXTag(headNode, linkTag)

@@ -77,4 +82,4 @@ }

addAttributeToJSXTag(scriptTag, { name: 'type', value: 'text/javascript' })
if (asset.path) {
addAttributeToJSXTag(scriptTag, { name: 'src', value: asset.path })
if (assetPath) {
addAttributeToJSXTag(scriptTag, { name: 'src', value: assetPath })
if (asset.meta && asset.meta.defer) {

@@ -101,6 +106,6 @@ addAttributeToJSXTag(scriptTag, { name: 'defer', value: true })

// icon
if (asset.type === 'icon' && asset.path) {
if (asset.type === 'icon' && assetPath) {
const iconTag = generateASTDefinitionForJSXTag('link')
addAttributeToJSXTag(iconTag, { name: 'rel', value: 'shortcut icon' })
addAttributeToJSXTag(iconTag, { name: 'href', value: asset.path })
addAttributeToJSXTag(iconTag, { name: 'href', value: assetPath })

@@ -107,0 +112,0 @@ if (typeof asset.meta === 'object') {

@@ -16,3 +16,3 @@ import { ProjectUIDL, ElementsMapping } from '../../uidl-definitions/types'

export interface ProjectGeneratorOptions {
sourcePackageJson?: Record<string, any>
sourcePackageJson?: PackageJSON
distPath?: string

@@ -29,1 +29,12 @@ customMapping?: ElementsMapping

}>
export interface PackageJSON {
name: string
description: string
version: string
main: string
author: string
license: string
scripts?: Record<string, string>
dependencies?: Record<string, string>
}
import { ComponentDependency, WebManifest } from '../../uidl-definitions/types'
import { PackageJSON } from '../../project-generators/types'
import { prefixPlaygroundAssetsURL } from '../../component-generators/utils/uidl-utils'
// Only package dependencies are needed for the package.json file
export const extractExternalDependencies = (dependencies: Record<string, ComponentDependency>) => {

@@ -20,3 +21,7 @@ return Object.keys(dependencies)

// Creates a manifest json with the UIDL having priority over the default values
export const createManifestJSON = (manifest: WebManifest, projectName?: string) => {
export const createManifestJSON = (
manifest: WebManifest,
projectName: string,
assetsPrefix?: string
) => {
const defaultManifest: WebManifest = {

@@ -29,6 +34,33 @@ short_name: projectName,

const icons = manifest.icons.map((icon) => {
const src = prefixPlaygroundAssetsURL(assetsPrefix, icon.src)
return { ...icon, src }
})
return {
...defaultManifest,
...manifest,
...{ icons },
}
}
export const createPackageJSON = (
packageJSONTemplate: PackageJSON,
dependencies: Record<string, ComponentDependency>,
overwrites: {
projectName: string
}
): PackageJSON => {
const { projectName } = overwrites
const externalDep = extractExternalDependencies(dependencies)
return {
...packageJSONTemplate,
name: projectName,
dependencies: {
...packageJSONTemplate.dependencies,
...externalDep,
},
}
}

@@ -9,3 +9,3 @@ import createVueGenerator from '../../component-generators/vue/vue-component'

import vueProjectMapping from './elements-mapping.json'
import vueProjectMapping from './vue-project-mapping.json'

@@ -12,0 +12,0 @@ export default async (uidl: ProjectUIDL, options: ProjectGeneratorOptions = {}) => {

@@ -7,3 +7,3 @@ import { File, Folder, ProjectGeneratorOptions } from '../types'

import createVueGenerator from '../../component-generators/vue/vue-component'
import nuxtMapping from './elements-mapping.json'
import nuxtMapping from './nuxt-mapping.json'

@@ -10,0 +10,0 @@ export default async (uidl: ProjectUIDL, options: ProjectGeneratorOptions = {}) => {

@@ -141,7 +141,28 @@ {

"video": {
"type": "video"
"type": "video",
"children": [
"$children",
"This browser does not support the video formats given"
]
},
"audio": {
"type": "audio"
"type": "audio",
"children": [
"$children",
"This browser does not support the audio formats given"
]
},
"picture": {
"type": "picture",
"children": [
"$children",
"This browser does not support the image formats given"
]
},
"source": {
"type": "source",
"attrs": {
"src": "$attrs.url"
}
},
"svg": {

@@ -148,0 +169,0 @@ "type": "svg"

@@ -10,8 +10,3 @@ export interface ProjectUIDL {

meta: Array<Record<string, string>>
assets: Array<{
type: string
path?: string
content?: string
meta?: Record<string, any>
}>
assets: GlobalAsset[]
manifest?: WebManifest

@@ -24,2 +19,9 @@ variables?: Record<string, string>

export interface GlobalAsset {
type: string
path?: string
content?: string
meta?: Record<string, any>
}
export interface ComponentUIDL {

@@ -26,0 +28,0 @@ $schema?: string

@@ -9,3 +9,3 @@ {

"ordered-imports": false,
"curly": false,
"curly": true,
"no-submodule-imports": false,

@@ -12,0 +12,0 @@ "interface-name": [true, "never-prefix"],

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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