diff --git a/src/generator/css.js b/src/generator/css.js index 0de701a..bdc2cf9 100644 --- a/src/generator/css.js +++ b/src/generator/css.js @@ -328,6 +328,29 @@ class Rules { } } + add_grid_style({ fill, clip, rotate, scale, flexRow, flexColumn }) { + if (fill) { + this.add_rule(':host', `background-color: ${fill};`); + } + if (!clip) { + this.add_rule(':host', 'contain: none;'); + } + if (rotate) { + this.add_rule(':container', `rotate: ${rotate};`); + } + if (scale) { + this.add_rule(':container', `scale: ${scale};`); + } + if (flexRow) { + this.add_rule(':container', `display: flex`); + this.add_rule('cell', `flex: 1`); + } + if (flexColumn) { + this.add_rule(':container', `display: flex; flex-direction: column;`); + this.add_rule('cell', `flex: 1`); + } + } + compose_rule(token, _coords, selector) { let coords = Object.assign({}, _coords); let prop = token.property; @@ -440,13 +463,7 @@ class Rules { case 'grid': { if (is_host_selector(selector)) { rule = transformed.size || ''; - let { fill, clip } = transformed; - if (fill) { - this.add_rule(':host', `background-color: ${fill};`); - } - if (!clip) { - this.add_rule(':host', 'contain: none;'); - } + this.add_grid_style(transformed); } else { rule = ''; if (!this.is_grid_defined) { @@ -456,13 +473,7 @@ class Rules { max_grid: coords.max_grid }); this.add_rule(':host', transformed.size || ''); - let { fill, clip } = transformed; - if (fill) { - this.add_rule(':host', `background-color: ${fill};`); - } - if (!clip) { - this.add_rule(':host', 'contain: none'); - } + this.add_grid_style(transformed); } } this.grid = coords.grid; diff --git a/src/parser/parse-value-group.js b/src/parser/parse-value-group.js index 41c3b37..9b3d460 100644 --- a/src/parser/parse-value-group.js +++ b/src/parser/parse-value-group.js @@ -1,12 +1,13 @@ import { is_empty } from '../utils/index.js'; import { scan, iterator } from './tokenizer.js'; -function parse(input, option = {symbol: ',', noSpace: false}) { +function parse(input, option = {symbol: ',', noSpace: false, verbose: false }) { let group = []; let skip = false; let tokens = []; let parenStack = []; let quoteStack = []; + let lastGroupName = ''; if (is_empty(input)) { return group; @@ -15,11 +16,25 @@ function parse(input, option = {symbol: ',', noSpace: false}) { let iter = iterator(scan(input)); function isSeperator(token) { - let symbol = option.symbol || ','; - if (option.noSpace) { - return token.isSymbol(symbol); + let symbol = option.symbol || [',']; + if (!Array.isArray(symbol)) { + symbol = [symbol]; + } + if (option.noSpace) { + return token.isSymbol(...symbol); + } + return token.isSymbol(...symbol) || token.isSpace(); + } + + function addGroup(tokens) { + let value = joinTokens(tokens); + if (option.verbose) { + if (lastGroupName.length || value.length) { + group.push({ group: lastGroupName, value }); + } + } else { + group.push(value); } - return token.isSymbol(symbol) || token.isSpace(); } while (iter.next()) { @@ -43,7 +58,9 @@ function parse(input, option = {symbol: ',', noSpace: false}) { if (isNextSpace || isPrevSpace) continue; } if (emptyStack && isSeperator(curr)) { - group.push(joinTokens(tokens)); + let groupName = lastGroupName; + addGroup(tokens); + lastGroupName = curr.value; tokens = []; } else { tokens.push(curr); @@ -51,7 +68,7 @@ function parse(input, option = {symbol: ',', noSpace: false}) { } if (tokens.length) { - group.push(joinTokens(tokens)); + addGroup(tokens); } return group; diff --git a/src/parser/tokenizer.js b/src/parser/tokenizer.js index c3fe0af..b6783b4 100644 --- a/src/parser/tokenizer.js +++ b/src/parser/tokenizer.js @@ -7,6 +7,7 @@ const symbols = [ ':', ';', ',', '(', ')', '[', ']', '{', '}', 'π', '±', '+', '-', '*', '/', '%', '"', "'", '`', '@', '=', + '^', ]; const is = { diff --git a/src/property.js b/src/property.js index 2c0d6db..4d1d6c4 100644 --- a/src/property.js +++ b/src/property.js @@ -72,18 +72,36 @@ export default add_alias({ }, grid(value, options) { - let clip = true; + let result = { + clip: true, + }; if (/no\-*clip/i.test(value)) { - clip = false; + result.clip = false; value = value.replace(/no\-*clip/i, ''); } - let [grid, size, fill] = parse_value_group(value, { symbol: '/', noSpace: true }); - return { - grid: parse_grid(grid, options.max_grid), - size: size ? this.size(size, options) : '', - fill: fill || '', - clip: clip, - }; + let groups = parse_value_group(value, { + symbol: ['/', '+', '*', '|', '-'], + noSpace: true, + verbose: true + }); + for (let { group, value } of groups) { + if (group === '+') result.scale = value; + if (group === '*') result.rotate = value; + if (group === '/') { + if (result.size === undefined) result.size = this.size(value, options); + else result.fill = value; + } + if ((group === '|' || group == '-' || group == '') && !result.grid) { + result.grid = parse_grid(value, options.max_grid); + if (group === '|') { + result.flexColumn = true; + } + if (group === '-') { + result.flexRow = true; + } + } + } + return result; }, seed(value) { diff --git a/test/parse-value-group.js b/test/parse-value-group.js index daac853..fa0d36e 100644 --- a/test/parse-value-group.js +++ b/test/parse-value-group.js @@ -83,3 +83,17 @@ test('space as separator', t => { compare(t, '5, 100% 5 8', ['5,100%', '5', '8']); }); + +test('verbose option', t => { + + compare.use(input => { + return parseValueGroup(input, { symbol: ['v', 'h'], noSpace: true, verbose: true }); + }); + + compare(t, 'v 10 h -10 v 5', [ + { group: 'v', value: '10' }, + { group: 'h', value: '-10' }, + { group: 'v', value: '5' }, + ]); + +});