Files
developtools_ace-js2bundle/ace-loader/src/lite/lite-transform-style.js
T
houhaoyu c134a7330b houhaoyu@huawei.com
合规处理

Signed-off-by: houhaoyu <houhaoyu@huawei.com>
Change-Id: Ief90befb5d50c540c0f0de0815f51ee2a97b9b72
2022-03-30 09:37:18 +08:00

211 lines
5.8 KiB
JavaScript

/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Customize the compiled style code into a styleSheet object, styleSheet object is divided into two parts, idSelectors
* and classSelectors. There are some detailed rules to explain:
* 1. Remove the "." And "#" symbols in front of the class selector and id selector;
* 2. Convert all numeric strings to numbers, such as:"32px" convert to number 32; "11" convert to number 11;
* 3. Convert all hex color to decimal number;
* 4. Convert all boolean strings to boolean type;
*/
const {
SPECIAL_STYLE,
REGEXP_NUMBER_PX,
REGEXP_COLOR,
REGEXP_UNIT,
REGXP_QUOTES,
} = require('./lite-enum');
/**
* Split style into id Selectors and classSelectors.
* @param {Object} value Preliminary compilation results of css files.
* @return {String} String result stylesheet.
*/
function transformStyle(value) {
const style = Function(`return ${value}`)();
const idSelectors = {};
const classSelectors = {};
const styleSheet = {};
let res = '';
const KEYFRAMES = '@KEYFRAMES';
const MEDIA_QUERY = '@MEDIA';
const keys = Object.keys(style);
for (const key of keys) {
if (key.charAt(0) === '.') {
classSelectors[key.slice(1)] = styleFormat(style[key]);
} else if (key.charAt(0) === '#') {
idSelectors[key.slice(1)] = styleFormat(style[key]);
} else if (key === KEYFRAMES) {
styleSheet['@keyframes'] = keyFrameFormat(style[key]);
} else if (key === MEDIA_QUERY) {
styleSheet['@media'] = mediaQueryFormat(style[key]);
} else {
}
}
if (style != null && keys.length !== 0) {
if (Object.keys(idSelectors).length !== 0) {
styleSheet['idSelectors'] = idSelectors;
}
if (Object.keys(classSelectors).length !== 0) {
styleSheet['classSelectors'] = classSelectors;
}
}
res = JSON.stringify(styleSheet);
return res;
}
/**
* keyFrame style special compilation.
* @param {Object} obj Preliminary compilation results of keyFrame style.
* @return {Object} keyFrame style object.
*/
function keyFrameFormat(obj) {
for (const key of Object.keys(obj)) {
const value = obj[key];
for (const styleValue of value) {
for (const styleKey of Object.keys(styleValue)) {
const innerValue = styleValue[styleKey];
if (REGEXP_COLOR.test(innerValue)) {
styleValue[styleKey] = parseInt(innerValue.slice(1), 16);
}
try {
styleValue[styleKey] = JSON.parse(styleValue[styleKey]);
} catch (e) {
// Values cannot be converted to objects are not processed
}
}
}
}
return obj;
}
/**
* media query special compilation.
* @param {Array} mediaQueries the array of media query
* @return {Array} media query style object
*/
function mediaQueryFormat(mediaQueries) {
const target = [];
for (const mediaQuery of mediaQueries) {
const { condition, ...selectors } = mediaQuery;
const style = transformStyle(JSON.stringify(selectors));
if (style) {
style = JSON.parse(style);
target.push({ condition, ...style });
}
}
return target;
}
const rules = [
{
match: function(key, value) {
return (
key === SPECIAL_STYLE.ANIMATION_DELAY ||
key === SPECIAL_STYLE.ANIMATION_DURATION
);
},
action: function(obj, key, value) {
obj[key] = value;
},
},
{
match: function(key, value) {
return key === SPECIAL_STYLE.ANIMATION_ITERATION_COUNT;
},
action: function(obj, key, value) {
if (value === -1) {
value = 'infinite';
}
obj[key] = value.toString();
},
},
{
match: function(key, value) {
return [
SPECIAL_STYLE.BACKGROUND_IMAGE,
SPECIAL_STYLE.BACKGROUND_IMAGE_ACTIVE,
SPECIAL_STYLE.BACKGROUND_IMAGE_CHECKED,
].includes(key);
},
action: function(obj, key, value) {
obj[key] = value.replace(REGXP_QUOTES, '');
},
},
{
match: function(key, value) {
return !isNaN(Number(value));
},
action: function(obj, key, value) {
obj[key] = Number(value);
},
},
{
match: function(key, value) {
return REGEXP_NUMBER_PX.test(value);
},
action: function(obj, key, value) {
obj[key] = parseInt(value.replace(REGEXP_UNIT, ''), 10);
},
},
{
match: function(key, value) {
return REGEXP_COLOR.test(value);
},
action: function(obj, key, value) {
obj[key] = parseInt(value.slice(1), 16);
},
},
{
match: function(key, value) {
return value === 'true';
},
action: function(obj, key, value) {
obj[key] = true;
},
},
{
match: function(key, value) {
return value === 'false';
},
action: function(obj, key, value) {
obj[key] = false;
},
},
];
/**
* Loop and format style, There are two rules defined here, types of number+px and color convert to number 16777215.
* @param {Object} obj Preliminary compilation results of style object.
* @return {Object} style object.
*/
function styleFormat(obj) {
let value = '';
for (const key of Object.keys(obj)) {
value = obj[key];
for (let i = 0; i < rules.length; i++) {
if (rules[i].match(key, value)) {
rules[i].action(obj, key, value);
break;
}
}
}
return obj;
}
exports.transformStyle = transformStyle;