nornj
Version:
A powerful template engine that can works with React, JSX enhancement or alternative tools.
276 lines (234 loc) • 7.43 kB
text/typescript
import nj from '../core';
import * as tools from '../utils/tools';
import { getAccessorData, styleProps } from '../transforms/transformData';
import { FilterDelegate, FilterOption } from '../interface';
const REGEX_DIGITS_RE = /(\d{3})(?=\d)/g;
//Global filter list
export const filters: { [name: string]: FilterDelegate } = {
//Get properties
'.': (obj, prop, callFn) => {
if (obj == null) {
return obj;
}
if (obj._njSrc) {
return {
source: obj.value,
value: obj.value[prop],
prop,
parent: obj,
_njSrc: true
};
} else if (callFn) {
return {
source: obj,
value: obj[prop],
prop,
_njSrc: true
};
}
return obj[prop];
},
//Call function
_: function(fn, args) {
if (fn == null) {
return fn;
}
if (fn._njSrc) {
const _fn = fn.source[fn.prop];
return _fn != null ? _fn.apply(fn.source, args) : _fn;
}
return fn.apply(null, args);
},
//Get accessor properties
'#': (obj, prop, options) => {
if (obj == null) {
return obj;
}
return getAccessorData(obj[prop], options.context);
},
'**': (val1: number, val2: number) => {
const ret = Math.pow(val1, val2);
return isNaN(ret) ? 0 : ret;
},
'%%': (val1: number, val2: number) => {
const ret = Math.floor(val1 / val2);
return isNaN(ret) ? 0 : ret;
},
//Ternary operator
'?:': (val, val1, val2) => (val ? val1 : val2),
'!': val => !val,
//Convert to int
int: (val: string, radix = 10) => {
const ret = parseInt(val, radix);
return isNaN(ret) ? 0 : ret;
},
//Convert to float
float: (val: string, bit: number) => {
const ret = parseFloat(val);
return isNaN(ret) ? 0 : bit != null ? ret.toFixed(bit) : ret;
},
//Convert to boolean
bool: (val: boolean | string) => {
if (val === 'false') {
return false;
}
return Boolean(val);
},
reg: (pattern: string | RegExp, flags: string) => new RegExp(pattern, flags),
//Transform css string to object
css: cssText => styleProps(cssText),
//Generate array by two positive integers,closed interval
rOpe: _getArrayByNum(1),
//Generate array by two positive integers,right open interval
rLt: _getArrayByNum(0),
//Compare two number or letter
'<=>': (val1, val2) => {
if (val1 > val2) {
return 1;
} else if (val1 == val2) {
return 0;
} else {
return -1;
}
},
upperFirst: (str: string) => tools.upperFirst(str),
lowerFirst: (str: string) => tools.lowerFirst(str),
camelCase: (str: string) => tools.camelCase(str),
isObject: val => tools.isObject(val),
isNumber: val => tools.isNumber(val),
isString: val => tools.isString(val),
isArrayLike: val => tools.isArrayLike(val),
currency(value, decimals: number, symbol, placeholder: string) {
if (!(value - parseFloat(value) >= 0)) {
return placeholder != null ? placeholder : filterConfig.currency.placeholder;
}
value = parseFloat(value);
symbol = decimals != null && tools.isString(decimals) ? decimals : symbol;
symbol = symbol != null && tools.isString(symbol) ? symbol : filterConfig.currency.symbol;
decimals = decimals != null && tools.isNumber(decimals) ? decimals : 2;
const stringified = Math.abs(value).toFixed(decimals);
const _int = decimals ? stringified.slice(0, -1 - decimals) : stringified;
const i = _int.length % 3;
const head = i > 0 ? _int.slice(0, i) + (_int.length > 3 ? ',' : '') : '';
const _float = decimals ? stringified.slice(-1 - decimals) : '';
const sign = value < 0 ? '-' : '';
return sign + symbol + head + _int.slice(i).replace(REGEX_DIGITS_RE, '$1,') + _float;
}
};
function _getArrayByNum(isContainEnd) {
return function(val1, val2) {
return Object.keys(Array.apply(null, { length: val2 - val1 + isContainEnd })).map(item => +item + val1);
};
}
function _config(params?: FilterOption, extra?: FilterOption): FilterOption {
let ret: FilterOption = {
onlyGlobal: false,
hasOptions: false,
isOperator: false,
hasLevel: false,
hasTmplCtx: true,
alias: null
};
if (params) {
ret = tools.assign(ret, params);
}
if (extra) {
ret = tools.assign(ret, extra);
}
return ret;
}
const _defaultCfg: FilterOption = { onlyGlobal: true, hasOptions: false };
//Filter default config
export const filterConfig: { [name: string]: FilterOption } = {
'.': _config(_defaultCfg),
_: _config({ onlyGlobal: true }),
'#': _config({ onlyGlobal: true, hasOptions: true, hasLevel: true }),
'**': _config(_defaultCfg),
'%%': _config(_defaultCfg),
'?:': _config(_defaultCfg),
'!': _config(_defaultCfg),
int: _config(_defaultCfg),
float: _config(_defaultCfg),
bool: _config(_defaultCfg),
reg: _config(_defaultCfg),
css: _config(_defaultCfg),
rOpe: _config(_defaultCfg),
rLt: _config(_defaultCfg),
'<=>': _config(_defaultCfg),
upperFirst: _config(_defaultCfg),
lowerFirst: _config(_defaultCfg),
camelCase: _config(_defaultCfg),
isObject: _config(_defaultCfg),
isNumber: _config(_defaultCfg),
isString: _config(_defaultCfg),
isArrayLike: _config(_defaultCfg),
currency: _config(_defaultCfg, { symbol: '$', placeholder: '' })
};
filters.capitalize = filters.upperFirst;
filterConfig.capitalize = _config(filterConfig.upperFirst);
export function registerFilter(options: {
[name: string]: FilterDelegate | { filter?: FilterDelegate; options?: FilterOption };
}): void;
export function registerFilter(
name: string,
filter: FilterDelegate,
options?: FilterOption,
mergeConfig?: boolean
): void;
export function registerFilter(name, filter?: FilterDelegate, options?: FilterOption, mergeConfig?: boolean): void {
let params = name;
if (!tools.isObject(name)) {
params = {};
params[name] = {
filter,
options
};
}
tools.each(
params,
(v, name) => {
if (v) {
const { filter, options }: { filter: FilterDelegate; options: FilterOption } = v;
if (options) {
if (options.isOperator) {
const createRegexOperators = nj.createRegexOperators;
if (createRegexOperators) {
createRegexOperators(name);
}
}
const { alias } = options;
if (alias) {
const createFilterAlias = nj.createFilterAlias;
if (createFilterAlias) {
createFilterAlias(name, alias);
}
name = alias;
}
}
if (filter) {
filters[name] = filter;
} else if (!mergeConfig) {
filters[name] = v;
}
if (mergeConfig) {
if (!filterConfig[name]) {
filterConfig[name] = _config();
}
if (tools.isObject(options)) {
tools.assign(filterConfig[name], options);
} else {
filterConfig[name] = _config();
}
} else {
filterConfig[name] = _config(options);
}
}
},
false
);
}
tools.assign(nj, {
filters,
filterConfig,
registerFilter
});