diff --git a/lib/_lu-utilities.js b/lib/_lu-utilities.js index 736f1cc6..70a5cbe8 100644 --- a/lib/_lu-utilities.js +++ b/lib/_lu-utilities.js @@ -3,6 +3,15 @@ const testRgb = new RegExp(/rgb/); const matchRgb = new RegExp(/rgba?\(([^\)]+)\)/); const testHex = new RegExp(/#\w+/); +/** + * Glues fraction members, meaning "1 / 6" becomes "1/6" + * @param {string} str + * @returns {string} + */ +const glueFractionMembers = function glueFractionMembers(str) { + return str.replace(/\s*\/\s*/, '/'); +}; + /** * Returns a three-member number array from a hex string * @param hex @@ -97,5 +106,6 @@ module.exports = { extractRgbSubstring, hToD, safeRgbToRgb, - safeHexToRgb + safeHexToRgb, + glueFractionMembers }; diff --git a/lib/lost-center.js b/lib/lost-center.js index 0076bf79..de552808 100644 --- a/lib/lost-center.js +++ b/lib/lost-center.js @@ -1,6 +1,7 @@ var newBlock = require('./new-block.js'); var lgLogic = require('./_lg-logic'); +var lgUtils = require('./_lu-utilities'); module.exports = function lostCenterDecl(css, settings, result) { css.walkDecls('lost-center', function lostCenterFunction(decl) { @@ -18,7 +19,8 @@ module.exports = function lostCenterDecl(css, settings, result) { return lostFractionPattern.test(value); }; - declArr = decl.value.split(' '); + const sanitizedDecl = lgUtils.glueFractionMembers(decl.value); + declArr = sanitizedDecl.split(' '); if (declArr[1] !== undefined && declArr[1].search(/^\d/) !== -1) { lostCenterPadding = declArr[1]; diff --git a/lib/lost-column.js b/lib/lost-column.js index 8bc0d8cc..daa75c72 100644 --- a/lib/lost-column.js +++ b/lib/lost-column.js @@ -1,6 +1,8 @@ var newBlock = require('./new-block.js'); var lgLogic = require('./_lg-logic'); +var lgUtils = require('./_lu-utilities'); + module.exports = function lostColumnDecl(css, settings, result) { css.walkDecls('lost-column', function lostColumnFunction(decl) { var declArr = []; @@ -20,7 +22,8 @@ module.exports = function lostColumnDecl(css, settings, result) { lostColumnCycle = settings.cycle; } - declArr = decl.value.split(' '); + const sanitizedDecl = lgUtils.glueFractionMembers(decl.value); + declArr = sanitizedDecl.split(' '); lostColumn = declArr[0]; if (declArr[1] !== undefined && declArr[1].search(/^\d/) !== -1) { diff --git a/lib/lost-masonry-column.js b/lib/lost-masonry-column.js index 847da053..48377391 100644 --- a/lib/lost-masonry-column.js +++ b/lib/lost-masonry-column.js @@ -1,3 +1,5 @@ +var lgUtils = require('./_lu-utilities'); + module.exports = function lostMasonryColumnDecl(css, settings) { css.walkDecls('lost-masonry-column', function lostMasonryColumnFunction( decl @@ -18,7 +20,8 @@ module.exports = function lostMasonryColumnDecl(css, settings) { }); } - declArr = decl.value.split(' '); + const sanitizedDecl = lgUtils.glueFractionMembers(decl.value); + declArr = sanitizedDecl.split(' '); lostMasonryColumn = declArr[0]; if (declArr[1] !== undefined && declArr[1].search(/^\d/) !== -1) { diff --git a/lib/lost-move.js b/lib/lost-move.js index f8833bfd..a41f036f 100644 --- a/lib/lost-move.js +++ b/lib/lost-move.js @@ -1,3 +1,5 @@ +var lgUtils = require('./_lu-utilities'); + module.exports = function lostMoveDecl(css, settings) { css.walkDecls('lost-move', function lostMoveDeclFunction(decl) { var declArr = []; @@ -6,7 +8,8 @@ module.exports = function lostMoveDecl(css, settings) { var lostMoveRounder = settings.rounder; var lostMoveGutter = settings.gutter; - declArr = decl.value.split(' '); + const sanitizedDecl = lgUtils.glueFractionMembers(decl.value); + declArr = sanitizedDecl.split(' '); lostMove = declArr[0]; if ( diff --git a/lib/lost-offset.js b/lib/lost-offset.js index 4bd58161..3e96b4fb 100644 --- a/lib/lost-offset.js +++ b/lib/lost-offset.js @@ -1,3 +1,5 @@ +var lgUtils = require('./_lu-utilities'); + module.exports = function lostOffsetDecl(css, settings) { css.walkDecls('lost-offset', function lostOffsetDeclFunction(decl) { var declArr = []; @@ -16,7 +18,8 @@ module.exports = function lostOffsetDecl(css, settings) { }); } - declArr = decl.value.split(' '); + const sanitizedDecl = lgUtils.glueFractionMembers(decl.value); + declArr = sanitizedDecl.split(' '); lostOffset = declArr[0]; lostOffsetNumerator = declArr[0].split('/')[0]; diff --git a/lib/lost-row.js b/lib/lost-row.js index df2b248c..1672aa5b 100644 --- a/lib/lost-row.js +++ b/lib/lost-row.js @@ -1,6 +1,7 @@ var newBlock = require('./new-block.js'); var lgLogic = require('./_lg-logic'); +var lgUtils = require('./_lu-utilities'); module.exports = function lostRowDecl(css, settings, result) { css.walkDecls('lost-row', function lostRowDeclFunction(decl) { @@ -13,7 +14,8 @@ module.exports = function lostRowDecl(css, settings, result) { var validUnits = ['%', 'vh']; if (decl.value !== 'none') { - declArr = decl.value.split(' '); + const sanitizedDecl = lgUtils.glueFractionMembers(decl.value); + declArr = sanitizedDecl.split(' '); lostRow = declArr[0]; if (declArr[1] !== undefined && declArr[1].search(/^\d/) !== -1) { diff --git a/lib/lost-waffle.js b/lib/lost-waffle.js index 58784688..1edca8ce 100644 --- a/lib/lost-waffle.js +++ b/lib/lost-waffle.js @@ -1,6 +1,7 @@ var newBlock = require('./new-block.js'); var lgLogic = require('./_lg-logic'); +var lgUtils = require('./_lu-utilities'); module.exports = function lostWaffleDecl(css, settings) { css.walkDecls('lost-waffle', function lostWaffleDeclFunction(decl) { @@ -30,7 +31,8 @@ module.exports = function lostWaffleDecl(css, settings) { lostWaffleCycle = settings.cycle; } - declArr = decl.value.split(' '); + const sanitizedDecl = lgUtils.glueFractionMembers(decl.value); + declArr = sanitizedDecl.split(' '); lostWaffle = declArr[0]; if (declArr[1] !== undefined && declArr[1].search(/^\d/) !== -1) { diff --git a/test/lost-center.js b/test/lost-center.js index 7ef31619..44b0fb82 100644 --- a/test/lost-center.js +++ b/test/lost-center.js @@ -23,6 +23,16 @@ describe('lost-center', function() { ); }); + it('generates valid output given spaces are present in the input', function() { + check( + 'a { lost-center: 3 / 9; lost-unit: vw }', + + 'a { max-width: calc(99.9vw * 3/9); margin-left: auto; margin-right: auto }\n' + + "a:before { content: ''; display: table }\n" + + "a:after { content: ''; display: table; clear: both }" + ); + }); + it('horizontally centers container', function() { check( 'a { lost-center: 980px }', diff --git a/test/lost-column.js b/test/lost-column.js index de45ea7e..41802025 100644 --- a/test/lost-column.js +++ b/test/lost-column.js @@ -31,6 +31,17 @@ describe('lost-column', function() { ); }); + it('generates valid output even with spaces at various places in the declaration', function() { + check( + 'a { lost-column: 1 / 3; }', + 'a { width: calc(99.9% * 1/3 - (30px - 30px * 1/3)); }\n' + + 'a:nth-child(1n) { float: left; margin-right: 30px; clear: none; }\n' + + 'a:last-child { margin-right: 0; }\n' + + 'a:nth-child(3n) { margin-right: 0; float: right; }\n' + + 'a:nth-child(3n + 1) { clear: both; }' + ); + }); + it('provides 2/5 column layout', function() { check( 'a { lost-column: 2/5; }', diff --git a/test/lost-move.js b/test/lost-move.js index 456b64a9..39c41c13 100644 --- a/test/lost-move.js +++ b/test/lost-move.js @@ -19,6 +19,14 @@ describe('lost-move', function() { ); }); + it('generates valid output even with spaces at various places in the declaration', function() { + check( + 'a { lost-move: -1 / 3; }', + 'a { position: relative; left: calc(99.9% * -1/3 -' + + ' (30px - 30px * -1/3) + 30px); }' + ); + }); + it('moves element up', function() { check( 'a { lost-move: 1/3 column; }', diff --git a/test/lost-offset.js b/test/lost-offset.js index 1041693f..06b1b78c 100644 --- a/test/lost-offset.js +++ b/test/lost-offset.js @@ -17,6 +17,14 @@ describe('lost-offset', function() { ); }); + it('generates valid output even with spaces at various places in the declaration', function() { + check( + 'a { lost-offset: 1 / 3; }', + 'a { margin-left: calc(99.9% * (-1/3 * -1) - (30px - 30px * (-1/3 * -1)) + 30px' + + ') !important; }' + ); + }); + it("Does not move with a zero numerator (of you're so inclined)", function() { check( 'a { lost-offset: 0/3; }', diff --git a/test/lost-row.js b/test/lost-row.js index 52acac7d..774c61b9 100644 --- a/test/lost-row.js +++ b/test/lost-row.js @@ -22,6 +22,15 @@ describe('lost-row', function() { ); }); + it('generates valid output even with spaces at various places in the declaration', function() { + check( + 'a { lost-row: 1 / 3; lost-row-flexbox: no-flex; }', + 'a { width: 100%; height: calc(99.9% * 1/3 - (30px - 30px * 1/3));' + + ' margin-bottom: 30px; }' + + 'a:last-child { margin-bottom: 0; }' + ); + }); + it('supports flex in long-form', function() { check( 'a { lost-row: 1/3; lost-row-flexbox: flex; }', diff --git a/test/lost-waffle.js b/test/lost-waffle.js index 5a80af12..58222be8 100644 --- a/test/lost-waffle.js +++ b/test/lost-waffle.js @@ -19,6 +19,21 @@ describe('lost-waffle', function() { ); }); + it('generates valid output even with spaces at various places in the declaration', function() { + check( + 'a { lost-waffle: 1 / 3; }', + 'a { width: calc(99.9% * 1/3 - (30px - 30px * 1/3));' + + ' max-width: calc(99.9% * 1/3 - (30px - 30px * 1/3));\n' + + ' height: calc(99.9% * 1/3 - (30px - 30px * 1/3)); }\n' + + 'a:nth-child(1n) { float: left; margin-right: 30px;' + + ' margin-bottom: 30px; clear: none; }\n' + + 'a:last-child { margin-right: 0; margin-bottom: 0; }\n' + + 'a:nth-child(3n) { margin-right: 0; }\n' + + 'a:nth-child(3n + 1) { clear: both; }\n' + + 'a:nth-last-child(-n + 3) { margin-bottom: 0; }' + ); + }); + it('supports a custom cycle', function() { check( 'a { lost-waffle: 2/4 2; }', diff --git a/test/lu-utility.js b/test/lu-utility.js index 1952d47c..792b8e25 100644 --- a/test/lu-utility.js +++ b/test/lu-utility.js @@ -3,6 +3,14 @@ var expect = require('chai').expect; var utils = require('../lib/_lu-utilities.js'); +describe('glueFractionMembers', () => { + it('glues fraction members together, avoiding a class of parsing errors', () => { + expect(utils.glueFractionMembers('-1 / 8')).to.equal('-1/8'); + expect(utils.glueFractionMembers('27 / 32')).to.equal('27/32'); + expect(utils.glueFractionMembers('1 /1')).to.equal('1/1'); + }); +}); + describe('hToD', () => { it('converts one or two hex digits to an int value', () => { expect(utils.hToD(0, 0)).to.equal(0);