'use strict'; var parseCSSFont = require('parse-css-font'); var postcss = require('postcss'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var parseCSSFont__default = /*#__PURE__*/_interopDefault(parseCSSFont); var postcss__default = /*#__PURE__*/_interopDefault(postcss); /** * Make a map and return a function for checking if a key * is in that map. * IMPORTANT: all calls of this function must be prefixed with * \/\*#\_\_PURE\_\_\*\/ * So that rollup can tree-shake them if necessary. */ (process.env.NODE_ENV !== 'production') ? Object.freeze({}) : {}; (process.env.NODE_ENV !== 'production') ? Object.freeze([]) : []; const extend = Object.assign; const hasOwnProperty = Object.prototype.hasOwnProperty; const hasOwn = (val, key) => hasOwnProperty.call(val, key); const isFunction = (val) => typeof val === 'function'; const isString = (val) => typeof val === 'string'; const cacheStringFunction$1 = (fn) => { const cache = Object.create(null); return ((str) => { const hit = cache[str]; return hit || (cache[str] = fn(str)); }); }; const camelizeRE = /-(\w)/g; /** * @private */ const camelize = cacheStringFunction$1((str) => { return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : '')); }); const hyphenateRE$1 = /\B([A-Z])/g; /** * @private */ const hyphenate = cacheStringFunction$1((str) => str.replace(hyphenateRE$1, '-$1').toLowerCase()); const COMBINATORS_RE = /^((?:(?:\.[A-Za-z0-9_\-]+)+[\+\~\> ])*)((?:\.[A-Za-z0-9_\-\:]+)+)$/; function createDecl(prop, value, important, raws, source) { const decl = { type: 'decl', prop, value: value.toString(), raws, source, }; if (important) { decl.important = true; } return decl; } const NUM_REGEXP = /^[-]?\d*\.?\d+$/; const LENGTH_REGEXP = /^[-+]?\d*\.?\d+(\S*)$/; const SUPPORT_CSS_UNIT = ['px', 'pt', 'wx', 'upx', 'rpx']; const isNumber = (val) => typeof val === 'number'; const cacheStringFunction = (fn) => { const cache = Object.create(null); return ((str) => { const hit = cache[str]; return hit || (cache[str] = fn(str)); }); }; const hyphenateRE = /([A-Z])/g; const hyphenateStyleProperty = cacheStringFunction((str) => str .replace(hyphenateRE, (_, m) => { if (typeof m === 'string') { return '-' + m.toLowerCase(); } return m; }) .toLowerCase()); function autofixedReason(v, result) { return 'NOTE: property value `' + v + '` is autofixed to `' + result + '`'; } function validReason(k, v) { return ('ERROR: property value `' + v + '` is not valid for `' + hyphenateStyleProperty(k) + '`'); } function defaultValueReason(k, v) { return ('NOTE: property value `' + v + '` is the DEFAULT value for `' + hyphenateStyleProperty(k) + '` (could be removed)'); } function supportedEnumReason(k, v, items) { return ('ERROR: property value `' + v + '` is not supported for `' + hyphenateStyleProperty(k) + '` (supported values are: `' + items.join('`|`') + '`)'); } function supportedValueWithTipsReason(k, v, tips) { return ('ERROR: property value `' + v + '` is not supported for `' + hyphenateStyleProperty(k) + '` ' + tips); } function supportedUnitWithAutofixedReason(unit, v, result) { return ('NOTE: unit `' + unit + '` is not supported and property value `' + v + '` is autofixed to `' + result + '`'); } function compatibilityReason(k) { return ('NOTE: the ' + hyphenateStyleProperty(k) + ' property may have compatibility problem on native'); } const backgroundColor = 'background-color' ; const backgroundImage = 'background-image' ; const transformBackground = (decl) => { const { value, important, raws, source } = decl; if (/^#?\S+$/.test(value) || /^rgba?(.+)$/.test(value)) { return [createDecl(backgroundColor, value, important, raws, source)]; } else if (/^linear-gradient(.+)$/.test(value)) { return [createDecl(backgroundImage, value, important, raws, source)]; } return [decl]; }; const borderWidth = '-width' ; const borderStyle = '-style' ; const borderColor = '-color' ; const transformBorder = (decl) => { const { prop, value, important, raws, source } = decl; const splitResult = value.replace(/\s*,\s*/g, ',').split(/\s+/); const result = [/^[\d\.]+\S*$/, /^(solid|dashed|dotted)$/, /\S+/].map((item) => { const index = splitResult.findIndex((str) => item.test(str)); return index < 0 ? null : splitResult.splice(index, 1)[0]; }); if (splitResult.length) { return [decl]; } return [ createDecl(prop + borderWidth, (result[0] || '0').trim(), important, raws, source), createDecl(prop + borderStyle, (result[1] || 'solid').trim(), important, raws, source), createDecl(prop + borderColor, (result[2] || '#000000').trim(), important, raws, source), ]; }; const borderTop = 'border-top-' ; const borderRight = 'border-right-' ; const borderBottom = 'border-bottom-' ; const borderLeft = 'border-left-' ; const transformBorderColor = (decl) => { const { prop, value, important, raws, source } = decl; let property = hyphenate(prop).split('-')[1]; const splitResult = value.replace(/\s*,\s*/g, ',').split(/\s+/); switch (splitResult.length) { case 1: return [decl]; case 2: splitResult.push(splitResult[0], splitResult[1]); break; case 3: splitResult.push(splitResult[1]); break; } return [ createDecl(borderTop + property, splitResult[0], important, raws, source), createDecl(borderRight + property, splitResult[1], important, raws, source), createDecl(borderBottom + property, splitResult[2], important, raws, source), createDecl(borderLeft + property, splitResult[3], important, raws, source), ]; }; const borderTopLeftRadius = 'border-top-left-radius' ; const borderTopRightRadius = 'border-top-right-radius' ; const borderBottomRightRadius = 'border-bottom-right-radius' ; const borderBottomLeftRadius = 'border-bottom-left-radius' ; const transformBorderRadius = (decl) => { const { value, important, raws, source } = decl; const splitResult = value.split(/\s+/); if (value.includes('/')) { return [decl]; } switch (splitResult.length) { case 1: return [decl]; case 2: splitResult.push(splitResult[0], splitResult[1]); break; case 3: splitResult.push(splitResult[1]); break; } return [ createDecl(borderTopLeftRadius, splitResult[0], important, raws, source), createDecl(borderTopRightRadius, splitResult[1], important, raws, source), createDecl(borderBottomRightRadius, splitResult[2], important, raws, source), createDecl(borderBottomLeftRadius, splitResult[3], important, raws, source), ]; }; const transformBorderStyle = transformBorderColor; const transformBorderWidth = transformBorderColor; const flexDirection = 'flex-direction' ; const flexWrap = 'flex-wrap' ; const transformFlexFlow = (decl) => { const { value, important, raws, source } = decl; const splitResult = value.split(/\s+/); const result = [ /^(column|column-reverse|row|row-reverse)$/, /^(nowrap|wrap|wrap-reverse)$/, ].map((item) => { const index = splitResult.findIndex((str) => item.test(str)); return index < 0 ? null : splitResult.splice(index, 1)[0]; }); if (splitResult.length) { return [decl]; } return [ createDecl(flexDirection, result[0] || 'column', important, raws, source), createDecl(flexWrap, result[1] || 'nowrap', important, raws, source), ]; }; const transformFont = (decl) => { const { value, important, raws, source } = decl; const result = []; const font = parseCSSFont__default.default(value); if (font.system) { return result; } const { style, weight, size, lineHeight, family } = font; if (style) { result.push(createDecl('font-style', style, important, raws, source)); } if (weight) { result.push(createDecl('font-weight', weight, important, raws, source)); } if (size) { result.push(createDecl('font-size', size, important, raws, source)); } if (lineHeight) { result.push(createDecl('line-height', lineHeight, important, raws, source)); } if (family) { result.push(createDecl('font-family', serialize(family), important, raws, source)); } return result; }; function serialize(family) { return family.map((f) => (f.includes(' ') ? `"${f}"` : f)).join(', '); } const top = '-top' ; const right = '-right' ; const bottom = '-bottom' ; const left = '-left' ; const createTransformBox = (type) => { return (decl) => { const { value, important, raws, source } = decl; const splitResult = value.split(/\s+/); switch (splitResult.length) { case 1: splitResult.push(splitResult[0], splitResult[0], splitResult[0]); break; case 2: splitResult.push(splitResult[0], splitResult[1]); break; case 3: splitResult.push(splitResult[1]); break; } return [ createDecl(type + top, splitResult[0], important, raws, source), createDecl(type + right, splitResult[1], important, raws, source), createDecl(type + bottom, splitResult[2], important, raws, source), createDecl(type + left, splitResult[3], important, raws, source), ]; }; }; const transformMargin = createTransformBox('margin'); const transformPadding = createTransformBox('padding'); const transitionProperty = 'transition-property' ; const transitionDuration = 'transition-duration' ; const transitionTimingFunction = 'transition-timing-function' ; const transitionDelay = 'transition-delay' ; const transformTransition = (decl) => { const CHUNK_REGEXP = /^(\S*)?\s*(\d*\.?\d+(?:ms|s)?)?\s*(\S*)?\s*(\d*\.?\d+(?:ms|s)?)?$/; const { value, important, raws, source } = decl; const result = []; const match = value.match(CHUNK_REGEXP); if (!match) { return result; } match[1] && result.push(createDecl(transitionProperty, match[1], important, raws, source)); match[2] && result.push(createDecl(transitionDuration, match[2], important, raws, source)); match[3] && result.push(createDecl(transitionTimingFunction, match[3], important, raws, source)); match[4] && result.push(createDecl(transitionDelay, match[4], important, raws, source)); return result; }; const DeclTransforms = { transition: transformTransition, margin: transformMargin, padding: transformPadding, border: transformBorder, background: transformBackground, }; { extend(DeclTransforms, { 'border-top': transformBorder, 'border-right': transformBorder, 'border-bottom': transformBorder, 'border-left': transformBorder, 'border-style': transformBorderStyle, 'border-width': transformBorderWidth, 'border-color': transformBorderColor, 'border-radius': transformBorderRadius, 'flex-flow': transformFlexFlow, font: transformFont, }); } const expanded = Symbol('expanded'); const expand = { postcssPlugin: 'nvue:expand', Declaration(decl) { if (decl[expanded]) { return; } const transform = DeclTransforms[decl.prop]; if (transform) { const res = transform(decl); const isSame = res.length === 1 && res[0] === decl; if (!isSame) { decl.replaceWith(res); } } decl[expanded] = true; }, }; const normalizeColor = (v) => { v = (v || '').toString(); if (v.match(/^#[0-9a-fA-F]{6}$/)) { return { value: v }; } if (v.match(/^#[0-9a-fA-F]{3}$/)) { return { value: '#' + v[1] + v[1] + v[2] + v[2] + v[3] + v[3], reason: function reason(k, v, result) { return autofixedReason(v, result); }, }; } if (EXTENDED_COLOR_KEYWORDS[v]) { return { value: EXTENDED_COLOR_KEYWORDS[v], reason: function reason(k, v, result) { return autofixedReason(v, result); }, }; } let arrColor, r, g, b, a; const RGB_REGEXP = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/gi; const RGBA_REGEXP = /^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d*\.?\d+)\s*\)$/gi; if ((arrColor = RGB_REGEXP.exec(v))) { r = parseInt(arrColor[1]); g = parseInt(arrColor[2]); b = parseInt(arrColor[3]); if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) { return { value: 'rgb(' + [r, g, b].join(',') + ')' }; } } if ((arrColor = RGBA_REGEXP.exec(v))) { r = parseInt(arrColor[1]); g = parseInt(arrColor[2]); b = parseInt(arrColor[3]); a = parseFloat(arrColor[4]); if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && a >= 0 && a <= 1) { return { value: 'rgba(' + [r, g, b, a].join(',') + ')' }; } } if (v === 'transparent') { return { value: 'rgba(0,0,0,0)' }; } return { value: null, reason(k, v, result) { return validReason(k, v); }, }; }; // http://www.w3.org/TR/css3-color/#svg-color const EXTENDED_COLOR_KEYWORDS = { aliceblue: '#F0F8FF', antiquewhite: '#FAEBD7', aqua: '#00FFFF', aquamarine: '#7FFFD4', azure: '#F0FFFF', beige: '#F5F5DC', bisque: '#FFE4C4', black: '#000000', blanchedalmond: '#FFEBCD', blue: '#0000FF', blueviolet: '#8A2BE2', brown: '#A52A2A', burlywood: '#DEB887', cadetblue: '#5F9EA0', chartreuse: '#7FFF00', chocolate: '#D2691E', coral: '#FF7F50', cornflowerblue: '#6495ED', cornsilk: '#FFF8DC', crimson: '#DC143C', cyan: '#00FFFF', darkblue: '#00008B', darkcyan: '#008B8B', darkgoldenrod: '#B8860B', darkgray: '#A9A9A9', darkgreen: '#006400', darkgrey: '#A9A9A9', darkkhaki: '#BDB76B', darkmagenta: '#8B008B', darkolivegreen: '#556B2F', darkorange: '#FF8C00', darkorchid: '#9932CC', darkred: '#8B0000', darksalmon: '#E9967A', darkseagreen: '#8FBC8F', darkslateblue: '#483D8B', darkslategray: '#2F4F4F', darkslategrey: '#2F4F4F', darkturquoise: '#00CED1', darkviolet: '#9400D3', deeppink: '#FF1493', deepskyblue: '#00BFFF', dimgray: '#696969', dimgrey: '#696969', dodgerblue: '#1E90FF', firebrick: '#B22222', floralwhite: '#FFFAF0', forestgreen: '#228B22', fuchsia: '#FF00FF', gainsboro: '#DCDCDC', ghostwhite: '#F8F8FF', gold: '#FFD700', goldenrod: '#DAA520', gray: '#808080', green: '#008000', greenyellow: '#ADFF2F', grey: '#808080', honeydew: '#F0FFF0', hotpink: '#FF69B4', indianred: '#CD5C5C', indigo: '#4B0082', ivory: '#FFFFF0', khaki: '#F0E68C', lavender: '#E6E6FA', lavenderblush: '#FFF0F5', lawngreen: '#7CFC00', lemonchiffon: '#FFFACD', lightblue: '#ADD8E6', lightcoral: '#F08080', lightcyan: '#E0FFFF', lightgoldenrodyellow: '#FAFAD2', lightgray: '#D3D3D3', lightgreen: '#90EE90', lightgrey: '#D3D3D3', lightpink: '#FFB6C1', lightsalmon: '#FFA07A', lightseagreen: '#20B2AA', lightskyblue: '#87CEFA', lightslategray: '#778899', lightslategrey: '#778899', lightsteelblue: '#B0C4DE', lightyellow: '#FFFFE0', lime: '#00FF00', limegreen: '#32CD32', linen: '#FAF0E6', magenta: '#FF00FF', maroon: '#800000', mediumaquamarine: '#66CDAA', mediumblue: '#0000CD', mediumorchid: '#BA55D3', mediumpurple: '#9370DB', mediumseagreen: '#3CB371', mediumslateblue: '#7B68EE', mediumspringgreen: '#00FA9A', mediumturquoise: '#48D1CC', mediumvioletred: '#C71585', midnightblue: '#191970', mintcream: '#F5FFFA', mistyrose: '#FFE4E1', moccasin: '#FFE4B5', navajowhite: '#FFDEAD', navy: '#000080', oldlace: '#FDF5E6', olive: '#808000', olivedrab: '#6B8E23', orange: '#FFA500', orangered: '#FF4500', orchid: '#DA70D6', palegoldenrod: '#EEE8AA', palegreen: '#98FB98', paleturquoise: '#AFEEEE', palevioletred: '#DB7093', papayawhip: '#FFEFD5', peachpuff: '#FFDAB9', peru: '#CD853F', pink: '#FFC0CB', plum: '#DDA0DD', powderblue: '#B0E0E6', purple: '#800080', red: '#FF0000', rosybrown: '#BC8F8F', royalblue: '#4169E1', saddlebrown: '#8B4513', salmon: '#FA8072', sandybrown: '#F4A460', seagreen: '#2E8B57', seashell: '#FFF5EE', sienna: '#A0522D', silver: '#C0C0C0', skyblue: '#87CEEB', slateblue: '#6A5ACD', slategray: '#708090', slategrey: '#708090', snow: '#FFFAFA', springgreen: '#00FF7F', steelblue: '#4682B4', tan: '#D2B48C', teal: '#008080', thistle: '#D8BFD8', tomato: '#FF6347', turquoise: '#40E0D0', violet: '#EE82EE', wheat: '#F5DEB3', white: '#FFFFFF', whitesmoke: '#F5F5F5', yellow: '#FFFF00', yellowgreen: '#9ACD32', }; function createEnumNormalize(items) { return (v) => { const index = items.indexOf(v); if (index > 0) { return { value: v }; } if (index === 0) { return { value: v, reason: function reason(k, v, result) { return defaultValueReason(k, v); }, }; } return { value: null, reason: function reason(k, v, result) { return supportedEnumReason(k, v, items); }, }; }; } const normalizeFlexWrap = (v) => { const values = ['nowrap', 'wrap', 'wrap-reverse']; const index = values.indexOf(v); if (index > 0) { return { value: v, reason(k, v, result) { return compatibilityReason(k); }, }; } if (index === 0) { return { value: v, reason: function reason(k, v, result) { return defaultValueReason(k, v); }, }; } return { value: null, reason(k, v, result) { return supportedEnumReason(k, v, values); }, }; }; const normalizeInteger = (v) => { v = (v || '').toString(); if (v.match(/^[-+]?\d+$/)) { return { value: parseInt(v, 10) }; } return { value: null, reason: function reason(k, v, result) { return supportedValueWithTipsReason(k, v, `(only integer is supported)`); }, }; }; const normalizeLength = createNormalizeLength(); const normalizeLengthWithPercent = createNormalizeLength({ percent: true, }); const normalizeLengthWithAutoAndPercent = createNormalizeLength({ auto: true, percent: true, }); function createNormalizeLength(options = {}) { return (v) => { v = (v || '').toString(); const match = v.match(LENGTH_REGEXP); if (match) { var unit = match[1]; if (!unit || unit === 'px') { return { value: parseFloat(v) }; } else if (SUPPORT_CSS_UNIT.includes(unit) || (options.percent && unit === '%')) { return { value: v }; } else { return { value: parseFloat(v), reason(k, v, result) { return supportedUnitWithAutofixedReason(unit, v, result); }, }; } } else { if (options.auto && v === 'auto') { return { value: v }; } } return { value: null, reason(k, v, result) { return supportedValueWithTipsReason(k, v, `(only number and pixel values are supported)`); }, }; }; } const normalizeNumber = (v) => { v = (v || '').toString(); var match = v.match(LENGTH_REGEXP); if (match && !match[1]) { return { value: parseFloat(v) }; } return { value: null, reason: function reason(k, v, result) { return supportedValueWithTipsReason(k, v, '(only number is supported)'); }, }; }; const normalizeShorthandLength = (v, options) => { v = (v || '').toString(); let value = []; let reason = []; const results = v.split(/\s+/).map((v) => normalizeLength(v, options)); for (let i = 0; i < results.length; ++i) { const res = results[i]; if (res.value === null) { return res; } value.push(res.value); reason.push(res.reason); } return { value: value.join(' '), reason: function (k, v, result) { return reason .map(function (res) { if (isFunction(res)) { return res(k, v, result); } }) .join('\n'); }, }; }; const normalizeTransform = (v) => { return { value: v }; }; const normalizeTransitionInterval = (v) => { v = (v || 0).toString(); let match, num; if ((match = v.match(/^\d*\.?\d+(ms|s)?$/))) { num = parseFloat(match[0]); if (!match[1]) { return { value: parseInt(num + '') }; } if (match[1] === 's') { num *= 1000; } return { value: parseInt(num + ''), reason(k, v, result) { return autofixedReason(v, result); }, }; } return { value: null, reason(k, v, result) { return supportedValueWithTipsReason(k, v, '(only number of seconds and milliseconds is valid)'); }, }; }; const normalizeTransitionProperty = (v, options) => { v = (v || '').toString(); v = v .split(/\s*,\s*/) .map(camelize) .join(','); if (v.split(/\s*,\s*/).every((p) => !!getNormalizeMap(options)[p])) { return { value: v }; } return { value: null, reason: function reason(k, v, result) { return supportedValueWithTipsReason(k, v, '(only css property is valid)'); }, }; }; const normalizeTransitionTimingFunction = (v) => { v = (v || '').toString(); if (v.match(/^linear|ease|ease-in|ease-out|ease-in-out$/)) { return { value: v }; } let match; if ((match = v.match(/^cubic-bezier\(\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*\)$/))) { if (match[1].match(NUM_REGEXP) && match[2].match(NUM_REGEXP) && match[3].match(NUM_REGEXP) && match[4].match(NUM_REGEXP)) { const ret = [ parseFloat(match[1]), parseFloat(match[2]), parseFloat(match[3]), parseFloat(match[4]), ].join(','); return { value: 'cubic-bezier(' + ret + ')' }; } } return { value: null, reason(k, v, result) { return supportedEnumReason(k, v, [ 'linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out', 'cubic-bezier(n,n,n,n)', ]); }, }; }; const normalizeDefault = (v) => { return { value: v }; }; const UVUE_PROP_NAME_GROUPS = { boxModel: { display: createEnumNormalize(['flex', 'none']), width: normalizeLengthWithPercent, height: normalizeLengthWithPercent, minWidth: normalizeLengthWithPercent, minHeight: normalizeLengthWithPercent, maxWidth: normalizeLengthWithPercent, maxHeight: normalizeLengthWithPercent, overflow: createEnumNormalize(['hidden', 'visible']), padding: normalizeShorthandLength, paddingLeft: normalizeLengthWithAutoAndPercent, paddingRight: normalizeLengthWithAutoAndPercent, paddingTop: normalizeLengthWithAutoAndPercent, paddingBottom: normalizeLengthWithAutoAndPercent, margin: normalizeShorthandLength, marginLeft: normalizeLengthWithAutoAndPercent, marginRight: normalizeLengthWithAutoAndPercent, marginTop: normalizeLengthWithAutoAndPercent, marginBottom: normalizeLengthWithAutoAndPercent, borderWidth: normalizeLength, borderLeftWidth: normalizeLength, borderTopWidth: normalizeLength, borderRightWidth: normalizeLength, borderBottomWidth: normalizeLength, borderColor: normalizeColor, borderLeftColor: normalizeColor, borderTopColor: normalizeColor, borderRightColor: normalizeColor, borderBottomColor: normalizeColor, borderStyle: createEnumNormalize(['dotted', 'dashed', 'solid']), borderTopStyle: createEnumNormalize(['dotted', 'dashed', 'solid']), borderRightStyle: createEnumNormalize(['dotted', 'dashed', 'solid']), borderBottomStyle: createEnumNormalize(['dotted', 'dashed', 'solid']), borderLeftStyle: createEnumNormalize(['dotted', 'dashed', 'solid']), borderRadius: normalizeLength, borderBottomLeftRadius: normalizeLength, borderBottomRightRadius: normalizeLength, borderTopLeftRadius: normalizeLength, borderTopRightRadius: normalizeLength, }, flexbox: { flex: normalizeDefault, flexShrink: normalizeDefault, flexGrow: normalizeDefault, flexBasis: normalizeDefault, flexWrap: normalizeFlexWrap, flexFlow: normalizeDefault, flexDirection: createEnumNormalize([ 'column', 'row', 'column-reverse', 'row-reverse', ]), justifyContent: createEnumNormalize([ 'flex-start', 'flex-end', 'center', 'space-between', 'space-around', ]), alignItems: createEnumNormalize([ 'stretch', 'flex-start', 'flex-end', 'center', 'baseline', ]), alignContent: createEnumNormalize([ 'stretch', 'flex-start', 'flex-end', 'center', 'space-between', 'space-around', ]), }, position: { position: createEnumNormalize(['relative', 'absolute', 'sticky', 'fixed']), top: normalizeLengthWithAutoAndPercent, bottom: normalizeLengthWithAutoAndPercent, left: normalizeLengthWithAutoAndPercent, right: normalizeLengthWithAutoAndPercent, zIndex: normalizeInteger, }, common: { opacity: normalizeNumber, boxShadow: normalizeDefault, boxSizing: createEnumNormalize(['content-box', 'border-box']), backgroundColor: normalizeColor, backgroundImage: normalizeDefault, backgroundClip: createEnumNormalize([ 'border-box', 'padding-box', 'content-box', ]), }, text: { lines: normalizeInteger, color: normalizeColor, fontSize: normalizeLength, fontStyle: createEnumNormalize(['normal', 'italic']), fontFamily: normalizeDefault, fontWeight: createEnumNormalize([ 'normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900', ]), textDecoration: createEnumNormalize(['none', 'underline', 'line-through']), textAlign: createEnumNormalize(['left', 'center', 'right']), textOverflow: createEnumNormalize(['clip', 'ellipsis', 'unset', 'fade']), lineHeight: normalizeLength, }, transition: { transitionProperty: normalizeTransitionProperty, transitionDuration: normalizeTransitionInterval, transitionDelay: normalizeTransitionInterval, transitionTimingFunction: normalizeTransitionTimingFunction, }, transform: { transform: normalizeTransform, transformOrigin: normalizeTransform, // fixed by xxxxxx }, customized: { itemSize: normalizeLength, itemColor: normalizeColor, itemSelectedColor: normalizeColor, textColor: normalizeColor, timeColor: normalizeColor, textHighlightColor: normalizeColor, }, }; const NVUE_PROP_NAME_GROUPS = { boxModel: { display: createEnumNormalize(['flex']), width: normalizeLength, height: normalizeLength, overflow: createEnumNormalize(['hidden']), padding: normalizeShorthandLength, paddingLeft: normalizeLength, paddingRight: normalizeLength, paddingTop: normalizeLength, paddingBottom: normalizeLength, margin: normalizeShorthandLength, marginLeft: normalizeLength, marginRight: normalizeLength, marginTop: normalizeLength, marginBottom: normalizeLength, borderWidth: normalizeLength, borderLeftWidth: normalizeLength, borderTopWidth: normalizeLength, borderRightWidth: normalizeLength, borderBottomWidth: normalizeLength, borderColor: normalizeColor, borderLeftColor: normalizeColor, borderTopColor: normalizeColor, borderRightColor: normalizeColor, borderBottomColor: normalizeColor, borderStyle: createEnumNormalize(['dotted', 'dashed', 'solid']), borderTopStyle: createEnumNormalize(['dotted', 'dashed', 'solid']), borderRightStyle: createEnumNormalize(['dotted', 'dashed', 'solid']), borderBottomStyle: createEnumNormalize(['dotted', 'dashed', 'solid']), borderLeftStyle: createEnumNormalize(['dotted', 'dashed', 'solid']), borderRadius: normalizeLength, borderBottomLeftRadius: normalizeLength, borderBottomRightRadius: normalizeLength, borderTopLeftRadius: normalizeLength, borderTopRightRadius: normalizeLength, }, flexbox: { flex: normalizeNumber, flexWrap: normalizeFlexWrap, flexDirection: createEnumNormalize([ 'column', 'row', 'column-reverse', 'row-reverse', ]), justifyContent: createEnumNormalize([ 'flex-start', 'flex-end', 'center', 'space-between', 'space-around', ]), alignItems: createEnumNormalize([ 'stretch', 'flex-start', 'flex-end', 'center', ]), }, position: { position: createEnumNormalize(['relative', 'absolute', 'sticky', 'fixed']), top: normalizeLength, bottom: normalizeLength, left: normalizeLength, right: normalizeLength, zIndex: normalizeInteger, }, common: { opacity: normalizeNumber, boxShadow: normalizeDefault, backgroundColor: normalizeColor, backgroundImage: normalizeDefault, }, text: { lines: normalizeInteger, color: normalizeColor, fontSize: normalizeLength, fontStyle: createEnumNormalize(['normal', 'italic']), fontFamily: normalizeDefault, fontWeight: createEnumNormalize([ 'normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900', ]), textDecoration: createEnumNormalize(['none', 'underline', 'line-through']), textAlign: createEnumNormalize(['left', 'center', 'right']), textOverflow: createEnumNormalize(['clip', 'ellipsis', 'unset', 'fade']), lineHeight: normalizeLength, }, transition: { transitionProperty: normalizeTransitionProperty, transitionDuration: normalizeTransitionInterval, transitionDelay: normalizeTransitionInterval, transitionTimingFunction: normalizeTransitionTimingFunction, }, transform: { transform: normalizeTransform, transformOrigin: normalizeTransform, // fixed by xxxxxx }, customized: { itemSize: normalizeLength, itemColor: normalizeColor, itemSelectedColor: normalizeColor, textColor: normalizeColor, timeColor: normalizeColor, textHighlightColor: normalizeColor, }, }; let normalizeMap; function getNormalizeMap(options) { if (normalizeMap) { return normalizeMap; } const uvue = options.type === 'uvue'; const PROP_NAME_GROUPS = uvue ? UVUE_PROP_NAME_GROUPS : NVUE_PROP_NAME_GROUPS; normalizeMap = Object.keys(PROP_NAME_GROUPS).reduce((res, name) => { const group = PROP_NAME_GROUPS[name]; Object.keys(group).forEach((prop) => { res[prop] = group[prop]; }); return res; }, {}); return normalizeMap; } const normalized = Symbol('normalized'); function normalize(opts = {}) { if (!hasOwn(opts, 'logLevel')) { opts.logLevel = 'WARNING'; } const plugin = { postcssPlugin: `${opts.type || 'nvue'}:normalize`, Declaration: createDeclarationProcessor(opts), }; { plugin.Rule = createRuleProcessor(); } return plugin; } function createRuleProcessor() { return (rule, helper) => { if (rule[normalized]) { return; } rule.selector = rule.selectors .map((selector) => { selector = selector .replace(/\s*([\+\~\>])\s*/g, '$1') .replace(/\s+/, ' '); if (COMBINATORS_RE.test(selector)) { return selector; } rule.warn(helper.result, 'ERROR: Selector `' + selector + '` is not supported. nvue only support classname selector'); return ''; }) .filter(Boolean) .join(', '); if (!rule.selector) { rule.remove(); } rule[normalized] = true; }; } function createDeclarationProcessor(options) { return (decl, helper) => { if (decl[normalized]) { return; } decl.prop = camelize(decl.prop); const { value, log } = normalizeDecl(decl.prop, decl.value, options); if (isString(value) || isNumber(value)) { decl.value = value; } if (log && log.reason && helper) { const { reason } = log; let needLog = false; if (options.logLevel === 'NOTE') { needLog = true; } else if (options.logLevel === 'ERROR') { if (reason.startsWith('ERROR:')) { needLog = true; } } else { if (!reason.startsWith('NOTE:')) { needLog = true; } } needLog && decl.warn(helper.result, reason); } if (value === null) { decl.remove(); } decl[normalized] = true; }; } function normalizeDecl(name, value, options) { let result, log; const normalize = getNormalizeMap(options)[name]; if (isFunction(normalize)) { if (!isFunction(value)) { result = normalize(value, options); } else { result = { value: value }; } if (result.reason) { log = { reason: result.reason(name, value, result.value) }; } } else { // ensure number type, no `px` if (isString(value)) { const match = value.match(LENGTH_REGEXP); if (match && (!match[1] || SUPPORT_CSS_UNIT.indexOf(match[1]) === -1)) { value = parseFloat(value); } } result = { value: value }; log = { reason: 'WARNING: `' + hyphenateStyleProperty(name) + '` is not a standard property name (may not be supported)', }; } return { value: result.value, log, }; } function objectifier(node) { if (!node) { return {}; } const context = { 'FONT-FACE': [], TRANSITION: {}, }; const result = transform(node, context); if (context['FONT-FACE'].length) { result['@FONT-FACE'] = context['FONT-FACE']; } if (Object.keys(context.TRANSITION).length) { result['@TRANSITION'] = context.TRANSITION; } return result; } function transform(node, context) { const result = {}; node.each((child) => { if (child.type === 'atrule') { const body = transform(child, context); const fontFamily = body.fontFamily; if (fontFamily && '"\''.indexOf(fontFamily[0]) > -1) { body.fontFamily = fontFamily.slice(1, fontFamily.length - 1); } context['FONT-FACE'].push(body); } else if (child.type === 'rule') { const body = transform(child, context); child.selectors.forEach((selector) => { transformSelector(selector, body, result, context); }); } else if (child.type === 'decl') { if (child.important) { result['!' + child.prop] = child.value; // !important的值域优先级高,故删除非!important的值域 delete result[child.prop]; } else { if (!hasOwn(result, '!' + child.prop)) { result[child.prop] = child.value; } } } }); return result; } function transformSelector(selector, body, result, context) { const res = selector.match(COMBINATORS_RE); if (!res) { return; } let parentSelector = res[1]; let curSelector = res[2].substring(1); // .a.b => a.b const dotIndex = curSelector.indexOf('.'); if (dotIndex > -1) { parentSelector += curSelector.substring(dotIndex); curSelector = curSelector.substring(0, dotIndex); } const pseudoIndex = curSelector.indexOf(':'); if (pseudoIndex > -1) { const pseudoClass = curSelector.slice(pseudoIndex); curSelector = curSelector.slice(0, pseudoIndex); Object.keys(body).forEach(function (name) { body[name + pseudoClass] = body[name]; delete body[name]; }); } transition(curSelector, body, context); if (!Object.keys(body).length) { return; } result = (result[curSelector] || (result[curSelector] = {})); if (result[parentSelector]) { // clone result[parentSelector] = processImportant(extend({}, result[parentSelector], body)); } else { result[parentSelector] = body; } } /** * 处理 important 属性,如果某个属性是 important,需要将非 important 的该属性移除掉 * @param body */ function processImportant(body) { Object.keys(body).forEach((name) => { if (name.startsWith('!')) { delete body[name.substring(1)]; } }); return body; } function transition(className, body, { TRANSITION }) { Object.keys(body).forEach((prop) => { if (prop.indexOf('transition') === 0 && prop !== 'transition') { const realProp = prop.replace('transition', ''); TRANSITION[className] = TRANSITION[className] || {}; TRANSITION[className][realProp[0].toLowerCase() + realProp.slice(1)] = body[prop]; } }); } async function parse(input, options = {}) { const { root, messages } = await postcss__default.default([expand, normalize(options)]) .process(input, { from: options.filename || 'foo.css', }) .catch((err) => { return { root: null, messages: [ { type: 'error', text: err.message, }, ], }; }); if (options.noCode === true) { return { code: '', messages }; } const obj = root ? objectifier(root) : {}; if (options.map) { return { code: mapToInitStringChunk(objToMap(obj), options.ts, true, options.chunk), messages, }; } return { code: JSON.stringify(obj), messages }; } function mapToInitStringChunk(map, ts = false, isRoot = false, chunk = 0) { if (!chunk) { return mapToInitString(map, ts, isRoot); } const chunks = []; let chunkMap = new Map(); let chunkCount = 0; for (const [key, value] of map) { if (chunkCount === chunk) { chunks.push(mapToInitString(chunkMap, ts, isRoot)); chunkMap = new Map(); chunkCount = 0; } chunkMap.set(key, value); chunkCount++; } if (chunkCount) { chunks.push(mapToInitString(chunkMap, ts, isRoot)); } return `[${chunks.join(',')}]`; } function mapToInitString(map, ts = false, isRoot = false) { const entries = []; for (let [key, value] of map) { if (value instanceof Map) { entries.push(`["${key}", ${mapToInitString(value, ts)}]`); } else { entries.push(`["${key}", ${JSON.stringify(value)}]`); } } return `new Map${ts ? isRoot ? '>>' : '' : ''}([${entries.join(', ')}])`; } function objToMap(obj) { const map = new Map(); for (const key in obj) { const value = obj[key]; if (typeof value === 'object') { map.set(key, objToMap(value)); } else { map.set(key, value); } } return map; } exports.expand = expand; exports.normalize = normalize; exports.objectifier = objectifier; exports.parse = parse;