UNPKG

views-morph

Version:
997 lines (875 loc) 30.5 kB
'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var Levenshtein = _interopDefault(require('levenshtein')); var sortBy = _interopDefault(require('lodash.sortby')); var STYLE = ['alignContent', 'alignItems', 'alignSelf', 'appRegion', 'background', 'backgroundColor', 'backgroundImage', 'backgroundSize', 'borderBottomColor', 'borderBottomLeftRadius', 'borderBottomRightRadius', 'borderBottomStyle', 'borderBottomWidth', 'borderColor', 'borderLeftColor', 'borderLeftStyle', 'borderLeftWidth', 'borderRightColor', 'borderRightStyle', 'borderRightWidth', 'borderStyle', 'borderTopColor', 'borderTopLeftRadius', 'borderTopRightRadius', 'borderTopStyle', 'borderTopWidth', 'borderWidth', 'bottom', 'clipPath', 'color', 'cursor', 'fill', 'filter', 'flex', 'flex-grow', 'flexBasis', 'flexDirection', 'flexFlow', 'flexShrink', 'flexWrap', 'fontFamily', 'fontSize', 'fontStyle', 'fontWeight', 'height', 'hyphens', 'justifyContent', 'left', 'letterSpacing', 'lineHeight', 'marginBottom', 'marginLeft', 'marginRight', 'marginTop', 'maxHeight', 'maxWidth', 'minHeight', 'minWidth', 'opacity', 'outlineColor', 'outlineOffset', 'outlineStyle', 'outlineWidth', 'overflowWrap', 'overflowX', 'overflowY', 'paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop', 'pointerEvents', 'position', 'resize', 'right', 'shadowColor', 'shadowOffsetX', 'shadowOffsetY', 'shadowRadius', 'shadowSpread', 'stroke', 'textAlign', 'textDecoration', 'top', 'transform', 'transformOrigin', 'transition', 'userSelect', 'whiteSpace', 'width', 'wordBreak', 'wordSpacing', 'wordWrap', 'zIndex']; var isStyle = function isStyle(name) { return STYLE.includes(name); }; /** * Creates a fuzzy matcher. * * Usage: * * ``` * var m = new Matcher({ * values: 'init install update upgrade', * threshold: 4 * }); * * m.list('udpate') // [ { value: 'update', distance: 2 }, { value: 'upgrade', distance: 4 } ] * m.get('udpate') // { value: 'update', distance: 2 } * ``` * * You can also initialize with an array or with a string directly: * * ``` * new Matcher('init install update upgrade'); * new Matcher(['init', 'install', 'update', 'upgrade']); * ``` * * @param options {Object} may contain: * * * `threshold` (number, default `2`) — maximum search distance, increase * for more relaxed search * * * `values` (array or string, default `[]`) — an array of words to match from; * if a string is given, values can be separated with comma or whitespace * * * `caseSensitive` (boolean, default `false`) — ignore case when matching */ var Matcher = function Matcher(options) { options = options || {}; if (typeof options == 'string' || Array.isArray(options)) options = { values: options }; this.values = []; this.threshold = options.threshold || 2; // Try to initialize via `options.values` if (Array.isArray(options.values)) this.values = options.values;else if (typeof options.values == 'string') this.values = options.values.split(/[, ]\s*/g); this.caseSensitive = options.caseSensitive || false; }; /** * Adds values to the dictionary. * * Usage: * * ``` * new Matcher().add('update', 'upgrade', 'delete').get('deete') * ``` * * @returns {Matcher} this for chaining */ Matcher.prototype.add = function () { [].push.apply(this.values, arguments); return this; }; /** * Chainable helper for settings `this.caseSensitive = false`. * * @returns {Matcher} this for chaining */ Matcher.prototype.ignoreCase = function () { this.caseSensitive = false; return this; }; /** * Chainable helper for settings `this.caseSensitive = true`. * * @returns {Matcher} this for chaining */ Matcher.prototype.matchCase = function () { this.caseSensitive = true; return this; }; /** * Chainable helper for settings `this.threshold`. * * @param num {Number} new threshold * @returns {Matcher} this for chaining */ Matcher.prototype.setThreshold = function (num) { this.threshold = num; return this; }; /** * Calculate distance (how much difference) between two strings * * @param word1 {String} a string input * @param word2 {String} the other string input * @returns {Number} Levenshtein distance between word1 and word2 */ Matcher.prototype.distance = function (word1, word2) { return new Levenshtein(word1, word2).distance; }; /** * Lists all results from dictionary which are similar to `q`. * * ``` * new Matcher({ * values: 'init install update upgrade', * threshold: 4 * }).list('udpdate'); * // [ { value: 'update', distance: 2 }, { value: 'upgrade', distance: 4 } ] * ``` * * The results are sorted by their distance (similarity). The distance of `0` means * a strict match. * * You can increase `threshold` for more relaxed search, or decrease it to shorten the results. * * @param q {String} — search string * @returns {Array} — an array of objects `{ value: String, distance: Number }` */ Matcher.prototype.list = function (q) { var m = this; q = q.trim(); if (!m.caseSensitive) q = q.toLowerCase(); var matches = this.values.reduce(function (results, word) { var d = m.distance(q, m.caseSensitive ? word : word.toLowerCase()); if (d > m.threshold) return results; return results.concat({ value: word, distance: d }); }, []); return sortBy(matches, 'distance'); }; /** * Returns a single closest match (or `null` if no values from the dictionary * are similar to `q`). * * @param q {String} — search string * @returns {String} — closest match or `null` */ Matcher.prototype.get = function (q) { var closest = this.list(q)[0]; return closest ? closest.value : null; }; var isNumber = { width: true, maxWidth: true, minWidth: true, height: true, maxHeight: true, minHeight: true, margin: true, marginBottom: true, marginLeft: true, marginRight: true, marginTop: true, padding: true, paddingBottom: true, paddingLeft: true, paddingRight: true, paddingTop: true, bottom: true, left: true, right: true, top: true, outline: true, opacity: true, zIndex: true, scale: true, translateX: true, translateY: true, borderBottomLeftRadius: true, borderBottomRightRadius: true, borderBottomWidth: true, borderLeftWidth: true, borderRadius: true, borderRightWidth: true, borderTopLeftRadius: true, borderTopRightRadius: true, borderTopWidth: true, borderWidth: true, fontSize: true, fontWeight: true, letterSpacing: true, lineHeight: true, wordSpacing: true }; 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 dymBlockMatcher = new Matcher('CaptureEmail|CaptureFile|CaptureNumber|CapturePhone|CaptureSecure|CaptureText|CaptureTextArea|G|Horizontal|Image|List|Svg|SvgCircle|SvgEllipse|SvgDefs|SvgGroup|SvgLinearGradient|SvgRadialGradient|SvgLine|SvgPath|SvgPolygon|SvgPolyline|SvgRect|SvgSymbol|SvgText|SvgUse|SvgStop|Text|Vertical'.split('|')); var dymPropMatcher = new Matcher([].concat(toConsumableArray(STYLE), ['defaultValue', 'fill', 'stroke', 'from', 'viewBox', 'stroke', 'strokeWidth', 'strokeLinecap', 'strokeMiterlimit', 'at', 'd', 'x', 'x1', 'y1', 'y', 'x2', 'y2', 'strokeLinejoin', 'onBlur', 'onChange', 'onClick', 'onDrag', 'onDragEnd', 'onDragOver', 'onDragStart', 'onFocus', 'onMouseDown', 'onMouseMove', 'onMouseOver', 'onMouseUp', 'onWheel', 'onWhen', 'ref', 'tabIndex', 'text', 'value', 'when'])); var didYouMeanBlock = function didYouMeanBlock(block) { return dymBlockMatcher.get(block); }; var didYouMeanProp = function didYouMeanProp(prop) { return dymPropMatcher.get(prop); }; var BASIC = /^(CaptureEmail|CaptureFile|CaptureNumber|CapturePhone|CaptureSecure|CaptureText|CaptureTextArea|Horizontal|Image|List|Svg|SvgCircle|SvgEllipse|SvgDefs|SvgGroup|SvgLinearGradient|SvgRadialGradient|SvgLine|SvgPath|SvgPolygon|SvgPolyline|SvgRect|SvgSymbol|SvgText|SvgUse|SvgStop|Text|Vertical)$/i; var BLOCK = /^([A-Z][a-zA-Z0-9]*)(\s+([A-Z][a-zA-Z0-9]*))?$/; var BOOL = /^(false|true)$/i; var CAPTURE = /^(CaptureEmail|CaptureFile|CaptureNumber|CapturePhone|CaptureSecure|CaptureText|CaptureTextArea)$/i; var COMMENT = /^#(.+)$/; var FLOAT = /^-?[0-9]+\.[0-9]+$/; var FONTABLE = /^(CaptureEmail|CaptureNumber|CapturePhone|CaptureSecure|CaptureText|CaptureTextArea|Text)$/; var INT = /^-?[0-9]+$/; var NOT_GROUP = /^(Image|Text|Proxy|SvgCircle|SvgEllipse|SvgLine|SvgPath|SvgPolygon|SvgPolyline|SvgRect|SvgText|SvgStop)$/i; var PROP = /^([a-z][a-zA-Z0-9]*)(\s+(.+))?$/; var UNSUPPORTED_SHORTHAND = { border: ['borderWidth', 'borderStyle', 'borderColor'], borderBottom: ['borderBottomWidth', 'borderBottomStyle', 'borderBottomColor'], borderTop: ['borderTopWidth', 'borderTopStyle', 'borderTopColor'], borderRight: ['borderRightWidth', 'borderRightStyle', 'borderRightColor'], borderLeft: ['borderLeftWidth', 'borderLeftStyle', 'borderLeftColor'], borderRadius: ['borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius'], boxShadow: ['shadowOffsetX', 'shadowOffsetY', 'shadowRadius', 'shadowSpread', 'shadowColor'], margin: ['marginTop', 'marginRight', 'marginBottom', 'marginLeft'], padding: ['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'], textShadow: ['shadowOffsetX', 'shadowOffsetY', 'shadowRadius', 'shadowColor'], outline: ['outlineWidth', 'outlineStyle', 'outlineColor'], overflow: ['overflowX', 'overflowY'] }; var TRUE = /^true$/i; var USER_COMMENT = /^##(.*)$/; // TODO slot can't start with a number var SLOT = /^<((!)?([a-zA-Z0-9]+))?(\s+(.+))?$/; var is = function is(thing, line) { return thing.test(line); }; var isBasic = function isBasic(line) { return is(BASIC, line); }; var isBlock = function isBlock(line) { return is(BLOCK, line); }; var isBool = function isBool(line) { return is(BOOL, line); }; var isCapture = function isCapture(line) { return is(CAPTURE, line); }; var isComment = function isComment(line) { return is(COMMENT, line); }; var isEmptyText = function isEmptyText(line) { return line === ''; }; var isEnd = function isEnd(line) { return line === ''; }; var isFloat = function isFloat(line) { return is(FLOAT, line); }; var isFontable = function isFontable(line) { return is(FONTABLE, line); }; var isGroup = function isGroup(line) { return !is(NOT_GROUP, line) && !isCapture(line); }; var isList = function isList(line) { return line === 'List'; }; var isInt = function isInt(line) { return is(INT, line); }; var isProp = function isProp(line) { return is(PROP, line); }; var isUnsupportedShorthand = function isUnsupportedShorthand(name) { return name in UNSUPPORTED_SHORTHAND; }; var isTrue = function isTrue(line) { return is(TRUE, line); }; var isUserComment = function isUserComment(line) { return is(USER_COMMENT, line); }; var get = function get(regex, line) { return line.match(regex); }; var getBlock = function getBlock(line) { // eslint-disable-next-line var _get = get(BLOCK, line), _get2 = slicedToArray(_get, 4), _ = _get2[0], is = _get2[1], _1 = _get2[2], block = _get2[3]; return { block: block || is, is: block ? is : null }; }; var getComment = function getComment(line) { try { return get(COMMENT, line).slice(1); } catch (err) { return ''; } }; var getProp = function getProp(line) { // eslint-disable-next-line var _get3 = get(PROP, line), _get4 = slicedToArray(_get3, 4), _ = _get4[0], name = _get4[1], _1 = _get4[2], _get4$ = _get4[3], value = _get4$ === undefined ? '' : _get4$; var prop = { name: name, isSlot: false, value: value }; if (is(SLOT, value)) { var _getSlot = getSlot(value), _getSlot2 = slicedToArray(_getSlot, 5), // eslint-disable-next-line _2 = _getSlot2[0], _getSlot2$ = _getSlot2[1], slotIsNot = _getSlot2$ === undefined ? false : _getSlot2$, _getSlot2$2 = _getSlot2[2], slotName = _getSlot2$2 === undefined ? '' : _getSlot2$2, // eslint-disable-next-line _3 = _getSlot2[3], _getSlot2$3 = _getSlot2[4], defaultValue = _getSlot2$3 === undefined ? '' : _getSlot2$3; prop.isSlot = true; prop.slotIsNot = slotIsNot === '!'; prop.slotName = slotName; prop.value = defaultValue || value; } return prop; }; var getSlot = function getSlot(line) { return get(SLOT, line).slice(1); }; var getUnsupportedShorthandExpanded = function getUnsupportedShorthandExpanded(name, value) { var props = UNSUPPORTED_SHORTHAND[name]; if (name === 'borderRadius') { var theValue = value.replace('px', ''); return [props[0] + ' ' + theValue, props[1] + ' ' + theValue, props[2] + ' ' + theValue, props[3] + ' ' + theValue]; } else if (name.startsWith('border') || name === 'outline') { var _value$split = value.split(' '), _value$split2 = toArray(_value$split), width = _value$split2[0], style = _value$split2[1], color = _value$split2.slice(2); return [props[0] + ' ' + width.replace('px', ''), props[1] + ' ' + style, props[2] + ' ' + color.join(' ')]; } else if (name === 'boxShadow') { var _value$split3 = value.split(' '), _value$split4 = toArray(_value$split3), offsetX = _value$split4[0], offsetY = _value$split4[1], blurRadius = _value$split4[2], spreadRadius = _value$split4[3], _color = _value$split4.slice(4); return [props[0] + ' ' + offsetX.replace('px', ''), props[1] + ' ' + offsetY.replace('px', ''), props[2] + ' ' + blurRadius.replace('px', ''), props[3] + ' ' + spreadRadius.replace('px', ''), props[4] + ' ' + _color.join(' ')]; } else if (name === 'textShadow') { var _value$split5 = value.split(' '), _value$split6 = toArray(_value$split5), _offsetX = _value$split6[0], _offsetY = _value$split6[1], _blurRadius = _value$split6[2], _color2 = _value$split6.slice(3); return [props[0] + ' ' + _offsetX.replace('px', ''), props[1] + ' ' + _offsetY.replace('px', ''), props[2] + ' ' + _blurRadius.replace('px', ''), props[3] + ' ' + _color2.join(' ')]; } else if (name === 'overflow') { return [props[0] + ' ' + value, props[1] + ' ' + value]; } else if (name === 'padding' || name === 'margin') { var _value$split7 = value.split(' '), _value$split8 = slicedToArray(_value$split7, 4), top = _value$split8[0], right = _value$split8[1], bottom = _value$split8[2], left = _value$split8[3]; top = top.replace('px', ''); right = right ? right.replace('px', '') : top; bottom = bottom ? bottom.replace('px', '') : top; left = left ? left.replace('px', '') : right || top; return [props[0] + ' ' + top, props[1] + ' ' + right, props[2] + ' ' + bottom, props[3] + ' ' + left]; } }; var getValue = function getValue(value) { if (isFloat(value)) { return parseFloat(value, 10); } else if (isInt(value)) { return parseInt(value, 10); } else if (isEmptyText(value)) { return ''; } else if (isBool(value)) { return isTrue(value); } else { return value; } }; var SYSTEM_SCOPES = ['active', // TODO disabled should be a prop instead I think 'disabled', 'focus', 'hover', 'placeholder', 'print']; var isSystemScope = function isSystemScope(name) { return SYSTEM_SCOPES.includes(name); }; var isActionable = function isActionable(name) { return name !== 'onWhen' && /^on[A-Z]/.test(name); }; var getPropType = function getPropType(block, name, defaultValue) { return block.isList && name === 'from' ? 'array' : isActionable(name) ? 'function' : isNumber[name] ? 'number' : 'string'; }; var getLoc = (function (line, scolumn, ecolumn) { return { start: { line: line, column: scolumn }, end: { line: line, column: ecolumn } }; }); var SLOT_PROPS = ['from', 'when', 'onClick', 'onFocus', 'onWhen']; var shouldBeSlot = function shouldBeSlot(prop) { return SLOT_PROPS.includes(prop) || /^on[A-Z]/.test(prop); }; var getTags = (function (_ref) { var name = _ref.name, isSlot$$1 = _ref.isSlot, slotName = _ref.slotName, slotIsNot = _ref.slotIsNot, value = _ref.value, block = _ref.block; var tags = {}; if (isStyle(name)) tags.style = true; if (isUnsupportedShorthand(name) && block.isBasic) { tags.unsupportedShorthand = true; } if (shouldBeSlot(name)) tags.shouldBeSlot = true; if (isSlot$$1) tags.slot = true; if (slotIsNot) tags.slotIsNot = true; tags.validSlot = tags.slot || tags.shouldBeSlot && tags.slot || null; return tags; }); var index = (function () { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$convertSlotToPro = _ref.convertSlotToProps, convertSlotToProps = _ref$convertSlotToPro === undefined ? true : _ref$convertSlotToPro, _ref$skipComments = _ref.skipComments, skipComments = _ref$skipComments === undefined ? true : _ref$skipComments, source = _ref.source; // convert crlf to lf var text = source.replace(/\r\n/g, '\n'); var rlines = text.split('\n'); var lines = rlines.map(function (line) { return line.trim(); }); var fonts = []; var stack = []; var slots = []; var views = []; var warnings = []; var lastCapture = void 0; var getChildrenProxyMap = function getChildrenProxyMap(block) { var childrenProxyMap = {}; block.children.forEach(function (child, i) { var maybeName = child.is || child.name; var name = maybeName; var next = 1; while (name in childrenProxyMap) { name = '' + maybeName + next; next++; } childrenProxyMap[name] = i; }); return Object.keys(childrenProxyMap).length === 0 ? null : childrenProxyMap; }; var lookForFonts = function lookForFonts(block) { if (block.properties && (isFontable(block.name) || !block.isBasic)) { var fontFamilyProp = block.properties.find(function (p) { return p.name === 'fontFamily'; }); if (fontFamilyProp) { var fontFamily = fontFamilyProp.value; var fontWeightProp = block.properties.find(function (p) { return p.name === 'fontWeight'; }); var fontStyleProp = block.properties.find(function (p) { return p.name === 'fontStyle'; }); var fontWeight = fontWeightProp ? fontWeightProp.value.toString() : '400'; var fontStyle = fontStyleProp ? fontStyleProp.value.toString() : 'normal'; if (!fonts.find(function (font) { return font.family === fontFamily && font.weight === fontWeight && font.style === fontStyle; })) { fonts.push({ id: fontFamily + '-' + fontWeight + (fontStyle === 'italic' ? '-italic' : ''), family: fontFamily, weight: fontWeight, style: fontStyle }); } } } }; var end = function end(block, endLine) { block.loc.end = { line: endLine, column: Math.max(0, lines[endLine].length - 1) }; if (block.isGroup && !block.isBasic) { block.childrenProxyMap = getChildrenProxyMap(block); } if (!block.properties) { block.properties = []; } if (block.name === 'List' && !block.properties.some(function (prop) { return prop.name === 'from'; })) { warnings.push({ loc: block.loc, type: 'A List needs "from <" to work', line: lines[block.loc.start.line] }); } if (stack.length === 0) { // if we're the last block on the stack, then this is the view! views.push(block); return true; } return false; }; var parseBlock = function parseBlock(line, i) { var _getBlock = getBlock(line), name = _getBlock.block, is$$1 = _getBlock.is; var shouldPushToStack = false; var block = { type: 'Block', name: name, isBasic: isBasic(name), isGroup: false, loc: getLoc(i, 0), properties: [], scopes: [] }; if (is$$1 && !block.isBasic) { var meant = didYouMeanBlock(name); if (meant && meant !== name) { warnings.push({ loc: block.loc, type: 'Did you mean "' + meant + '" instead of "' + name + '"?', line: line }); } } if (is$$1) { block.is = is$$1; if (isCapture(name)) { if (lastCapture) { lastCapture.captureNext = is$$1; } lastCapture = block; } } var last = stack[stack.length - 1]; if (last) { shouldPushToStack = true; if (last.isGroup) { if (last.isList) { if (block.isBasic) { warnings.push({ loc: block.loc, type: 'A basic block "' + block.name + '" can\'t be inside a List. Use a view you made instead.', line: line, blocker: true }); } else if (last.children.length > 0) { warnings.push({ loc: block.loc, type: 'A List can only have one view inside. "' + block.name + '" is outside of it. Put 1 empty line before.', line: line }); } else { last.children.push(block); } } else { last.children.push(block); } } else { // the block is inside a block that isn't a group end(stack.pop(), i); if (last.isBasic) { warnings.push({ loc: block.loc, type: 'An empty line is required after every block. Put 1 empty line before', line: line }); } else if (views[0] && views[0].isGroup) { warnings.push({ loc: block.loc, type: lines[i - 1] === '' ? 'Put 1 empty line before' : 'Put 2 empty lines before', line: line }); } else { warnings.push({ loc: block.loc, type: 'Add Vertical at the top', line: line }); } } } else if (views.length > 0) { // the block is outside the top level block var newLinesBeforePreviousBlock = 1; while (isEnd(lines[i - newLinesBeforePreviousBlock])) { newLinesBeforePreviousBlock++; } var help = []; if (!views[0].isGroup) { help.push('Add Vertical at the top'); } if (newLinesBeforePreviousBlock > 2) { var linesToRemove = newLinesBeforePreviousBlock - 2; help.push('remove ' + linesToRemove + ' empty line' + (linesToRemove > 1 ? 's' : '') + ' before'); } warnings.push({ loc: block.loc, type: help.join(', '), line: line }); } if (isGroup(name)) { block.isGroup = true; block.isList = isList(name); block.children = []; } if (shouldPushToStack || stack.length === 0) { stack.push(block); } parseProps(i, block); lookForFonts(block); }; var parseProps = function parseProps(i, block) { var endOfBlockIndex = i; while (endOfBlockIndex < lines.length - 1 && !isBlock(lines[endOfBlockIndex + 1])) { endOfBlockIndex++; } var properties = []; var scopes = []; var scope = void 0; var inScope = false; var _loop = function _loop(j) { var line = lines[j]; var propNode = null; if (isProp(line)) { var _getProp = getProp(line), name = _getProp.name, isSlot$$1 = _getProp.isSlot, slotName = _getProp.slotName, slotIsNot = _getProp.slotIsNot, value = _getProp.value; var loc = getLoc(j, line.indexOf(name), line.length - 1); var tags = getTags({ name: name, isSlot: isSlot$$1, slotIsNot: slotIsNot, slotName: slotName, value: value, block: block }); if (block.isBasic) { if (tags.unsupportedShorthand) { warnings.push({ loc: loc, type: 'The shorthand ' + name + ' isn\'t supported. You need to expand it like:\n' + getUnsupportedShorthandExpanded(name, value).join('\n'), line: line }); } else { var meant = didYouMeanProp(name); if (meant && meant !== name) { warnings.push({ loc: loc, type: 'Did you mean "' + meant + '" instead of "' + name + '"?', line: line }); } } } if (name === 'when') { var isSystem = isSystemScope(value); if (value === '' || value === '<' || value === '<!') { warnings.push({ loc: loc, type: 'This when has no condition assigned to it. Add one like: when <isCondition', line: line }); } else if (!isSystem && !tags.validSlot) { warnings.push({ loc: loc, type: 'The value you used in the slot "' + name + '" is invalid', line: line }); } tags.scope = value; inScope = true; scope = { isSystem: isSystem, value: value, name: name, properties: [] }; if (!isSystem) { if (convertSlotToProps) { scope.value = (slotIsNot ? '!' : '') + 'props.' + (slotName || name); } scope.slotIsNot = slotIsNot; scope.slotName = slotName; } scopes.push(scope); } else if ((tags.slot || tags.shouldBeSlot) && !tags.validSlot) { warnings.push({ loc: loc, type: 'The value you used in the slot "' + name + '" is invalid', line: line }); } if (name === 'onWhen' && properties.length > 0) { warnings.push({ type: 'Put onWhen at the top of the block. It\'s easier to see it that way!', line: line, loc: loc }); } propNode = { type: 'Property', loc: loc, name: name, tags: tags, value: getValue(value) }; if (tags.slot) { var needsDefaultValue = block.isBasic && !tags.shouldBeSlot && /</.test(propNode.value); propNode.defaultValue = propNode.value; propNode.slotName = slotName; if (convertSlotToProps) { propNode.value = (slotIsNot ? '!' : '') + 'props.' + (slotName || name); } if (needsDefaultValue) { if (name === 'text' && block.name === 'Text') { propNode.defaultValue = ''; } else { propNode.defaultValue = false; warnings.push({ loc: loc, type: 'Add a default value to "' + name + '" like: "' + name + ' <' + slotName + ' default value"', line: line }); } } if (!inScope && !slots.some(function (vp) { return vp.name === name; })) { slots.push({ name: slotName || name, type: getPropType(block, name, value), defaultValue: tags.shouldBeSlot || !block.isBasic ? false : propNode.defaultValue }); } } } else if (isComment(line) && !skipComments) { var _getComment = getComment(line), _getComment2 = slicedToArray(_getComment, 1), _value = _getComment2[0]; var userComment = isUserComment(line); if (userComment) { _value = getComment(_value); } propNode = { type: 'Property', loc: getLoc(j, 0, line.length - 1), value: _value, tags: { comment: true, userComment: userComment } }; } if (propNode) { block.loc.end = propNode.loc.end; if (inScope) { if (propNode.name !== 'when' && !propNode.tags.comment && !properties.some(function (baseProp) { return baseProp.name === propNode.name; })) { warnings.push({ loc: propNode.loc, type: 'You\'re missing a base prop for ' + propNode.name + '. Add it before all whens on the block.', line: line }); } scope.properties.push(propNode); } else { properties.push(propNode); } } }; for (var j = i; j <= endOfBlockIndex; j++) { _loop(j); } block.properties = properties; block.scopes = scopes; }; lines.forEach(function (line, i) { if (line !== rlines[i]) { warnings.push({ type: 'You have some spaces before or after this line. Clean them up.', loc: { start: { line: i } }, line: rlines[i] }); } if (isBlock(line)) { parseBlock(line, i); } else if (isEnd(line) && stack.length > 0) { end(stack.pop(), i); } }); if (stack.length > 0) { while (!end(stack.pop(), lines.length - 1)) {} } return { fonts: fonts, slots: slots, views: views, warnings: warnings }; }); module.exports = index; //# sourceMappingURL=parse.js.map