-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(okam-build): add specified app type style property declaration s…
…upport
- Loading branch information
Showing
1 changed file
with
105 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | ||
*/ | ||
|
||
|
@@ -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) | ||
); | ||
}; | ||
}); |