vue-css-modules
Version:
Seamless mapping of class names to CSS modules inside of Vue components.
207 lines (170 loc) • 5.16 kB
JavaScript
/*!
* vue-css-modules v1.2.0
* (c) 2018-present fjc0k <fjc0kb@gmail.com> (https://github.com/fjc0k)
* Released under the MIT License.
*/
function includes(arrayLike, element, fromIndex) {
if (fromIndex === void 0) {
fromIndex = 0;
}
for (var i = fromIndex, len = arrayLike.length; i < len; i++) {
if (arrayLike[i] === element) {
return true;
}
}
return false;
}
function isObject(value) {
return value !== null && typeof value === 'object';
}
function isFunction(value) {
return typeof value === 'function';
}
function isString(value) {
return typeof value === 'string';
}
var camelCaseCache = Object.create(null);
function camelCase(value) {
if (camelCaseCache[value]) return camelCaseCache[value];
var result = '';
var shouldUpperCase = false;
for (var i = 0, len = value.length; i < len; i++) {
var char = value[i];
if (char === '-') {
shouldUpperCase = true;
} else {
result += result && shouldUpperCase ? char.toUpperCase() : char;
shouldUpperCase = false;
}
}
camelCaseCache[value] = result;
return result;
}
var cache = Object.create(null);
var parseClassExpression = (function (expression) {
if (cache[expression]) return cache[expression];
var className;
var binding;
var bindingValue;
var role;
if (includes(expression, '=', 1)) {
// eg: disabled=isDisabled
var _expression$split = expression.split('=');
className = _expression$split[0];
binding = _expression$split[1];
} else {
var modifier = expression[0];
if (modifier === '$') {
// eg: $type
binding = expression.substr(1);
bindingValue = true;
} else if (modifier === '@') {
// eg: @button
className = expression.substr(1);
role = className;
} else if (modifier === ':') {
// eg: :disabled
className = expression.substr(1);
binding = camelCase(className);
} else {
className = expression;
}
}
cache[expression] = {
className: className,
binding: binding,
bindingValue: bindingValue,
role: role
};
return cache[expression];
});
var INJECT_ATTR = 'styleName';
/* eslint max-depth: 0 guard-for-in: 0 */
function createElement(_) {
var args = [].slice.call(arguments, 1); // for functional component
if (isFunction(_)) {
return createElement.bind(_, {
functional: true,
createElement: _,
styles: args[0],
context: args[1]
});
}
var _$functional = _.functional,
functional = _$functional === void 0 ? false : _$functional,
h = _.createElement,
_$context = _.context,
context = _$context === void 0 ? {} : _$context,
_$styles = _.styles,
styles = _$styles === void 0 ? context.$style || {} : _$styles;
if (isString(styles)) {
styles = (functional ? (context.injections || {})[styles] : context[styles]) || {};
}
if (functional) {
context = context.props || {};
}
var data = args[1];
if (isObject(data)) {
if (!data.staticClass) {
data.staticClass = '';
}
if (!data.attrs) {
data.attrs = {};
}
var modules = data[INJECT_ATTR] || data.attrs[INJECT_ATTR] || '';
if (modules.length) {
var _modules = Array.isArray(modules) ? modules : [modules];
for (var i in _modules) {
var module = _modules[i];
if (module && typeof module === 'string') {
var classExpressions = module.split(/\s+/g);
for (var _i in classExpressions) {
var classExpression = classExpressions[_i];
var _parseClassExpression = parseClassExpression(classExpression),
className = _parseClassExpression.className,
binding = _parseClassExpression.binding,
bindingValue = _parseClassExpression.bindingValue,
role = _parseClassExpression.role;
if (bindingValue) {
className = context[binding];
binding = undefined;
}
if ((binding ? context[binding] : true) && styles[className]) {
data.staticClass += " " + styles[className];
data.staticClass = data.staticClass.trim();
}
if (role) {
data.attrs["data-component-" + role] = '';
}
}
}
}
} // remove styleName attr
delete data[INJECT_ATTR];
delete data.attrs[INJECT_ATTR];
}
return h.apply(null, args);
}
/* eslint camelcase: 0 */
var CSSModules = function CSSModules(styles) {
return {
beforeCreate: function beforeCreate() {
this.original$createElement = this.original$createElement || this.$createElement;
this.original_c = this.original_c || this._c;
this.$createElement = createElement.bind(this, {
createElement: this.original$createElement,
context: this,
styles: styles
});
this._c = createElement.bind(this, {
createElement: this.original_c,
context: this,
styles: styles
});
}
};
};
CSSModules.install = function (Vue) {
Vue.mixin(CSSModules());
};
export default CSSModules;