Skip to content

Commit

Permalink
fix(okam-build): fix transform template style binding and add es6 tem…
Browse files Browse the repository at this point in the history
…plate string support #37
  • Loading branch information
wuhy committed Feb 10, 2019
1 parent 07e74f8 commit 9814fc7
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 29 deletions.
33 changes: 4 additions & 29 deletions packages/okam-build/lib/processor/template/transform/base/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

const {transformFilterSyntaxValue} = require('./filter');
const {CURLY_BRACE_HAS_REGEXP} = require('./constant');
const {parseBindingStyleValue} = require('../helper/style');

module.exports = function (attrs, name, tplOpts, opts, element) {
let value = attrs[name];
Expand All @@ -28,7 +29,7 @@ module.exports = function (attrs, name, tplOpts, opts, element) {
let {config, logger} = tplOpts;
let wrapCurlyBrace = false;
if (CURLY_BRACE_HAS_REGEXP.test(value)) {
value = transformObjStyle(value, logger);
value = transformObjStyle(value);
}
else {
wrapCurlyBrace = true;
Expand All @@ -55,34 +56,8 @@ module.exports = function (attrs, name, tplOpts, opts, element) {
* [{ color: activeColor,fontWeight: 'bold'}, {fontSize: fontSize + 'px' }] -> color: activeColor, font-size: {{fontSize + 'px'}}
*
* @param {string} value string to be transformed
* @param {Object} logger the logger util
* @return {string} transformed result
*/
function transformObjStyle(value, logger) {
// 去掉首尾空格、去掉首尾方括号、去掉花括号,以`,`为分隔。将字符串重组为style的字面量语法
let stylePropValues = value
.trim()
.replace(/^\[|]$/g, '')
.replace(/[{}]/g, '')
.split(',');

let result = [];
stylePropValues.forEach(item => {
let colonIdx = item.indexOf(':');
let styleProp;
let styleValue;
if (colonIdx === -1) {
styleProp = item.trim();
styleValue = styleProp;
}
else {
styleProp = item.substring(0, colonIdx).trim();
styleValue = item.substr(colonIdx + 1).trim();
}

styleProp = styleProp.replace(/([A-Z])/g, '-$1').toLowerCase();
result.push(`${styleProp}:{{${styleValue}}}`);
});

return result.join(';');
function transformObjStyle(value) {
return parseBindingStyleValue(value).join(';');
}
101 changes: 101 additions & 0 deletions packages/okam-build/lib/processor/template/transform/helper/style.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
* @file Template style binding syntax helper
* @author [email protected]
*/

'use strict';

function isValidatedStylePropSeperator(value, startIdx, commaIdx) {
let leftBraceNum = 0;
let rightBraceNum = 0;

let idx = commaIdx + 1;
while (idx > startIdx) {
let token = value.charAt(idx);
if (token === '(') {
leftBraceNum++;
}
else if (token === ')') {
rightBraceNum++;
}
idx--;
}

return leftBraceNum === rightBraceNum;
}

function parseStyleProp(style) {
let colonIdx = style.indexOf(':');
let styleProp;
let styleValue;
if (colonIdx === -1) {
styleProp = style.trim();
styleValue = styleProp;
}
else {
styleProp = style.substring(0, colonIdx).trim();
styleValue = style.substr(colonIdx + 1).trim();
}

if (!styleProp) {
return;
}

styleValue = styleValue.replace(/`(.+)`/g, (match, str) => {
return '\'' + str.replace(/\${(.+?)}/g, (subMatch, express) => {
return '\' + ' + express + ' + \'';
}) + '\'';
});
styleProp = styleProp.replace(/([A-Z])/g, '-$1').toLowerCase();
return `${styleProp}:{{${styleValue}}}`;
}

const ES6_STRING_VAR_PLACEHOLDER = '<@%#!=>';
const ES6_STRING_VAR_REGEXP = new RegExp(ES6_STRING_VAR_PLACEHOLDER, 'g');

/**
* Parse template style binding value
*
* @param {string} bindingValue the style binding value to parse
* @return {Array.<string>}
*/
exports.parseBindingStyleValue = function (bindingValue) {
let value = bindingValue
.trim()
.replace(/^\[|]$/g, '');

// remove {} except for es6 string variable {}
const strPlaceHolders = [];
value = value.replace(/\${.+?}/g, match => {
strPlaceHolders.push(match);
return ES6_STRING_VAR_PLACEHOLDER;
}).replace(/[{}]/g, '').replace(
ES6_STRING_VAR_REGEXP,
() => strPlaceHolders.shift()
);

const result = [];
const commaRegex = /,/g;
let startIdx = 0;
const len = value.length;
while (startIdx < len) {
let styleProp;
let match = commaRegex.exec(value);
if (!match) {
styleProp = value.substr(startIdx);
startIdx = value.length;
}
else if (isValidatedStylePropSeperator(value, startIdx, match.index)) {
styleProp = value.substring(startIdx, match.index);
startIdx = match.index + 1;
}
else {
continue;
}

let styleInfo = parseStyleProp(styleProp);
styleInfo && result.push(styleInfo);
}

return result;
};
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,26 @@ describe('style binding', function () {
assert.equal(result.content,
'<view style="height:{{height}};font-size:{{fontSize}}"></view>');
});

it('should support transform style binding syntax with comma', function () {
const file = {
content: '<div :style="{ transform: \'translate(-50%, -50%) rotate(\' + preview.rotate + \'deg)\', fontSize, \'font-size\': \'12px\' }"></div>'
};
const result = templateProcessor(file, fakeProcessorOptions());
assert.equal(
result.content,
'<view style="transform:{{\'translate(-50%, -50%) rotate(\' + preview.rotate + \'deg)\'}};font-size:{{fontSize}};\'font-size\':{{\'12px\'}}"></view>'
);
});

it('should support es6 template string style binding', function () {
const file = {
content: '<div :style="{fontSize: `${fontSize}px`, width}"></div>'
};
const result = templateProcessor(file, fakeProcessorOptions());
assert.equal(
result.content,
'<view style="font-size:{{\'\' + fontSize + \'px\'}};width:{{width}}"></view>'
);
});
});

0 comments on commit 9814fc7

Please sign in to comment.