diff --git a/.gitignore b/.gitignore index 3ba3e2b..14cf2c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules coverage .DS_Store +.idea diff --git a/index.js b/index.js index 9630ab6..84de525 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,7 @@ var css = require('css') var util = require('./lib/util') var validateItem = require('./lib/validator').validate +var shorthandParser = require('./lib/shorthand-parser') // padding & margin shorthand parsing function convertLengthShorthand (rule, prop) { @@ -58,24 +59,7 @@ function parse(code, done) { if (type === 'rule') { if (rule.declarations && rule.declarations.length) { - // transition shorthand parsing - var CHUNK_REGEXP = /^(\S*)?\s*(\d*\.?\d+(?:ms|s)?)?\s*(\S*)?\s*(\d*\.?\d+(?:ms|s)?)?$/ - for (var i = 0; i < rule.declarations.length; i++) { - var declaration = rule.declarations[i] - if (declaration.property === 'transition') { - var match = declaration.value.match(CHUNK_REGEXP) - /* istanbul ignore else */ - if (match) { - rule.declarations.splice(i, 1) - match[4] && rule.declarations.push(i, 0, {type: 'declaration', property: 'transition-delay', value: match[4], position: declaration.position}) - match[3] && rule.declarations.push(i, 0, {type: 'declaration', property: 'transition-timing-function', value: match[3], position: declaration.position}) - match[2] && rule.declarations.push(i, 0, {type: 'declaration', property: 'transition-duration', value: match[2], position: declaration.position}) - match[1] && rule.declarations.push(i, 0, {type: 'declaration', property: 'transition-property', value: match[1], position: declaration.position}) - break - } - } - } - + rule.declarations = shorthandParser(rule.declarations) // padding & margin shorthand parsing convertLengthShorthand(rule, 'padding') convertLengthShorthand(rule, 'margin') diff --git a/lib/shorthand-parser.js b/lib/shorthand-parser.js new file mode 100644 index 0000000..9964066 --- /dev/null +++ b/lib/shorthand-parser.js @@ -0,0 +1,60 @@ +function generateDeclaration (property, value, position) { + return { + type: 'declaration', + property, + value, + position + } +} +function transition (declaration) { + let CHUNK_REGEXP = /^(\S*)?\s*(\d*\.?\d+(?:ms|s)?)?\s*(\S*)?\s*(\d*\.?\d+(?:ms|s)?)?$/ + const match = declaration.value.match(CHUNK_REGEXP) + let result = [] + const position = declaration.position + match[1] && result.push(generateDeclaration('transition-property', match[1], position)) + match[2] && result.push(generateDeclaration('transition-duration', match[2], position)) + match[3] && result.push(generateDeclaration('transition-timing-function', match[3], position)) + match[4] && result.push(generateDeclaration('transition-delay', match[4], position)) + return result +} + +function margin (declaration) { + const position = declaration.position + const splitResult = declaration.value.split(/\s+/) + let 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('margin-top', splitResult[0], position), + generateDeclaration('margin-right', splitResult[1], position), + generateDeclaration('margin-bottom', splitResult[2], position), + generateDeclaration('margin-left', splitResult[3], position) + ) + return result +} + +const parserCollection = { + transition, + margin +} + +module.exports = function (declarations) { + return declarations.reduce((result, declaration) => { + const parser = parserCollection[declaration.property] + if (parser) { + return result.concat(parser(declaration)) + } else { + result.push(declaration) + return result + } + }, []) +} \ No newline at end of file diff --git a/test/shorthand-parser.spec.js b/test/shorthand-parser.spec.js new file mode 100644 index 0000000..f29863e --- /dev/null +++ b/test/shorthand-parser.spec.js @@ -0,0 +1,178 @@ +var chai = require('chai') +var sinon = require('sinon') +var sinonChai = require('sinon-chai') +var expect = chai.expect +chai.use(sinonChai) + +var shorthandParser = require('../lib/shorthand-parser') + +describe('shorthand-parser', function () { + it('parse transition', function () { + const declarations = [ + { + type: 'declaration', + property: 'transition', + value: 'margin-top 500ms ease-in-out 1s', + position: {} + } + ] + const result = shorthandParser(declarations) + expect(result).eql([ + { + type: 'declaration', + property: 'transition-property', + value: 'margin-top', + position: {} + }, + { + type: 'declaration', + property: 'transition-duration', + value: '500ms', + position: {} + }, + { + type: 'declaration', + property: 'transition-timing-function', + value: 'ease-in-out', + position: {} + }, + { + type: 'declaration', + property: 'transition-delay', + value: '1s', + position: {} + } + ]) + }) + + it('parse margin', function () { + const declarations = [ + { + type: 'declaration', + property: 'margin', + value: '1px', + position: {} + }, + { + type: 'declaration', + property: 'margin', + value: '21px 22px', + position: {} + }, + { + type: 'declaration', + property: 'margin', + value: '31px 32px 33px', + position: {} + }, + { + type: 'declaration', + property: 'margin', + value: '41px 42px 43px 44px', + position: {} + } + ] + const result = shorthandParser(declarations) + expect(result).eql([ + { + type: 'declaration', + property: 'margin-top', + value: '1px', + position: {} + }, + { + type: 'declaration', + property: 'margin-right', + value: '1px', + position: {} + }, + { + type: 'declaration', + property: 'margin-bottom', + value: '1px', + position: {} + }, + { + type: 'declaration', + property: 'margin-left', + value: '1px', + position: {} + }, + + { + type: 'declaration', + property: 'margin-top', + value: '21px', + position: {} + }, + { + type: 'declaration', + property: 'margin-right', + value: '22px', + position: {} + }, + { + type: 'declaration', + property: 'margin-bottom', + value: '21px', + position: {} + }, + { + type: 'declaration', + property: 'margin-left', + value: '22px', + position: {} + }, + + { + type: 'declaration', + property: 'margin-top', + value: '31px', + position: {} + }, + { + type: 'declaration', + property: 'margin-right', + value: '32px', + position: {} + }, + { + type: 'declaration', + property: 'margin-bottom', + value: '33px', + position: {} + }, + { + type: 'declaration', + property: 'margin-left', + value: '32px', + position: {} + }, + + { + type: 'declaration', + property: 'margin-top', + value: '41px', + position: {} + }, + { + type: 'declaration', + property: 'margin-right', + value: '42px', + position: {} + }, + { + type: 'declaration', + property: 'margin-bottom', + value: '43px', + position: {} + }, + { + type: 'declaration', + property: 'margin-left', + value: '44px', + position: {} + } + ]) + }) +}) \ No newline at end of file