function generateDeclaration (property, value, important, position) {
|
return {
|
type: 'declaration',
|
property,
|
value: value + (important ? ' !important' : ''),
|
position
|
}
|
}
|
|
function clearImportant (value) {
|
var newValue = value.replace(/\s*!important/g, '')
|
return {
|
value: newValue,
|
important: value !== newValue
|
}
|
}
|
|
function transition (declaration) {
|
var CHUNK_REGEXP = /^([a-z-_]\S*)(\s+[\d.]+m?s)?(\s+[a-z-_]\S*)?(\s+[\d.]+m?s)?/
|
var { value, important } = clearImportant(declaration.value)
|
var values = value.replace(/(\d)\s*,\s*/g, '$1#').split(',')
|
var position = declaration.position
|
var result = []
|
var map = {
|
'transition-property': [],
|
'transition-duration': [],
|
'transition-timing-function': [],
|
'transition-delay': []
|
}
|
if (values.length) {
|
for (var i1 = 0; i1 < values.length; i1++) {
|
var match = values[i1].trim().match(CHUNK_REGEXP)
|
if (!match) {
|
return []
|
}
|
map['transition-property'].push(match[1] || 'all')
|
map['transition-duration'].push((match[2] || '0s').trim())
|
map['transition-timing-function'].push((match[3] || 'ease').trim().replace(/#/g, ', '))
|
map['transition-delay'].push((match[4] || '0s').trim())
|
}
|
for (var key in map) {
|
var value = map[key]
|
value = value.find(item => item !== value[0]) ? value.join(', ') : value[0]
|
result.push(generateDeclaration(key, value, important, position))
|
}
|
}
|
return result
|
}
|
|
function createParser (property) {
|
return function (declaration) {
|
var { value, important } = clearImportant(declaration.value)
|
var position = declaration.position
|
var splitResult = value.split(/\s+/)
|
var result = []
|
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
|
}
|
result.push(
|
generateDeclaration(property + '-top', splitResult[0], important, position),
|
generateDeclaration(property + '-right', splitResult[1], important, position),
|
generateDeclaration(property + '-bottom', splitResult[2], important, position),
|
generateDeclaration(property + '-left', splitResult[3], important, position)
|
)
|
return result
|
}
|
}
|
|
var margin = createParser('margin')
|
|
var padding = createParser('padding')
|
|
function border (declaration) {
|
var { value, important } = clearImportant(declaration.value)
|
var property = declaration.property
|
var position = declaration.position
|
var splitResult = value.replace(/\s*,\s*/g, ',').split(/\s+/)
|
var result = [/^[\d\.]+\S*$/, /^(solid|dashed|dotted)$/, /\S+/].map(item => {
|
var index = splitResult.findIndex(str => item.test(str))
|
return index < 0 ? null : splitResult.splice(index, 1)[0]
|
})
|
if (splitResult.length) {
|
return declaration
|
}
|
return [
|
generateDeclaration(property + '-width', (result[0] || '0').trim(), important, position),
|
generateDeclaration(property + '-style', (result[1] || 'solid').trim(), important, position),
|
generateDeclaration(property + '-color', (result[2] || '#000000').trim(), important, position)
|
]
|
}
|
|
function borderProperty (declaration) {
|
var { value, important } = clearImportant(declaration.value)
|
var position = declaration.position
|
var property = declaration.property.split('-')[1]
|
var splitResult = value.replace(/\s*,\s*/g, ',').split(/\s+/)
|
var result = []
|
switch (splitResult.length) {
|
case 1:
|
return declaration
|
case 2:
|
splitResult.push(splitResult[0], splitResult[1])
|
break
|
case 3:
|
splitResult.push(splitResult[1])
|
break
|
}
|
result.push(
|
generateDeclaration('border-top-' + property, splitResult[0], important, position),
|
generateDeclaration('border-right-' + property, splitResult[1], important, position),
|
generateDeclaration('border-bottom-' + property, splitResult[2], important, position),
|
generateDeclaration('border-left-' + property, splitResult[3], important, position)
|
)
|
return result
|
}
|
|
function borderRadius (declaration) {
|
var { value, important } = clearImportant(declaration.value)
|
var position = declaration.position
|
var splitResult = value.split(/\s+/)
|
var result = []
|
if (value.includes('/')) {
|
return declaration
|
}
|
switch (splitResult.length) {
|
case 1:
|
return declaration
|
case 2:
|
splitResult.push(splitResult[0], splitResult[1])
|
break
|
case 3:
|
splitResult.push(splitResult[1])
|
break
|
}
|
result.push(
|
generateDeclaration('border-top-left-radius', splitResult[0], important, position),
|
generateDeclaration('border-top-right-radius', splitResult[1], important, position),
|
generateDeclaration('border-bottom-right-radius', splitResult[2], important, position),
|
generateDeclaration('border-bottom-left-radius', splitResult[3], important, position)
|
)
|
return result
|
}
|
|
function flexFlow (declaration) {
|
var { value, important } = clearImportant(declaration.value)
|
var position = declaration.position
|
var splitResult = value.split(/\s+/)
|
var result = [/^(column|column-reverse|row|row-reverse)$/, /^(nowrap|wrap|wrap-reverse)$/].map(item => {
|
var index = splitResult.findIndex(str => item.test(str))
|
return index < 0 ? null : splitResult.splice(index, 1)[0]
|
})
|
if (splitResult.length) {
|
return declaration
|
}
|
return [
|
generateDeclaration('flex-direction', result[0] || 'column', important, position),
|
generateDeclaration('flex-wrap', result[1] || 'nowrap', important, position)
|
]
|
}
|
|
function font (declaration) {
|
var { value, important } = clearImportant(declaration.value)
|
var position = declaration.position
|
var splitResult = value.replace(/,\s*/g, ',').replace(/\s*\/\s*/, '/').replace(/['"].+?['"]/g, str => str.replace(/\s+/g, '#')).split(/\s+/)
|
var result = []
|
var styleValues = ['normal', 'italic', 'oblique']
|
result.push(generateDeclaration('font-style', styleValues[Math.max(0, styleValues.indexOf(splitResult[0]))], important, position))
|
var weight = splitResult.slice(0, -2).find(str => /normal|bold|lighter|bolder|\d+/.test(str))
|
if (weight) {
|
result.push(generateDeclaration('font-weight', weight, important, position))
|
}
|
splitResult = splitResult.slice(-2)
|
if (/[\d\.]+\S*(\/[\d\.]+\S*)?/.test(splitResult[0])) {
|
var [size, height] = splitResult[0].split('/')
|
result.push(
|
generateDeclaration('font-size', size, important, position),
|
generateDeclaration('line-height', height || 'normal', important, position),
|
generateDeclaration('font-family', splitResult[1].replace(/#/g, ' '), important, position)
|
)
|
return result
|
}
|
return []
|
}
|
|
function background (declaration) {
|
var { value, important } = clearImportant(declaration.value)
|
var position = declaration.position
|
if (/^#?\S+$/.test(value) || /^rgba?(.+)$/.test(value)) {
|
return generateDeclaration('background-color', value, important, position)
|
} else if (/^linear-gradient(.+)$/.test(value)) {
|
return generateDeclaration('background-image', value, important, position)
|
} else {
|
return declaration
|
}
|
}
|
|
var parserCollection = {
|
transition,
|
margin,
|
padding,
|
border,
|
'border-top': border,
|
'border-right': border,
|
'border-bottom': border,
|
'border-left': border,
|
'border-style': borderProperty,
|
'border-width': borderProperty,
|
'border-color': borderProperty,
|
'border-radius': borderRadius,
|
'flex-flow': flexFlow,
|
font,
|
background
|
}
|
|
module.exports = function (declarations) {
|
return declarations.reduce((result, declaration) => {
|
var parser = parserCollection[declaration.property]
|
if (parser) {
|
return result.concat(parser(declaration))
|
} else {
|
result.push(declaration)
|
return result
|
}
|
}, [])
|
}
|