views-morph
Version:
Views language morpher
1,789 lines (1,406 loc) • 94.2 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var path = require('path');
var buble = _interopDefault(require('buble'));
var toCamelCase = _interopDefault(require('to-camel-case'));
var toSlugCase = _interopDefault(require('to-slug-case'));
var list = _interopDefault(require('google-fonts-complete/api-response.json'));
var toPascalCase = _interopDefault(require('to-pascal-case'));
var sort = _interopDefault(require('bubblesort'));
var prettier = _interopDefault(require('prettier'));
var Levenshtein = _interopDefault(require('levenshtein'));
var sortBy = _interopDefault(require('lodash.sortby'));
var wrap = (function (s) {
return "{" + s + "}";
});
var safe = (function (value) {
return typeof value === 'string' && !isSlot(value) ? JSON.stringify(value) : wrap(value);
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var defineProperty = function (obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
};
var objectWithoutProperties = function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
};
var slicedToArray = function () {
function sliceIterator(arr, i) {
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"]) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
return function (arr, i) {
if (Array.isArray(arr)) {
return arr;
} else if (Symbol.iterator in Object(arr)) {
return sliceIterator(arr, i);
} else {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
};
}();
var toArray = function (arr) {
return Array.isArray(arr) ? arr : Array.from(arr);
};
var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
};
var safeScope = function safeScope(value) {
return typeof value === 'string' && !isSlot(value) ? JSON.stringify(value) : value;
};
var checkParentStem = function checkParentStem(node, styleKey) {
if (styleKey !== 'hover' || styleKey !== 'disabled' || !node.parent) return false;
var matchingParentStem = node.parent.scopes.some(function (scope) {
return scope.value === styleKey;
});
return matchingParentStem && (node.parent.is || node.parent.name);
};
var INTERPOLATION = /\${(.+)}/;
var isInterpolation = function isInterpolation(str) {
return INTERPOLATION.test(str);
};
var deinterpolate = function deinterpolate(str) {
var match = str.match(INTERPOLATION);
return match ? match[1] : str;
};
var getObjectAsString = function getObjectAsString(obj) {
return wrap(Object.keys(obj).map(function (k) {
var v = _typeof(obj[k]) === 'object' && hasKeys(obj[k]) ? getObjectAsString(obj[k]) : obj[k];
return JSON.stringify(k) + ': ' + v;
}).join(','));
};
var getPropertiesAsObject = function getPropertiesAsObject(list$$1) {
var obj = {};
list$$1.forEach(function (prop) {
obj[prop.name] = safeScope(prop.value);
});
return getObjectAsString(obj);
};
var getProp = function getProp(node, key) {
var finder = typeof key === 'string' ? function (p) {
return p.name === key;
} : function (p) {
return key.test(p.name);
};
return node.properties && node.properties.find(finder);
};
var maybeSafe = function maybeSafe(node) {
return node.tags.slot ? node.value : typeof node.value === 'string' ? safe(node.value) : node.value;
};
var getScopedProps = function getScopedProps(propNode, blockNode) {
var scopes = blockNode.scopes.filter(function (scope) {
return !scope.isSystem;
}).map(function (scope) {
var prop = scope.properties.find(function (prop) {
return prop.name === propNode.name;
});
return prop && { prop: prop, when: scope.value };
}).filter(Boolean).reverse();
if (isEmpty(scopes)) return false;
return scopes;
};
var getScopedCondition = function getScopedCondition(propNode, blockNode) {
var conditional = maybeSafe(propNode);
if (!getScopedProps(propNode, blockNode)) return false;
getScopedProps(propNode, blockNode).forEach(function (scope) {
conditional = scope.when + ' ? ' + maybeSafe(scope.prop) + ' : ' + conditional;
});
return conditional;
};
var getScopedImageCondition = function getScopedImageCondition(scopes, scopedNames, defaultName) {
var conditional = defaultName;
scopes.forEach(function (scope, index) {
conditional = scope.when + ' ? ' + scopedNames[index] + ' : ' + conditional;
});
return conditional;
};
var getScopedRequireCondition = function getScopedRequireCondition(scopes, paths, defaultName) {
var conditional = 'requireImage(\'' + defaultName + '\')';
scopes.forEach(function (scope, index) {
conditional = scope.when + ' ? requireImage(\'' + paths[index] + '\') : ' + conditional;
});
return conditional;
};
var styleStems = ['hover', 'focus', 'placeholder', 'disabled', 'print'];
var getStyleType = function getStyleType(node) {
return styleStems.find(function (tag) {
return isTag(node, tag);
}) || 'base';
};
var hasKeys = function hasKeys(obj) {
return Object.keys(obj).length > 0;
};
var hasKeysInChildren = function hasKeysInChildren(obj) {
return Object.keys(obj).some(function (k) {
return hasKeys(obj[k]);
});
};
var hasProp = function hasProp(node, key, match) {
var prop = getProp(node, key);
if (!prop) return false;
return typeof match === 'function' ? match(prop.value) : true;
};
var isSlot = function isSlot(node) {
return typeof node === 'string' ? /props/.test(node) : isTag(node, 'slot');
};
var isStyle = function isStyle(node) {
return isTag(node, 'style');
};
var isTag = function isTag(node, tag) {
return node && node.tags[tag];
};
var getActionableParent = function getActionableParent(node) {
if (!node.parent) return false;
if (node.parent.action) return node.parent;
return getActionableParent(node.parent);
};
var getAllowedStyleKeys = function getAllowedStyleKeys(node) {
if (node.isCapture) {
return ['base', 'focus', 'hover', 'disabled', 'placeholder', 'print'];
} else if (node.action || getActionableParent(node)) {
return ['base', 'focus', 'hover', 'disabled', 'print'];
}
return ['base', 'focus', 'print'];
};
var isList = function isList(node) {
return node && node.type === 'Block' && node.name === 'List';
};
var isEmpty = function isEmpty(list$$1) {
return list$$1.length === 0;
};
var isValidImgSrc = function isValidImgSrc(node, parent) {
return node.name === 'source' && parent.name === 'Image' && parent.isBasic;
};
var pushImageToState = function pushImageToState(state, scopedNames, paths) {
return scopedNames.forEach(function (name) {
var path$$1 = paths[scopedNames.findIndex(function (item) {
return item === name;
})];
if (!state.images.includes(path$$1)) {
state.images.push({
name: name,
file: path$$1
});
}
});
};
var getScopes = function getScopes(node, parent) {
var scopedProps = getScopedProps(node, parent);
if (!scopedProps) return false;
var paths = scopedProps.map(function (scope) {
return scope.prop.value;
});
var scopedNames = paths.map(function (path$$1) {
return toCamelCase(path$$1);
});
return { scopedProps: scopedProps, paths: paths, scopedNames: scopedNames };
};
var isSvg = function isSvg(node) {
return (/^Svg/.test(node.name) && node.isBasic
);
};
var getScopeDescription = function getScopeDescription(scope) {
var dictionary = {};
var re = /(?:^|\W)props.(\w+)(?!\w)/g;
var match = re.exec(scope);
while (match) {
dictionary[match[1]] = toSlugCase(match[1]);
match = re.exec(scope);
}
for (var key in dictionary) {
scope = scope.replace(new RegExp(key, 'g'), dictionary[key]);
}
return toCamelCase(scope.replace(/\|\|/g, '-or-').replace(/!/g, 'not-').replace(/&&/g, '-and-').replace(/props\./g, '').replace(/\s/g, ''));
};
var makeOnClickTracker = function makeOnClickTracker(node, state) {
var block = node.testId ? '"' + state.name + '.' + node.testId + '"' : 'props["' + state.testIdKey + '"] || "' + state.name + '"';
state.isTracking = true;
return 'event => context.track({ block: ' + block + ', action: "click", callback: ' + node.value + ', event })';
};
var enter$1 = function enter(node, parent, state) {
if (node.name === 'Proxy') return;
var scopes = node.scopes.filter(function (scope) {
return !scope.isSystem;
}).map(function (scope) {
return scope.value;
}).filter(Boolean).reverse();
var conditional = scopes.reduce(function (prev, scope) {
return scope + ' ? \'' + getScopeDescription(scope) + '|\' : ' + prev;
}, "''");
conditional = scopes.length > 0 ? '${' + conditional + '}' : '';
var value = void 0;
if (parent) {
value = '{`' + state.name + '.' + node.testId + '|' + conditional + '`}';
} else {
value = '{`${props[\'' + state.testIdKey + '\'] || \'' + node.testId + '\'}|' + conditional + '`}';
}
state.render.push(' ' + state.testIdKey + '=' + value);
};
var typesMap = {
CaptureEmail: 'email',
CaptureText: 'text',
CaptureNumber: 'number',
CapturePhone: 'tel',
CaptureSecure: 'password'
};
var enter$2 = function enter(node, parent, state) {
var blockType = node.name;
if (!/Capture/.test(blockType)) return;
node.isCapture = true;
var name = toCamelCase(node.is || blockType);
state.captures.push(name);
if (typesMap[blockType]) {
state.render.push(' type=\'' + typesMap[blockType] + '\'');
}
// if you specify a value, then you're supposed to manage the input from
// outside the view
if (getProp(node, 'value')) return;
state.render.push(' onChange={event => this.setState({ ' + name + ': event.target.value })}');
state.render.push(' value={state.' + name + '}');
if (state.debug) {
state.render.push(' tabIndex={-1}');
}
};
function leave$1(node, parent, state) {
if (node.explicitChildren) {
state.render.push('>');
state.render.push(node.explicitChildren);
}
}
var enter$3 = function enter(node, parent, state) {
if (node.goTo) {
var goTo = getProp(node, 'goTo');
state.render.push(' href=' + safe(goTo.value, goTo) + ' rel=\'noopener noreferrer\' target=\'_blank\'');
}
};
function enter$4(node, parent, state) {
if (node.isGroup && node.children.length > 0) {
state.render.push('>');
}
}
function enter$5(node, parent, state) {
if (isList(parent)) {
state.render.push(' {...item} key={item.id || index}');
}
}
function enter$6(node, parent, state) {
if (isList(node)) {
var from = getProp(node, 'from');
if (!from) return;
state.render.push('{Array.isArray(' + from.value + ') && ' + from.value + '.map((item, index) => ');
}
}
function leave$2(node, parent, state) {
if (isList(node)) {
state.render.push(')}');
}
}
function leave$3(node, parent, state) {
if (!parent && node.isGroup || node.explicitChildren || node.isGroup && node.children.length > 0) {
if (!parent && node.isGroup) {
if (node.children.length === 0) {
state.render.push('>');
}
if (!node.usesProxy) {
state.render.push('{props.children}');
}
}
state.render.push('</' + node.nameFinal + '>');
} else {
state.render.push('/>');
}
}
var getBlockName = (function (node, parent, state) {
var name = node.name;
switch (node.name) {
case 'CaptureEmail':
case 'CaptureFile':
case 'CaptureNumber':
case 'CapturePhone':
case 'CaptureSecure':
case 'CaptureText':
name = 'input';
break;
case 'CaptureTextArea':
name = 'textarea';
break;
case 'Horizontal':
case 'Vertical':
name = getGroupBlockName(node, parent, state);
break;
case 'Image':
name = 'img';
break;
case 'Text':
return 'span';
case 'List':
name = 'div';
break;
case 'Proxy':
return null;
case 'Svg':
name = 'svg';
break;
case 'SvgGroup':
name = 'g';
break;
case 'SvgCircle':
case 'SvgEllipse':
case 'SvgLinearGradient':
case 'SvgRadialGradient':
case 'SvgLine':
case 'SvgText':
case 'SvgPath':
case 'SvgPolygon':
case 'SvgPolyline':
case 'SvgRect':
case 'SvgSymbol':
case 'SvgUse':
case 'SvgDefs':
case 'SvgStop':
name = toCamelCase(node.name.replace('Svg', ''));
break;
default:
break;
}
return name;
});
var getGroupBlockName = function getGroupBlockName(node, parent, state) {
var name = 'div';
if (hasProp(node, 'teleportTo')) {
name = 'Link';
node.teleport = true;
} else if (hasProp(node, 'goTo')) {
name = 'a';
node.goTo = true;
} else if (hasProp(node, 'onClick')) {
var propNode = getProp(node, 'onClick');
var prevParent = parent;
var canBeButton = true;
while (prevParent && canBeButton) {
if (prevParent.type === 'Block') {
canBeButton = !hasProp(prevParent, 'onClick');
}
prevParent = prevParent.parent;
}
if (canBeButton) {
name = 'button';
node.action = propNode.value;
}
} else if (hasProp(node, 'overflowY', function (v) {
return v === 'auto' || v === 'scroll';
})) {
name = 'div';
} else if (hasProp(node, 'onSubmit')) {
name = 'form';
}
return name;
};
function enter$7(node, parent, state) {
var name = getBlockName(node, parent, state);
if (name === null) return true;
node.nameFinal = name;
node.nameTag = name;
state.use(name);
if (node.isBasic) {
var hasDynamicStyles = node.properties.some(function (prop) {
return prop.tags.style && prop.tags.slot;
});
var hasDynamicScopedStyles = node.scopes.some(function (scope) {
return scope.isSystem ? scope.properties.some(function (prop) {
return prop.tags.style && prop.tags.slot;
}) : scope.properties.some(function (prop) {
return prop.tags.style;
});
});
// TODO expand to active, focus, etc
var hasHoverStem = node.scopes.some(function (scope) {
return scope.value === 'hover';
});
var hasMatchingParentWithHover = hasHoverStem && checkParentStem(node, 'hover');
node.isDynamic = hasDynamicStyles || hasDynamicScopedStyles || hasMatchingParentWithHover;
if (node.isDynamic) {
// we need to reset it to the block's name or value
var finalValue = node.is || node.name;
// count repeatead ones
if (state.usedBlockNames[finalValue]) {
finalValue = '' + finalValue + state.usedBlockNames[finalValue]++;
} else {
state.usedBlockNames[finalValue] = 1;
}
node.nameFinal = finalValue;
}
}
state.render.push('<' + node.nameFinal);
}
function enter$8(node, parent, state) {
// onWhen lets you show/hide blocks depending on props
var onWhen = getProp(node, 'onWhen');
if (onWhen) {
node.onWhen = true;
if (parent && !isList(parent)) state.render.push('{');
state.render.push(onWhen.value + ' ? ');
}
}
function leave$4(node, parent, state) {
if (node.onWhen) {
state.render.push(' : null');
if (parent && !isList(parent)) state.render.push('}');
}
}
function leave$5(node, parent, state) {
if (node.childrenProxyMap) {
state.render.push(' childrenProxyMap={' + getObjectAsString(node.childrenProxyMap) + '}');
}
}
var enter$10 = function enter(node, parent, state) {
node.className = ['views-block'];
var className = getProp(node, 'className');
if (className) {
node.className.push(className.tags.slot ? '${' + className.value + '}' : className.value);
}
if (state.debug && node.isCapture) {
node.className.push('mousetrap');
}
};
var leave$6 = function leave(node, parent, state) {
if (node.className.length === 1) {
var className = node.className[0];
var shouldWrap = true;
if (isInterpolation(className)) {
className = deinterpolate(className);
} else if (!isSlot(className)) {
className = '"' + className + '"';
shouldWrap = false;
}
state.render.push(' className=' + (shouldWrap ? wrap(className) : className));
} else if (node.className.length > 1) {
var _className = '`' + node.className.join(' ') + '`';
state.render.push(' className=' + wrap(_className));
}
};
var enter$11 = function enter(node, parent, state) {
// TODO caption
if (node.name === 'Image') {
state.render.push(' alt={""}');
}
};
function leave$7(node, parent, state) {
if (node.isRoute) {
state.render.push(' {...routeProps}');
}
}
function enter$12(node, parent, state) {
node.style = {
dynamic: {
base: {},
hover: {},
focus: {},
disabled: {},
placeholder: {},
print: {}
},
static: {
base: {},
hover: {},
focus: {},
disabled: {},
placeholder: {},
print: {}
}
// TODO use this directly in styles without having to go through this
};node.scopes.filter(function (scope) {
return scope.isSystem;
}).forEach(function (scope) {
scope.properties.forEach(function (propNode) {
if (propNode.name === 'when') return;
var _state$getStyleForPro = state.getStyleForProperty(propNode, node, isSlot(propNode)),
_isProp = _state$getStyleForPro._isProp,
styleForProperty = objectWithoutProperties(_state$getStyleForPro, ['_isProp']);
if (_isProp) {
Object.keys(styleForProperty).forEach(function (k) {
return state.render.push(' ' + k + '=' + safe(styleForProperty[k], node));
});
} else {
var hasMatchingParent = parent && node.isDynamic ? checkParentStem(node, scope.value) : false;
var target = isSlot(propNode) || hasMatchingParent ? node.style.dynamic : node.style.static;
Object.assign(target[scope.value], styleForProperty);
}
});
});
// ensure flex-direction in Horizontals
if (node.isGroup && node.name === 'Horizontal') {
node.style.static.base.flexDirection = 'row';
}
}
// https://raw.githubusercontent.com/threepointone/glam/master/src/hash.js
// murmurhash2 via https://gist.github.com/raycmorgan/588423
var hash = (function (arr) {
return 'h' + hash$1(arr);
});
function hash$1(arr) {
var str = (Array.isArray(arr) ? arr : Object.keys(arr).map(function (k) {
return k + ':' + JSON.stringify(arr[k]);
})).join(',');
return murmur2(str, str.length).toString(36);
}
function murmur2(str, seed) {
var m = 0x5bd1e995;
var r = 24;
var h = seed ^ str.length;
var length = str.length;
var currentIndex = 0;
while (length >= 4) {
var k = UInt32(str, currentIndex);
k = Umul32(k, m);
k ^= k >>> r;
k = Umul32(k, m);
h = Umul32(h, m);
h ^= k;
currentIndex += 4;
length -= 4;
}
switch (length) {
case 3:
h ^= UInt16(str, currentIndex);
h ^= str.charCodeAt(currentIndex + 2) << 16;
h = Umul32(h, m);
break;
case 2:
h ^= UInt16(str, currentIndex);
h = Umul32(h, m);
break;
case 1:
h ^= str.charCodeAt(currentIndex);
h = Umul32(h, m);
break;
}
h ^= h >>> 13;
h = Umul32(h, m);
h ^= h >>> 15;
return h >>> 0;
}
function UInt32(str, pos) {
return str.charCodeAt(pos++) + (str.charCodeAt(pos++) << 8) + (str.charCodeAt(pos++) << 16) + (str.charCodeAt(pos) << 24);
}
function UInt16(str, pos) {
return str.charCodeAt(pos++) + (str.charCodeAt(pos++) << 8);
}
function Umul32(n, m) {
n = n | 0;
m = m | 0;
var nlo = n & 0xffff;
var nhi = n >>> 16;
var res = nlo * m + ((nhi * m & 0xffff) << 16) | 0;
return res;
}
function leave$8(node, parent, state) {
var _node$style = node.style,
dynamic = _node$style.dynamic,
staticStyle = _node$style.static;
var allowedStyleKeys = getAllowedStyleKeys(node);
var scopedUnderParent = !node.isCapture && !node.action && getActionableParent(node);
if (scopedUnderParent) {
scopedUnderParent = scopedUnderParent.styleName;
}
// dynamic merges static styles
if (hasKeysInChildren(dynamic)) {
state.cssDynamic = true;
node.styleName = node.nameFinal;
var cssStatic = Object.keys(staticStyle).filter(function (key) {
return allowedStyleKeys.includes(key) && hasKeys(staticStyle[key]);
}).map(function (key) {
return asCss(asStaticCss(staticStyle[key], Object.keys(dynamic[key])), key, scopedUnderParent).join('\n');
}).join(',\n');
var cssDynamic = ['({ props }) => ({'];
cssDynamic = cssDynamic.concat(Object.keys(dynamic).filter(function (key) {
return allowedStyleKeys.includes(key) && hasKeys(dynamic[key]);
}).map(function (key) {
return asCss(asDynamicCss(dynamic[key]), key, scopedUnderParent).join('\n');
}).join(',\n'));
cssDynamic.push('})');
cssDynamic = cssDynamic.join('\n');
if (cssStatic || cssDynamic) {
state.styles[node.nameFinal] = 'const ' + node.nameFinal + ' = styled(\'' + node.nameTag + '\')(' + (cssStatic ? '{' + cssStatic + '}, ' : '') + cssDynamic + ')';
// TODO we may want to be smarter here and only pass what's needed
state.render.push(' props={props}');
}
} else if (hasKeysInChildren(staticStyle)) {
state.cssStatic = true;
var id = (node.is || node.name) + '_' + hash(staticStyle);
node.styleName = id;
node.className.push('${' + id + '}');
var css = Object.keys(staticStyle).filter(function (key) {
return allowedStyleKeys.includes(key) && hasKeys(staticStyle[key]);
}).map(function (key) {
return asCss(asStaticCss(staticStyle[key]), key, scopedUnderParent).join('\n');
}).join(',\n');
if (css) {
state.styles[id] = 'const ' + id + ' = css({' + css + '})';
}
}
}
var asDynamicCss = function asDynamicCss(styles) {
return Object.keys(styles).map(function (prop) {
return prop + ': ' + styles[prop];
});
};
var safe$1 = function safe(str) {
return typeof str === 'string' ? '"' + str.replace(/"/g, "'") + '"' : str;
};
var asStaticCss = function asStaticCss(styles) {
var dynamicStyles = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
return Object.keys(styles).filter(function (prop) {
return !dynamicStyles.includes(prop);
}).map(function (prop) {
return prop + ': ' + safe$1(styles[prop]);
});
};
var asCss = function asCss(styles, key, scopedUnderParent) {
var css = [];
if (key !== 'base') {
if (scopedUnderParent) {
var parent = '${' + scopedUnderParent + '}';
if (/_/.test(scopedUnderParent)) {
parent = '.' + parent;
}
css.push('[`' + parent + ':' + key + ' &, ' + parent + '.' + key + ' &`]: {');
} else if (key === 'hover' || key === 'disabled' || key === 'focus' || key === 'placeholder') {
css.push('"&:' + key + ', &.' + key + '": {');
} else if (key === 'print') {
// TODO can we use this to support all media queries?
css.push('"@media print": {');
}
}
css.push(styles.join(',\n'));
if (key !== 'base') css.push('}');
return css;
};
function enter$13(node, parent, state) {
if (node.name === 'ref') {
state.render.push(' ' + (parent.isDynamic ? 'innerRef' : 'ref') + '=' + wrap(node.value));
return true;
}
}
function enter$14(node, parent, state) {
var value = state.getValueForProperty(node, parent, state);
if (value) {
Object.keys(value).forEach(function (k) {
return state.render.push(" " + k + "=" + value[k]);
});
}
}
function enter$15(node, parent, state) {
if (!isStyle(node) || !parent.isBasic || isSvg(parent) && state.isReactNative || parent.name === 'SvgGroup') return;
var styleForProperty = void 0,
isScopedVal = void 0,
_isProp = void 0;
var code = isSlot(node);
// TODO refactor
if (getScopedCondition(node, parent)) {
isScopedVal = true;
styleForProperty = defineProperty({}, node.name, getScopedCondition(node, parent));
} else {
var _state$getStyleForPro = state.getStyleForProperty(node, parent, code);
_isProp = _state$getStyleForPro._isProp;
styleForProperty = objectWithoutProperties(_state$getStyleForPro, ['_isProp']);
}
if (_isProp) {
Object.keys(styleForProperty).forEach(function (k) {
return state.render.push(' ' + k + '=' + safe(styleForProperty[k], node));
});
} else {
var hasMatchingParent = parent && node.isDynamic ? checkParentStem(node, getStyleType(node)) : false;
var target = code || isScopedVal || hasMatchingParent ? parent.style.dynamic : parent.style.static;
Object.assign(target[getStyleType(node)], styleForProperty);
}
return true;
}
function enter$16(node, parent, state) {
if (node.name === 'text' && parent.name === 'Text') {
if (getScopedCondition(node, parent)) {
parent.explicitChildren = wrap(getScopedCondition(node, parent));
} else {
parent.explicitChildren = isSlot(node) ? wrap(node.value) : node.value;
}
return true;
}
}
var blacklist = ['classname', 'teleportto', 'goto'];
var blacklistDebug = ['autofocus', 'tabindex'];
var isValidPropertyForBlock = (function (node, parent, state) {
var name = node.name.toLowerCase();
return !(blacklist.includes(name) || state.debug && blacklistDebug.includes(name));
});
function enter$9(node, parent, state) {
enter$12(node, parent, state);
enter$10(node, parent, state);
enter$11(node, parent, state);
node.properties.forEach(function (propNode) {
if (propNode.name === 'at' || propNode.name === 'when' || propNode.name === 'onWhen' || propNode.name === 'ref' && state.debug || propNode.tags.unsupportedShorthand || !isValidPropertyForBlock(propNode, node, state) && node.isBasic || propNode.name === 'from' && node.name === 'List') return;
!enter$13(propNode, node, state) && !enter$15(propNode, node, state) && !enter$16(propNode, node, state) && enter$14(propNode, node, state);
});
leave$8(node, parent, state);
leave$7(node, parent, state);
leave$5(node, parent, state);
leave$6(node, parent, state);
}
function enter$17(node, parent, state) {
if (node.name !== 'Proxy') return;
var prevParent = parent;
while (prevParent) {
if (prevParent.type === 'Block' && !prevParent.parent) {
prevParent.usesProxy = true;
}
prevParent = prevParent.parent;
}
var proxied = node.properties.find(function (p) {
return p.name === 'from';
});
if (!proxied) return;
proxied = proxied.value;
var otherProperties = node.properties.filter(function (p) {
return p.name !== 'from' && p.name !== 'onWhen' && p.name !== 'when';
});
if (!node.onWhen) {
state.render.push('{');
}
if (proxied === 'all') {
var childContent = otherProperties.length > 0 ? 'React.Children.map(props.children, child => React.cloneElement(child, ' + getPropertiesAsObject(otherProperties) + '))' : 'props.children';
state.render.push(childContent);
} else {
if (!node.onWhen) {
state.render.push('props.childrenProxyMap && ');
}
var child = 'childrenArray[props.childrenProxyMap[\'' + proxied + '\']]';
if (otherProperties.length > 0) {
if (node.onWhen) {
if (state.render[state.render.length - 1].endsWith(' ? ')) {
state.render[state.render.length - 1] = state.render[state.render.length - 1].replace(' ? ', ' && ');
}
}
state.render.push(' ' + child + ' ? React.cloneElement(' + child + ', ' + getPropertiesAsObject(otherProperties) + ') : null');
} else {
state.render.push(child);
}
state.usesChildrenArray = true;
}
state.render.push('}');
// skip next
return true;
}
function enter$18(node, parent, state) {
var at = getProp(node, 'at');
if (at) {
var _at$value$split = at.value.split(' '),
_at$value$split2 = slicedToArray(_at$value$split, 2),
path$$1 = _at$value$split2[0],
_at$value$split2$ = _at$value$split2[1],
isExact = _at$value$split2$ === undefined ? false : _at$value$split2$;
state.use('Route');
if (path$$1 === '/') state.use('Router');
if (!path$$1.startsWith('/')) {
path$$1 = isSlot(path$$1) ? '`${' + path$$1 + '}`' : path$$1;
// path = `\`\${props.match.url}/${to}\``
}
node.isRoute = true;
state.render.push('<Route path=' + safe(path$$1) + ' ' + (isExact ? 'exact' : '') + ' render={routeProps => ');
}
}
function leave$9(node, parent, state) {
if (node.isRoute) {
state.render.push('} />');
}
}
var enter$19 = function enter(node, parent, state) {
if (node.name === 'Proxy') return;
var blockName = node.is || node.name;
if (typeof state.testIds[blockName] === 'number') {
state.testIds[blockName]++;
blockName = blockName + ':' + state.testIds[blockName];
} else {
state.testIds[blockName] = 0;
}
node.testId = blockName;
};
var enter$20 = function enter(node, parent, state) {
if (node.teleport) {
var to = getProp(node, 'teleportTo').value;
state.render.push(' to=' + safe(to));
}
};
var enter = [enter$19, enter$8, enter$17, enter$18, enter$7, enter$2, enter$20, enter$3, enter$5, enter$1, enter$9, enter$4, enter$6];
var leave = [leave$2, leave$1, leave$3, leave$9, leave$4];
var visitor = Object.freeze({
enter: enter,
leave: leave
});
var getWeights = function getWeights(variants) {
return variants.filter(function (v) {
return !v.includes('italic');
}).map(function (v) {
return v === 'regular' ? 400 : v;
});
};
var all = list.map(function (font) {
return {
category: font.category,
value: font.family,
weights: getWeights(font.variants)
};
});
var byName = {};
all.forEach(function (f) {
return byName[f.value] = f;
});
var fontFamily = all.map(function (f) {
return f.value;
});
var isGoogleFont = function isGoogleFont(family) {
return !!byName[family];
};
var maybeAddFallbackFont = function maybeAddFallbackFont(f) {
var font = byName[f];
return font && font.category ? f + ', ' + font.category : f;
};
var getStyleForProperty = (function (node, parent, code) {
switch (node.name) {
case 'appRegion':
return {
WebkitAppRegion: node.value
};
case 'backgroundImage':
return {
backgroundImage: code ? '`url(${' + node.value + '})`' : 'url("' + node.value + '")'
};
case 'fontFamily':
return {
fontFamily: code ? node.value : maybeAddFallbackFont(node.value)
};
case 'shadowColor':
case 'shadowRadius':
case 'shadowOffsetX':
case 'shadowOffsetY':
case 'shadowSpread':
return getShadow(node, parent);
case 'userSelect':
return {
WebkitUserSelect: node.value
};
case 'zIndex':
return {
zIndex: code ? node.value : parseInt(node.value, 10)
};
default:
return defineProperty({}, node.name, node.value);
}
});
var getPropValue = function getPropValue(prop) {
var unit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
if (!prop) return false;
if (prop.tags.slot) {
return '${' + prop.value + '}' + unit;
}
return '' + prop.value + unit;
};
var getShadow = function getShadow(node, parent) {
var isText = parent.name === 'Text';
var shadowColor = getProp(parent, 'shadowColor');
var shadowRadius = getProp(parent, 'shadowRadius');
var shadowOffsetX = getProp(parent, 'shadowOffsetX');
var shadowOffsetY = getProp(parent, 'shadowOffsetY');
var shadowSpread = getProp(parent, 'shadowSpread');
var value = [getPropValue(shadowOffsetX, 'px'), getPropValue(shadowOffsetY, 'px'), getPropValue(shadowRadius, 'px'), !isText && getPropValue(shadowSpread, 'px'), getPropValue(shadowColor)].filter(Boolean).join(' ');
if (isSlot(shadowColor) || isSlot(shadowRadius) || isSlot(shadowOffsetY) || isSlot(shadowOffsetX) || isSlot(shadowSpread)) {
value = '`' + value + '`';
}
return defineProperty({}, isText ? 'textShadow' : 'boxShadow', value);
};
var getStyles = (function (_ref) {
var styles = _ref.styles;
return '\n' + Object.keys(styles).map(function (k) {
return styles[k];
}).join('\n');
});
var isUrl = function isUrl(str) {
return (/^https?:\/\//.test(str)
);
};
var getImageSource = function getImageSource(node, state, parent) {
var scopes = getScopes(node, parent);
if (scopes && (isUrl(node.value) || node.tags.slot)) {
return wrap(getScopedCondition(node, parent));
} else if (isUrl(node.value) || node.tags.slot) {
return safe(node.value);
} else {
if (scopes && state.debug) {
return wrap(getScopedRequireCondition(scopes.scopedProps, scopes.paths, node.value));
} else if (state.debug) {
return '{requireImage("' + node.value + '")}';
} else {
if (scopes) {
pushImageToState(state, scopes.scopedNames, scopes.paths);
}
var name = toCamelCase(node.value);
if (!state.images.includes(node.value)) {
state.images.push({
name: name,
file: node.value
});
}
return scopes ? wrap(getScopedImageCondition(scopes.scopedProps, scopes.scopedNames, name)) : '{' + name + '}';
}
}
};
var getValueForProperty = (function (node, parent, state) {
if (isValidImgSrc(node, parent)) {
return {
src: getImageSource(node, state, parent)
};
} else if (parent.isBasic && node.name === 'isDisabled') {
return {
disabled: safe(node.value, node)
};
} else if (getScopedCondition(node, parent)) {
return defineProperty({}, node.name, safe(getScopedCondition(node, parent)));
} else if (parent.isBasic && node.name === 'onClick' && state.track && !state.debug) {
return {
onClick: wrap(makeOnClickTracker(node, state))
};
} else {
return defineProperty({}, node.name, safe(node.value, node));
}
});
var maybeUsesRouter = (function (state) {
if (state.uses.includes('Router')) {
state.render = ['<Router>'].concat(toConsumableArray(state.render), ['</Router>']);
}
});
var reactNative = ['CaptureEmail', 'CaptureFile', 'CaptureInput', 'CaptureNumber', 'CapturePhone', 'CaptureSecure', 'CaptureText', 'Horizontal', 'Vertical', 'Image', 'Text', 'List', 'Proxy', 'SvgText', 'Svg', 'SvgCircle', 'SvgEllipse', 'SvgGroup', 'SvgLinearGradient', 'SvgRadialGradient', 'SvgLine', 'SvgPath', 'SvgPolygon', 'SvgPolyline', 'SvgRect', 'SvgSymbol', 'SvgUse', 'SvgDefs', 'SvgStop', 'Router', 'Route', 'Link'];
var getBody = (function (_ref) {
var state = _ref.state,
name = _ref.name;
var render = state.render.join('');
var maybeChildrenArray = state.usesChildrenArray ? 'const childrenArray = React.Children.toArray(props.children)' : '';
var maybeState = state.captures.length > 0 ? 'constructor(props) {\n super(props)\n this.state = {}\n }' : '';
var block = 'this.props["' + state.testIdKey + '"] || "' + state.name + '"';
var maybeTracking = state.track && !state.debug ? 'componentDidMount() {\n this.context.track({ block: ' + block + ', action: "enter" })\n}\n\ncomponentWillUnmount() {\n this.context.track({ block: ' + block + ', action: "leave" })\n}' : '';
if (maybeState || maybeTracking) {
return 'class ' + name + ' extends React.Component {\n ' + maybeState + '\n ' + maybeTracking + '\n\n render() {\n const { ' + (maybeTracking ? 'context,' : '') + ' props, ' + (maybeState ? 'state' : '') + ' } = this\n ' + maybeChildrenArray + '\n return (' + render + ')\n }\n}';
} else {
return 'const ' + name + ' = (props ' + (maybeTracking ? ', context' : '') + ') => {\n ' + maybeChildrenArray + '\n return (' + render + ')\n}';
}
});
var getContext = (function (_ref) {
var state = _ref.state,
name = _ref.name;
if (state.track && !state.debug) {
return name + '.contextTypes = {\n track: PropTypes.func.isRequired\n}';
}
return '';
});
var stringify = function stringify(slot) {
return (/^[0-9]+$/.test(slot.defaultValue) ? slot.defaultValue : JSON.stringify(slot.defaultValue)
);
};
var getDefaultProps = (function (_ref) {
var state = _ref.state,
name = _ref.name;
var slots = state.slots.filter(function (slot) {
return slot.defaultValue !== false;
}).map(function (slot) {
return slot.name + ': ' + stringify(slot);
});
return slots.length === 0 ? '' : name + '.defaultProps = {' + slots.join(',\n') + '}';
});
var SVG = ['Svg', 'SvgCircle', 'SvgEllipse', 'SvgDefs', 'SvgGroup', 'SvgLinearGradient', 'SvgRadialGradient', 'SvgLine', 'SvgPath', 'SvgPolygon', 'SvgPolyline', 'SvgRect', 'SvgSymbol', 'SvgText', 'SvgUse', 'SvgDefs', 'SvgStop'];
var NATIVE = ['Animated', 'Image', 'KeyboardAvoidingView', 'ScrollView', 'StyleSheet', 'Text', 'TextInput', 'TouchableWithoutFeedback', 'TouchableHighlight', 'View'];
var getDependencies = (function (state, getImport) {
var usesNative = [];
var usesSvg = [];
var useNative = function useNative(d) {
if (!usesNative.includes(d)) {
usesNative.push(d);
}
};
var useSvg = function useSvg(d) {
if (!usesSvg.includes(d)) {
usesSvg.push(d);
}
};
var dependencies = [];
state.uses.sort().forEach(function (d) {
if (state.isReactNative && NATIVE.includes(d)) {
useNative(d);
} else if (state.isReactNative && SVG.includes(d)) {
useSvg(d === 'Svg' ? d : d === 'SvgGroup' ? 'G as SvgGroup' : d.replace('Svg', '') + ' as ' + d);
} else if (d.endsWith('SvgInline')) {
dependencies.push('import ' + d + ' from "./' + d + '.view.js"');
} else if (/^[A-Z]/.test(d)) {
dependencies.push(getImport(d));
}
});
// TODO native
if (!state.isReactNative) {
dependencies.push(getImport('ViewsBaseCss'));
state.fonts.forEach(function (usedFont) {
var font = state.getFont(usedFont);
if (font) {
dependencies.push('import "' + font + '"');
}
});
}
// TODO we probably want to check that the file exists and do something if it
// doesn;t, like warn the user at least?
state.images.forEach(function (img) {
return dependencies.push('import ' + img.name + ' from "' + img.file + '"');
});
if (state.cssDynamic && state.cssStatic) {
dependencies.push('import styled, { css } from "react-emotion"');
} else if (state.cssStatic) {
dependencies.push('import { css } from "react-emotion"');
} else if (state.cssDynamic) {
dependencies.push('import styled from "react-emotion"');
}
if (usesSvg.length > 0) {
var svg = usesSvg.filter(function (m) {
return m !== 'Svg';
}).join(', ');
dependencies.push('import Svg, { ' + svg + ' } from \'react-native-svg\'');
}
if (usesNative.length > 0) {
dependencies.push('import { ' + usesNative.join(', ') + ' } from \'react-native\'');
}
if (state.track && !state.debug) {
dependencies.push('import PropTypes from "prop-types"');
}
return dependencies.join('\n');
});
var toComponent = (function (_ref) {
var getImport = _ref.getImport,
getStyles = _ref.getStyles,
name = _ref.name,
state = _ref.state;
// TODO Emojis should be wrapped in <span>, have role="img", and have an accessible description
// with aria-label or aria-labelledby jsx-a11y/accessible-emoji
return '/* eslint-disable jsx-a11y/accessible-emoji, no-unused-vars */\nimport React from \'react\'\n' + getDependencies(state, getImport) + '\n' + getStyles(state, name) + '\n\n' + getBody({ state: state, name: name }) + '\n' + getContext({ state: state, name: name }) + '\n' + getDefaultProps({ state: state, name: name }) + '\nexport default ' + name;
});
function walk(ast, _ref, state) {
var enter = _ref.enter,
leave = _ref.leave;
visit(ast, null, enter, leave, state);
}
function visit(node, parent, enter, leave, state) {
if (!node) return;
if (enter) {
if (enter.some(function (fn) {
return fn(node, parent, state);
})) return;
}
if (Array.isArray(node.children)) {
node.children.forEach(function (child) {
child.parent = node;
visit(child, node, enter, leave, state);
});
}
if (leave) {
leave.forEach(function (fn) {
return fn(node, parent, state);
});
}
}
var imports = {
Animated: "import Animated from 'react-dom-animated'",
Link: "import { Link } from 'react-router-dom'",
Route: "import { Route } from 'react-router-dom'",
Router: "import { BrowserRouter as Router } from 'react-router-dom'"
};
var reactDom = (function (_ref) {
var debug = _ref.debug,
_ref$enableAnimated = _ref.enableAnimated,
enableAnimated = _ref$enableAnimated === undefined ? true : _ref$enableAnimated,
file = _ref.file,
_ref$getFont = _ref.getFont,
getFont = _ref$getFont === undefined ? function () {
return false;
} : _ref$getFont,
getImport = _ref.getImport,
name = _ref.name,
_ref$track = _ref.track,
track = _ref$track === undefined ? true : _ref$track,
views = _ref.views;
var finalName = reactNative.includes(name) ? name + '1' : name;
if (name !== finalName) {
console.warn('// "' + name + '" is a Views reserved name.\n We\'ve renamed it to "' + finalName + '", so your view should work but this isn\'t ideal.\n To fix this, change its file name to something else.');
}
var state = {
captures: [],
cssDynamic: false,
cssStatic: false,
enableAnimated: enableAnimated,
debug: debug,
file: file,
getFont: getFont,
getStyleForProperty: getStyleForProperty,
getValueForProperty: getValueForProperty,
images: [],
isDynamic: false,
isReactNative: false,
name: finalName,
render: [],
styles: {},
svgs: [],
usedBlockNames: defineProperty({}, finalName, 1),
uses: [],
testIdKey: 'data-test-id',
testIds: {},
track: track,
use: function use(block) {
if (state.uses.includes(block) || /props/.test(block) || block === finalName) return;
state.uses.push(block);
}
};
if (name !== finalName) {
console.warn('// ' + name + ' is a Views reserved name. To fix this, change its file name to something else.');
}
var parsed = views[name];
state.fonts = parsed.fonts;
state.slots = parsed.slots;
walk(parsed.views[0], visitor, state);
maybeUsesRouter(state);
var finalGetImport = function finalGetImport(name) {
return imports[name] || getImport(name);
};
return {
code: toComponent({
getImport: finalGetImport,
getStyles: getStyles,
name: finalName,
state: state
}),
fonts: parsed.fonts,
slots: parsed.slots,
svgs: state.svgs
};
});
var BORDER_RADIUS = ['borderRadius', 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius'];
var enter$22 = function enter(node, parent, state) {
if (node.backgroundImage) {
var source = getObjectAsString({ uri: node.backgroundImage });
var resizeMode = getProp(node, 'backgroundSize');
resizeMode = safe(resizeMode ? resizeMode.value.value : 'cover');
state.render.push(' resizeMode=' + resizeMode + ' source={' + source + '}');
// hack until https://github.com/facebook/react-native/issues/8885
// is fixed
BORDER_RADIUS.forEach(function (prop) {
if (hasProp(node, prop)) {
var propNode = getProp(node, prop);
state.render.push(' ' + prop + '={' + propNode.value.value + '}');
}
});
}
};
var keyboardType = {
CaptureEmail: 'email-address',
CaptureText: 'default',
CaptureTextArea: 'default',
CaptureNumber: 'numeric',
CapturePhone: 'phone-pad'
};
var enter$23 = function enter(node, parent, state) {
var blockType = node.name;
if (!/Capture/.test(node.name)) return;
node.isCapture = true;
var name = toCamelCase(node.is || blockType);
state.captures.push(name);
var captureNext = node.captureNext;
var onSubmit = getProp(node, 'onSubmit') || null;
if (onSubmit) onSubmit = onSubmit.value.value;
if (captureNext) {
state.render.push(' blurOnSubmit={false}');
state.render.push(' onSubmitEditing={this.$' + captureNext + '? () => this.$' + captureNext + '.focus() : ' + onSubmit + '}');
state.render.push(' returnKeyType = {this.$' + captureNext + '? \'next\' : \'go\'}');
} else {
if (onSubmit) {
state.render.push(' onSubmitEditing={' + onSubmit + '}');
state.render.push(' returnKeyType="go"');
} else {
state.render.push(' returnKeyType="done"');
}
}
state.render.push(' onChangeText = {' + name + ' => this.setState({ ' + name + ' })}');
state.render.push(' ref={$e => this.$' + name + ' = $e}');
state.render.push(' value={state.' + name + '}');
if (node.name === 'CaptureSecure') {
state.render.push(' secureTextEntry');
} else {
state.render.push(' keyboardType=\'' + keyboardType[blockType] + '\'');
}
if (node.name === 'CaptureTextArea') {
state.render.push(' multiline={true}');
}
// TODO rest of props
var onBlur = getProp(node, 'onBlur');
if (onBlur) {
state.render.push(' onBlur=' + safe(onBlur.value.value));
}
var onFocus = getProp(node, 'onFocus');
if (onFocus) {
state.render.push(' onFocus=' + safe(onFocus.value.value));
}
var autoCorrect = getProp(node, 'autoCorrect');
state.render.push(' autoCorrect=' + (autoCorrect ? safe(autoCorrect.value.value) : '{false}'));
var placeholder = getProp(node, 'placeholder');
if (placeholder) {
state.render.push(' placeholder=' + safe(placeholder.value.value));
}
var defaultValue = getProp(node, 'defaultValue');
if (defaultValue) {
state.render.push(' defaultValue=' + safe(defaultValue.value.value));
}
var underlineColorAndroid = getProp(node, 'underlineColorAndroid');
var underlineColorAndroidValue = underlineColorAndroid ? underlineColorAndroid.value.value : 'transparent';
state.render.push(' underlineColorAndroid=' + safe(underlineColorAndroidValue));
};
var getBlockName$1 = (function (node, parent, state) {
switch (node.name) {
case 'CaptureEmail':
// case 'CaptureFile':
case 'CaptureNumber':
case 'CapturePhone':
case 'CaptureSecure':
case 'CaptureText':
case 'CaptureTextArea':
return 'TextInput';
case 'Horizontal':
case 'Vertical':
return getGroupBlockName$1(node, state);
case 'Image':
return getImageName(node, state);
case 'List':
return getListBlockName(node);
case 'Proxy':
return null;
case 'Text':
return node.maybeAnimated ? 'Animated.Text' : 'Text';
default:
return node.name;
}
});
var getGroupBlockName$1 = function getGroupBlockName(node, state) {
var name = 'View';
if (hasProp(node, 'teleportTo')) {
node.teleport = true;
} else if (hasProp(node, 'goTo')) {
node.goTo = true;
} else if (hasProp(node, 'onClick')) {
var propNode = getProp(node, 'onClick');
node.action = propNode.value;
}
if (hasProp(node, 'backgroundImage')) {
var _propNode = getProp(node, 'backgroundImage');
node.backgroundImage = isSlot(_propNode) ? _propNode.value : JSON.stringify(_propNode.value);
name = 'Image';
} else if (hasProp(node, 'overflowY', function (v) {
return v === 'auto' || v === 'scroll';
})) {
name = 'ScrollView';
}
if (node.maybeAnimated && name !== 'Link') {
name = 'Animated.' + name;
}
return name;
};
var getListBlockName = function getListBlockName(node) {
var base = hasProp(node, /^overflow/, function (v) {
return v === 'auto' || v === 'scroll';
}) ? 'ScrollView' : 'View';
return node.maybeAnimated ? 'Animated.' + base : base;
};
var isSvg$1 = function isSvg$$1(str) {
return (/\.svg$/.test(str)
);
};
var getImageName = function getImageName(node, state) {
if (hasProp(node, 'source')) {
var source = getProp(node, 'source');
var value = source.value.value;
if (isSvg$1(value)) {
var name = toPascalCase(value) + 'Inline';
node.isSvg = true;
if (!state.svgs.some(function (svg) {
return svg.source === value;
})) {
state.svgs.push({
source: value,
view: name
});
}
return name;
}
}
return 'Image';
};
function enter$24(node, parent, state) {
var name = getBlockName$1(node, parent, state);
if (name === null) return true;
state.use(/Animated/.test(name) ? 'Animated' : name);
node.nameFinal = name;
state.render.push('<' + name);
}
var leave$11 = function leave(node, parent, state) {
var style = null;
if (node.ensureBackgroundColor && (!('backgroundColor' in node.style.static.base) || !('backgroundColor' in node.style.dynamic.base))) {
node.style.static.base.backgroundColor = 'transparent';
}
if (hasKeys(node.style.static.base)) {
var id = hash(node.style.static.base);
state.styles[id] = node.style.static.base;
node.styleId = id;
style = 'styles.' + id;
}
if (hasKeys(node.style.dynamic.base)) {
var dynamic = getObjectAsString(node.styl