mirror of
https://github.com/tenrok/maska.git
synced 2026-06-23 20:40:35 +03:00
Initial commit
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
node_modules/
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
# Maska
|
||||||
|
|
||||||
|
Simple zero-dependency input mask for Vue.js and vanilla JS.
|
||||||
|
|
||||||
|
- No dependencies
|
||||||
|
- Small size (~2 Kb gziped)
|
||||||
|
- Ability to define custom tokens
|
||||||
|
- Supports repeat symbols
|
||||||
|
- Works on any input (custom or native)
|
||||||
|
|
||||||
|
## Usage with Vue.js
|
||||||
|
|
||||||
|
If you load Vue.js via `<script>` then just add `v-maska` directive to your input:
|
||||||
|
|
||||||
|
``` html
|
||||||
|
<input v-maska="'###'">
|
||||||
|
```
|
||||||
|
|
||||||
|
You can add custom tokens by passing in object instead of string to directive:
|
||||||
|
|
||||||
|
``` html
|
||||||
|
<input v-maska="{ mask: 'Z*', tokens: { 'Z': { pattern: /[а-яА-Я]/ }}}">
|
||||||
|
```
|
||||||
|
|
||||||
|
If you use SFC then import `directive` component from library:
|
||||||
|
|
||||||
|
``` html
|
||||||
|
<template>
|
||||||
|
<form>
|
||||||
|
<input v-maska="'###'">
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { maska } from 'maska'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
directives: { maska }
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage with vanilla JS
|
||||||
|
|
||||||
|
Just load script `maska.js` and init it, passing element(s) or selector expression:
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
var mask = Maska.create('.masked');
|
||||||
|
```
|
||||||
|
|
||||||
|
You can pass custom tokens while initialization:
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
var mask = Maska.create('.masked', {
|
||||||
|
tokens: { 'Z': { pattern: /[а-яА-Я]/ }}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
You can destroy mask like that:
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
var mask = Maska.create('.masked');
|
||||||
|
mask.destroy();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Mask syntax
|
||||||
|
|
||||||
|
Default tokens:
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
{
|
||||||
|
'#': { pattern: /[0-9]/ },
|
||||||
|
'X': { pattern: /[0-9a-zA-Z]/ },
|
||||||
|
'S': { pattern: /[a-zA-Z]/ },
|
||||||
|
'A': { pattern: /[a-zA-Z]/, uppercase: true },
|
||||||
|
'a': { pattern: /[a-zA-Z]/, lowercase: true },
|
||||||
|
'!': { escape: true },
|
||||||
|
'*': { repeat: true }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Escape symbol escapes next token (mask `!#` will render `#`)
|
||||||
|
- Repeat symbol allows repeating current token until it’s valid (e.g. mask `#*` for all digits or `A* A*` for `CARDHOLDER NAME`)
|
||||||
|
|
||||||
|
You can add your own tokens by passing them in `maska` directive or `create` method at initialization (see above). **Important**: `pattern` field should be JS *regular expression* (`/[0-9]/`) or *string without delimiters* (`"[0-9]"`).
|
||||||
|
|
||||||
|
## Source of Inspiration
|
||||||
|
|
||||||
|
- [vue-the-mask](https://vuejs-tips.github.io/vue-the-mask/)
|
||||||
|
- [jQuery Mask Plugin](http://igorescobar.github.io/jQuery-Mask-Plugin/)
|
||||||
+116
@@ -0,0 +1,116 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<title>Maska demo</title>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css" integrity="sha256-vK3UTo/8wHbaUn+dTQD0X6dzidqc5l7gczvH+Bnowwk=" crossorigin="anonymous" />
|
||||||
|
<style>
|
||||||
|
body { padding: 2em 0 5em; background: #fafafa }
|
||||||
|
.container { max-width: 800px }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="content">
|
||||||
|
<h1 class="is-size-1">Maska library demo</h1>
|
||||||
|
|
||||||
|
<h2 class="is-size-3">Vue.js examples</h2>
|
||||||
|
<div class="box">
|
||||||
|
<form id="vue-form">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Phone with code</label>
|
||||||
|
<div class="control">
|
||||||
|
<input v-maska="'+1 (###) ###-##-##'" value="12345678901" class="input">
|
||||||
|
</div>
|
||||||
|
<p class="help is-family-code">v-maska="'+1 (###) ###-##-##'"</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Hex color (custom tokens)</label>
|
||||||
|
<div class="control">
|
||||||
|
<input v-maska="{ mask: '!#HHHHHH', tokens: { 'H': { pattern: /[0-9a-fA-F]/, uppercase: true }}}" class="input">
|
||||||
|
</div>
|
||||||
|
<p class="help is-family-code">v-maska="{ mask: '!#HHHHHH', tokens: { 'H': { pattern: /[0-9a-fA-F]/, uppercase: true }}}"</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="is-size-3">Vanilla JS examples</h2>
|
||||||
|
<div class="box">
|
||||||
|
<form id="vanilla-form">
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Phone with code</label>
|
||||||
|
<div class="control">
|
||||||
|
<input data-mask="+1 (###) ###-####" class="masked input">
|
||||||
|
</div>
|
||||||
|
<p class="help is-family-code">data-mask="+1 (###) ###-####"</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Cardholder name</label>
|
||||||
|
<div class="control">
|
||||||
|
<input data-mask="A* A*" class="masked input">
|
||||||
|
</div>
|
||||||
|
<p class="help is-family-code">data-mask="A* A*"</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">All digits</label>
|
||||||
|
<div class="control">
|
||||||
|
<input data-mask="#*" class="masked input">
|
||||||
|
</div>
|
||||||
|
<p class="help is-family-code">data-mask="#*"</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Date</label>
|
||||||
|
<div class="control">
|
||||||
|
<input data-mask="##/##/####" class="masked input">
|
||||||
|
</div>
|
||||||
|
<p class="help is-family-code">data-mask="##/##/####"</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Hex color (custom tokens)</label>
|
||||||
|
<div class="control">
|
||||||
|
<input data-mask="!#HHHHHH" class="custom-masked input">
|
||||||
|
</div>
|
||||||
|
<p class="help is-family-code">data-mask="!#HHHHHH"</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Without mask (destroyed)</label>
|
||||||
|
<div class="control">
|
||||||
|
<input data-mask="###" class="unmasked input">
|
||||||
|
</div>
|
||||||
|
<p class="help is-family-code">data-mask="###"</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
|
||||||
|
<script src="../dist/maska.js"></script>
|
||||||
|
<script>
|
||||||
|
// vue
|
||||||
|
new Vue({
|
||||||
|
el: '#vue-form'
|
||||||
|
});
|
||||||
|
|
||||||
|
// vanilla default
|
||||||
|
Maska.create('#vanilla-form .masked');
|
||||||
|
|
||||||
|
// vanilla custom tokens
|
||||||
|
Maska.create('#vanilla-form .custom-masked', {
|
||||||
|
tokens: { 'H': { pattern: '[0-9a-fA-F]', uppercase: true }}
|
||||||
|
});
|
||||||
|
|
||||||
|
// vanilla destroy
|
||||||
|
var mask = Maska.create('#vanilla-form .unmasked');
|
||||||
|
mask.destroy();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
+8440
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "maska",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Simple zero-dependency input mask for Vue.js and vanilla JS",
|
||||||
|
"keywords": [
|
||||||
|
"mask",
|
||||||
|
"input",
|
||||||
|
"vue"
|
||||||
|
],
|
||||||
|
"author": "Alexander Shabunevich <alex@aether.ru>",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"serve": "rimraf dist && webpack --watch",
|
||||||
|
"build": "rimraf dist && webpack -p",
|
||||||
|
"test": "jest",
|
||||||
|
"lint": "standard 'src/**'"
|
||||||
|
},
|
||||||
|
"module": "src/index.js",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.6.0",
|
||||||
|
"@babel/preset-env": "^7.6.0",
|
||||||
|
"babel-jest": "^24.9.0",
|
||||||
|
"babel-loader": "^8.0.6",
|
||||||
|
"jest": "^24.9.0",
|
||||||
|
"rimraf": "^3.0.0",
|
||||||
|
"standard": "^14.3.1",
|
||||||
|
"webpack": "^4.40.2",
|
||||||
|
"webpack-cli": "^3.3.9"
|
||||||
|
},
|
||||||
|
"browserslist": "> 0.25%, ie 11",
|
||||||
|
"babel": {
|
||||||
|
"presets": [
|
||||||
|
"@babel/preset-env"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import Maska from './maska'
|
||||||
|
import { isString } from './utils'
|
||||||
|
|
||||||
|
function getOpts (mask) {
|
||||||
|
const opts = {}
|
||||||
|
|
||||||
|
if (isString(mask)) {
|
||||||
|
opts.mask = mask
|
||||||
|
} else if (mask.mask) {
|
||||||
|
opts.mask = mask.mask
|
||||||
|
opts.tokens = mask.tokens ? mask.tokens : {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts
|
||||||
|
}
|
||||||
|
|
||||||
|
function needUpdate (mask) {
|
||||||
|
if (isString(mask.value) && isString(mask.oldValue) && mask.value === mask.oldValue) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask.value && mask.oldValue && mask.value.mask === mask.oldValue.mask) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function directive (el, mask) {
|
||||||
|
if (!mask.value) return
|
||||||
|
|
||||||
|
if (mask.value && needUpdate(mask)) {
|
||||||
|
return new Maska(el, getOpts(mask.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import directive from './directive'
|
||||||
|
import mask from './mask'
|
||||||
|
import Maska from './maska'
|
||||||
|
import tokens from './tokens'
|
||||||
|
|
||||||
|
function install (Vue) {
|
||||||
|
Vue.directive('maska', directive)
|
||||||
|
}
|
||||||
|
// Install by default if included from script tag
|
||||||
|
if (typeof window !== 'undefined' && window.Vue) {
|
||||||
|
window.Vue.use(install)
|
||||||
|
}
|
||||||
|
|
||||||
|
function create (el, options) {
|
||||||
|
return new Maska(el, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default install
|
||||||
|
export {
|
||||||
|
create,
|
||||||
|
mask,
|
||||||
|
directive as maska,
|
||||||
|
tokens
|
||||||
|
}
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
export default function mask (value, mask, tokens, masked = true) {
|
||||||
|
let im = 0
|
||||||
|
let iv = 0
|
||||||
|
let ret = ''
|
||||||
|
let rest = ''
|
||||||
|
|
||||||
|
while (im < mask.length && iv < value.length) {
|
||||||
|
let maskChar = mask[im]
|
||||||
|
const valueChar = value[iv]
|
||||||
|
const token = tokens[maskChar]
|
||||||
|
|
||||||
|
if (token && token.pattern) {
|
||||||
|
if (token.pattern.test(valueChar)) {
|
||||||
|
ret += tokenTransform(valueChar, token)
|
||||||
|
im++
|
||||||
|
}
|
||||||
|
iv++
|
||||||
|
} else if (token && token.repeat) {
|
||||||
|
const maskCharPrev = mask[im - 1]
|
||||||
|
const tokenPrev = tokens[maskCharPrev]
|
||||||
|
if (token && token.repeat && tokenPrev && !tokenPrev.pattern.test(valueChar)) {
|
||||||
|
im++
|
||||||
|
} else {
|
||||||
|
im--
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (token && token.escape) {
|
||||||
|
im++
|
||||||
|
maskChar = mask[im]
|
||||||
|
}
|
||||||
|
if (masked) ret += maskChar
|
||||||
|
if (valueChar === maskChar) iv++
|
||||||
|
im++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix mask that ends with parentesis
|
||||||
|
while (masked && im < mask.length) { // eslint-disable-line no-unmodified-loop-condition
|
||||||
|
const maskCharRest = mask[im]
|
||||||
|
if (tokens[maskCharRest] && !tokens[maskCharRest].repeat) {
|
||||||
|
rest = ''
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (!tokens[maskCharRest]) {
|
||||||
|
rest += maskCharRest
|
||||||
|
}
|
||||||
|
im++
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret + rest
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenTransform (value, token) {
|
||||||
|
if (token.uppercase) {
|
||||||
|
return value.toLocaleUpperCase()
|
||||||
|
} else if (token.lowercase) {
|
||||||
|
return value.toLocaleLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import mask from './mask'
|
||||||
|
import tokens from './tokens'
|
||||||
|
import { event, findInputElement, fixInputSelection, isString } from './utils'
|
||||||
|
|
||||||
|
export default class Maska {
|
||||||
|
constructor (el, opts = {}) {
|
||||||
|
if (!el) throw new Error('Maska: no element for mask')
|
||||||
|
|
||||||
|
if (opts.tokens) {
|
||||||
|
for (const i in opts.tokens) {
|
||||||
|
opts.tokens[i] = { ...opts.tokens[i] }
|
||||||
|
if (opts.tokens[i].pattern && isString(opts.tokens[i].pattern)) {
|
||||||
|
opts.tokens[i].pattern = new RegExp(opts.tokens[i].pattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._opts = {
|
||||||
|
mask: opts.mask,
|
||||||
|
tokens: { ...tokens, ...opts.tokens }
|
||||||
|
}
|
||||||
|
this._el = isString(el) ? document.querySelectorAll(el) : !el.length ? [el] : el
|
||||||
|
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
init () {
|
||||||
|
for (let i = 0; i < this._el.length; i++) {
|
||||||
|
const el = findInputElement(this._el[i])
|
||||||
|
if (!el.dataset.mask && this._opts.mask) {
|
||||||
|
el.dataset.mask = this._opts.mask
|
||||||
|
}
|
||||||
|
this.updateValue(el)
|
||||||
|
el.addEventListener('input', evt => this.onInput(evt))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy () {
|
||||||
|
for (let i = 0; i < this._el.length; i++) {
|
||||||
|
const el = findInputElement(this._el[i])
|
||||||
|
el.removeEventListener('input', evt => this.onInput(evt))
|
||||||
|
delete el.dataset.mask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateValue (el) {
|
||||||
|
if (!el.value || !el.dataset.mask) return
|
||||||
|
|
||||||
|
const position = el.selectionEnd
|
||||||
|
const digit = el.value[position - 1]
|
||||||
|
el.value = mask(el.value, el.dataset.mask, this._opts.tokens)
|
||||||
|
fixInputSelection(el, position, digit)
|
||||||
|
el.dispatchEvent(event('input'))
|
||||||
|
}
|
||||||
|
|
||||||
|
onInput (event) {
|
||||||
|
if (event.isTrusted) {
|
||||||
|
this.updateValue(event.target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/* eslint quote-props: ["error", "consistent"] */
|
||||||
|
export default {
|
||||||
|
'#': { pattern: /[0-9]/ },
|
||||||
|
'X': { pattern: /[0-9a-zA-Z]/ },
|
||||||
|
'S': { pattern: /[a-zA-Z]/ },
|
||||||
|
'A': { pattern: /[a-zA-Z]/, uppercase: true },
|
||||||
|
'a': { pattern: /[a-zA-Z]/, lowercase: true },
|
||||||
|
'!': { escape: true },
|
||||||
|
'*': { repeat: true }
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/* global HTMLInputElement */
|
||||||
|
|
||||||
|
function event (name) {
|
||||||
|
const event = document.createEvent('Event')
|
||||||
|
event.initEvent(name, true, true)
|
||||||
|
|
||||||
|
return event
|
||||||
|
}
|
||||||
|
|
||||||
|
function findInputElement (el) {
|
||||||
|
return (el instanceof HTMLInputElement) ? el : el.querySelector('input') || el
|
||||||
|
}
|
||||||
|
|
||||||
|
function fixInputSelection (el, position, digit) {
|
||||||
|
while (position < el.value.length && el.value.charAt(position - 1) !== digit) {
|
||||||
|
position++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (el === document.activeElement) {
|
||||||
|
el.setSelectionRange(position, position)
|
||||||
|
setTimeout(function () {
|
||||||
|
el.setSelectionRange(position, position)
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isString (val) {
|
||||||
|
return Object.prototype.toString.call(val) === '[object String]'
|
||||||
|
}
|
||||||
|
|
||||||
|
export { event, findInputElement, fixInputSelection, isString }
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
import mask from './../src/mask'
|
||||||
|
import tokens from './../src/tokens'
|
||||||
|
|
||||||
|
test('12 #.#', () => {
|
||||||
|
expect(mask('12', '#.#', tokens)).toBe('1.2')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('1 (#)', () => {
|
||||||
|
expect(mask('1', '(#)', tokens)).toBe('(1)')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('1 [(#)]', () => {
|
||||||
|
expect(mask('1', '[(#)]', tokens)).toBe('[(1)]')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('1 #.#', () => {
|
||||||
|
expect(mask('1', '#.#', tokens)).toBe('1')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('1. #.#', () => {
|
||||||
|
expect(mask('1.', '#.#', tokens)).toBe('1.')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123 #.#', () => {
|
||||||
|
expect(mask('123', '#.#', tokens)).toBe('1.2')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Raw phone number', () => {
|
||||||
|
expect(mask('44998765432', '+55 (##) #####-####', tokens, false)).toBe('44998765432')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('abcd12345 AAA-####', () => {
|
||||||
|
expect(mask('abcd12345', 'AAA-####', tokens)).toBe('ABC-1234')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('a5-12-34 (XX) - ## - ##', () => {
|
||||||
|
expect(mask('a5-12-34', '(XX) - ## - ##', tokens)).toBe('(a5) - 12 - 34')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123 ##(#)', () => {
|
||||||
|
expect(mask('123', '##(#)', tokens)).toBe('12(3)')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('12 #!#(#)', () => {
|
||||||
|
expect(mask('12', '#!#(#)', tokens)).toBe('1#(2)')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('12 +1 #', () => {
|
||||||
|
expect(mask('12', '+1 #', tokens)).toBe('+1 2')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('2 +1 #', () => {
|
||||||
|
expect(mask('2', '+1 #', tokens)).toBe('+1 2')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('abc DEF AAA aaa', () => {
|
||||||
|
expect(mask('abc DEF', 'AAA aaa', tokens)).toBe('ABC def')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123abc #*', () => {
|
||||||
|
expect(mask('123abc', '#*', tokens)).toBe('123')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123abc A*', () => {
|
||||||
|
expect(mask('123abc', 'A*', tokens)).toBe('ABC')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123abc #A*', () => {
|
||||||
|
expect(mask('123abc', '#A*', tokens)).toBe('1ABC')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123abc ## A*', () => {
|
||||||
|
expect(mask('123abc', '## A*', tokens)).toBe('12 ABC')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123abc #*A', () => {
|
||||||
|
expect(mask('123abc', '#*A', tokens)).toBe('123A')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123abc #*A*', () => {
|
||||||
|
expect(mask('123abc', '#*A*', tokens)).toBe('123ABC')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123 abc DEF 456 -> A* a*', () => {
|
||||||
|
expect(mask('123 abc DEF 456', 'A* a*', tokens)).toBe('ABC def')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('abc123 A!*', () => {
|
||||||
|
expect(mask('abc123', 'A!*', tokens)).toBe('A*')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123abc #!*A*', () => {
|
||||||
|
expect(mask('123abc', '#!*A*', tokens)).toBe('1*ABC')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123abc (#*)A*', () => {
|
||||||
|
expect(mask('123abc', '(#*)A*', tokens)).toBe('(123)ABC')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('123abc -> # (A*)', () => {
|
||||||
|
expect(mask('123abc', '# (A*)', tokens)).toBe('1 (ABC)')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Raw 123abc ##(A*)', () => {
|
||||||
|
expect(mask('123abc', '##(A*)', tokens, false)).toBe('12ABC')
|
||||||
|
})
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
const prod = process.env.NODE_ENV === 'production'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: prod ? 'production' : 'development',
|
||||||
|
output: {
|
||||||
|
filename: 'maska.js',
|
||||||
|
library: 'Maska',
|
||||||
|
libraryTarget: 'umd',
|
||||||
|
umdNamedDefine: true
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.m?js$/,
|
||||||
|
exclude: /(node_modules|bower_components)/,
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader',
|
||||||
|
options: {
|
||||||
|
presets: ['@babel/preset-env']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user