You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1387 lines
42 KiB

'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
? '<string, Map<string, Map<string, any>>>'
: '<string, any>'
: ''}([${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;