'use strict' var css = require('css') var util = require('./lib/util') var validateItem = require('./lib/validator').validate var fs = require('fs') var path = require('path') var lodash = require('lodash') var SELECTOR_MATCHER = /^[\.#]?[A-Za-z0-9_\-:]+$/ var DESCENDANT_SELECTOR_MATCHER = /^([.#]?[A-Za-z0-9_-]+(\s+|\s*>\s*))+([.#]?[A-Za-z0-9_\-:]+)$/ var IMPORT_MATCHER = /(['"]([^()]+?)['"])|(['"]([^()]+?)['"]\s+(only|not)?\s?(screen)?\s?((and|or|,|not|landscape)?\s?[(]([^()])+[)]\s*)+)/g var LENGTH_REGEXP = /^[-+]?\d*\.?\d+(\S*)$/ const CARD_SELECTOR = /^[\.#][A-Za-z0-9_\-]+$/ const card = process.env.DEVICE_LEVEL === 'card' var ALL_SELECTOR_MATCHER = /^\*$/ var ATTRIBUTE_SELECTOR = /^\[+(?![0-9])\w{0,}(\s*=\s*)((?![0-9])\w{0,}|\"\w{0,}\")\]+$/ var ELEMENT_AND_ELEMENT = /^[a-zA-Z][a-zA-Z-]{0,}\s{0,}(\+\s{0,}[a-zA-Z][a-zA-Z-]{0,})+$/ var CONTENT_ID = /^[a-zA-Z][a-zA-Z-]{0,}([#][a-zA-Z][a-zA-Z0-9-]{0,})(.+?::(after|before))+$/ /** * expand margin、padding、border、borderWidth、borderColor、borderStyle properties、animation * * @param {object} subResult * @param {String} camelCasedName * @param {object} ruleResult */ function expand (subResult, camelCasedName, ruleResult) { if (camelCasedName === 'border') { subResult.value.forEach(function (item) { if (item.type === 'Width' || item.type === 'Color' || item.type === 'Style') { const spliceName = [camelCasedName + 'Top' + item.type, camelCasedName + 'Right' + item.type, camelCasedName + 'Bottom' + item.type, camelCasedName + 'Left' + item.type] util.splitAttr(ruleResult, item.value, spliceName) } else { ruleResult[camelCasedName + item.type] = item.value } }) } else if (['borderTop', 'borderRight', 'borderBottom', 'borderLeft'].includes(camelCasedName)) { subResult.value.forEach(function (item) { ruleResult[camelCasedName + item.type] = item.value }) } else if (camelCasedName === 'margin' || camelCasedName === 'padding') { const spliceName = [camelCasedName + 'Top', camelCasedName + 'Right', camelCasedName + 'Bottom', camelCasedName + 'Left'] util.splitAttr(ruleResult, subResult.value, spliceName) } else if (camelCasedName === 'borderWidth') { util.splitAttr(ruleResult, subResult.value, ['borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth']) } else if (camelCasedName === 'borderColor') { util.splitAttr(ruleResult, subResult.value, ['borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor']) } else if (camelCasedName === 'borderStyle') { util.splitAttr(ruleResult, subResult.value, ['borderTopStyle', 'borderRightStyle', 'borderBottomStyle', 'borderLeftStyle']) } else if (camelCasedName === 'borderRadius') { util.splitAttr(ruleResult, subResult.value, ['borderBottomLeftRadius', 'borderBottomRightRadius', 'borderTopLeftRadius', 'borderTopRightRadius']) } else if (camelCasedName === 'gridGap') { util.splitAttr(ruleResult, subResult.value, ['gridRowsGap', 'gridColumnsGap']) } else if (camelCasedName === 'boxShadow') { subResult.value.forEach(function (item) { if (item.type === 'H' || item.type === 'V' || item.type === 'Blur' || item.type === 'Spread' || item.type === 'Color') { util.splitAttr(ruleResult, item.value, [camelCasedName + item.type]) } }) } else if (camelCasedName === 'animation') { Object.assign(ruleResult, subResult.value); } else { // never to do } } /** * expand flex style * * @param {object} rule * @param {Array} ruleLog */ function flexExpand(rule, ruleLog) { for (let i = 0; i < rule.declarations.length; i++) { let declaration = rule.declarations[i] if (declaration.property === 'flex') { let values = declaration.value.split(/\s+/) rule.declarations.splice(i, 1) if (values.length === 1) { checkFlexOne(rule, ruleLog, declaration, values, i) } else if (values.length === 2) { checkFlexTwo(rule, ruleLog, declaration, values, i) } else if (values.length === 3) { checkFlexThree(rule, ruleLog, declaration, values, i) } else { ruleLog.push({ line: declaration.position.start.line, column: declaration.position.start.column, reason: 'ERROR: Value `' + declaration.value + '` of the `' + declaration.property + '` attribute is incorrect.' }) } } } } function getUnit(value) { value = value.toString().trim() let match = value.match(LENGTH_REGEXP) if (match) { let unit = match[1] if (unit) { if (unit === 'px') { return "px" } } else { return "none" } } return null } function checkFlexOne(rule, ruleLog, declaration, values, i) { const array = ['none', 'auto', 'initial'] if (array.includes(values[0])) { rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex', value: values[0], position: declaration.position}) } else if (getUnit(values[0]) === 'px') { rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-basis', value: values[0], position: declaration.position}) } else if (getUnit(values[0]) === 'none') { rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-grow', value: values[0], position: declaration.position}) } else { ruleLog.push({ line: declaration.position.start.line, column: declaration.position.start.column, reason: 'ERROR: Value `' + declaration.value + '` of the `' + declaration.property + '` attribute is incorrect.' + 'It must be a number, a number with unit `' + 'px`' + ', none, auto, or initial.' }) } } function checkFlexTwo(rule, ruleLog, declaration, values, i) { if (getUnit(values[0]) === 'none') { rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-grow', value: values[0], position: declaration.position}) if (getUnit(values[1]) === 'px') { rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-basis', value: values[1], position: declaration.position}) } else if (getUnit(values[1]) === 'none') { rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-shrink', value: values[1], position: declaration.position}) } else { ruleLog.push({ line: declaration.position.start.line, column: declaration.position.start.column, reason: 'ERROR: Value `' + declaration.value + '` of the `' + declaration.property + '` attribute is incorrect. Value `' + values[1] + '` must be a number or a number with unit `' + 'px`.' }) } } else { ruleLog.push({ line: declaration.position.start.line, column: declaration.position.start.column, reason: 'ERROR: Value `' + declaration.value + '` of the `' + declaration.property + '` attribute is incorrect. Value `' + values[0] + '` must be a number.' }) } } function checkFlexThree(rule, ruleLog, declaration, values, i) { if (getUnit(values[0]) === 'none' && getUnit(values[1]) === 'none' && getUnit(values[2]) === 'px') { rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-grow', value: values[0], position: declaration.position}) rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-shrink', value: values[1], position: declaration.position}) rule.declarations.splice(i, 0, {type: 'declaration', property: 'flex-basis', value: values[2], position: declaration.position}) } else { ruleLog.push({ line: declaration.position.start.line, column: declaration.position.start.column, reason: 'ERROR: Value `' + declaration.value + '` of the `' + declaration.property + '` attribute is incorrect. It must be in the format of (1, 1, 1px).' }) } } /** * Parse `