Skip to content

Commit

Permalink
feat(okam-build): add specified app type style property declaration s…
Browse files Browse the repository at this point in the history
…upport
  • Loading branch information
wuhy committed Nov 24, 2018
1 parent e14139d commit d028262
Showing 1 changed file with 105 additions and 7 deletions.
112 changes: 105 additions & 7 deletions packages/okam-build/lib/processor/css/plugins/postcss-plugin-env.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
/**
* @file Postcss env plugin: remove not current app type style definition info.
* e.g.,
* @media swan, wx {
*
* .title {
* font-size: 20px;
* -wx-font-size: 17px;
* -quick-font-size: 18px;
* }
*
* @media not quick {
* .title {
* font-size: 15px;
* }
* }
*
* @media not quick {
* @media quick {
* .title {
* font-size: 15px;
* font-size: 33px;
* }
* }
*
* If the current build app target is `quick` app, then the above style rules
* will be transformed and the output as the following:
*
* .title {
* font-size: 18px;
* }
*
* .title {
* font-size: 33px;
* }
*
* @author [email protected]
*/

Expand All @@ -20,47 +39,126 @@
const postcss = require('postcss');
const matchAppMediaParams = require('./match-media-params');

function processMediaRule(allAppTypes, appType, rule) {
/**
* Process media rule.
* Remove not current app media query target rule.
* Remove current app media query params.
*
* @inner
* @param {Array.<string>} allAppTypes all supported build media target
* @param {string} appType the current build media target
* @param {Object} rule the media query rule
*/
function processAppSpecifiedMediaRule(allAppTypes, appType, rule) {
let result = matchAppMediaParams(allAppTypes, appType, rule.params);
if (!result) {
return;
}

// remove media rule
let {removed, params} = result;
params && (params = params.trim());
if (removed) {
// remove media rule, not current app media query target
rule.remove();
}
else if (params) {
// remove current app media query params
rule.params = params;
}
else {
// remove current app media query rule wrapping
let children = rule.parent.nodes;
let currRuleIdx = children.indexOf(rule);

rule.nodes.forEach((item, index) => {
item.parent = rule.parent;
item.parent = rule.parent; // up parent

let itemRaws = item.raws;
let subNodes = item.nodes;

// up raw style format
subNodes && subNodes.forEach(
sub => sub.raws.before = itemRaws.before
);
itemRaws.before = index ? '\n' : '';
itemRaws.after = '\n';
});

children.splice(currRuleIdx, 1, ...rule.nodes);
rule.nodes = null;
rule.parent = null;
}
}

/**
* Remove the given property name style declaration that the position is
* front of the current given style declaration.
*
* @inner
* @param {Object} decl the style property declaration that will override
* the front of the style declaration that has the same property name
* @param {string} toRemovePropName the property name to remove
*/
function removeNoUseDecl(decl, toRemovePropName) {
let nodes = decl.parent.nodes;
let currIdx = nodes.indexOf(decl);

for (let i = currIdx - 1; i >= 0; i--) {
let item = nodes[i];
if (item.type === 'decl' && item.prop === toRemovePropName) {
item.remove();
}
}
}

/**
* The specified app related property declaration regexp
*
* @const
* @type {RegExp}
*/
const SPECIFIED_APP_PROP_DECL_REGEXP = /^\-(\w+)\-/;

/**
* Process specified app target css style property declaration
*
* @inner
* @param {Array.<string>} allAppTypes all supported build media target
* @param {string} appType the current build media target
* @param {Object} decl css style declaration
*/
function processAppSpecifiedDeclaration(allAppTypes, appType, decl) {
let {prop} = decl;
let result;
if ((result = SPECIFIED_APP_PROP_DECL_REGEXP.exec(prop))) {
let propApp = result[1];
let isMatchApp = appType === propApp;
if (allAppTypes.includes(propApp) && !isMatchApp) {
// remove not current app build type style declaration
decl.remove();
}
else if (isMatchApp) {
// remove the previous property style declaration that has same
// style property name declaration that ignore app type prefix
// and remove the specified app type prefix of the property
let newPropName = prop.replace(SPECIFIED_APP_PROP_DECL_REGEXP, '');
removeNoUseDecl(decl, newPropName);
decl.prop = newPropName;
}
}
}

module.exports = postcss.plugin('postcss-plugin-env', function (opts = {}) {
const {allAppTypes, appType} = opts;
return function (css, result) {
css.walkAtRules(rule => {
if (rule.name === 'media') {
processMediaRule(allAppTypes, appType, rule);
processAppSpecifiedMediaRule(allAppTypes, appType, rule);
}
});

css.walkDecls(
decl => processAppSpecifiedDeclaration(allAppTypes, appType, decl)
);
};
});

0 comments on commit d028262

Please sign in to comment.