sophisticated rollup setup and eslint base setup

This commit is contained in:
Rene
2020-07-25 01:10:04 +02:00
parent 118aaf0d32
commit eb10b3d723
116 changed files with 15667 additions and 13077 deletions
+4
View File
@@ -0,0 +1,4 @@
node_modules
coverage
dist
types
+72
View File
@@ -0,0 +1,72 @@
const resolve = require('./resolve.config');
module.exports = {
extends: ['plugin:@typescript-eslint/recommended', 'plugin:react/recommended', 'airbnb', 'prettier'],
env: {
browser: true,
es2020: true,
node: true,
jest: true,
},
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 11,
sourceType: 'module',
},
settings: {
'import/resolver': {
node: {
extensions: resolve.extensions,
moduleDirectory: resolve.directories,
},
},
},
plugins: ['prettier', 'json', 'react', 'jest', 'import', '@typescript-eslint'],
rules: {
'func-names': 'off',
'no-plusplus': 'off',
'no-continue': 'off',
'no-param-reassign': 'off',
'no-nested-ternary': 'off',
'no-console': ['error', { allow: ['warn', 'error'] }],
'no-empty': ['error', { allowEmptyCatch: true }],
'no-cond-assign': ['error', 'except-parens'],
camelcase: ['error', { allow: ['^__', '^UNSAFE_'] }],
'consistent-return': 'off',
'import/prefer-default-export': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-var-requires': 'off',
},
overrides: [
{
files: ['*.test.*'],
rules: {
'no-restricted-syntax': 'off',
'no-param-reassign': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/ban-types': 'off',
'no-console': 'off',
'consistent-return': 'off',
'symbol-description': 'off',
'no-new-wrappers': 'off',
'no-prototype-builtins': 'off',
'no-void': 'off',
'no-empty-function': 'off',
'no-new-func': 'off',
},
},
{
files: ['rollup.config.*'],
rules: {
'no-console': 'off',
},
},
],
};
+5 -4
View File
@@ -4,7 +4,6 @@ about: Create a report to help improve OverlayScrollbars
title: '' title: ''
labels: '' labels: ''
assignees: '' assignees: ''
--- ---
**Describe the bug** **Describe the bug**
@@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
**To Reproduce** **To Reproduce**
Steps to reproduce the behavior: Steps to reproduce the behavior:
1. Go to '...' 1. Go to '...'
2. Click on '....' 2. Click on '....'
3. Scroll down to '....' 3. Scroll down to '....'
@@ -21,12 +21,13 @@ Steps to reproduce the behavior:
A clear and concise description of what you expected to happen. A clear and concise description of what you expected to happen.
**Examples** **Examples**
Please create a small example of the bug. Please create a small example of the bug.
To do this you can use online platforms like [JSFiddle](https://jsfiddle.net/), [CodeSandbox](https://codesandbox.io/) or [StackBlitz](https://stackblitz.com/). You can also create a separate Github repository which I can clone. To do this you can use online platforms like [JSFiddle](https://jsfiddle.net/), [CodeSandbox](https://codesandbox.io/) or [StackBlitz](https://stackblitz.com/). You can also create a separate Github repository which I can clone.
**Environment** **Environment**
- Used Operating System(s):
- Used Browser(s) (with version): - Used Operating System(s):
- Used Browser(s) (with version):
**Additional context** **Additional context**
Add any other context about the problem here. Add any other context about the problem here.
@@ -4,7 +4,6 @@ about: Suggest an idea for this project
title: '' title: ''
labels: '' labels: ''
assignees: '' assignees: ''
--- ---
**Is your feature request related to a problem? Please describe.** **Is your feature request related to a problem? Please describe.**
+4
View File
@@ -0,0 +1,4 @@
node_modules
coverage
dist
types
+7
View File
@@ -0,0 +1,7 @@
{
"printWidth": 150,
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "all",
"jsxBracketSameLine": true
}
+12 -14
View File
@@ -1,16 +1,14 @@
module.exports = { module.exports = {
"plugins": [ plugins: ['@babel/plugin-transform-modules-commonjs'],
"@babel/plugin-transform-modules-commonjs" presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
], ],
"presets": [ '@babel/preset-typescript',
[ ],
"@babel/preset-env", };
{
"targets": {
"node": "current"
}
}
],
"@babel/preset-typescript"
]
};
+287 -301
View File
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1595257697964" clover="3.2.0"> <coverage generated="1595630216423" clover="3.2.0">
<project timestamp="1595257697964" name="All files"> <project timestamp="1595630216423" name="All files">
<metrics statements="324" coveredstatements="307" conditionals="204" coveredconditionals="192" methods="79" coveredmethods="72" elements="607" coveredelements="571" complexity="0" loc="324" ncloc="324" packages="5" files="18" classes="18"/> <metrics statements="310" coveredstatements="295" conditionals="202" coveredconditionals="190" methods="81" coveredmethods="73" elements="593" coveredelements="558" complexity="0" loc="310" ncloc="310" packages="5" files="18" classes="18"/>
<package name="src"> <package name="src">
<metrics statements="33" coveredstatements="33" conditionals="1" coveredconditionals="1" methods="6" coveredmethods="6"/> <metrics statements="32" coveredstatements="32" conditionals="1" coveredconditionals="1" methods="6" coveredmethods="6"/>
<file name="instances.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\instances.ts"> <file name="instances.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\instances.ts">
<metrics statements="19" coveredstatements="19" conditionals="1" coveredconditionals="1" methods="6" coveredmethods="6"/> <metrics statements="18" coveredstatements="18" conditionals="1" coveredconditionals="1" methods="6" coveredmethods="6"/>
<line num="1" count="1" type="stmt"/> <line num="1" count="1" type="stmt"/>
<line num="2" count="1" type="stmt"/> <line num="2" count="1" type="stmt"/>
<line num="9" count="1" type="stmt"/> <line num="9" count="1" type="stmt"/>
@@ -15,18 +15,17 @@
<line num="19" count="4" type="stmt"/> <line num="19" count="4" type="stmt"/>
<line num="20" count="4" type="stmt"/> <line num="20" count="4" type="stmt"/>
<line num="27" count="1" type="stmt"/> <line num="27" count="1" type="stmt"/>
<line num="28" count="1" type="stmt"/> <line num="33" count="1" type="stmt"/>
<line num="35" count="1" type="stmt"/> <line num="34" count="2" type="stmt"/>
<line num="36" count="2" type="stmt"/> <line num="36" count="2" type="stmt"/>
<line num="38" count="2" type="stmt"/> <line num="38" count="1" type="cond" truecount="1" falsecount="0"/>
<line num="40" count="1" type="cond" truecount="1" falsecount="0"/> <line num="39" count="1" type="stmt"/>
<line num="41" count="1" type="stmt"/> <line num="43" count="2" type="stmt"/>
<line num="45" count="2" type="stmt"/> <line num="45" count="2" type="stmt"/>
<line num="47" count="2" type="stmt"/> <line num="46" count="1" type="stmt"/>
<line num="48" count="1" type="stmt"/> <line num="49" count="2" type="stmt"/>
<line num="51" count="2" type="stmt"/>
</file> </file>
<file name="options.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\options.ts"> <file name="options.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\options.ts">
<metrics statements="14" coveredstatements="14" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/> <metrics statements="14" coveredstatements="14" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/>
<line num="5" count="1" type="stmt"/> <line num="5" count="1" type="stmt"/>
<line num="6" count="1" type="stmt"/> <line num="6" count="1" type="stmt"/>
@@ -45,354 +44,341 @@
</file> </file>
</package> </package>
<package name="src.core.compatibility"> <package name="src.core.compatibility">
<metrics statements="49" coveredstatements="49" conditionals="14" coveredconditionals="14" methods="10" coveredmethods="10"/> <metrics statements="47" coveredstatements="47" conditionals="14" coveredconditionals="14" methods="10" coveredmethods="10"/>
<file name="vendors.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\compatibility\vendors.ts"> <file name="vendors.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\compatibility\vendors.ts">
<metrics statements="49" coveredstatements="49" conditionals="14" coveredconditionals="14" methods="10" coveredmethods="10"/> <metrics statements="47" coveredstatements="47" conditionals="14" coveredconditionals="14" methods="10" coveredmethods="10"/>
<line num="4" count="1" type="stmt"/> <line num="4" count="20" type="stmt"/>
<line num="5" count="20" type="stmt"/> <line num="5" count="10" type="stmt"/>
<line num="7" count="1" type="stmt"/> <line num="9" count="1" type="stmt"/>
<line num="8" count="10" type="stmt"/> <line num="10" count="1" type="stmt"/>
<line num="12" count="1" type="stmt"/>
<line num="13" count="1" type="stmt"/> <line num="13" count="1" type="stmt"/>
<line num="14" count="1" type="stmt"/> <line num="19" count="1" type="stmt"/>
<line num="16" count="1" type="stmt"/> <line num="20" count="4" type="stmt"/>
<line num="17" count="1" type="stmt"/> <line num="22" count="4" type="cond" truecount="2" falsecount="0"/>
<line num="23" count="1" type="stmt"/> <line num="23" count="1" type="stmt"/>
<line num="24" count="4" type="stmt"/> <line num="26" count="3" type="stmt"/>
<line num="26" count="4" type="cond" truecount="2" falsecount="0"/> <line num="27" count="3" type="stmt"/>
<line num="27" count="1" type="stmt"/>
<line num="29" count="3" type="stmt"/> <line num="29" count="3" type="stmt"/>
<line num="30" count="3" type="stmt"/> <line num="30" count="9" type="stmt"/>
<line num="32" count="3" type="stmt"/> <line num="31" count="9" type="stmt"/>
<line num="33" count="9" type="stmt"/> <line num="37" count="33" type="stmt"/>
<line num="34" count="9" type="stmt"/> <line num="38" count="9" type="stmt"/>
<line num="40" count="33" type="stmt"/> <line num="41" count="3" type="stmt"/>
<line num="41" count="9" type="stmt"/> <line num="42" count="3" type="stmt"/>
<line num="44" count="3" type="stmt"/> <line num="51" count="1" type="stmt"/>
<line num="45" count="3" type="stmt"/> <line num="52" count="11" type="stmt"/>
<line num="54" count="1" type="stmt"/> <line num="53" count="11" type="stmt"/>
<line num="55" count="11" type="stmt"/> <line num="55" count="11" type="cond" truecount="2" falsecount="0"/>
<line num="56" count="11" type="stmt"/> <line num="56" count="4" type="stmt"/>
<line num="58" count="11" type="cond" truecount="2" falsecount="0"/> <line num="59" count="7" type="stmt"/>
<line num="59" count="4" type="stmt"/> <line num="60" count="7" type="stmt"/>
<line num="61" count="7" type="stmt"/> <line num="61" count="7" type="cond" truecount="2" falsecount="0"/>
<line num="62" count="7" type="stmt"/> <line num="62" count="7" type="stmt"/>
<line num="63" count="7" type="cond" truecount="2" falsecount="0"/>
<line num="64" count="7" type="stmt"/> <line num="64" count="7" type="stmt"/>
<line num="66" count="7" type="stmt"/> <line num="65" count="10" type="stmt"/>
<line num="67" count="10" type="stmt"/> <line num="66" count="42" type="stmt"/>
<line num="68" count="42" type="stmt"/> <line num="67" count="42" type="stmt"/>
<line num="69" count="42" type="stmt"/> <line num="68" count="42" type="cond" truecount="2" falsecount="0"/>
<line num="70" count="42" type="cond" truecount="2" falsecount="0"/> <line num="69" count="2" type="stmt"/>
<line num="71" count="2" type="stmt"/> <line num="70" count="2" type="stmt"/>
<line num="72" count="2" type="stmt"/> <line num="73" count="10" type="stmt"/>
<line num="75" count="10" type="stmt"/> <line num="76" count="7" type="stmt"/>
<line num="78" count="7" type="stmt"/> <line num="77" count="7" type="stmt"/>
<line num="79" count="7" type="stmt"/> <line num="84" count="1" type="stmt"/>
<line num="86" count="1" type="stmt"/> <line num="85" count="5" type="cond" truecount="2" falsecount="0"/>
<line num="87" count="5" type="cond" truecount="2" falsecount="0"/> <line num="87" count="5" type="cond" truecount="2" falsecount="0"/>
<line num="89" count="5" type="cond" truecount="2" falsecount="0"/> <line num="88" count="1" type="stmt"/>
<line num="90" count="1" type="stmt"/> <line num="91" count="4" type="stmt"/>
<line num="92" count="4" type="stmt"/> <line num="92" count="11" type="cond" truecount="2" falsecount="0"/>
<line num="93" count="11" type="cond" truecount="2" falsecount="0"/> <line num="93" count="11" type="stmt"/>
<line num="94" count="11" type="stmt"/> <line num="96" count="4" type="stmt"/>
<line num="97" count="4" type="stmt"/> <line num="97" count="4" type="stmt"/>
<line num="98" count="4" type="stmt"/>
</file> </file>
</package> </package>
<package name="src.core.dom"> <package name="src.core.dom">
<metrics statements="124" coveredstatements="107" conditionals="79" coveredconditionals="67" methods="36" coveredmethods="29"/> <metrics statements="121" coveredstatements="106" conditionals="79" coveredconditionals="67" methods="37" coveredmethods="29"/>
<file name="attributes.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\attributes.ts"> <file name="attributes.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\attributes.ts">
<metrics statements="18" coveredstatements="18" conditionals="8" coveredconditionals="8" methods="5" coveredmethods="5"/> <metrics statements="18" coveredstatements="18" conditionals="8" coveredconditionals="8" methods="5" coveredmethods="5"/>
<line num="8" count="4" type="stmt"/> <line num="8" count="4" type="stmt"/>
<line num="9" count="7" type="cond" truecount="2" falsecount="0"/> <line num="9" count="7" type="cond" truecount="2" falsecount="0"/>
<line num="10" count="5" type="stmt"/> <line num="10" count="5" type="stmt"/>
<line num="11" count="2" type="stmt"/> <line num="12" count="2" type="stmt"/>
<line num="19" count="4" type="stmt"/> <line num="20" count="4" type="stmt"/>
<line num="20" count="1" type="stmt"/> <line num="21" count="1" type="stmt"/>
<line num="28" count="4" type="stmt"/> <line num="29" count="4" type="stmt"/>
<line num="29" count="3" type="cond" truecount="2" falsecount="0"/> <line num="30" count="3" type="cond" truecount="2" falsecount="0"/>
<line num="30" count="2" type="stmt"/> <line num="31" count="2" type="stmt"/>
<line num="31" count="1" type="stmt"/> <line num="33" count="1" type="stmt"/>
<line num="39" count="4" type="stmt"/> <line num="41" count="4" type="stmt"/>
<line num="40" count="3" type="cond" truecount="2" falsecount="0"/> <line num="42" count="3" type="cond" truecount="2" falsecount="0"/>
<line num="41" count="2" type="stmt"/> <line num="43" count="2" type="stmt"/>
<line num="42" count="1" type="stmt"/> <line num="45" count="1" type="stmt"/>
<line num="50" count="4" type="stmt"/> <line num="53" count="4" type="stmt"/>
<line num="51" count="5" type="cond" truecount="2" falsecount="0"/> <line num="54" count="5" type="cond" truecount="2" falsecount="0"/>
<line num="52" count="3" type="stmt"/> <line num="55" count="3" type="stmt"/>
<line num="53" count="2" type="stmt"/> <line num="57" count="2" type="stmt"/>
</file> </file>
<file name="classes.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\classes.ts"> <file name="classes.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\classes.ts">
<metrics statements="19" coveredstatements="19" conditionals="10" coveredconditionals="10" methods="4" coveredmethods="4"/> <metrics statements="18" coveredstatements="18" conditionals="10" coveredconditionals="10" methods="4" coveredmethods="4"/>
<line num="3" count="4" type="stmt"/> <line num="3" count="4" type="stmt"/>
<line num="10" count="4" type="stmt"/> <line num="10" count="7" type="stmt"/>
<line num="11" count="7" type="stmt"/> <line num="17" count="4" type="stmt"/>
<line num="19" count="4" type="stmt"/> <line num="19" count="11" type="stmt"/>
<line num="21" count="11" type="stmt"/> <line num="21" count="11" type="cond" truecount="2" falsecount="0"/>
<line num="23" count="11" type="cond" truecount="2" falsecount="0"/> <line num="22" count="9" type="cond" truecount="2" falsecount="0"/>
<line num="24" count="9" type="cond" truecount="2" falsecount="0"/> <line num="23" count="9" type="stmt"/>
<line num="25" count="9" type="stmt"/> <line num="24" count="11" type="stmt"/>
<line num="26" count="11" type="stmt"/> <line num="34" count="4" type="stmt"/>
<line num="35" count="4" type="stmt"/> <line num="36" count="7" type="stmt"/>
<line num="37" count="7" type="stmt"/> <line num="38" count="7" type="cond" truecount="2" falsecount="0"/>
<line num="39" count="7" type="cond" truecount="2" falsecount="0"/> <line num="39" count="5" type="cond" truecount="2" falsecount="0"/>
<line num="40" count="5" type="cond" truecount="2" falsecount="0"/> <line num="40" count="5" type="stmt"/>
<line num="41" count="5" type="stmt"/> <line num="41" count="6" type="stmt"/>
<line num="42" count="6" type="stmt"/>
<line num="52" count="4" type="stmt"/> <line num="52" count="4" type="stmt"/>
<line num="53" count="4" type="cond" truecount="2" falsecount="0"/> <line num="53" count="4" type="cond" truecount="2" falsecount="0"/>
<line num="54" count="2" type="stmt"/> <line num="54" count="2" type="stmt"/>
<line num="57" count="2" type="stmt"/> <line num="56" count="2" type="stmt"/>
</file> </file>
<file name="create.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\create.ts"> <file name="create.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\create.ts">
<metrics statements="6" coveredstatements="6" conditionals="0" coveredconditionals="0" methods="3" coveredmethods="3"/> <metrics statements="5" coveredstatements="5" conditionals="0" coveredconditionals="0" methods="3" coveredmethods="3"/>
<line num="5" count="4" type="stmt"/> <line num="5" count="204" type="stmt"/>
<line num="6" count="204" type="stmt"/> <line num="7" count="4" type="stmt"/>
<line num="9" count="4" type="stmt"/> <line num="8" count="3" type="stmt"/>
<line num="10" count="3" type="stmt"/> <line num="9" count="3" type="stmt"/>
<line num="11" count="3" type="stmt"/> <line num="11" count="9" type="stmt"/>
<line num="13" count="9" type="stmt"/>
</file> </file>
<file name="index.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\index.ts"> <file name="index.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\index.ts">
<metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/> <metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/>
</file> </file>
<file name="manipulation.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\manipulation.ts"> <file name="manipulation.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\manipulation.ts">
<metrics statements="28" coveredstatements="28" conditionals="24" coveredconditionals="24" methods="8" coveredmethods="8"/> <metrics statements="32" coveredstatements="32" conditionals="24" coveredconditionals="24" methods="8" coveredmethods="8"/>
<line num="13" count="4" type="stmt"/> <line num="13" count="4" type="stmt"/>
<line num="14" count="24" type="cond" truecount="2" falsecount="0"/> <line num="18" count="24" type="cond" truecount="2" falsecount="0"/>
<line num="15" count="20" type="stmt"/> <line num="19" count="20" type="stmt"/>
<line num="19" count="20" type="cond" truecount="2" falsecount="0"/> <line num="23" count="20" type="cond" truecount="2" falsecount="0"/>
<line num="20" count="16" type="cond" truecount="2" falsecount="0"/> <line num="24" count="16" type="cond" truecount="2" falsecount="0"/>
<line num="21" count="8" type="stmt"/> <line num="25" count="8" type="stmt"/>
<line num="24" count="8" type="stmt"/> <line num="28" count="8" type="stmt"/>
<line num="25" count="24" type="cond" truecount="2" falsecount="0"/> <line num="29" count="24" type="cond" truecount="2" falsecount="0"/>
<line num="26" count="3" type="stmt"/> <line num="30" count="3" type="stmt"/>
<line num="28" count="24" type="stmt"/> <line num="32" count="24" type="stmt"/>
<line num="32" count="8" type="stmt"/> <line num="35" count="8" type="stmt"/>
<line num="36" count="16" type="cond" truecount="2" falsecount="0"/> <line num="39" count="16" type="cond" truecount="2" falsecount="0"/>
<line num="37" count="12" type="cond" truecount="2" falsecount="0"/> <line num="40" count="12" type="cond" truecount="2" falsecount="0"/>
<line num="38" count="1" type="stmt"/> <line num="41" count="1" type="stmt"/>
<line num="40" count="11" type="cond" truecount="2" falsecount="0"/> <line num="42" count="11" type="cond" truecount="2" falsecount="0"/>
<line num="41" count="2" type="stmt"/> <line num="43" count="2" type="stmt"/>
<line num="45" count="16" type="stmt"/> <line num="47" count="16" type="stmt"/>
<line num="55" count="6" type="stmt"/> <line num="57" count="4" type="stmt"/>
<line num="62" count="6" type="cond" truecount="2" falsecount="0"/> <line num="58" count="6" type="stmt"/>
<line num="69" count="6" type="stmt"/> <line num="66" count="4" type="stmt"/>
<line num="76" count="6" type="cond" truecount="2" falsecount="0"/> <line num="67" count="6" type="cond" truecount="2" falsecount="0"/>
<line num="82" count="4" type="stmt"/> <line num="75" count="4" type="stmt"/>
<line num="83" count="23" type="cond" truecount="2" falsecount="0"/> <line num="76" count="6" type="stmt"/>
<line num="84" count="9" type="stmt"/> <line num="84" count="4" type="stmt"/>
<line num="86" count="21" type="cond" truecount="2" falsecount="0"/> <line num="85" count="6" type="cond" truecount="2" falsecount="0"/>
<line num="87" count="20" type="stmt"/> <line num="92" count="4" type="stmt"/>
<line num="88" count="20" type="cond" truecount="2" falsecount="0"/> <line num="93" count="23" type="cond" truecount="2" falsecount="0"/>
<line num="89" count="15" type="stmt"/> <line num="94" count="9" type="stmt"/>
<line num="95" count="21" type="cond" truecount="2" falsecount="0"/>
<line num="96" count="20" type="stmt"/>
<line num="97" count="20" type="cond" truecount="2" falsecount="0"/>
<line num="98" count="15" type="stmt"/>
</file> </file>
<file name="offset.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\offset.ts"> <file name="offset.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\offset.ts">
<metrics statements="5" coveredstatements="2" conditionals="0" coveredconditionals="0" methods="2" coveredmethods="0"/> <metrics statements="4" coveredstatements="2" conditionals="0" coveredconditionals="0" methods="2" coveredmethods="0"/>
<line num="1" count="3" type="stmt"/> <line num="1" count="3" type="stmt"/>
<line num="2" count="0" type="stmt"/> <line num="2" count="0" type="stmt"/>
<line num="3" count="0" type="stmt"/> <line num="3" count="0" type="stmt"/>
<line num="9" count="3" type="stmt"/> <line num="9" count="3" type="stmt"/>
<line num="10" count="0" type="stmt"/>
</file> </file>
<file name="style.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\style.ts"> <file name="style.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\style.ts">
<metrics statements="19" coveredstatements="5" conditionals="12" coveredconditionals="0" methods="5" coveredmethods="0"/> <metrics statements="18" coveredstatements="5" conditionals="12" coveredconditionals="0" methods="6" coveredmethods="0"/>
<line num="5" count="3" type="stmt"/> <line num="5" count="3" type="stmt"/>
<line num="21" count="3" type="stmt"/> <line num="21" count="3" type="stmt"/>
<line num="22" count="0" type="stmt"/> <line num="22" count="0" type="cond" truecount="0" falsecount="4"/>
<line num="23" count="0" type="cond" truecount="0" falsecount="2"/> <line num="24" count="3" type="stmt"/>
<line num="24" count="0" type="stmt"/> <line num="25" count="0" type="stmt"/>
<line num="29" count="3" type="stmt"/> <line num="26" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="30" count="0" type="cond" truecount="0" falsecount="4"/> <line num="27" count="0" type="stmt"/>
<line num="36" count="0" type="stmt"/> <line num="35" count="0" type="stmt"/>
<line num="37" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="38" count="0" type="cond" truecount="0" falsecount="2"/> <line num="38" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="39" count="0" type="cond" truecount="0" falsecount="2"/> <line num="39" count="0" type="stmt"/>
<line num="40" count="0" type="stmt"/> <line num="42" count="0" type="cond" truecount="0" falsecount="2"/>
<line num="43" count="0" type="cond" truecount="0" falsecount="2"/> <line num="44" count="0" type="stmt"/>
<line num="46" count="0" type="stmt"/> <line num="46" count="0" type="stmt"/>
<line num="50" count="0" type="stmt"/> <line num="50" count="3" type="stmt"/>
<line num="51" count="0" type="stmt"/> <line num="51" count="0" type="stmt"/>
<line num="55" count="3" type="stmt"/> <line num="54" count="3" type="stmt"/>
<line num="56" count="0" type="stmt"/> <line num="55" count="0" type="stmt"/>
<line num="59" count="3" type="stmt"/>
<line num="60" count="0" type="stmt"/>
</file> </file>
<file name="traversal.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\traversal.ts"> <file name="traversal.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\dom\traversal.ts">
<metrics statements="29" coveredstatements="29" conditionals="25" coveredconditionals="25" methods="9" coveredmethods="9"/> <metrics statements="26" coveredstatements="26" conditionals="25" coveredconditionals="25" methods="9" coveredmethods="9"/>
<line num="3" count="4" type="stmt"/> <line num="3" count="4" type="cond" truecount="3" falsecount="0"/>
<line num="4" count="4" type="cond" truecount="3" falsecount="0"/> <line num="5" count="4" type="stmt"/>
<line num="7" count="4" type="stmt"/> <line num="6" count="6" type="stmt"/>
<line num="8" count="6" type="stmt"/> <line num="8" count="6" type="cond" truecount="2" falsecount="0"/>
<line num="10" count="6" type="cond" truecount="2" falsecount="0"/> <line num="9" count="18" type="stmt"/>
<line num="11" count="18" type="stmt"/> <line num="12" count="6" type="stmt"/>
<line num="14" count="6" type="stmt"/> <line num="15" count="19" type="cond" truecount="2" falsecount="0"/>
<line num="17" count="4" type="stmt"/> <line num="17" count="4" type="stmt"/>
<line num="18" count="19" type="cond" truecount="2" falsecount="0"/> <line num="18" count="31" type="cond" truecount="2" falsecount="0"/>
<line num="21" count="4" type="stmt"/> <line num="19" count="22" type="cond" truecount="2" falsecount="0"/>
<line num="22" count="31" type="cond" truecount="2" falsecount="0"/> <line num="20" count="2" type="stmt"/>
<line num="23" count="22" type="cond" truecount="2" falsecount="0"/> <line num="22" count="20" type="cond" truecount="2" falsecount="0"/>
<line num="24" count="2" type="stmt"/> <line num="23" count="2" type="stmt"/>
<line num="25" count="20" type="cond" truecount="2" falsecount="0"/> <line num="25" count="18" type="cond" truecount="2" falsecount="0"/>
<line num="26" count="2" type="stmt"/> <line num="26" count="6" type="stmt"/>
<line num="27" count="18" type="cond" truecount="2" falsecount="0"/> <line num="29" count="21" type="stmt"/>
<line num="28" count="6" type="stmt"/> <line num="32" count="4" type="stmt"/>
<line num="30" count="21" type="stmt"/> <line num="33" count="3" type="stmt"/>
<line num="33" count="4" type="stmt"/> <line num="35" count="3" type="cond" truecount="2" falsecount="0"/>
<line num="34" count="3" type="stmt"/> <line num="36" count="6" type="cond" truecount="2" falsecount="0"/>
<line num="36" count="3" type="cond" truecount="2" falsecount="0"/> <line num="37" count="3" type="cond" truecount="2" falsecount="0"/>
<line num="37" count="6" type="cond" truecount="2" falsecount="0"/> <line num="38" count="1" type="stmt"/>
<line num="38" count="3" type="cond" truecount="2" falsecount="0"/> <line num="41" count="3" type="stmt"/>
<line num="39" count="1" type="stmt"/>
<line num="42" count="3" type="stmt"/>
<line num="45" count="3" type="stmt"/> <line num="45" count="3" type="stmt"/>
<line num="48" count="4" type="stmt"/> <line num="48" count="38" type="cond" truecount="2" falsecount="0"/>
<line num="49" count="38" type="cond" truecount="2" falsecount="0"/> <line num="50" count="14" type="cond" truecount="2" falsecount="0"/>
<line num="52" count="14" type="cond" truecount="2" falsecount="0"/>
</file> </file>
</package> </package>
<package name="src.core.options"> <package name="src.core.options">
<metrics statements="53" coveredstatements="53" conditionals="39" coveredconditionals="39" methods="10" coveredmethods="10"/> <metrics statements="53" coveredstatements="53" conditionals="39" coveredconditionals="39" methods="10" coveredmethods="10"/>
<file name="index.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\options\index.ts"> <file name="index.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\options\index.ts">
<metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/> <metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/>
</file> </file>
<file name="transformation.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\options\transformation.ts"> <file name="transformation.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\options\transformation.ts">
<metrics statements="6" coveredstatements="6" conditionals="3" coveredconditionals="3" methods="2" coveredmethods="2"/> <metrics statements="6" coveredstatements="6" conditionals="3" coveredconditionals="3" methods="2" coveredmethods="2"/>
<line num="13" count="16" type="stmt"/> <line num="19" count="16" type="stmt"/>
<line num="15" count="16" type="stmt"/> <line num="21" count="16" type="stmt"/>
<line num="16" count="102" type="stmt"/> <line num="22" count="102" type="stmt"/>
<line num="19" count="102" type="cond" truecount="1" falsecount="0"/> <line num="25" count="102" type="cond" truecount="1" falsecount="0"/>
<line num="20" count="90" type="cond" truecount="2" falsecount="0"/> <line num="26" count="90" type="cond" truecount="2" falsecount="0"/>
<line num="25" count="16" type="stmt"/> <line num="32" count="16" type="stmt"/>
</file> </file>
<file name="validation.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\options\validation.ts"> <file name="validation.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\options\validation.ts">
<metrics statements="47" coveredstatements="47" conditionals="36" coveredconditionals="36" methods="8" coveredmethods="8"/> <metrics statements="47" coveredstatements="47" conditionals="36" coveredconditionals="36" methods="8" coveredmethods="8"/>
<line num="5" count="3" type="stmt"/> <line num="13" count="3" type="stmt"/>
<line num="10" count="3" type="stmt"/> <line num="18" count="3" type="stmt"/>
<line num="16" count="3" type="stmt"/> <line num="24" count="3" type="stmt"/>
<line num="25" count="21" type="stmt"/>
<line num="26" count="21" type="stmt"/> <line num="26" count="21" type="stmt"/>
<line num="47" count="3" type="stmt"/> <line num="27" count="21" type="stmt"/>
<line num="48" count="65" type="stmt"/> <line num="50" count="3" type="stmt"/>
<line num="49" count="65" type="stmt"/> <line num="57" count="65" type="stmt"/>
<line num="50" count="372" type="stmt"/> <line num="58" count="65" type="stmt"/>
<line num="52" count="65" type="stmt"/> <line num="59" count="372" type="stmt"/>
<line num="53" count="372" type="cond" truecount="2" falsecount="0"/> <line num="61" count="65" type="stmt"/>
<line num="54" count="372" type="stmt"/> <line num="62" count="372" type="cond" truecount="2" falsecount="0"/>
<line num="55" count="372" type="stmt"/> <line num="63" count="372" type="stmt"/>
<line num="56" count="372" type="stmt"/> <line num="64" count="372" type="stmt"/>
<line num="57" count="372" type="cond" truecount="2" falsecount="0"/> <line num="65" count="372" type="stmt"/>
<line num="60" count="372" type="cond" truecount="4" falsecount="0"/> <line num="66" count="372" type="cond" truecount="2" falsecount="0"/>
<line num="61" count="33" type="stmt"/> <line num="69" count="372" type="cond" truecount="4" falsecount="0"/>
<line num="62" count="33" type="stmt"/> <line num="70" count="33" type="stmt"/>
<line num="63" count="33" type="stmt"/> <line num="71" count="33" type="stmt"/>
<line num="65" count="33" type="stmt"/> <line num="72" count="33" type="stmt"/>
<line num="66" count="66" type="cond" truecount="2" falsecount="0"/> <line num="74" count="33" type="stmt"/>
<line num="67" count="33" type="stmt"/> <line num="75" count="66" type="cond" truecount="2" falsecount="0"/>
<line num="71" count="339" type="cond" truecount="2" falsecount="0"/> <line num="76" count="33" type="stmt"/>
<line num="72" count="336" type="stmt"/> <line num="79" count="339" type="cond" truecount="2" falsecount="0"/>
<line num="73" count="336" type="stmt"/> <line num="80" count="336" type="stmt"/>
<line num="74" count="336" type="stmt"/> <line num="81" count="336" type="stmt"/>
<line num="75" count="336" type="stmt"/> <line num="82" count="336" type="stmt"/>
<line num="76" count="336" type="cond" truecount="2" falsecount="0"/> <line num="83" count="336" type="stmt"/>
<line num="78" count="336" type="stmt"/> <line num="84" count="336" type="cond" truecount="2" falsecount="0"/>
<line num="80" count="417" type="stmt"/> <line num="88" count="336" type="stmt"/>
<line num="81" count="417" type="cond" truecount="4" falsecount="0"/> <line num="90" count="417" type="stmt"/>
<line num="83" count="64" type="stmt"/> <line num="91" count="417" type="cond" truecount="4" falsecount="0"/>
<line num="84" count="121" type="stmt"/> <line num="93" count="64" type="stmt"/>
<line num="87" count="64" type="stmt"/> <line num="94" count="121" type="stmt"/>
<line num="90" count="353" type="stmt"/> <line num="97" count="64" type="stmt"/>
<line num="94" count="417" type="cond" truecount="2" falsecount="0"/> <line num="99" count="353" type="stmt"/>
<line num="97" count="417" type="stmt"/> <line num="103" count="417" type="cond" truecount="2" falsecount="0"/>
<line num="101" count="336" type="cond" truecount="2" falsecount="0"/> <line num="106" count="417" type="stmt"/>
<line num="102" count="310" type="cond" truecount="2" falsecount="0"/> <line num="109" count="336" type="cond" truecount="2" falsecount="0"/>
<line num="103" count="310" type="cond" truecount="4" falsecount="0"/> <line num="110" count="310" type="cond" truecount="2" falsecount="0"/>
<line num="104" count="256" type="stmt"/> <line num="111" count="310" type="cond" truecount="4" falsecount="0"/>
<line num="107" count="26" type="cond" truecount="2" falsecount="0"/> <line num="112" count="256" type="stmt"/>
<line num="108" count="2" type="stmt"/> <line num="114" count="26" type="cond" truecount="2" falsecount="0"/>
<line num="113" count="336" type="stmt"/> <line num="115" count="2" type="stmt"/>
<line num="117" count="65" type="stmt"/> <line num="123" count="336" type="stmt"/>
<line num="140" count="3" type="stmt"/> <line num="127" count="65" type="stmt"/>
<line num="151" count="32" type="cond" truecount="4" falsecount="0"/> <line num="150" count="3" type="stmt"/>
<line num="165" count="32" type="cond" truecount="4" falsecount="0"/>
</file> </file>
</package> </package>
<package name="src.core.utils"> <package name="src.core.utils">
<metrics statements="65" coveredstatements="65" conditionals="71" coveredconditionals="71" methods="17" coveredmethods="17"/> <metrics statements="57" coveredstatements="57" conditionals="69" coveredconditionals="69" methods="18" coveredmethods="18"/>
<file name="arrays.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\utils\arrays.ts"> <file name="arrays.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\utils\arrays.ts">
<metrics statements="12" coveredstatements="12" conditionals="8" coveredconditionals="8" methods="2" coveredmethods="2"/> <metrics statements="8" coveredstatements="8" conditionals="6" coveredconditionals="6" methods="3" coveredmethods="3"/>
<line num="19" count="694" type="stmt"/> <line num="33" count="699" type="cond" truecount="2" falsecount="0"/>
<line num="21" count="694" type="cond" truecount="2" falsecount="0"/> <line num="34" count="693" type="stmt"/>
<line num="22" count="688" type="stmt"/> <line num="35" count="2224" type="cond" truecount="2" falsecount="0"/>
<line num="23" count="2211" type="cond" truecount="2" falsecount="0"/> <line num="36" count="321" type="stmt"/>
<line num="24" count="320" type="stmt"/> <line num="39" count="6" type="cond" truecount="2" falsecount="0"/>
<line num="27" count="6" type="cond" truecount="2" falsecount="0"/> <line num="40" count="13" type="stmt"/>
<line num="28" count="5" type="stmt"/> <line num="42" count="699" type="stmt"/>
<line num="29" count="13" type="cond" truecount="2" falsecount="0"/> <line num="51" count="418" type="stmt"/>
<line num="30" count="1" type="stmt"/>
<line num="33" count="694" type="stmt"/>
<line num="42" count="9" type="stmt"/>
<line num="43" count="418" type="stmt"/>
</file> </file>
<file name="extend.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\utils\extend.ts"> <file name="extend.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\utils\extend.ts">
<metrics statements="21" coveredstatements="21" conditionals="26" coveredconditionals="26" methods="2" coveredmethods="2"/> <metrics statements="21" coveredstatements="21" conditionals="26" coveredconditionals="26" methods="2" coveredmethods="2"/>
<line num="11" count="180" type="stmt"/> <line num="20" count="180" type="stmt"/>
<line num="14" count="180" type="cond" truecount="5" falsecount="0"/> <line num="23" count="180" type="cond" truecount="5" falsecount="0"/>
<line num="15" count="3" type="stmt"/> <line num="24" count="3" type="stmt"/>
<line num="18" count="180" type="stmt"/> <line num="27" count="180" type="stmt"/>
<line num="20" count="1080" type="cond" truecount="2" falsecount="0"/> <line num="29" count="1080" type="cond" truecount="2" falsecount="0"/>
<line num="23" count="217" type="stmt"/> <line num="31" count="217" type="stmt"/>
<line num="24" count="632" type="stmt"/> <line num="32" count="632" type="stmt"/>
<line num="28" count="632" type="cond" truecount="4" falsecount="0"/> <line num="36" count="632" type="cond" truecount="4" falsecount="0"/>
<line num="29" count="1" type="stmt"/> <line num="37" count="1" type="stmt"/>
<line num="32" count="631" type="stmt"/> <line num="40" count="631" type="stmt"/>
<line num="35" count="631" type="cond" truecount="5" falsecount="0"/> <line num="43" count="631" type="cond" truecount="5" falsecount="0"/>
<line num="36" count="126" type="stmt"/> <line num="44" count="126" type="stmt"/>
<line num="37" count="126" type="stmt"/> <line num="45" count="126" type="stmt"/>
<line num="40" count="126" type="cond" truecount="4" falsecount="0"/> <line num="48" count="126" type="cond" truecount="4" falsecount="0"/>
<line num="41" count="33" type="stmt"/> <line num="49" count="33" type="stmt"/>
<line num="42" count="93" type="cond" truecount="4" falsecount="0"/> <line num="50" count="93" type="cond" truecount="4" falsecount="0"/>
<line num="43" count="76" type="stmt"/> <line num="51" count="76" type="stmt"/>
<line num="47" count="126" type="stmt"/> <line num="55" count="126" type="stmt"/>
<line num="50" count="505" type="cond" truecount="2" falsecount="0"/> <line num="58" count="505" type="cond" truecount="2" falsecount="0"/>
<line num="51" count="504" type="stmt"/> <line num="59" count="504" type="stmt"/>
<line num="58" count="180" type="stmt"/> <line num="66" count="180" type="stmt"/>
</file> </file>
<file name="index.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\utils\index.ts"> <file name="index.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\utils\index.ts">
<metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/> <metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/>
</file> </file>
<file name="types.ts" path="C:\Git\OverlayScrollbars\packages\overlayscrollbars\src\core\utils\types.ts"> <file name="types.ts" path="D:\Github\OverlayScrollbars\packages\overlayscrollbars\src\core\utils\types.ts">
<metrics statements="32" coveredstatements="32" conditionals="37" coveredconditionals="37" methods="13" coveredmethods="13"/> <metrics statements="28" coveredstatements="28" conditionals="37" coveredconditionals="37" methods="13" coveredmethods="13"/>
<line num="3" count="11" type="stmt"/> <line num="3" count="11" type="stmt"/>
<line num="4" count="576" type="cond" truecount="2" falsecount="0"/> <line num="4" count="576" type="cond" truecount="2" falsecount="0"/>
<line num="5" count="1" type="stmt"/> <line num="5" count="575" type="cond" truecount="2" falsecount="0"/>
<line num="6" count="575" type="cond" truecount="2" falsecount="0"/> <line num="6" count="527" type="stmt"/>
<line num="7" count="48" type="stmt"/> <line num="13" count="97" type="stmt"/>
<line num="8" count="527" type="stmt"/> <line num="17" count="114" type="stmt"/>
<line num="12" count="97" type="stmt"/> <line num="21" count="28" type="stmt"/>
<line num="16" count="114" type="stmt"/> <line num="25" count="464" type="stmt"/>
<line num="20" count="28" type="stmt"/> <line num="29" count="611" type="stmt"/>
<line num="24" count="1605" type="cond" truecount="3" falsecount="0"/> <line num="33" count="500" type="stmt"/>
<line num="28" count="464" type="stmt"/> <line num="37" count="2671" type="stmt"/>
<line num="32" count="611" type="stmt"/> <line num="41" count="1605" type="cond" truecount="3" falsecount="0"/>
<line num="36" count="500" type="stmt"/> <line num="49" count="766" type="cond" truecount="2" falsecount="0"/>
<line num="40" count="2666" type="stmt"/> <line num="50" count="766" type="cond" truecount="5" falsecount="0"/>
<line num="49" count="761" type="cond" truecount="2" falsecount="0"/>
<line num="50" count="761" type="cond" truecount="5" falsecount="0"/>
<line num="58" count="1337" type="cond" truecount="5" falsecount="0"/> <line num="58" count="1337" type="cond" truecount="5" falsecount="0"/>
<line num="59" count="1123" type="stmt"/> <line num="61" count="214" type="stmt"/>
<line num="62" count="214" type="stmt"/> <line num="62" count="214" type="stmt"/>
<line num="63" count="214" type="stmt"/> <line num="63" count="214" type="stmt"/>
<line num="64" count="214" type="stmt"/> <line num="64" count="214" type="cond" truecount="3" falsecount="0"/>
<line num="65" count="214" type="cond" truecount="3" falsecount="0"/> <line num="66" count="214" type="cond" truecount="5" falsecount="0"/>
<line num="67" count="214" type="cond" truecount="5" falsecount="0"/> <line num="67" count="3" type="stmt"/>
<line num="68" count="3" type="stmt"/>
<line num="71" count="211" type="stmt"/> <line num="71" count="211" type="stmt"/>
<line num="73" count="211" type="cond" truecount="2" falsecount="0"/> <line num="76" count="211" type="cond" truecount="2" falsecount="0"/>
<line num="81" count="358" type="stmt"/> <line num="84" count="358" type="stmt"/>
<line num="82" count="358" type="cond" truecount="2" falsecount="0"/> <line num="85" count="358" type="cond" truecount="2" falsecount="0"/>
<line num="83" count="358" type="stmt"/> <line num="86" count="358" type="cond" truecount="6" falsecount="0"/>
<line num="93" count="105" type="stmt"/> <line num="95" count="105" type="stmt"/>
<line num="94" count="42" type="stmt"/> <line num="96" count="63" type="stmt"/>
<line num="95" count="63" type="stmt"/>
</file> </file>
</package> </package>
</project> </project>
File diff suppressed because one or more lines are too long
+19 -19
View File
@@ -23,30 +23,30 @@
<div class='clearfix'> <div class='clearfix'>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">94.91% </span> <span class="strong">94.89% </span>
<span class="quiet">Statements</span> <span class="quiet">Statements</span>
<span class='fraction'>317/334</span> <span class='fraction'>316/333</span>
</div> </div>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">94.12% </span> <span class="strong">94.06% </span>
<span class="quiet">Branches</span> <span class="quiet">Branches</span>
<span class='fraction'>192/204</span> <span class='fraction'>190/202</span>
</div> </div>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">91.14% </span> <span class="strong">90.12% </span>
<span class="quiet">Functions</span> <span class="quiet">Functions</span>
<span class='fraction'>72/79</span> <span class='fraction'>73/81</span>
</div> </div>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">94.75% </span> <span class="strong">95.16% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>307/324</span> <span class='fraction'>295/310</span>
</div> </div>
@@ -84,7 +84,7 @@
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="6" class="abs high">6/6</td> <td data-value="6" class="abs high">6/6</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="33" class="abs high">33/33</td> <td data-value="32" class="abs high">32/32</td>
</tr> </tr>
<tr> <tr>
@@ -99,7 +99,7 @@
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="10" class="abs high">10/10</td> <td data-value="10" class="abs high">10/10</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="49" class="abs high">49/49</td> <td data-value="47" class="abs high">47/47</td>
</tr> </tr>
<tr> <tr>
@@ -111,10 +111,10 @@
<td data-value="131" class="abs high">114/131</td> <td data-value="131" class="abs high">114/131</td>
<td data-value="84.81" class="pct high">84.81%</td> <td data-value="84.81" class="pct high">84.81%</td>
<td data-value="79" class="abs high">67/79</td> <td data-value="79" class="abs high">67/79</td>
<td data-value="80.56" class="pct high">80.56%</td> <td data-value="78.38" class="pct medium">78.38%</td>
<td data-value="36" class="abs high">29/36</td> <td data-value="37" class="abs medium">29/37</td>
<td data-value="86.29" class="pct high">86.29%</td> <td data-value="87.6" class="pct high">87.6%</td>
<td data-value="124" class="abs high">107/124</td> <td data-value="121" class="abs high">106/121</td>
</tr> </tr>
<tr> <tr>
@@ -138,13 +138,13 @@
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div> <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
</td> </td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="65" class="abs high">65/65</td> <td data-value="64" class="abs high">64/64</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="71" class="abs high">71/71</td> <td data-value="69" class="abs high">69/69</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="17" class="abs high">17/17</td> <td data-value="18" class="abs high">18/18</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="65" class="abs high">65/65</td> <td data-value="57" class="abs high">57/57</td>
</tr> </tr>
</tbody> </tbody>
@@ -155,7 +155,7 @@
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="prettify.js"></script> <script src="prettify.js"></script>
@@ -46,7 +46,7 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>49/49</span> <span class='fraction'>47/47</span>
</div> </div>
@@ -84,7 +84,7 @@
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="10" class="abs high">10/10</td> <td data-value="10" class="abs high">10/10</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="49" class="abs high">49/49</td> <td data-value="47" class="abs high">47/47</td>
</tr> </tr>
</tbody> </tbody>
@@ -95,7 +95,7 @@
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -46,7 +46,7 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>49/49</span> <span class='fraction'>47/47</span>
</div> </div>
@@ -155,19 +155,14 @@
<a name='L96'></a><a href='#L96'>96</a> <a name='L96'></a><a href='#L96'>96</a>
<a name='L97'></a><a href='#L97'>97</a> <a name='L97'></a><a href='#L97'>97</a>
<a name='L98'></a><a href='#L98'>98</a> <a name='L98'></a><a href='#L98'>98</a>
<a name='L99'></a><a href='#L99'>99</a> <a name='L99'></a><a href='#L99'>99</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<a name='L100'></a><a href='#L100'>100</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">20x</span> <span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">10x</span> <span class="cline-any cline-yes">10x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span> <span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span> <span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -184,6 +179,7 @@
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">1x</span> <span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -216,6 +212,7 @@
<span class="cline-any cline-yes">11x</span> <span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">7x</span> <span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span> <span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">7x</span> <span class="cline-any cline-yes">7x</span>
@@ -247,6 +244,7 @@
<span class="cline-any cline-yes">5x</span> <span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">1x</span> <span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">11x</span> <span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-yes">11x</span> <span class="cline-any cline-yes">11x</span>
@@ -258,14 +256,10 @@
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { each } from 'core/utils'; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { each } from 'core/utils';
import { createDiv } from 'core/dom'; import { createDiv } from 'core/dom';
&nbsp; &nbsp;
const firstLetterToUpper: (str: string) =&gt; string = (str) =&gt; { const firstLetterToUpper: (str: string) =&gt; string = (str) =&gt; str.charAt(0).toUpperCase() + str.slice(1);
return str.charAt(0).toUpperCase() + str.slice(1); const getDummyStyle: () =&gt; CSSStyleDeclaration = () =&gt; createDiv().style;
}
const getDummyStyle: () =&gt; CSSStyleDeclaration = () =&gt; {
return createDiv().style;
}
&nbsp; &nbsp;
//https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix // https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix
&nbsp; &nbsp;
export const cssPrefixes: ReadonlyArray&lt;string&gt; = ['-webkit-', '-moz-', '-o-', '-ms-']; export const cssPrefixes: ReadonlyArray&lt;string&gt; = ['-webkit-', '-moz-', '-o-', '-ms-'];
export const jsPrefixes: ReadonlyArray&lt;string&gt; = ['WebKit', 'Moz', 'O', 'MS', 'webkit', 'moz', 'o', 'ms']; export const jsPrefixes: ReadonlyArray&lt;string&gt; = ['WebKit', 'Moz', 'O', 'MS', 'webkit', 'moz', 'o', 'ms'];
@@ -278,82 +272,85 @@ export const cssCache: { [key: string]: string } = {};
* @param name The name of the CSS property which shall be get. * @param name The name of the CSS property which shall be get.
*/ */
export const cssProperty: (name: string) =&gt; string | undefined = (name) =&gt; { export const cssProperty: (name: string) =&gt; string | undefined = (name) =&gt; {
let result: string | undefined = cssCache[name]; let result: string | undefined = cssCache[name];
&nbsp; &nbsp;
if (cssCache.hasOwnProperty(name)) if (cssCache.hasOwnProperty(name)) {
return result;
&nbsp;
const uppercasedName: string = firstLetterToUpper(name);
const elmStyle: CSSStyleDeclaration = getDummyStyle();
&nbsp;
each(cssPrefixes, (prefix: string) =&gt; {
const prefixWithoutDashes: string = prefix.replace(/-/g, '');
const resultPossibilities: Array&lt;string&gt; = [
name, //transition
prefix + name, //-webkit-transition
prefixWithoutDashes + uppercasedName, //webkitTransition
firstLetterToUpper(prefixWithoutDashes) + uppercasedName //WebkitTransition
];
result = resultPossibilities.find((resultPossibility: string) =&gt; elmStyle[resultPossibility] !== undefined);
return !result;
});
&nbsp;
cssCache[name] = result;
return result; return result;
} }
&nbsp;
const uppercasedName: string = firstLetterToUpper(name);
const elmStyle: CSSStyleDeclaration = getDummyStyle();
&nbsp;
each(cssPrefixes, (prefix: string) =&gt; {
const prefixWithoutDashes: string = prefix.replace(/-/g, '');
const resultPossibilities: Array&lt;string&gt; = [
name, // transition
prefix + name, // -webkit-transition
prefixWithoutDashes + uppercasedName, // webkitTransition
firstLetterToUpper(prefixWithoutDashes) + uppercasedName, // WebkitTransition
];
result = resultPossibilities.find((resultPossibility: string) =&gt; elmStyle[resultPossibility] !== undefined);
return !result;
});
&nbsp;
cssCache[name] = result;
return result;
};
&nbsp; &nbsp;
/** /**
* Get the name of the given CSS property value(s), with vendor prefix if it isn't supported wuthout, or undefined if no value is supported. * Get the name of the given CSS property value(s), with vendor prefix if it isn't supported wuthout, or undefined if no value is supported.
* @param property The CSS property to which the CSS property value(s) belong. * @param property The CSS property to which the CSS property value(s) belong.
* @param values The value(s) separated by spaces which shall be get. * @param values The value(s) separated by spaces which shall be get.
* @param suffix A suffix which is added to each value in case the value is a function or something else more advanced. * @param suffix A suffix which is added to each value in case the value is a function or something else more advanced.
*/ */
export const cssPropertyValue: (property: string, values: string, suffix?: string) =&gt; string | undefined = (property, values, suffix) =&gt; { export const cssPropertyValue: (property: string, values: string, suffix?: string) =&gt; string | undefined = (property, values, suffix) =&gt; {
const name: string = property + ' ' + values; const name = `${property} ${values}`;
let result: string | undefined = cssCache[name]; let result: string | undefined = cssCache[name];
&nbsp; &nbsp;
if (cssCache.hasOwnProperty(name)) if (cssCache.hasOwnProperty(name)) {
return result;
&nbsp;
const dummyStyle: CSSStyleDeclaration = getDummyStyle();
const possbleValues: Array&lt;string&gt; = values.split(' ');
const preparedSuffix: string = suffix || '';
const cssPrefixesWithFirstEmpty = [''].concat(cssPrefixes);
&nbsp;
each(possbleValues, (possibleValue: string) =&gt; {
each(cssPrefixesWithFirstEmpty, (prefix: string) =&gt; {
const prop = prefix + possibleValue;
dummyStyle.cssText = property + ':' + prop + preparedSuffix;
if (dummyStyle.length) {
result = prop;
return false;
}
});
return !result;
});
&nbsp;
cssCache[name] = result;
return result; return result;
} }
&nbsp;
const dummyStyle: CSSStyleDeclaration = getDummyStyle();
const possbleValues: Array&lt;string&gt; = values.split(' ');
const preparedSuffix: string = suffix || '';
const cssPrefixesWithFirstEmpty = [''].concat(cssPrefixes);
&nbsp;
each(possbleValues, (possibleValue: string) =&gt; {
each(cssPrefixesWithFirstEmpty, (prefix: string) =&gt; {
const prop = prefix + possibleValue;
dummyStyle.cssText = `${property}:${prop}${preparedSuffix}`;
if (dummyStyle.length) {
result = prop;
return false;
}
});
return !result;
});
&nbsp;
cssCache[name] = result;
return result;
};
&nbsp; &nbsp;
/** /**
* Get the requested JS function, object or constructor with vendor prefix if it isn't supported without or undefined if unsupported. * Get the requested JS function, object or constructor with vendor prefix if it isn't supported without or undefined if unsupported.
* @param name The name of the JS function, object or constructor. * @param name The name of the JS function, object or constructor.
*/ */
export const jsAPI: (name: string) =&gt; any = (name) =&gt; { export const jsAPI: (name: string) =&gt; any = (name) =&gt; {
let result: any = jsCache[name] || window[name]; let result: any = jsCache[name] || window[name];
&nbsp; &nbsp;
if (jsCache.hasOwnProperty(name)) if (jsCache.hasOwnProperty(name)) {
return result;
&nbsp;
each(jsPrefixes, (prefix: string) =&gt; {
result = result || window[prefix + firstLetterToUpper(name)];
return !result;
});
&nbsp;
jsCache[name] = result;
return result; return result;
} }
&nbsp;
each(jsPrefixes, (prefix: string) =&gt; {
result = result || window[prefix + firstLetterToUpper(name)];
return !result;
});
&nbsp;
jsCache[name] = result;
return result;
};
&nbsp;</pre></td></tr></table></pre> &nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
@@ -361,7 +358,7 @@ export const jsAPI: (name: string) =&gt; any = (name) =&gt; {
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -110,7 +110,12 @@
<a name='L51'></a><a href='#L51'>51</a> <a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a> <a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a> <a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span> <a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -120,6 +125,7 @@
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">7x</span> <span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-yes">5x</span> <span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2x</span> <span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -140,6 +146,7 @@
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">2x</span> <span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span> <span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -151,6 +158,7 @@
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">2x</span> <span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span> <span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -162,7 +170,9 @@
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">5x</span> <span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2x</span> <span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/** <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Gets or sets a attribute with the given attribute of the given element depending whether the value attribute is given. * Gets or sets a attribute with the given attribute of the given element depending whether the value attribute is given.
* Returns null if the element has no attribute with the given name. * Returns null if the element has no attribute with the given name.
@@ -171,10 +181,11 @@
* @param value The value of the attribute which shall be set. * @param value The value of the attribute which shall be set.
*/ */
export const attr: (elm: Element, attrName: string, value?: string) =&gt; string | null | void = (elm, attrName, value) =&gt; { export const attr: (elm: Element, attrName: string, value?: string) =&gt; string | null | void = (elm, attrName, value) =&gt; {
if (value === undefined) if (value === undefined) {
return elm.getAttribute(attrName); return elm.getAttribute(attrName);
elm.setAttribute(attrName, value); }
} elm.setAttribute(attrName, value);
};
&nbsp; &nbsp;
/** /**
* Removes the given attribute from the given element. * Removes the given attribute from the given element.
@@ -182,8 +193,8 @@ export const attr: (elm: Element, attrName: string, value?: string) =&gt; string
* @param attrName The attribute name. * @param attrName The attribute name.
*/ */
export const removeAttr: (elm: Element, attrName: string) =&gt; void = (elm, attrName) =&gt; { export const removeAttr: (elm: Element, attrName: string) =&gt; void = (elm, attrName) =&gt; {
elm.removeAttribute(attrName); elm.removeAttribute(attrName);
} };
&nbsp; &nbsp;
/** /**
* Gets or sets the scrollLeft value of the given element depending whether the value attribute is given. * Gets or sets the scrollLeft value of the given element depending whether the value attribute is given.
@@ -191,10 +202,11 @@ export const removeAttr: (elm: Element, attrName: string) =&gt; void = (elm, att
* @param value The scrollLeft value which shall be set. * @param value The scrollLeft value which shall be set.
*/ */
export const scrollLeft: (elm: HTMLElement, value?: number) =&gt; number | void = (elm, value) =&gt; { export const scrollLeft: (elm: HTMLElement, value?: number) =&gt; number | void = (elm, value) =&gt; {
if (value === undefined) if (value === undefined) {
return elm.scrollLeft; return elm.scrollLeft;
elm.scrollLeft = value; }
} elm.scrollLeft = value;
};
&nbsp; &nbsp;
/** /**
* Gets or sets the scrollTop value of the given element depending whether the value attribute is given. * Gets or sets the scrollTop value of the given element depending whether the value attribute is given.
@@ -202,10 +214,11 @@ export const scrollLeft: (elm: HTMLElement, value?: number) =&gt; number | void
* @param value The scrollTop value which shall be set. * @param value The scrollTop value which shall be set.
*/ */
export const scrollTop: (elm: HTMLElement, value?: number) =&gt; number | void = (elm, value) =&gt; { export const scrollTop: (elm: HTMLElement, value?: number) =&gt; number | void = (elm, value) =&gt; {
if (value === undefined) if (value === undefined) {
return elm.scrollTop; return elm.scrollTop;
elm.scrollTop = value; }
} elm.scrollTop = value;
};
&nbsp; &nbsp;
/** /**
* Gets or sets the value of the given input element depending whether the value attribute is given. * Gets or sets the value of the given input element depending whether the value attribute is given.
@@ -213,17 +226,19 @@ export const scrollTop: (elm: HTMLElement, value?: number) =&gt; number | void =
* @param value The value which shall be set. * @param value The value which shall be set.
*/ */
export const val: (elm: HTMLInputElement, value?: string) =&gt; string | void = (elm, value) =&gt; { export const val: (elm: HTMLInputElement, value?: string) =&gt; string | void = (elm, value) =&gt; {
if (value === undefined) if (value === undefined) {
return elm.value; return elm.value;
elm.value = value; }
}</pre></td></tr></table></pre> elm.value = value;
};
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -46,7 +46,7 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>19/19</span> <span class='fraction'>18/18</span>
</div> </div>
@@ -124,7 +124,6 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">7x</span> <span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -132,7 +131,6 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">11x</span> <span class="cline-any cline-yes">11x</span>
@@ -149,6 +147,7 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">7x</span> <span class="cline-any cline-yes">7x</span>
@@ -166,25 +165,24 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">2x</span> <span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2x</span> <span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { isString } from 'core/utils/types'; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { isString } from 'core/utils/types';
&nbsp; &nbsp;
const rnothtmlwhite: RegExp = (/[^\x20\t\r\n\f]+/g); const rnothtmlwhite = /[^\x20\t\r\n\f]+/g;
&nbsp; &nbsp;
/** /**
* Check whether the given element has the given class name. * Check whether the given element has the given class name.
* @param elm The element. * @param elm The element.
* @param className The class name. * @param className The class name.
*/ */
export const hasClass: (elm: Element, className: string) =&gt; boolean = (elm, className) =&gt; { export const hasClass: (elm: Element, className: string) =&gt; boolean = (elm, className) =&gt; elm.classList.contains(className);
return elm.classList.contains(className);
}
&nbsp; &nbsp;
/** /**
* Adds the given class name(s) to the given element. * Adds the given class name(s) to the given element.
@@ -192,15 +190,16 @@ export const hasClass: (elm: Element, className: string) =&gt; boolean = (elm, c
* @param className The class name(s) which shall be added. (separated by spaces) * @param className The class name(s) which shall be added. (separated by spaces)
*/ */
export const addClass: (elm: Element, className: string) =&gt; void = (elm, className) =&gt; { export const addClass: (elm: Element, className: string) =&gt; void = (elm, className) =&gt; {
let clazz: string; let clazz: string;
let i: number = 0; let i = 0;
&nbsp; &nbsp;
if (isString(className)) { if (isString(className)) {
const classes: Array&lt;string&gt; = className.match(rnothtmlwhite) || []; const classes: Array&lt;string&gt; = className.match(rnothtmlwhite) || [];
while ((clazz = classes[i++])) while ((clazz = classes[i++])) {
elm.classList.add(clazz); elm.classList.add(clazz);
} }
} }
};
&nbsp; &nbsp;
/** /**
* Removes the given class name(s) from the given element. * Removes the given class name(s) from the given element.
@@ -208,15 +207,16 @@ export const addClass: (elm: Element, className: string) =&gt; void = (elm, clas
* @param className The class name(s) which shall be removed. (separated by spaces) * @param className The class name(s) which shall be removed. (separated by spaces)
*/ */
export const removeClass: (elm: Element, className: string) =&gt; void = (elm, className) =&gt; { export const removeClass: (elm: Element, className: string) =&gt; void = (elm, className) =&gt; {
let clazz: string; let clazz: string;
let i: number = 0; let i = 0;
&nbsp; &nbsp;
if (isString(className)) { if (isString(className)) {
const classes: Array&lt;string&gt; = className.match(rnothtmlwhite) || []; const classes: Array&lt;string&gt; = className.match(rnothtmlwhite) || [];
while ((clazz = classes[i++])) while ((clazz = classes[i++])) {
elm.classList.remove(clazz); elm.classList.remove(clazz);
} }
} }
};
&nbsp; &nbsp;
/** /**
* Adds or removes the given class name(s) from the given element depending on the given condition. * Adds or removes the given class name(s) from the given element depending on the given condition.
@@ -225,20 +225,20 @@ export const removeClass: (elm: Element, className: string) =&gt; void = (elm, c
* @param className The class name(s) which shall be added or removed. (separated by spaces) * @param className The class name(s) which shall be added or removed. (separated by spaces)
*/ */
export const conditionalClass: (elm: Element, className: string, condition: boolean) =&gt; void = (elm, className, condition) =&gt; { export const conditionalClass: (elm: Element, className: string, condition: boolean) =&gt; void = (elm, className, condition) =&gt; {
if (condition) { if (condition) {
addClass(elm, className); addClass(elm, className);
} } else {
else { removeClass(elm, className);
removeClass(elm, className); }
} };
}</pre></td></tr></table></pre> &nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -46,7 +46,7 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>6/6</span> <span class='fraction'>5/5</span>
</div> </div>
@@ -69,41 +69,38 @@
<a name='L10'></a><a href='#L10'>10</a> <a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a> <a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a> <a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a> <a name='L13'></a><a href='#L13'>13</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<a name='L14'></a><a href='#L14'>14</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">204x</span> <span class="cline-any cline-yes">204x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">9x</span> <span class="cline-any cline-yes">9x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { each } from 'core/utils/arrays'; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { each } from 'core/utils/arrays';
import { contents } from 'core/dom/traversal'; import { contents } from 'core/dom/traversal';
import { removeElements } from 'core/dom/manipulation'; import { removeElements } from 'core/dom/manipulation';
&nbsp; &nbsp;
export const createDiv: () =&gt; HTMLDivElement = () =&gt; { export const createDiv: () =&gt; HTMLDivElement = () =&gt; document.createElement('div');
return document.createElement('div');
}
&nbsp; &nbsp;
export const createDOM: (html: string) =&gt; ReadonlyArray&lt;Node&gt; = (html) =&gt; { export const createDOM: (html: string) =&gt; ReadonlyArray&lt;Node&gt; = (html) =&gt; {
const elm = createDiv(); const createdDiv = createDiv();
elm.innerHTML = html.trim(); createdDiv.innerHTML = html.trim();
&nbsp; &nbsp;
return each(contents(elm), (elm) =&gt; removeElements(elm)); return each(contents(createdDiv), (elm) =&gt; removeElements(elm));
}</pre></td></tr></table></pre> };
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
+14 -14
View File
@@ -37,16 +37,16 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">80.56% </span> <span class="strong">78.38% </span>
<span class="quiet">Functions</span> <span class="quiet">Functions</span>
<span class='fraction'>29/36</span> <span class='fraction'>29/37</span>
</div> </div>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">86.29% </span> <span class="strong">87.6% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>107/124</span> <span class='fraction'>106/121</span>
</div> </div>
@@ -99,7 +99,7 @@
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="4" class="abs high">4/4</td> <td data-value="4" class="abs high">4/4</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="19" class="abs high">19/19</td> <td data-value="18" class="abs high">18/18</td>
</tr> </tr>
<tr> <tr>
@@ -114,7 +114,7 @@
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="3" class="abs high">3/3</td> <td data-value="3" class="abs high">3/3</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="6" class="abs high">6/6</td> <td data-value="5" class="abs high">5/5</td>
</tr> </tr>
<tr> <tr>
@@ -144,7 +144,7 @@
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="8" class="abs high">8/8</td> <td data-value="8" class="abs high">8/8</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="28" class="abs high">28/28</td> <td data-value="32" class="abs high">32/32</td>
</tr> </tr>
<tr> <tr>
@@ -158,8 +158,8 @@
<td data-value="0" class="abs high">0/0</td> <td data-value="0" class="abs high">0/0</td>
<td data-value="0" class="pct low">0%</td> <td data-value="0" class="pct low">0%</td>
<td data-value="2" class="abs low">0/2</td> <td data-value="2" class="abs low">0/2</td>
<td data-value="40" class="pct low">40%</td> <td data-value="50" class="pct medium">50%</td>
<td data-value="5" class="abs low">2/5</td> <td data-value="4" class="abs medium">2/4</td>
</tr> </tr>
<tr> <tr>
@@ -172,9 +172,9 @@
<td data-value="0" class="pct low">0%</td> <td data-value="0" class="pct low">0%</td>
<td data-value="12" class="abs low">0/12</td> <td data-value="12" class="abs low">0/12</td>
<td data-value="0" class="pct low">0%</td> <td data-value="0" class="pct low">0%</td>
<td data-value="5" class="abs low">0/5</td> <td data-value="6" class="abs low">0/6</td>
<td data-value="26.32" class="pct low">26.32%</td> <td data-value="27.78" class="pct low">27.78%</td>
<td data-value="19" class="abs low">5/19</td> <td data-value="18" class="abs low">5/18</td>
</tr> </tr>
<tr> <tr>
@@ -189,7 +189,7 @@
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="9" class="abs high">9/9</td> <td data-value="9" class="abs high">9/9</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="29" class="abs high">29/29</td> <td data-value="26" class="abs high">26/26</td>
</tr> </tr>
</tbody> </tbody>
@@ -200,7 +200,7 @@
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -63,7 +63,9 @@
<a name='L4'></a><a href='#L4'>4</a> <a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a> <a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a> <a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span> <a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -75,14 +77,15 @@ export * from 'core/dom/create';
export * from 'core/dom/style'; export * from 'core/dom/style';
export * from 'core/dom/manipulation'; export * from 'core/dom/manipulation';
export * from 'core/dom/offset'; export * from 'core/dom/offset';
export * from 'core/dom/traversal';</pre></td></tr></table></pre> export * from 'core/dom/traversal';
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -46,7 +46,7 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>28/28</span> <span class='fraction'>32/32</span>
</div> </div>
@@ -147,7 +147,18 @@
<a name='L88'></a><a href='#L88'>88</a> <a name='L88'></a><a href='#L88'>88</a>
<a name='L89'></a><a href='#L89'>89</a> <a name='L89'></a><a href='#L89'>89</a>
<a name='L90'></a><a href='#L90'>90</a> <a name='L90'></a><a href='#L90'>90</a>
<a name='L91'></a><a href='#L91'>91</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span> <a name='L91'></a><a href='#L91'>91</a>
<a name='L92'></a><a href='#L92'>92</a>
<a name='L93'></a><a href='#L93'>93</a>
<a name='L94'></a><a href='#L94'>94</a>
<a name='L95'></a><a href='#L95'>95</a>
<a name='L96'></a><a href='#L96'>96</a>
<a name='L97'></a><a href='#L97'>97</a>
<a name='L98'></a><a href='#L98'>98</a>
<a name='L99'></a><a href='#L99'>99</a>
<a name='L100'></a><a href='#L100'>100</a>
<a name='L101'></a><a href='#L101'>101</a>
<a name='L102'></a><a href='#L102'>102</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -160,6 +171,10 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">24x</span> <span class="cline-any cline-yes">24x</span>
<span class="cline-any cline-yes">20x</span> <span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -177,7 +192,6 @@
<span class="cline-any cline-yes">24x</span> <span class="cline-any cline-yes">24x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">8x</span> <span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -185,7 +199,6 @@
<span class="cline-any cline-yes">16x</span> <span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-yes">12x</span> <span class="cline-any cline-yes">12x</span>
<span class="cline-any cline-yes">1x</span> <span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">11x</span> <span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-yes">2x</span> <span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -201,6 +214,7 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">6x</span> <span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -208,6 +222,8 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">6x</span> <span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -215,6 +231,8 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">6x</span> <span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -222,22 +240,26 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">6x</span> <span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">23x</span> <span class="cline-any cline-yes">23x</span>
<span class="cline-any cline-yes">9x</span> <span class="cline-any cline-yes">9x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">21x</span> <span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">20x</span> <span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">20x</span> <span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">15x</span> <span class="cline-any cline-yes">15x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { isArrayLike, isHTMLElement } from 'core/utils/types'; <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { isArrayLike } from 'core/utils/types';
import { each } from 'core/utils/arrays'; import { each } from 'core/utils/arrays';
import { parent } from 'core/dom/traversal'; import { parent } from 'core/dom/traversal';
&nbsp; &nbsp;
@@ -245,96 +267,107 @@ type NodeCollection = ArrayLike&lt;Node&gt; | Node | undefined | null;
&nbsp; &nbsp;
/** /**
* Inserts Nodes before the given preferredAnchor element. * Inserts Nodes before the given preferredAnchor element.
* @param parent The parent of the preferredAnchor element or the element which shall be the parent of the inserted Nodes. * @param parentElm The parent of the preferredAnchor element or the element which shall be the parent of the inserted Nodes.
* @param preferredAnchor The element before which the Nodes shall be inserted or null if the elements shall be appended at the end. * @param preferredAnchor The element before which the Nodes shall be inserted or null if the elements shall be appended at the end.
* @param insertedElms The Nodes which shall be inserted. * @param insertedElms The Nodes which shall be inserted.
*/ */
const before: (parent: Node | null, preferredAnchor: Node | null, insertedElms: NodeCollection) =&gt; void = (parent, preferredAnchor, insertedElms) =&gt; { const before: (parentElm: Node | null, preferredAnchor: Node | null, insertedElms: NodeCollection) =&gt; void = (
if (insertedElms) { parentElm,
let anchor: Node | null = preferredAnchor; preferredAnchor,
let fragment: DocumentFragment | Node | undefined | null; insertedElms,
) =&gt; {
if (insertedElms) {
let anchor: Node | null = preferredAnchor;
let fragment: DocumentFragment | Node | undefined | null;
&nbsp; &nbsp;
// parent must be defined // parent must be defined
if (parent) { if (parentElm) {
if (isArrayLike(insertedElms)) { if (isArrayLike(insertedElms)) {
fragment = document.createDocumentFragment(); fragment = document.createDocumentFragment();
&nbsp; &nbsp;
// append all insertedElms to the fragment and if one of these is the anchor, change the anchor // append all insertedElms to the fragment and if one of these is the anchor, change the anchor
each(insertedElms, (insertedElm) =&gt; { each(insertedElms, (insertedElm) =&gt; {
if (insertedElm === anchor) { if (insertedElm === anchor) {
anchor = insertedElm.previousSibling; anchor = insertedElm.previousSibling;
} }
fragment!.appendChild(insertedElm); fragment!.appendChild(insertedElm);
}); });
} } else {
else { fragment = insertedElms;
fragment = insertedElms; }
}
&nbsp; &nbsp;
// if the preferred anchor isn't null set it to a valid anchor // if the preferred anchor isn't null set it to a valid anchor
if (preferredAnchor) { if (preferredAnchor) {
if (!anchor) { if (!anchor) {
anchor = parent.firstChild; anchor = parentElm.firstChild;
} } else if (anchor !== preferredAnchor) {
else if (anchor !== preferredAnchor) { anchor = anchor.nextSibling;
anchor = anchor.nextSibling;
}
}
&nbsp;
parent.insertBefore(fragment, anchor);
} }
}
&nbsp;
parentElm.insertBefore(fragment, anchor);
} }
} }
};
&nbsp; &nbsp;
/** /**
* Appends the given children at the end of the given Node. * Appends the given children at the end of the given Node.
* @param node The Node to which the children shall be appended. * @param node The Node to which the children shall be appended.
* @param children The Nodes which shall be appended. * @param children The Nodes which shall be appended.
*/ */
export const appendChildren: (node: Node | null, children: NodeCollection) =&gt; void = (node, children) =&gt; { before(node, null, children) }; export const appendChildren: (node: Node | null, children: NodeCollection) =&gt; void = (node, children) =&gt; {
before(node, null, children);
};
&nbsp; &nbsp;
/** /**
* Prepends the given children at the start of the given Node. * Prepends the given children at the start of the given Node.
* @param node The Node to which the children shall be prepended. * @param node The Node to which the children shall be prepended.
* @param children The Nodes which shall be prepended. * @param children The Nodes which shall be prepended.
*/ */
export const prependChildren: (node: Node | null, children: NodeCollection) =&gt; void = (node, children) =&gt; { before(node, node &amp;&amp; node.firstChild, children) }; export const prependChildren: (node: Node | null, children: NodeCollection) =&gt; void = (node, children) =&gt; {
before(node, node &amp;&amp; node.firstChild, children);
};
&nbsp; &nbsp;
/** /**
* Inserts the given Nodes before the given Node. * Inserts the given Nodes before the given Node.
* @param node The Node before which the given Nodes shall be inserted. * @param node The Node before which the given Nodes shall be inserted.
* @param insertedNodes The Nodes which shall be inserted. * @param insertedNodes The Nodes which shall be inserted.
*/ */
export const insertBefore: (node: Node | null, insertedNodes: NodeCollection) =&gt; void = (node, insertedNodes) =&gt; { before(parent(node), node, insertedNodes) }; export const insertBefore: (node: Node | null, insertedNodes: NodeCollection) =&gt; void = (node, insertedNodes) =&gt; {
before(parent(node), node, insertedNodes);
};
&nbsp; &nbsp;
/** /**
* Inserts the given Nodes after the given Node. * Inserts the given Nodes after the given Node.
* @param node The Node after which the given Nodes shall be inserted. * @param node The Node after which the given Nodes shall be inserted.
* @param insertedNodes The Nodes which shall be inserted. * @param insertedNodes The Nodes which shall be inserted.
*/ */
export const insertAfter: (node: Node | null, insertedNodes: NodeCollection) =&gt; void = (node, insertedNodes) =&gt; { before(parent(node), node &amp;&amp; node.nextSibling, insertedNodes) }; export const insertAfter: (node: Node | null, insertedNodes: NodeCollection) =&gt; void = (node, insertedNodes) =&gt; {
before(parent(node), node &amp;&amp; node.nextSibling, insertedNodes);
};
&nbsp; &nbsp;
/** /**
* Removes the given Nodes from their parent. * Removes the given Nodes from their parent.
* @param nodes The Nodes which shall be removed. * @param nodes The Nodes which shall be removed.
*/ */
export const removeElements: (nodes: NodeCollection) =&gt; void = (nodes) =&gt; { export const removeElements: (nodes: NodeCollection) =&gt; void = (nodes) =&gt; {
if (isArrayLike(nodes)) { if (isArrayLike(nodes)) {
each(Array.from(nodes), (e) =&gt; removeElements(e)); each(Array.from(nodes), (e) =&gt; removeElements(e));
} else if (nodes) {
const { parentNode } = nodes;
if (parentNode) {
parentNode.removeChild(nodes);
} }
else if (nodes) { }
const parentNode = nodes.parentNode; };
if (parentNode) &nbsp;</pre></td></tr></table></pre>
parentNode.removeChild(nodes);
}
}</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -44,9 +44,9 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">40% </span> <span class="strong">50% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>2/5</span> <span class='fraction'>2/4</span>
</div> </div>
@@ -69,8 +69,7 @@
<a name='L10'></a><a href='#L10'>10</a> <a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a> <a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a> <a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a> <a name='L13'></a><a href='#L13'>13</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">3x</span>
<a name='L14'></a><a href='#L14'>14</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-no">&nbsp;</span> <span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span> <span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -79,31 +78,29 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">export const offset = <span class="fstat-no" title="function not covered" >(e</span>lm: HTMLElement) =&gt; { <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">export const offset = <span class="fstat-no" title="function not covered" >(e</span>lm: HTMLElement) =&gt; {
const rect = <span class="cstat-no" title="statement not covered" >elm.getBoundingClientRect();</span> const rect = <span class="cstat-no" title="statement not covered" >elm.getBoundingClientRect();</span>
<span class="cstat-no" title="statement not covered" > return {</span> <span class="cstat-no" title="statement not covered" > return {</span>
top: rect.top + window.pageXOffset, top: rect.top + window.pageXOffset,
left: rect.left + window.pageYOffset left: rect.left + window.pageYOffset,
}; };
} };
&nbsp; &nbsp;
export const position = <span class="fstat-no" title="function not covered" >(e</span>lm: HTMLElement) =&gt; { export const position = <span class="fstat-no" title="function not covered" >(e</span>lm: HTMLElement) =&gt; (<span class="cstat-no" title="statement not covered" >{</span>
<span class="cstat-no" title="statement not covered" > return {</span> top: elm.offsetTop,
top: elm.offsetTop, left: elm.offsetLeft,
left: elm.offsetLeft });
}; &nbsp;</pre></td></tr></table></pre>
}</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
+45 -63
View File
@@ -39,14 +39,14 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">0% </span> <span class="strong">0% </span>
<span class="quiet">Functions</span> <span class="quiet">Functions</span>
<span class='fraction'>0/5</span> <span class='fraction'>0/6</span>
</div> </div>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">26.32% </span> <span class="strong">27.78% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>5/19</span> <span class='fraction'>5/18</span>
</div> </div>
@@ -113,13 +113,7 @@
<a name='L54'></a><a href='#L54'>54</a> <a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a> <a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a> <a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a> <a name='L57'></a><a href='#L57'>57</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -141,14 +135,13 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-no">&nbsp;</span> <span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-no">&nbsp;</span> <span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -163,12 +156,8 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span> <span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span> <span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span> <span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -180,69 +169,62 @@
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-no">&nbsp;</span> <span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { isString, isNumber, isUndefined } from 'core/utils/types'; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { isString, isNumber, isUndefined } from 'core/utils/types';
&nbsp; &nbsp;
type cssStyleObj = { [key: string]: string | number }; type cssStyleObj = { [key: string]: string | number };
&nbsp; &nbsp;
const cssNumber = { const cssNumber = {
animationIterationCount: true, animationIterationCount: true,
columnCount: true, columnCount: true,
fillOpacity: true, fillOpacity: true,
flexGrow: true, flexGrow: true,
flexShrink: true, flexShrink: true,
fontWeight: true, fontWeight: true,
lineHeight: true, lineHeight: true,
opacity: true, opacity: true,
order: true, order: true,
orphans: true, orphans: true,
widows: true, widows: true,
zIndex: true, zIndex: true,
zoom: true zoom: true,
}; };
&nbsp; &nbsp;
const setCSSVal: (elm: HTMLElement, prop: string, val: string | number) =&gt; void = <span class="fstat-no" title="function not covered" >(e</span>lm, prop, val) =&gt; { const parseCSSVal: (prop: string, val: string | number) =&gt; string | number = <span class="fstat-no" title="function not covered" >(p</span>rop, val) =&gt;
<span class="cstat-no" title="statement not covered" > try {</span> <span class="cstat-no" title="statement not covered" > !cssNumber[prop.toLowerCase()] &amp;&amp; isNumber(val) ? `${val}px` : val;</span>
<span class="cstat-no" title="statement not covered" > if (elm.style[prop] !== undefined) {</span>
<span class="cstat-no" title="statement not covered" > elm.style[prop] = parseCSSVal(prop, val);</span>
}
} catch (e) { }
}
&nbsp; &nbsp;
const parseCSSVal: (prop: string, val: string | number) =&gt; string | number = <span class="fstat-no" title="function not covered" >(p</span>rop, val) =&gt; { const setCSSVal: (elm: HTMLElement, prop: string, val: string | number) =&gt; void = <span class="fstat-no" title="function not covered" >(e</span>lm, prop, val) =&gt; {
<span class="cstat-no" title="statement not covered" > return !cssNumber[prop.toLowerCase()] &amp;&amp; isNumber(val) ? val + 'px' : val;</span> <span class="cstat-no" title="statement not covered" > try {</span>
} <span class="cstat-no" title="statement not covered" > if (elm.style[prop] !== undefined) {</span>
<span class="cstat-no" title="statement not covered" > elm.style[prop] = parseCSSVal(prop, val);</span>
}
} catch (e) {}
};
&nbsp; &nbsp;
export function style(elm: HTMLElement, styles: string | cssStyleObj): string; export function style(elm: HTMLElement, styles: string | cssStyleObj): string;
export function style(elm: HTMLElement, styles: string | cssStyleObj, val: string | number): void; export function style(elm: HTMLElement, styles: string | cssStyleObj, val: string | number): void;
export function <span class="fstat-no" title="function not covered" >style(</span>elm: HTMLElement, styles: string | cssStyleObj, val?: string | number): string | void { export function <span class="fstat-no" title="function not covered" >style(</span>elm: HTMLElement, styles: string | cssStyleObj, val?: string | number): string | void {
const getCptStyle: Function = <span class="cstat-no" title="statement not covered" >window.getComputedStyle;</span> const getCptStyle = <span class="cstat-no" title="statement not covered" >window.getComputedStyle;</span>
&nbsp; &nbsp;
<span class="cstat-no" title="statement not covered" > if (isString(styles)) {</span> <span class="cstat-no" title="statement not covered" > if (isString(styles)) {</span>
<span class="cstat-no" title="statement not covered" > if (isUndefined(val)) {</span> <span class="cstat-no" title="statement not covered" > if (isUndefined(val)) {</span>
const cptStyle: CSSStyleDeclaration = <span class="cstat-no" title="statement not covered" >getCptStyle(elm, null);</span> const cptStyle: CSSStyleDeclaration = <span class="cstat-no" title="statement not covered" >getCptStyle(elm, null);</span>
&nbsp; &nbsp;
//https://bugzilla.mozilla.org/show_bug.cgi?id=548397 can be null sometimes if iframe with display: none (firefox only!) // https://bugzilla.mozilla.org/show_bug.cgi?id=548397 can be null sometimes if iframe with display: none (firefox only!)
<span class="cstat-no" title="statement not covered" > return cptStyle != null ? cptStyle.getPropertyValue(styles) : elm.style[styles];</span> <span class="cstat-no" title="statement not covered" > return cptStyle != null ? cptStyle.getPropertyValue(styles) : elm.style[styles];</span>
}
else {
<span class="cstat-no" title="statement not covered" > setCSSVal(elm, styles, val);</span>
}
}
else {
<span class="cstat-no" title="statement not covered" > for (const key in styles)</span>
<span class="cstat-no" title="statement not covered" > setCSSVal(elm, key, styles[key]);</span>
} }
<span class="cstat-no" title="statement not covered" > setCSSVal(elm, styles, val);</span>
} else {
<span class="cstat-no" title="statement not covered" > Object.keys(styles).forEach(<span class="fstat-no" title="function not covered" >(k</span>ey) =&gt; <span class="cstat-no" title="statement not covered" >setCSSVal(elm, key, styles[key]))</span>;</span>
}
} }
&nbsp; &nbsp;
export const hide: (elm: HTMLElement) =&gt; void = <span class="fstat-no" title="function not covered" >(e</span>lm) =&gt; { export const hide: (elm: HTMLElement) =&gt; void = <span class="fstat-no" title="function not covered" >(e</span>lm) =&gt; {
<span class="cstat-no" title="statement not covered" > elm.style.display = 'none';</span> <span class="cstat-no" title="statement not covered" > elm.style.display = 'none';</span>
} };
&nbsp; &nbsp;
export const show: (elm: HTMLElement) =&gt; void = <span class="fstat-no" title="function not covered" >(e</span>lm) =&gt; { export const show: (elm: HTMLElement) =&gt; void = <span class="fstat-no" title="function not covered" >(e</span>lm) =&gt; {
<span class="cstat-no" title="statement not covered" > elm.style.display = 'block';</span> <span class="cstat-no" title="statement not covered" > elm.style.display = 'block';</span>
} };
&nbsp;
&nbsp;</pre></td></tr></table></pre> &nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
@@ -250,7 +232,7 @@ export const show: (elm: HTMLElement) =&gt; void = <span class="fstat-no" title=
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -46,7 +46,7 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>29/29</span> <span class='fraction'>26/26</span>
</div> </div>
@@ -107,12 +107,9 @@
<a name='L48'></a><a href='#L48'>48</a> <a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a> <a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a> <a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a> <a name='L51'></a><a href='#L51'>51</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<a name='L52'></a><a href='#L52'>52</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">6x</span> <span class="cline-any cline-yes">6x</span>
@@ -124,19 +121,20 @@
<span class="cline-any cline-yes">6x</span> <span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">19x</span> <span class="cline-any cline-yes">19x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span> <span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">31x</span> <span class="cline-any cline-yes">31x</span>
<span class="cline-any cline-yes">22x</span> <span class="cline-any cline-yes">22x</span>
<span class="cline-any cline-yes">2x</span> <span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">20x</span> <span class="cline-any cline-yes">20x</span>
<span class="cline-any cline-yes">2x</span> <span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">18x</span> <span class="cline-any cline-yes">18x</span>
<span class="cline-any cline-yes">6x</span> <span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">21x</span> <span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -152,72 +150,71 @@
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-yes">38x</span> <span class="cline-any cline-yes">38x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">14x</span></td><td class="text"><pre class="prettyprint lang-js">import { each } from 'core/utils/arrays'; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { each } from 'core/utils/arrays';
&nbsp; &nbsp;
const elementIsVisible: (elm: HTMLElement) =&gt; boolean = (elm) =&gt; { const elementIsVisible: (elm: HTMLElement) =&gt; boolean = (elm) =&gt; !!(elm.offsetWidth || elm.offsetHeight || elm.getClientRects().length);
return !!(elm.offsetWidth || elm.offsetHeight || elm.getClientRects().length);
}
&nbsp; &nbsp;
export const find: (selector: string, elm?: Element | null) =&gt; ReadonlyArray&lt;Element&gt; = (selector, elm?) =&gt; { export const find: (selector: string, elm?: Element | null) =&gt; ReadonlyArray&lt;Element&gt; = (selector, elm?) =&gt; {
const arr: Array&lt;Element&gt; = []; const arr: Array&lt;Element&gt; = [];
&nbsp; &nbsp;
each((elm || document).querySelectorAll(selector), (e: Element) =&gt; { each((elm || document).querySelectorAll(selector), (e: Element) =&gt; {
arr.push(e); arr.push(e);
}); });
&nbsp; &nbsp;
return arr; return arr;
} };
&nbsp; &nbsp;
export const findFirst: (selector: string, elm?: Element | null) =&gt; Element | null = (selector, elm?) =&gt; { export const findFirst: (selector: string, elm?: Element | null) =&gt; Element | null = (selector, elm?) =&gt; (elm || document).querySelector(selector);
return (elm || document).querySelector(selector);
}
&nbsp; &nbsp;
export const is: (elm: Element | null, selector: string) =&gt; boolean = (elm, selector) =&gt; { export const is: (elm: Element | null, selector: string) =&gt; boolean = (elm, selector) =&gt; {
if (elm) { if (elm) {
if (selector === ':visible') if (selector === ':visible') {
return elementIsVisible(elm as HTMLElement); return elementIsVisible(elm as HTMLElement);
if (selector === ':hidden')
return !elementIsVisible(elm as HTMLElement);
if (elm.matches(selector))
return true;
} }
return false; if (selector === ':hidden') {
} return !elementIsVisible(elm as HTMLElement);
}
if (elm.matches(selector)) {
return true;
}
}
return false;
};
&nbsp; &nbsp;
export const children: (elm: Element | null, selector?: string) =&gt; ReadonlyArray&lt;Element&gt; = (elm, selector?) =&gt; { export const children: (elm: Element | null, selector?: string) =&gt; ReadonlyArray&lt;Element&gt; = (elm, selector?) =&gt; {
const children: Array&lt;Element&gt; = []; const childs: Array&lt;Element&gt; = [];
&nbsp; &nbsp;
each(elm &amp;&amp; elm.children, (child: Element) =&gt; { each(elm &amp;&amp; elm.children, (child: Element) =&gt; {
if (selector) { if (selector) {
if (child.matches(selector)) if (child.matches(selector)) {
children.push(child); childs.push(child);
} }
else } else {
children.push(child); childs.push(child);
}); }
});
&nbsp; &nbsp;
return children; return childs;
} };
&nbsp; &nbsp;
export const contents: (elm: Element | null) =&gt; ReadonlyArray&lt;ChildNode&gt; = (elm) =&gt; { export const contents: (elm: Element | null) =&gt; ReadonlyArray&lt;ChildNode&gt; = (elm) =&gt; (elm ? Array.from&lt;ChildNode&gt;(elm.childNodes) : []);
return elm ? Array.from&lt;ChildNode&gt;(elm.childNodes) : [];
}
&nbsp; &nbsp;
export const parent: (elm: Node | null) =&gt; Node | null = (elm) =&gt; elm ? elm.parentElement : null;</pre></td></tr></table></pre> export const parent: (elm: Node | null) =&gt; Node | null = (elm) =&gt; (elm ? elm.parentElement : null);
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -125,7 +125,7 @@
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -58,16 +58,19 @@
<div class='status-line low'></div> <div class='status-line low'></div>
<pre><table class="coverage"> <pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span> <a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">export * from 'core/options/validation'; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">export * from 'core/options/validation';
export * from 'core/options/transformation';</pre></td></tr></table></pre> export * from 'core/options/transformation';
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -83,7 +83,20 @@
<a name='L24'></a><a href='#L24'>24</a> <a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a> <a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a> <a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span> <a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -107,11 +120,12 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">16x</span> <span class="cline-any cline-yes">16x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { OptionsTemplate, OptionsAndOptionsTemplate, PlainObject, OptionsTemplateTypes } from "core/typings"; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { OptionsTemplate, OptionsAndOptionsTemplate, PlainObject, OptionsTemplateTypes } from 'core/typings';
import { isArray, isObject } from "core/utils/types"; import { isArray, isObject } from 'core/utils/types';
import { each } from "core/utils/arrays"; import { each } from 'core/utils/arrays';
&nbsp; &nbsp;
/** /**
* Transforms the given OptionsAndOptionsTemplate&lt;T&gt; object to its corresponding generic (T) Object or its corresponding Template object. * Transforms the given OptionsAndOptionsTemplate&lt;T&gt; object to its corresponding generic (T) Object or its corresponding Template object.
@@ -119,22 +133,29 @@ import { each } from "core/utils/arrays";
* @param toTemplate True if the given OptionsAndOptionsTemplate&lt;T&gt; shall be converted to its corresponding Template object. * @param toTemplate True if the given OptionsAndOptionsTemplate&lt;T&gt; shall be converted to its corresponding Template object.
*/ */
export function transform&lt;T extends Required&lt;T&gt;&gt;(optionsWithOptionsTemplate: OptionsAndOptionsTemplate&lt;T&gt;): T; export function transform&lt;T extends Required&lt;T&gt;&gt;(optionsWithOptionsTemplate: OptionsAndOptionsTemplate&lt;T&gt;): T;
export function transform&lt;T extends Required&lt;T&gt;&gt;(optionsWithOptionsTemplate: OptionsAndOptionsTemplate&lt;T&gt;, toTemplate: true | void): OptionsTemplate&lt;T&gt;; export function transform&lt;T extends Required&lt;T&gt;&gt;(
export function transform&lt;T extends Required&lt;T&gt;&gt;(optionsWithOptionsTemplate: OptionsAndOptionsTemplate&lt;T&gt;, toTemplate?: true | void): OptionsTemplate&lt;T&gt; | T { optionsWithOptionsTemplate: OptionsAndOptionsTemplate&lt;T&gt;,
const result: any = {}; toTemplate: true | void,
): OptionsTemplate&lt;T&gt;;
export function transform&lt;T extends Required&lt;T&gt;&gt;(
optionsWithOptionsTemplate: OptionsAndOptionsTemplate&lt;T&gt;,
toTemplate?: true | void,
): OptionsTemplate&lt;T&gt; | T {
const result: any = {};
&nbsp; &nbsp;
each(Object.keys(optionsWithOptionsTemplate), (key: Extract&lt;keyof T, string&gt;) =&gt; { each(Object.keys(optionsWithOptionsTemplate), (key: Extract&lt;keyof T, string&gt;) =&gt; {
const val: PlainObject | OptionsTemplateTypes | Array&lt;OptionsTemplateTypes&gt; = optionsWithOptionsTemplate[key]; const val: PlainObject | OptionsTemplateTypes | Array&lt;OptionsTemplateTypes&gt; = optionsWithOptionsTemplate[key];
&nbsp; &nbsp;
/* istanbul ignore else */ /* istanbul ignore else */
if (isArray(val)) if (isArray(val)) {
result[key] = val[toTemplate ? 1 : 0]; result[key] = val[toTemplate ? 1 : 0];
else if (isObject(val)) } else if (isObject(val)) {
result[key] = transform(val as OptionsAndOptionsTemplate&lt;typeof val&gt;, toTemplate); result[key] = transform(val as OptionsAndOptionsTemplate&lt;typeof val&gt;, toTemplate);
}); }
});
&nbsp; &nbsp;
return result; return result;
}; }
&nbsp;</pre></td></tr></table></pre> &nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
@@ -142,7 +163,7 @@ export function transform&lt;T extends Required&lt;T&gt;&gt;(optionsWithOptionsT
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -221,7 +221,29 @@
<a name='L162'></a><a href='#L162'>162</a> <a name='L162'></a><a href='#L162'>162</a>
<a name='L163'></a><a href='#L163'>163</a> <a name='L163'></a><a href='#L163'>163</a>
<a name='L164'></a><a href='#L164'>164</a> <a name='L164'></a><a href='#L164'>164</a>
<a name='L165'></a><a href='#L165'>165</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span> <a name='L165'></a><a href='#L165'>165</a>
<a name='L166'></a><a href='#L166'>166</a>
<a name='L167'></a><a href='#L167'>167</a>
<a name='L168'></a><a href='#L168'>168</a>
<a name='L169'></a><a href='#L169'>169</a>
<a name='L170'></a><a href='#L170'>170</a>
<a name='L171'></a><a href='#L171'>171</a>
<a name='L172'></a><a href='#L172'>172</a>
<a name='L173'></a><a href='#L173'>173</a>
<a name='L174'></a><a href='#L174'>174</a>
<a name='L175'></a><a href='#L175'>175</a>
<a name='L176'></a><a href='#L176'>176</a>
<a name='L177'></a><a href='#L177'>177</a>
<a name='L178'></a><a href='#L178'>178</a>
<a name='L179'></a><a href='#L179'>179</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -238,13 +260,6 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">21x</span> <span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-yes">21x</span> <span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -267,7 +282,15 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">65x</span> <span class="cline-any cline-yes">65x</span>
<span class="cline-any cline-yes">65x</span> <span class="cline-any cline-yes">65x</span>
<span class="cline-any cline-yes">372x</span> <span class="cline-any cline-yes">372x</span>
@@ -290,7 +313,6 @@
<span class="cline-any cline-yes">33x</span> <span class="cline-any cline-yes">33x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">339x</span> <span class="cline-any cline-yes">339x</span>
<span class="cline-any cline-yes">336x</span> <span class="cline-any cline-yes">336x</span>
<span class="cline-any cline-yes">336x</span> <span class="cline-any cline-yes">336x</span>
@@ -298,6 +320,8 @@
<span class="cline-any cline-yes">336x</span> <span class="cline-any cline-yes">336x</span>
<span class="cline-any cline-yes">336x</span> <span class="cline-any cline-yes">336x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">336x</span> <span class="cline-any cline-yes">336x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">417x</span> <span class="cline-any cline-yes">417x</span>
@@ -309,7 +333,6 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">64x</span> <span class="cline-any cline-yes">64x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">353x</span> <span class="cline-any cline-yes">353x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -320,19 +343,20 @@
<span class="cline-any cline-yes">417x</span> <span class="cline-any cline-yes">417x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">336x</span> <span class="cline-any cline-yes">336x</span>
<span class="cline-any cline-yes">310x</span> <span class="cline-any cline-yes">310x</span>
<span class="cline-any cline-yes">310x</span> <span class="cline-any cline-yes">310x</span>
<span class="cline-any cline-yes">256x</span> <span class="cline-any cline-yes">256x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">26x</span> <span class="cline-any cline-yes">26x</span>
<span class="cline-any cline-yes">2x</span> <span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">336x</span> <span class="cline-any cline-yes">336x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -371,6 +395,10 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">32x</span> <span class="cline-any cline-yes">32x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -387,9 +415,17 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { each, indexOf } from 'core/utils/arrays'; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { each, indexOf } from 'core/utils/arrays';
import { type, isArray, isUndefined, isEmptyObject, isPlainObject, isString } from 'core/utils/types'; import { type, isArray, isUndefined, isEmptyObject, isPlainObject, isString } from 'core/utils/types';
import { PlainObject, OptionsTemplate, OptionsTemplateTypes, OptionsTemplateType, OptionsValidated, Func, OptionsValidatedResult } from 'core/typings'; import {
PlainObject,
OptionsTemplate,
OptionsTemplateTypes,
OptionsTemplateType,
OptionsValidated,
Func,
OptionsValidatedResult,
} from 'core/typings';
&nbsp; &nbsp;
const stringify = JSON.stringify; const { stringify } = JSON;
&nbsp; &nbsp;
/** /**
* A prefix and suffix tuple which serves as recognition pattern for template types. * A prefix and suffix tuple which serves as recognition pattern for template types.
@@ -400,18 +436,13 @@ const templateTypePrefixSuffix: readonly [string, string] = ['__TPL_', '_TYPE__'
* Key = normal type string * Key = normal type string
* value = template type string * value = template type string
*/ */
const optionsTemplateTypes: OptionsTemplateTypesDictionary = [ const optionsTemplateTypes: OptionsTemplateTypesDictionary = ['boolean', 'number', 'string', 'array', 'object', 'function', 'null'].reduce(
'boolean', (result, item) =&gt; {
'number',
'string',
'array',
'object',
'function',
'null'
].reduce((result, item) =&gt; {
result[item] = templateTypePrefixSuffix[0] + item + templateTypePrefixSuffix[1]; result[item] = templateTypePrefixSuffix[0] + item + templateTypePrefixSuffix[1];
return result; return result;
}, {} as OptionsTemplateTypesDictionary); },
{} as OptionsTemplateTypesDictionary,
);
&nbsp; &nbsp;
/** /**
* Validates the given options object according to the given template object and returns a object which looks like: * Validates the given options object according to the given template object and returns a object which looks like:
@@ -422,7 +453,7 @@ const optionsTemplateTypes: OptionsTemplateTypesDictionary = [
* @param options The options object which shall be validated. * @param options The options object which shall be validated.
* @param template The template according to which the options object shall be validated. * @param template The template according to which the options object shall be validated.
* @param optionsDiff When provided the returned validated object will only have properties which are different to this objects properties. * @param optionsDiff When provided the returned validated object will only have properties which are different to this objects properties.
* Example (assume all properties are valid to the template): * Example (assume all properties are valid to the template):
* Options object : { a: 'a', b: 'b', c: 'c' } * Options object : { a: 'a', b: 'b', c: 'c' }
* optionsDiff object : { a: 'a', b: 'b', c: undefined } * optionsDiff object : { a: 'a', b: 'b', c: undefined }
* Returned validated object : { c: 'c' } * Returned validated object : { c: 'c' }
@@ -431,80 +462,87 @@ const optionsTemplateTypes: OptionsTemplateTypesDictionary = [
* @param doWriteErrors True if errors shall be logged into the console, false otherwise. * @param doWriteErrors True if errors shall be logged into the console, false otherwise.
* @param propPath The propertyPath which lead to this object. (used for error logging) * @param propPath The propertyPath which lead to this object. (used for error logging)
*/ */
const validateRecursive = function &lt;T extends PlainObject&gt;(options: T, template: OptionsTemplate&lt;Required&lt;T&gt;&gt;, optionsDiff: OptionsValidated&lt;T&gt;, doWriteErrors?: boolean, propPath?: string): OptionsValidatedResult&lt;T&gt; { const validateRecursive = function &lt;T extends PlainObject&gt;(
const validatedOptions: OptionsValidated&lt;T&gt; = {}; options: T,
const optionsCopy: T = Object.assign({}, options); template: OptionsTemplate&lt;Required&lt;T&gt;&gt;,
const props = Object.keys(template).filter(prop =&gt; options.hasOwnProperty(prop)); optionsDiff: OptionsValidated&lt;T&gt;,
doWriteErrors?: boolean,
propPath?: string,
): OptionsValidatedResult&lt;T&gt; {
const validatedOptions: OptionsValidated&lt;T&gt; = {};
const optionsCopy: T = { ...options };
const props = Object.keys(template).filter((prop) =&gt; options.hasOwnProperty(prop));
&nbsp; &nbsp;
each(props, (prop: Extract&lt;keyof T, string&gt;) =&gt; { each(props, (prop: Extract&lt;keyof T, string&gt;) =&gt; {
const optionsDiffValue: any = isUndefined(optionsDiff[prop]) ? {} : optionsDiff[prop]; const optionsDiffValue: any = isUndefined(optionsDiff[prop]) ? {} : optionsDiff[prop];
const optionsValue: any = options[prop]; const optionsValue: any = options[prop];
const templateValue: PlainObject | string | OptionsTemplateTypes | Array&lt;OptionsTemplateTypes&gt; = template[prop]; const templateValue: PlainObject | string | OptionsTemplateTypes | Array&lt;OptionsTemplateTypes&gt; = template[prop];
const templateIsComplex = isPlainObject(templateValue); const templateIsComplex = isPlainObject(templateValue);
const propPrefix = propPath ? propPath + '.' : ''; const propPrefix = propPath ? `${propPath}.` : '';
&nbsp; &nbsp;
//if the template has a object as value, it means that the options are complex (verschachtelt) // if the template has a object as value, it means that the options are complex (verschachtelt)
if (templateIsComplex &amp;&amp; isPlainObject(optionsValue)) { if (templateIsComplex &amp;&amp; isPlainObject(optionsValue)) {
const validatedResult = validateRecursive(optionsValue, templateValue as PlainObject, optionsDiffValue, doWriteErrors, propPrefix + prop); const validatedResult = validateRecursive(optionsValue, templateValue as PlainObject, optionsDiffValue, doWriteErrors, propPrefix + prop);
validatedOptions[prop] = validatedResult.validated; validatedOptions[prop] = validatedResult.validated;
optionsCopy[prop] = validatedResult.foreign as any; optionsCopy[prop] = validatedResult.foreign as any;
&nbsp; &nbsp;
each([optionsCopy, validatedOptions], (value) =&gt; { each([optionsCopy, validatedOptions], (value) =&gt; {
if (isEmptyObject(value[prop])) { if (isEmptyObject(value[prop])) {
delete value[prop]; delete value[prop];
}
});
} }
else if (!templateIsComplex) { });
let isValid = false; } else if (!templateIsComplex) {
const errorEnumStrings: Array&lt;string&gt; = []; let isValid = false;
const errorPossibleTypes: Array&lt;string&gt; = []; const errorEnumStrings: Array&lt;string&gt; = [];
const optionsValueType = type(optionsValue); const errorPossibleTypes: Array&lt;string&gt; = [];
const templateValueArr: Array&lt;string | OptionsTemplateTypes&gt; = !isArray(templateValue) ? [templateValue as string | OptionsTemplateTypes] : templateValue as Array&lt;OptionsTemplateTypes&gt;; const optionsValueType = type(optionsValue);
const templateValueArr: Array&lt;string | OptionsTemplateTypes&gt; = !isArray(templateValue)
? [templateValue as string | OptionsTemplateTypes]
: (templateValue as Array&lt;OptionsTemplateTypes&gt;);
&nbsp; &nbsp;
each(templateValueArr, (currTemplateType) =&gt; { each(templateValueArr, (currTemplateType) =&gt; {
//if currType value isn't inside possibleTemplateTypes we assume its a enum string value // if currType value isn't inside possibleTemplateTypes we assume its a enum string value
const isEnumString = indexOf(Object.values(optionsTemplateTypes), currTemplateType) &lt; 0; const isEnumString = indexOf(Object.values(optionsTemplateTypes), currTemplateType) &lt; 0;
if (isEnumString &amp;&amp; isString(optionsValue)) { if (isEnumString &amp;&amp; isString(optionsValue)) {
//split it into a array which contains all possible values for example: ["yes", "no", "maybe"] // split it into a array which contains all possible values for example: ["yes", "no", "maybe"]
const enumStringSplit = currTemplateType.split(' '); const enumStringSplit = currTemplateType.split(' ');
isValid = !!enumStringSplit.find(possibility =&gt; possibility === optionsValue); isValid = !!enumStringSplit.find((possibility) =&gt; possibility === optionsValue);
&nbsp; &nbsp;
// build error message // build error message
errorEnumStrings.push(...enumStringSplit); errorEnumStrings.push(...enumStringSplit);
} } else {
else { isValid = optionsTemplateTypes[optionsValueType] === currTemplateType;
isValid = optionsTemplateTypes[optionsValueType] === currTemplateType;
}
&nbsp;
// build error message
errorPossibleTypes.push(isEnumString ? optionsTemplateTypes.string : currTemplateType);
&nbsp;
// continue if invalid, break if valid
return !isValid;
});
&nbsp;
&nbsp;
if (isValid) {
const doStringifyComparison = isArray(optionsValue) || isPlainObject(optionsValue);
if (doStringifyComparison ? stringify(optionsValue) !== stringify(optionsDiffValue) : optionsValue !== optionsDiffValue) {
validatedOptions[prop] = optionsValue;
}
}
else if (doWriteErrors) {
console.warn(`The option "${propPrefix}${prop}" wasn't set, because it doesn't accept the type [ ${optionsValueType.toUpperCase()} ] with the value of "${optionsValue}".\r\n` +
`Accepted types are: [ ${errorPossibleTypes.join(', ').toUpperCase()} ].\r\n` +
(errorEnumStrings.length &gt; 0 ? `\r\nValid strings are: [ ${errorEnumStrings.join(', ')} ].` : ''))
}
&nbsp;
delete optionsCopy[prop];
} }
});
&nbsp; &nbsp;
return { // build error message
foreign: optionsCopy, errorPossibleTypes.push(isEnumString ? optionsTemplateTypes.string : currTemplateType);
validated: validatedOptions &nbsp;
}; // continue if invalid, break if valid
return !isValid;
});
&nbsp;
if (isValid) {
const doStringifyComparison = isArray(optionsValue) || isPlainObject(optionsValue);
if (doStringifyComparison ? stringify(optionsValue) !== stringify(optionsDiffValue) : optionsValue !== optionsDiffValue) {
validatedOptions[prop] = optionsValue;
}
} else if (doWriteErrors) {
console.warn(
`${
`The option "${propPrefix}${prop}" wasn't set, because it doesn't accept the type [ ${optionsValueType.toUpperCase()} ] with the value of "${optionsValue}".\r\n` +
`Accepted types are: [ ${errorPossibleTypes.join(', ').toUpperCase()} ].\r\n`
}${errorEnumStrings.length &gt; 0 ? `\r\nValid strings are: [ ${errorEnumStrings.join(', ')} ].` : ''}`,
);
}
&nbsp;
delete optionsCopy[prop];
}
});
&nbsp;
return {
foreign: optionsCopy,
validated: validatedOptions,
};
}; };
&nbsp; &nbsp;
/** /**
@@ -516,7 +554,7 @@ const validateRecursive = function &lt;T extends PlainObject&gt;(options: T, tem
* @param options The options object which shall be validated. * @param options The options object which shall be validated.
* @param template The template according to which the options object shall be validated. * @param template The template according to which the options object shall be validated.
* @param optionsDiff When provided the returned validated object will only have properties which are different to this objects properties. * @param optionsDiff When provided the returned validated object will only have properties which are different to this objects properties.
* Example (assume all properties are valid to the template): * Example (assume all properties are valid to the template):
* Options object : { a: 'a', b: 'b', c: 'c' } * Options object : { a: 'a', b: 'b', c: 'c' }
* optionsDiff object : { a: 'a', b: 'b', c: undefined } * optionsDiff object : { a: 'a', b: 'b', c: undefined }
* Returned validated object : { c: 'c' } * Returned validated object : { c: 'c' }
@@ -524,31 +562,35 @@ const validateRecursive = function &lt;T extends PlainObject&gt;(options: T, tem
* Without the optionsDiff object the returned validated object would be: { a: 'a', b: 'b', c: 'c' } * Without the optionsDiff object the returned validated object would be: { a: 'a', b: 'b', c: 'c' }
* @param doWriteErrors True if errors shall be logged into the console, false otherwise. * @param doWriteErrors True if errors shall be logged into the console, false otherwise.
*/ */
const validate = function &lt;T extends PlainObject&gt;(options: T, template: OptionsTemplate&lt;Required&lt;T&gt;&gt;, optionsDiff?: OptionsValidated&lt;T&gt;, doWriteErrors?: boolean): OptionsValidatedResult&lt;T&gt; { const validate = function &lt;T extends PlainObject&gt;(
/* options: T,
template: OptionsTemplate&lt;Required&lt;T&gt;&gt;,
optionsDiff?: OptionsValidated&lt;T&gt;,
doWriteErrors?: boolean,
): OptionsValidatedResult&lt;T&gt; {
/*
if (!isEmptyObject(foreign) &amp;&amp; doWriteErrors) if (!isEmptyObject(foreign) &amp;&amp; doWriteErrors)
console.warn(`The following options are discarded due to invalidity:\r\n ${window.JSON.stringify(foreign, null, 2)}`); console.warn(`The following options are discarded due to invalidity:\r\n ${window.JSON.stringify(foreign, null, 2)}`);
&nbsp; &nbsp;
//add values, which aren't specified in the template, to the finished validated object to prevent them from being discarded //add values, which aren't specified in the template, to the finished validated object to prevent them from being discarded
if (keepForeignProps) { if (keepForeignProps) {
Object.assign(result.validated, foreign); Object.assign(result.validated, foreign);
} }
*/ */
return validateRecursive(options, template, optionsDiff || {}, doWriteErrors || false); return validateRecursive(options, template, optionsDiff || {}, doWriteErrors || false);
}; };
&nbsp; &nbsp;
export { validate, optionsTemplateTypes }; export { validate, optionsTemplateTypes };
&nbsp; &nbsp;
type OptionsTemplateTypesDictionary = { type OptionsTemplateTypesDictionary = {
readonly boolean: OptionsTemplateType&lt;boolean&gt;; readonly boolean: OptionsTemplateType&lt;boolean&gt;;
readonly number: OptionsTemplateType&lt;number&gt;; readonly number: OptionsTemplateType&lt;number&gt;;
readonly string: OptionsTemplateType&lt;string&gt;; readonly string: OptionsTemplateType&lt;string&gt;;
readonly array: OptionsTemplateType&lt;Array&lt;any&gt;&gt;; readonly array: OptionsTemplateType&lt;Array&lt;any&gt;&gt;;
readonly object: OptionsTemplateType&lt;object&gt;; readonly object: OptionsTemplateType&lt;object&gt;; // eslint-disable-line @typescript-eslint/ban-types
readonly function: OptionsTemplateType&lt;Func&gt;; readonly function: OptionsTemplateType&lt;Func&gt;;
readonly null: OptionsTemplateType&lt;null&gt;; readonly null: OptionsTemplateType&lt;null&gt;;
} };
&nbsp;</pre></td></tr></table></pre> &nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
@@ -556,7 +598,7 @@ type OptionsTemplateTypesDictionary = {
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -25,28 +25,28 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Statements</span> <span class="quiet">Statements</span>
<span class='fraction'>12/12</span> <span class='fraction'>11/11</span>
</div> </div>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Branches</span> <span class="quiet">Branches</span>
<span class='fraction'>8/8</span> <span class='fraction'>6/6</span>
</div> </div>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Functions</span> <span class="quiet">Functions</span>
<span class='fraction'>2/2</span> <span class='fraction'>3/3</span>
</div> </div>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>12/12</span> <span class='fraction'>8/8</span>
</div> </div>
@@ -100,7 +100,15 @@
<a name='L41'></a><a href='#L41'>41</a> <a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a> <a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a> <a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span> <a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -118,21 +126,30 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">694x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">694x</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">688x</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2211x</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">320x</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">699x</span>
<span class="cline-any cline-yes">693x</span>
<span class="cline-any cline-yes">2224x</span>
<span class="cline-any cline-yes">321x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">6x</span> <span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">13x</span> <span class="cline-any cline-yes">13x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-yes">699x</span>
<span class="cline-any cline-yes">694x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -141,42 +158,50 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">9x</span>
<span class="cline-any cline-yes">418x</span> <span class="cline-any cline-yes">418x</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { isArrayLike } from 'core/utils/types'; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { isArrayLike } from 'core/utils/types';
import { PlainObject } from 'core/typings'; import { PlainObject } from 'core/typings';
&nbsp; &nbsp;
&nbsp;
/** /**
* Iterates through a array or object * Iterates through a array or object
* @param arrayLikeOrObject The array or object through which shall be iterated. * @param arrayLikeOrObject The array or object through which shall be iterated.
* @param callback The function which is responsible for the iteration. * @param callback The function which is responsible for the iteration.
* If the function returns true its treated like a "continue" statement. * If the function returns true its treated like a "continue" statement.
* If the function returns false its treated like a "break" statement. * If the function returns false its treated like a "break" statement.
*/ */
export function each&lt;T&gt;(array: Array&lt;T&gt; | ReadonlyArray&lt;T&gt;, callback: (value: T, indexOrKey: number, source: Array&lt;T&gt;) =&gt; boolean | void): Array&lt;T&gt; | ReadonlyArray&lt;T&gt;; export function each&lt;T&gt;(
export function each&lt;T&gt;(array: Array&lt;T&gt; | ReadonlyArray&lt;T&gt; | null, callback: (value: T, indexOrKey: number, source: Array&lt;T&gt;) =&gt; boolean | void): Array&lt;T&gt; | ReadonlyArray&lt;T&gt; | null; array: Array&lt;T&gt; | ReadonlyArray&lt;T&gt;,
export function each&lt;T&gt;(arrayLikeObject: ArrayLike&lt;T&gt;, callback: (value: T, indexOrKey: number, source: ArrayLike&lt;T&gt;) =&gt; boolean | void): ArrayLike&lt;T&gt;; callback: (value: T, indexOrKey: number, source: Array&lt;T&gt;) =&gt; boolean | void,
export function each&lt;T&gt;(arrayLikeObject: ArrayLike&lt;T&gt; | null, callback: (value: T, indexOrKey: number, source: ArrayLike&lt;T&gt;) =&gt; boolean | void): ArrayLike&lt;T&gt; | null; ): Array&lt;T&gt; | ReadonlyArray&lt;T&gt;;
export function each&lt;T&gt;(
array: Array&lt;T&gt; | ReadonlyArray&lt;T&gt; | null,
callback: (value: T, indexOrKey: number, source: Array&lt;T&gt;) =&gt; boolean | void,
): Array&lt;T&gt; | ReadonlyArray&lt;T&gt; | null;
export function each&lt;T&gt;(
arrayLikeObject: ArrayLike&lt;T&gt;,
callback: (value: T, indexOrKey: number, source: ArrayLike&lt;T&gt;) =&gt; boolean | void,
): ArrayLike&lt;T&gt;;
export function each&lt;T&gt;(
arrayLikeObject: ArrayLike&lt;T&gt; | null,
callback: (value: T, indexOrKey: number, source: ArrayLike&lt;T&gt;) =&gt; boolean | void,
): ArrayLike&lt;T&gt; | null;
export function each(obj: PlainObject, callback: (value: any, indexOrKey: string, source: PlainObject) =&gt; boolean | void): PlainObject; export function each(obj: PlainObject, callback: (value: any, indexOrKey: string, source: PlainObject) =&gt; boolean | void): PlainObject;
export function each(obj: PlainObject | null, callback: (value: any, indexOrKey: string, source: PlainObject) =&gt; boolean | void): PlainObject | null; export function each(obj: PlainObject | null, callback: (value: any, indexOrKey: string, source: PlainObject) =&gt; boolean | void): PlainObject | null;
export function each&lt;T&gt;(source: ArrayLike&lt;T&gt; | PlainObject | null, callback: (value: T | any, indexOrKey: any, source: any) =&gt; boolean | void): Array&lt;T&gt; | ReadonlyArray&lt;T&gt; | ArrayLike&lt;T&gt; | PlainObject | null { export function each&lt;T&gt;(
let i: number | string = 0; source: ArrayLike&lt;T&gt; | PlainObject | null,
&nbsp; callback: (value: T | any, indexOrKey: any, source: any) =&gt; boolean | void,
if (isArrayLike(source)) { ): Array&lt;T&gt; | ReadonlyArray&lt;T&gt; | ArrayLike&lt;T&gt; | PlainObject | null {
for (; i &lt; source.length; i++) { if (isArrayLike(source)) {
if (callback(source[i], i, source) === false) for (let i = 0; i &lt; source.length; i++) {
break; if (callback(source[i], i, source) === false) {
} break;
}
} }
else if (source) { } else if (source) {
for (i in source) { each(Object.keys(source), (key) =&gt; callback(source[key], key, source));
if (callback(source[i], i, source) === false) }
break; return source;
} }
}
return source;
};
&nbsp; &nbsp;
/** /**
* Returns the index of the given inside the given array or -1 if the given item isn't part of the given array. * Returns the index of the given inside the given array or -1 if the given item isn't part of the given array.
@@ -184,16 +209,15 @@ export function each&lt;T&gt;(source: ArrayLike&lt;T&gt; | PlainObject | null, c
* @param item The item. * @param item The item.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0. * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
*/ */
export const indexOf: &lt;T = any&gt;(arr: Array&lt;T&gt;, item: T, fromIndex?: number) =&gt; number = (arr, item, fromIndex) =&gt; { export const indexOf: &lt;T = any&gt;(arr: Array&lt;T&gt;, item: T, fromIndex?: number) =&gt; number = (arr, item, fromIndex) =&gt; arr.indexOf(item, fromIndex);
return arr.indexOf(item, fromIndex); &nbsp;</pre></td></tr></table></pre>
}</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -115,7 +115,26 @@
<a name='L56'></a><a href='#L56'>56</a> <a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a> <a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a> <a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span> <a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -136,7 +155,6 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1080x</span> <span class="cline-any cline-yes">1080x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">217x</span> <span class="cline-any cline-yes">217x</span>
<span class="cline-any cline-yes">632x</span> <span class="cline-any cline-yes">632x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -173,6 +191,8 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">180x</span> <span class="cline-any cline-yes">180x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { isArray, isFunction, isPlainObject, isNull } from 'core/utils/types'; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { isArray, isFunction, isPlainObject, isNull } from 'core/utils/types';
import { each } from 'core/utils/arrays'; import { each } from 'core/utils/arrays';
&nbsp; &nbsp;
@@ -182,63 +202,73 @@ export function extend&lt;T, U, V&gt;(target: T, object1: U, object2: V): T &amp
export function extend&lt;T, U, V, W&gt;(target: T, object1: U, object2: V, object3: W): T &amp; U &amp; V &amp; W; export function extend&lt;T, U, V, W&gt;(target: T, object1: U, object2: V, object3: W): T &amp; U &amp; V &amp; W;
export function extend&lt;T, U, V, W, X&gt;(target: T, object1: U, object2: V, object3: W, object4: X): T &amp; U &amp; V &amp; W &amp; X; export function extend&lt;T, U, V, W, X&gt;(target: T, object1: U, object2: V, object3: W, object4: X): T &amp; U &amp; V &amp; W &amp; X;
export function extend&lt;T, U, V, W, X, Y&gt;(target: T, object1: U, object2: V, object3: W, object4: X, object5: Y): T &amp; U &amp; V &amp; W &amp; X &amp; Y; export function extend&lt;T, U, V, W, X, Y&gt;(target: T, object1: U, object2: V, object3: W, object4: X, object5: Y): T &amp; U &amp; V &amp; W &amp; X &amp; Y;
export function extend&lt;T, U, V, W, X, Y, Z&gt;(target: T, object1?: U, object2?: V, object3?: W, object4?: X, object5?: Y, object6?: Z): T &amp; U &amp; V &amp; W &amp; X &amp; Y &amp; Z { export function extend&lt;T, U, V, W, X, Y, Z&gt;(
const sources: Array&lt;any&gt; = [object1, object2, object3, object4, object5, object6]; target: T,
object1?: U,
object2?: V,
object3?: W,
object4?: X,
object5?: Y,
object6?: Z,
): T &amp; U &amp; V &amp; W &amp; X &amp; Y &amp; Z {
/* eslint-disable no-restricted-syntax, guard-for-in */
const sources: Array&lt;any&gt; = [object1, object2, object3, object4, object5, object6];
&nbsp; &nbsp;
// Handle case when target is a string or something (possible in deep copy) // Handle case when target is a string or something (possible in deep copy)
if ((typeof target !== "object" || isNull(target)) &amp;&amp; !isFunction(target)) { if ((typeof target !== 'object' || isNull(target)) &amp;&amp; !isFunction(target)) {
target = {} as T; target = {} as T;
} }
&nbsp; &nbsp;
each(sources, (source) =&gt; { each(sources, (source) =&gt; {
// Only deal with non-null/undefined values // Only deal with non-null/undefined values
if (source != null) { if (source != null) {
// Extend the base object
for (const name in source) {
const copy: any = source[name];
&nbsp; &nbsp;
// Extend the base object // Prevent Object.prototype pollution
for (const name in source) { // Prevent never-ending loop
const copy: any = source[name]; if (name === '__proto__' || target === copy) {
&nbsp; continue;
// Prevent Object.prototype pollution
// Prevent never-ending loop
if (name === "__proto__" || target === copy) {
continue;
}
&nbsp;
const copyIsArray = isArray(copy);
&nbsp;
// Recurse if we're merging plain objects or arrays
if (copy &amp;&amp; (isPlainObject(copy) || copyIsArray)) {
const src = target[name];
let clone: any = src;
&nbsp;
// Ensure proper type for the source value
if (copyIsArray &amp;&amp; !isArray(src)) {
clone = [];
} else if (!copyIsArray &amp;&amp; !isPlainObject(src)) {
clone = {};
}
&nbsp;
// Never move original objects, clone them
target[name] = extend(clone, copy) as any;
&nbsp;
// Don't bring in undefined values
} else if (copy !== undefined) {
target[name] = copy;
}
}
} }
});
&nbsp; &nbsp;
// Return the modified object const copyIsArray = isArray(copy);
return target as any; &nbsp;
}</pre></td></tr></table></pre> // Recurse if we're merging plain objects or arrays
if (copy &amp;&amp; (isPlainObject(copy) || copyIsArray)) {
const src = target[name];
let clone: any = src;
&nbsp;
// Ensure proper type for the source value
if (copyIsArray &amp;&amp; !isArray(src)) {
clone = [];
} else if (!copyIsArray &amp;&amp; !isPlainObject(src)) {
clone = {};
}
&nbsp;
// Never move original objects, clone them
target[name] = extend(clone, copy) as any;
&nbsp;
// Don't bring in undefined values
} else if (copy !== undefined) {
target[name] = copy;
}
}
}
});
&nbsp;
// Return the modified object
return target as any;
/* eslint-enable */
}
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
+11 -11
View File
@@ -25,28 +25,28 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Statements</span> <span class="quiet">Statements</span>
<span class='fraction'>65/65</span> <span class='fraction'>64/64</span>
</div> </div>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Branches</span> <span class="quiet">Branches</span>
<span class='fraction'>71/71</span> <span class='fraction'>69/69</span>
</div> </div>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Functions</span> <span class="quiet">Functions</span>
<span class='fraction'>17/17</span> <span class='fraction'>18/18</span>
</div> </div>
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>65/65</span> <span class='fraction'>57/57</span>
</div> </div>
@@ -78,13 +78,13 @@
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div> <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
</td> </td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="12" class="abs high">12/12</td> <td data-value="11" class="abs high">11/11</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="6" class="abs high">6/6</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="3" class="abs high">3/3</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="8" class="abs high">8/8</td> <td data-value="8" class="abs high">8/8</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="2" class="abs high">2/2</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="12" class="abs high">12/12</td>
</tr> </tr>
<tr> <tr>
@@ -129,7 +129,7 @@
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="13" class="abs high">13/13</td> <td data-value="13" class="abs high">13/13</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="32" class="abs high">32/32</td> <td data-value="28" class="abs high">28/28</td>
</tr> </tr>
</tbody> </tbody>
@@ -140,7 +140,7 @@
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -59,18 +59,21 @@
<pre><table class="coverage"> <pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a> <a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span> <a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">export * from 'core/utils/arrays'; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">export * from 'core/utils/arrays';
export * from 'core/utils/extend'; export * from 'core/utils/extend';
export * from 'core/utils/types';</pre></td></tr></table></pre> export * from 'core/utils/types';
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
@@ -46,7 +46,7 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>32/32</span> <span class='fraction'>28/28</span>
</div> </div>
@@ -152,17 +152,21 @@
<a name='L93'></a><a href='#L93'>93</a> <a name='L93'></a><a href='#L93'>93</a>
<a name='L94'></a><a href='#L94'>94</a> <a name='L94'></a><a href='#L94'>94</a>
<a name='L95'></a><a href='#L95'>95</a> <a name='L95'></a><a href='#L95'>95</a>
<a name='L96'></a><a href='#L96'>96</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span> <a name='L96'></a><a href='#L96'>96</a>
<a name='L97'></a><a href='#L97'>97</a>
<a name='L98'></a><a href='#L98'>98</a>
<a name='L99'></a><a href='#L99'>99</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">11x</span> <span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-yes">576x</span> <span class="cline-any cline-yes">576x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">575x</span> <span class="cline-any cline-yes">575x</span>
<span class="cline-any cline-yes">48x</span>
<span class="cline-any cline-yes">527x</span> <span class="cline-any cline-yes">527x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">97x</span> <span class="cline-any cline-yes">97x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -175,10 +179,6 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1605x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">464x</span> <span class="cline-any cline-yes">464x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -191,7 +191,11 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2666x</span> <span class="cline-any cline-yes">2671x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1605x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -199,9 +203,8 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-yes">766x</span>
<span class="cline-any cline-yes">761x</span> <span class="cline-any cline-yes">766x</span>
<span class="cline-any cline-yes">761x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -210,7 +213,6 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1337x</span> <span class="cline-any cline-yes">1337x</span>
<span class="cline-any cline-yes">1123x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">214x</span> <span class="cline-any cline-yes">214x</span>
@@ -222,8 +224,12 @@
<span class="cline-any cline-yes">3x</span> <span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">211x</span> <span class="cline-any cline-yes">211x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">211x</span> <span class="cline-any cline-yes">211x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -243,95 +249,96 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">105x</span> <span class="cline-any cline-yes">105x</span>
<span class="cline-any cline-yes">42x</span>
<span class="cline-any cline-yes">63x</span> <span class="cline-any cline-yes">63x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { PlainObject } from 'core/typings'; <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { PlainObject } from 'core/typings';
&nbsp; &nbsp;
export const type: (obj: any) =&gt; string = (obj) =&gt; { export const type: (obj: any) =&gt; string = (obj) =&gt; {
if (obj === undefined) if (obj === undefined) return `${obj}`;
return obj + ''; if (obj === null) return `${obj}`;
if (obj === null) return Object.prototype.toString
return obj + ''; .call(obj)
return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase(); .replace(/^\[object (.+)\]$/, '$1')
} .toLowerCase();
&nbsp;
export function isNumber(obj: any): obj is number {
return typeof obj === 'number';
}; };
&nbsp; &nbsp;
export function isNumber(obj: any): obj is number {
return typeof obj === 'number';
}
&nbsp;
export function isString(obj: any): obj is string { export function isString(obj: any): obj is string {
return typeof obj === 'string'; return typeof obj === 'string';
} }
&nbsp; &nbsp;
export function isBoolean(obj: any): obj is boolean { export function isBoolean(obj: any): obj is boolean {
return typeof obj === 'boolean'; return typeof obj === 'boolean';
} }
&nbsp; &nbsp;
export function isObject(obj: any): boolean { export function isFunction(obj: any): obj is (...args: Array&lt;unknown&gt;) =&gt; unknown {
return typeof obj === 'object' &amp;&amp; !isArray(obj) &amp;&amp; !isNull(obj); return typeof obj === 'function';
}
&nbsp;
export function isFunction(obj: any): obj is Function {
return typeof obj === 'function';
} }
&nbsp; &nbsp;
export function isUndefined(obj: any): obj is undefined { export function isUndefined(obj: any): obj is undefined {
return obj === undefined; return obj === undefined;
} }
&nbsp; &nbsp;
export function isNull(obj: any): obj is null { export function isNull(obj: any): obj is null {
return obj === null; return obj === null;
} }
&nbsp; &nbsp;
export function isArray(obj: any): obj is Array&lt;any&gt; { export function isArray(obj: any): obj is Array&lt;any&gt; {
return Array.isArray(obj); return Array.isArray(obj);
} }
&nbsp; &nbsp;
export function isObject(obj: any): boolean {
return typeof obj === 'object' &amp;&amp; !isArray(obj) &amp;&amp; !isNull(obj);
}
&nbsp; &nbsp;
/** /**
* Returns true if the given object is array like, false otherwise. * Returns true if the given object is array like, false otherwise.
* @param obj The Object * @param obj The Object
*/ */
export function isArrayLike&lt;T extends PlainObject = any&gt;(obj: any): obj is ArrayLike&lt;T&gt; { export function isArrayLike&lt;T extends PlainObject = any&gt;(obj: any): obj is ArrayLike&lt;T&gt; {
const length = !!obj &amp;&amp; obj.length; const length = !!obj &amp;&amp; obj.length;
return isArray(obj) || (!isFunction(obj) &amp;&amp; isNumber(length) &amp;&amp; length &gt; -1 &amp;&amp; length % 1 == 0); return isArray(obj) || (!isFunction(obj) &amp;&amp; isNumber(length) &amp;&amp; length &gt; -1 &amp;&amp; length % 1 == 0); // eslint-disable-line eqeqeq
} }
&nbsp; &nbsp;
/** /**
* Returns true if the given object is a "plain" (e.g. { key: value }) object, false otherwise. * Returns true if the given object is a "plain" (e.g. { key: value }) object, false otherwise.
* @param obj The Object. * @param obj The Object.
*/ */
export function isPlainObject&lt;T = any&gt;(obj: any): obj is PlainObject&lt;T&gt; { export function isPlainObject&lt;T = any&gt;(obj: any): obj is PlainObject&lt;T&gt; {
if (!obj || !isObject(obj) || type(obj) !== 'object') if (!obj || !isObject(obj) || type(obj) !== 'object') return false;
return false;
&nbsp; &nbsp;
let key; let key;
const proto = 'prototype'; const proto = 'prototype';
const hasOwnProperty = Object[proto].hasOwnProperty; const { hasOwnProperty } = Object[proto];
const hasOwnConstructor = hasOwnProperty.call(obj, 'constructor'); const hasOwnConstructor = hasOwnProperty.call(obj, 'constructor');
const hasIsPrototypeOf = obj.constructor &amp;&amp; obj.constructor[proto] &amp;&amp; hasOwnProperty.call(obj.constructor[proto], 'isPrototypeOf'); const hasIsPrototypeOf = obj.constructor &amp;&amp; obj.constructor[proto] &amp;&amp; hasOwnProperty.call(obj.constructor[proto], 'isPrototypeOf');
&nbsp; &nbsp;
if (obj.constructor &amp;&amp; !hasOwnConstructor &amp;&amp; !hasIsPrototypeOf) { if (obj.constructor &amp;&amp; !hasOwnConstructor &amp;&amp; !hasIsPrototypeOf) {
return false; return false;
} }
&nbsp; &nbsp;
for (key in obj) { /**/ } /* eslint-disable no-restricted-syntax */
for (key in obj) {
/**/
}
/* eslint-enable */
&nbsp; &nbsp;
return isUndefined(key) || hasOwnProperty.call(obj, key); return isUndefined(key) || hasOwnProperty.call(obj, key);
}; }
&nbsp; &nbsp;
/** /**
* Checks whether the given object is a HTMLElement. * Checks whether the given object is a HTMLElement.
* @param obj The object which shall be checked. * @param obj The object which shall be checked.
*/ */
export function isHTMLElement(obj: any): obj is HTMLElement { export function isHTMLElement(obj: any): obj is HTMLElement {
const instaceOfRightHandSide = window.HTMLElement; const instaceOfRightHandSide = window.HTMLElement;
const doInstanceOf = isObject(instaceOfRightHandSide) || isFunction(instaceOfRightHandSide); const doInstanceOf = isObject(instaceOfRightHandSide) || isFunction(instaceOfRightHandSide);
return !!( return !!(doInstanceOf ? obj instanceof instaceOfRightHandSide : obj &amp;&amp; isObject(obj) &amp;&amp; obj.nodeType === 1 &amp;&amp; isString(obj.nodeName));
doInstanceOf ? obj instanceof instaceOfRightHandSide : (obj &amp;&amp; isObject(obj) &amp;&amp; obj.nodeType === 1 &amp;&amp; isString(obj.nodeName))
);
} }
&nbsp; &nbsp;
/** /**
@@ -339,17 +346,19 @@ export function isHTMLElement(obj: any): obj is HTMLElement {
* @param obj The Object. * @param obj The Object.
*/ */
export function isEmptyObject(obj: any): boolean { export function isEmptyObject(obj: any): boolean {
for (let name in obj) /* eslint-disable no-restricted-syntax, guard-for-in */
return false; for (const name in obj) return false;
return true; return true;
};</pre></td></tr></table></pre> /* eslint-enable */
}
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../../../prettify.js"></script> <script src="../../../prettify.js"></script>
+3 -3
View File
@@ -46,7 +46,7 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>33/33</span> <span class='fraction'>32/32</span>
</div> </div>
@@ -84,7 +84,7 @@
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="6" class="abs high">6/6</td> <td data-value="6" class="abs high">6/6</td>
<td data-value="100" class="pct high">100%</td> <td data-value="100" class="pct high">100%</td>
<td data-value="19" class="abs high">19/19</td> <td data-value="18" class="abs high">18/18</td>
</tr> </tr>
<tr> <tr>
@@ -110,7 +110,7 @@
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../prettify.js"></script> <script src="../prettify.js"></script>
+26 -29
View File
@@ -46,7 +46,7 @@
<div class='fl pad1y space-right2'> <div class='fl pad1y space-right2'>
<span class="strong">100% </span> <span class="strong">100% </span>
<span class="quiet">Lines</span> <span class="quiet">Lines</span>
<span class='fraction'>19/19</span> <span class='fraction'>18/18</span>
</div> </div>
@@ -107,8 +107,7 @@
<a name='L48'></a><a href='#L48'>48</a> <a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a> <a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a> <a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a> <a name='L51'></a><a href='#L51'>51</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
<a name='L52'></a><a href='#L52'>52</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span> <span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -135,8 +134,6 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span> <span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -159,6 +156,7 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2x</span> <span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const targets: Set&lt;Element&gt; = new Set(); <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const targets: Set&lt;Element&gt; = new Set();
const targetInstanceMap: WeakMap&lt;Element, any&gt; = new WeakMap(); const targetInstanceMap: WeakMap&lt;Element, any&gt; = new WeakMap();
&nbsp; &nbsp;
@@ -168,56 +166,55 @@ const targetInstanceMap: WeakMap&lt;Element, any&gt; = new WeakMap();
* @param osInstance The OverlayScrollbars instance. * @param osInstance The OverlayScrollbars instance.
*/ */
export const addInstance: (target: Element, osInstance: any) =&gt; void = (target, osInstance) =&gt; { export const addInstance: (target: Element, osInstance: any) =&gt; void = (target, osInstance) =&gt; {
targetInstanceMap.set(target, osInstance); targetInstanceMap.set(target, osInstance);
targets.add(target); targets.add(target);
} };
&nbsp; &nbsp;
/** /**
* Removes a OverlayScrollbars instance from the given element. * Removes a OverlayScrollbars instance from the given element.
* @param target The element from which its OverlayScrollbars instance shall be removed. * @param target The element from which its OverlayScrollbars instance shall be removed.
*/ */
export const removeInstance: (target: Element) =&gt; void = (target) =&gt; { export const removeInstance: (target: Element) =&gt; void = (target) =&gt; {
targetInstanceMap.delete(target); targetInstanceMap.delete(target);
targets.delete(target); targets.delete(target);
} };
&nbsp; &nbsp;
/** /**
* Gets the OverlayScrollbars from the given element or undefined if it doesn't have one. * Gets the OverlayScrollbars from the given element or undefined if it doesn't have one.
* @param target The element of which its OverlayScrollbars instance shall be get. * @param target The element of which its OverlayScrollbars instance shall be get.
*/ */
export const getInstance: (target: Element) =&gt; any = (target) =&gt; { export const getInstance: (target: Element) =&gt; any = (target) =&gt; targetInstanceMap.get(target);
return targetInstanceMap.get(target);
}
&nbsp; &nbsp;
/** /**
* Gets a Map which represents all active OverayScrollbars instances. * Gets a Map which represents all active OverayScrollbars instances.
* The Key is the ekement and the value is the instance. * The Key is the ekement and the value is the instance.
*/ */
export const allInstances: () =&gt; ReadonlyMap&lt;Element, any&gt; = () =&gt; { export const allInstances: () =&gt; ReadonlyMap&lt;Element, any&gt; = () =&gt; {
const validTargetInstanceMap: Map&lt;Element, any&gt; = new Map(); const validTargetInstanceMap: Map&lt;Element, any&gt; = new Map();
&nbsp; &nbsp;
targets.forEach((target: Element) =&gt; { targets.forEach((target: Element) =&gt; {
/* istanbul ignore else */ /* istanbul ignore else */
if (targetInstanceMap.has(target)) { if (targetInstanceMap.has(target)) {
validTargetInstanceMap.set(target, targetInstanceMap.get(target)) validTargetInstanceMap.set(target, targetInstanceMap.get(target));
} }
}); });
&nbsp; &nbsp;
targets.clear(); targets.clear();
&nbsp; &nbsp;
validTargetInstanceMap.forEach((instance: any, validTarget: Element) =&gt; { validTargetInstanceMap.forEach((instance: any, validTarget: Element) =&gt; {
targets.add(validTarget); targets.add(validTarget);
}); });
&nbsp; &nbsp;
return validTargetInstanceMap; return validTargetInstanceMap;
}</pre></td></tr></table></pre> };
&nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper --> </div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../prettify.js"></script> <script src="../prettify.js"></script>
+52 -55
View File
@@ -138,8 +138,7 @@
<a name='L79'></a><a href='#L79'>79</a> <a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a> <a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</a> <a name='L81'></a><a href='#L81'>81</a>
<a name='L82'></a><a href='#L82'>82</a> <a name='L82'></a><a href='#L82'>82</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<a name='L83'></a><a href='#L83'>83</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
@@ -220,10 +219,9 @@
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span> <span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span> <span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span> <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { OptionsTemplate, OptionsTemplateValue, OptionsAndOptionsTemplateValue, OptionsAndOptionsTemplate, Func } from 'core/typings';
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { OptionsTemplate, OptionsTemplateValue, OptionsAndOptionsTemplateValue, OptionsAndOptionsTemplate, Func } from "core/typings"; import { optionsTemplateTypes as oTypes, transform } from 'core/options';
import { optionsTemplateTypes as oTypes, transform } from "core/options"; import { OverlayScrollbars } from 'typings';
import { OverlayScrollbars } from "typings";
&nbsp; &nbsp;
const classNameAllowedValues: OptionsTemplateValue&lt;string | null&gt; = [oTypes.string, oTypes.null]; const classNameAllowedValues: OptionsTemplateValue&lt;string | null&gt; = [oTypes.string, oTypes.null];
const numberAllowedValues: OptionsTemplateValue&lt;number&gt; = oTypes.number; const numberAllowedValues: OptionsTemplateValue&lt;number&gt; = oTypes.number;
@@ -240,7 +238,7 @@ const scrollbarsAutoHideAllowedValues: OptionsTemplateValue&lt;OverlayScrollbars
/** /**
* A object which serves as "default options object" and "options template object". * A object which serves as "default options object" and "options template object".
* I combined these two into one object so that I don't have to define two separate big objects, instead I define one big object. * I combined these two into one object so that I don't have to define two separate big objects, instead I define one big object.
* *
* The property value is a tuple: * The property value is a tuple:
* the first value is the default value * the first value is the default value
* the second value is the template value * the second value is the template value
@@ -253,56 +251,55 @@ const scrollbarsAutoHideAllowedValues: OptionsTemplateValue&lt;OverlayScrollbars
* Property "b" has a default value of 250 and it can be number * Property "b" has a default value of 250 and it can be number
*/ */
const defaultOptionsWithTemplate: OptionsAndOptionsTemplate&lt;Required&lt;OverlayScrollbars.Options&gt;&gt; = { const defaultOptionsWithTemplate: OptionsAndOptionsTemplate&lt;Required&lt;OverlayScrollbars.Options&gt;&gt; = {
className: ['os-theme-dark', classNameAllowedValues], //null || string className: ['os-theme-dark', classNameAllowedValues], // null || string
resize: ['none', resizeAllowedValues], //none || both || horizontal || vertical || n || b || h || v resize: ['none', resizeAllowedValues], // none || both || horizontal || vertical || n || b || h || v
sizeAutoCapable: booleanTrueTemplate, //true || false sizeAutoCapable: booleanTrueTemplate, // true || false
clipAlways: booleanTrueTemplate, //true || false clipAlways: booleanTrueTemplate, // true || false
normalizeRTL: booleanTrueTemplate, //true || false normalizeRTL: booleanTrueTemplate, // true || false
paddingAbsolute: booleanFalseTemplate, //true || false paddingAbsolute: booleanFalseTemplate, // true || false
autoUpdate: [null, booleanNullAllowedValues], //true || false || null autoUpdate: [null, booleanNullAllowedValues], // true || false || null
autoUpdateInterval: [33, numberAllowedValues], //number autoUpdateInterval: [33, numberAllowedValues], // number
updateOnLoad: [['img'], stringArrayNullAllowedValues], //string || array || null updateOnLoad: [['img'], stringArrayNullAllowedValues], // string || array || null
nativeScrollbarsOverlaid: { nativeScrollbarsOverlaid: {
showNativeScrollbars: booleanFalseTemplate, //true || false showNativeScrollbars: booleanFalseTemplate, // true || false
initialize: booleanFalseTemplate //true || false initialize: booleanFalseTemplate, // true || false
}, },
overflowBehavior: { overflowBehavior: {
x: ['scroll', overflowBehaviorAllowedValues], //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s x: ['scroll', overflowBehaviorAllowedValues], // visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s
y: ['scroll', overflowBehaviorAllowedValues] //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s y: ['scroll', overflowBehaviorAllowedValues], // visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s
}, },
scrollbars: { scrollbars: {
visibility: ['auto', scrollbarsVisibilityAllowedValues], //visible || hidden || auto || v || h || a visibility: ['auto', scrollbarsVisibilityAllowedValues], // visible || hidden || auto || v || h || a
autoHide: ['never', scrollbarsAutoHideAllowedValues], //never || scroll || leave || move || n || s || l || m autoHide: ['never', scrollbarsAutoHideAllowedValues], // never || scroll || leave || move || n || s || l || m
autoHideDelay: [800, numberAllowedValues], //number autoHideDelay: [800, numberAllowedValues], // number
dragScrolling: booleanTrueTemplate, //true || false dragScrolling: booleanTrueTemplate, // true || false
clickScrolling: booleanFalseTemplate, //true || false clickScrolling: booleanFalseTemplate, // true || false
touchSupport: booleanTrueTemplate, //true || false touchSupport: booleanTrueTemplate, // true || false
snapHandle: booleanFalseTemplate //true || false snapHandle: booleanFalseTemplate, // true || false
}, },
textarea: { textarea: {
dynWidth: booleanFalseTemplate, //true || false dynWidth: booleanFalseTemplate, // true || false
dynHeight: booleanFalseTemplate, //true || false dynHeight: booleanFalseTemplate, // true || false
inheritedAttrs: [['style', 'class'], stringArrayNullAllowedValues], //string || array || null inheritedAttrs: [['style', 'class'], stringArrayNullAllowedValues], // string || array || null
}, },
callbacks: { callbacks: {
onInitialized: callbackTemplate, //null || function onInitialized: callbackTemplate, // null || function
onInitializationWithdrawn: callbackTemplate, //null || function onInitializationWithdrawn: callbackTemplate, // null || function
onDestroyed: callbackTemplate, //null || function onDestroyed: callbackTemplate, // null || function
onScrollStart: callbackTemplate, //null || function onScrollStart: callbackTemplate, // null || function
onScroll: callbackTemplate, //null || function onScroll: callbackTemplate, // null || function
onScrollStop: callbackTemplate, //null || function onScrollStop: callbackTemplate, // null || function
onOverflowChanged: callbackTemplate, //null || function onOverflowChanged: callbackTemplate, // null || function
onOverflowAmountChanged: callbackTemplate, //null || function onOverflowAmountChanged: callbackTemplate, // null || function
onDirectionChanged: callbackTemplate, //null || function onDirectionChanged: callbackTemplate, // null || function
onContentSizeChanged: callbackTemplate, //null || function onContentSizeChanged: callbackTemplate, // null || function
onHostSizeChanged: callbackTemplate, //null || function onHostSizeChanged: callbackTemplate, // null || function
onUpdated: callbackTemplate //null || function onUpdated: callbackTemplate, // null || function
} },
} };
&nbsp; &nbsp;
export const optionsTemplate: OptionsTemplate&lt;Required&lt;OverlayScrollbars.Options&gt;&gt; = transform(defaultOptionsWithTemplate, true); export const optionsTemplate: OptionsTemplate&lt;Required&lt;OverlayScrollbars.Options&gt;&gt; = transform(defaultOptionsWithTemplate, true);
export const defaultOptions: OverlayScrollbars.Options = transform(defaultOptionsWithTemplate); export const defaultOptions: OverlayScrollbars.Options = transform(defaultOptionsWithTemplate);
&nbsp;
&nbsp;</pre></td></tr></table></pre> &nbsp;</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer --> <div class='push'></div><!-- for sticky footer -->
@@ -310,7 +307,7 @@ export const defaultOptions: OverlayScrollbars.Options = transform(defaultOption
<div class='footer quiet pad2 space-top1 center small'> <div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank">istanbul</a> <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
at Mon Jul 20 2020 17:08:17 GMT+0200 (GMT+02:00) at Sat Jul 25 2020 00:36:56 GMT+0200 (GMT+02:00)
</div> </div>
</div> </div>
<script src="../prettify.js"></script> <script src="../prettify.js"></script>
+519 -531
View File
File diff suppressed because it is too large Load Diff
+10 -20
View File
@@ -1,24 +1,14 @@
const resolve = require('./resolve.config');
// For a detailed explanation regarding each configuration property, visit: // For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html // https://jestjs.io/docs/en/configuration.html
module.exports = { module.exports = {
clearMocks: true, clearMocks: true,
collectCoverage: true, collectCoverage: true,
coverageDirectory: "coverage", coverageDirectory: 'coverage',
moduleDirectories: [ moduleDirectories: resolve.directories,
"src", moduleFileExtensions: resolve.extensions.map((ext) => ext.replace(/\./, '')),
"node_modules", testPathIgnorePatterns: ['\\\\node_modules\\\\', 'src/', 'dist/'],
], verbose: true,
moduleFileExtensions: [ };
"js",
"json",
"jsx",
"ts",
"tsx",
"node"
],
testPathIgnorePatterns: [
"\\\\node_modules\\\\", "./dist"
],
verbose: true,
};
+10356 -8339
View File
File diff suppressed because it is too large Load Diff
+17 -2
View File
@@ -13,16 +13,31 @@
"@rollup/plugin-node-resolve": "^8.4.0", "@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-typescript": "^5.0.2", "@rollup/plugin-typescript": "^5.0.2",
"@types/jest": "^25.2.3", "@types/jest": "^25.2.3",
"@typescript-eslint/eslint-plugin": "^3.7.0",
"@typescript-eslint/parser": "^3.7.0",
"babel-jest": "^26.0.1", "babel-jest": "^26.0.1",
"del": "^5.1.0",
"eslint": "^7.5.0",
"eslint-config-airbnb": "^18.2.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-jest": "^23.18.0",
"eslint-plugin-json": "^2.1.2",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.20.3",
"eslint-plugin-react-hooks": "^4.0.8",
"jest": "^26.0.1", "jest": "^26.0.1",
"prettier-eslint": "^11.0.0",
"rollup": "^2.22.1", "rollup": "^2.22.1",
"rollup-plugin-terser": "^6.1.0", "rollup-plugin-terser": "^6.1.0",
"rollup-plugin-typescript2": "^0.27.1", "rollup-plugin-typescript2": "^0.27.1",
"tslib": "^2.0.0", "tslib": "^2.0.0",
"typescript": "^3.9.3" "typescript": "^3.9.7"
}, },
"scripts": { "scripts": {
"test": "jest --coverage", "test": "jest --coverage",
"build": "npx webpack --env.project=overlayscrollbars" "build": "npx rollup -c --config-project='overlayscrollbars'",
"lint": "npx eslint --fix ."
} }
} }
@@ -0,0 +1,9 @@
{
"legacy": {
"name": "OverlayScrollbars",
"exports": "auto",
"globals": {
"jquery": "jQuery"
}
}
}
@@ -0,0 +1,14 @@
export { default as not } from 'dir/not.png';
import j from 'jquery';
var abc = 'abc';
const a = 1 + 1;
var file = {
a
};
const a$1 = 'a';
const b = 'b';
const c = 'c';
var index = j('div');
export default index;
export { a$1 as a, abc, b, c, file };
//# sourceMappingURL=overlayscrollbars-jquery.esm.js.map
@@ -0,0 +1 @@
{"version":3,"file":"overlayscrollbars-jquery.esm.js","sources":["../src/dir/abc.js","../src/file.js","../src/test.js","../src/index.js"],"sourcesContent":["export default 'abc';\n","const a = 1 + 1;\nexport default {\n a,\n};\n","export const a = 'a';\nexport const b = 'b';\nexport const c = 'c';\n","import abc from 'dir/abc';\nimport not from 'dir/not.png';\nimport file from 'file';\nimport j from 'jquery';\nimport { a, b, c } from 'test';\n\nexport default j('div');\nexport { a, b, c, file, abc, not };\n"],"names":["a","b","c","j"],"mappings":";;AAAA,UAAe,KAAf;ACAA,MAAMA,CAAC,GAAG,IAAI,CAAd;AACA,WAAe;AACbA,EAAAA;AADa,CAAf;ACDY,MAACA,GAAC,GAAG,GAAL;AACA,MAACC,CAAC,GAAG,GAAL;AACA,MAACC,CAAC,GAAG,GAAL;ACIZ,YAAeC,CAAC,CAAC,KAAD,CAAhB;;"}
@@ -0,0 +1 @@
export{default as not}from"dir/not.png";import a from"jquery";var r="abc";var o={a:2};const t="a",e="b",p="c";var d=a("div");export default d;export{t as a,r as abc,e as b,p as c,o as file};
@@ -0,0 +1,24 @@
var OverlayScrollbars = function (exports, not_png, j) {
'use strict';
not_png = not_png && Object.prototype.hasOwnProperty.call(not_png, 'default') ? not_png['default'] : not_png;
j = j && Object.prototype.hasOwnProperty.call(j, 'default') ? j['default'] : j;
var abc = 'abc';
var a = 1 + 1;
var file = {
a: a
};
var a$1 = 'a';
var b = 'b';
var c = 'c';
var index = j('div');
exports.not = not_png;
exports.a = a$1;
exports.abc = abc;
exports.b = b;
exports.c = c;
exports.default = index;
exports.file = file;
return exports;
}({}, not_png, jQuery);
//# sourceMappingURL=overlayscrollbars-jquery.js.map
@@ -0,0 +1 @@
{"version":3,"file":"overlayscrollbars-jquery.js","sources":["../src/dir/abc.js","../src/file.js","../src/test.js","../src/index.js"],"sourcesContent":["export default 'abc';\n","const a = 1 + 1;\nexport default {\n a,\n};\n","export const a = 'a';\nexport const b = 'b';\nexport const c = 'c';\n","import abc from 'dir/abc';\nimport not from 'dir/not.png';\nimport file from 'file';\nimport j from 'jquery';\nimport { a, b, c } from 'test';\n\nexport default j('div');\nexport { a, b, c, file, abc, not };\n"],"names":["a","b","c","j"],"mappings":";;;;;YAAe;ACAf,MAAMA,CAAC,GAAG,IAAI,CAAd;aACe;AACbA,IAAAA,CAAC,EAADA;AADa;MCDFA,GAAC,GAAG;MACJC,CAAC,GAAG;MACJC,CAAC,GAAG;cCIFC,CAAC,CAAC,KAAD;;;;;;;;;"}
@@ -0,0 +1 @@
var OverlayScrollbars=function(t,a,e){"use strict";a=a&&Object.prototype.hasOwnProperty.call(a,"default")?a.default:a;var r={a:2},l=(e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e)("div");return t.not=a,t.a="a",t.abc="abc",t.b="b",t.c="c",t.default=l,t.file=r,t}({},not_png,jQuery);
+27
View File
@@ -0,0 +1,27 @@
{
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/jquery": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.0.tgz",
"integrity": "sha512-C7qQUjpMWDUNYQRTXsP5nbYYwCwwgy84yPgoTT7fPN69NH92wLeCtFaMsWeolJD1AF/6uQw3pYt62rzv83sMmw==",
"dev": true,
"requires": {
"@types/sizzle": "*"
}
},
"@types/sizzle": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
"integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
"dev": true
},
"jquery": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
"integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
}
}
}
@@ -0,0 +1,11 @@
{
"private": true,
"description": "OverlayScrollbars version 2",
"version": "0.0.1",
"peerDependencies": {
"jquery": "^3.5.1"
},
"devDependencies": {
"@types/jquery": "^3.5.0"
}
}
@@ -0,0 +1 @@
export default 'abc';
@@ -0,0 +1,4 @@
const a = 1 + 1;
export default {
a,
};
@@ -0,0 +1,8 @@
import abc from 'dir/abc';
import not from 'dir/not.png';
import file from 'file';
import j from 'jquery';
import { a, b, c } from 'test';
export default j('div');
export { a, b, c, file, abc, not };
@@ -0,0 +1,3 @@
export const a = 'a';
export const b = 'b';
export const c = 'c';
+3 -4
View File
@@ -1,10 +1,9 @@
{ {
"minVersions": true, "legacy": {
"umd": {
"name": "OverlayScrollbars", "name": "OverlayScrollbars",
"exports": "auto",
"globals": { "globals": {
"jquery": "jQuery" "jquery": "jQuery"
} }
}, }
"esm": {}
} }
@@ -0,0 +1,97 @@
function isNumber(obj) {
return typeof obj === 'number';
}
function isFunction(obj) {
return typeof obj === 'function';
}
function isArray(obj) {
return Array.isArray(obj);
}
function isArrayLike(obj) {
const length = !!obj && obj.length;
return isArray(obj) || !isFunction(obj) && isNumber(length) && length > -1 && length % 1 == 0;
}
const keys = obj => Object.keys(obj);
function each(source, callback) {
if (isArrayLike(source)) {
for (let i = 0; i < source.length; i++) {
if (callback(source[i], i, source) === false) {
break;
}
}
} else if (source) {
each(keys(source), key => callback(source[key], key, source));
}
return source;
}
const contents = elm => elm ? Array.from(elm.childNodes) : [];
const removeElements = nodes => {
if (isArrayLike(nodes)) {
each(Array.from(nodes), e => removeElements(e));
} else if (nodes) {
const {
parentNode
} = nodes;
if (parentNode) {
parentNode.removeChild(nodes);
}
}
};
const createDiv = () => document.createElement('div');
const createDOM = html => {
const createdDiv = createDiv();
createdDiv.innerHTML = html.trim();
return each(contents(createdDiv), elm => removeElements(elm));
};
const abc = {
a: 1,
b: 1,
c: 1
};
var index = () => {
const {
a,
b,
c
} = abc;
return [createDOM('\
<div class="os-host">\
<div class="os-resize-observer-host"></div>\
<div class="os-padding">\
<div class="os-viewport">\
<div class="os-content">\
fdfhdfgh\
</div>\
</div>\
</div>\
<div class="os-scrollbar os-scrollbar-horizontal">\
<div class="os-scrollbar-track">\
<div class="os-scrollbar-handle"></div>\
</div>\
</div>\
<div class="os-scrollbar os-scrollbar-vertical">\
<div class="os-scrollbar-track">\
<div class="os-scrollbar-handle"></div>\
</div>\
</div>\
<div class="os-scrollbar-corner"></div>\
</div>'), a, b, c];
};
const a = 1;
export default index;
export { a };
//# sourceMappingURL=overlayscrollbars.esm.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
function r(r){const s=!!r&&r.length;return function(r){return Array.isArray(r)}(r)||!function(r){return"function"==typeof r}(r)&&function(r){return"number"==typeof r}(s)&&s>-1&&s%1==0}function s(o,c){if(r(o))for(let r=0;r<o.length&&!1!==c(o[r],r,o);r++);else o&&s((i=o,Object.keys(i)),r=>c(o[r],r,o));var i;return o}const o=c=>{if(r(c))s(Array.from(c),r=>o(r));else if(c){const{parentNode:r}=c;r&&r.removeChild(c)}},c=r=>{const c=document.createElement("div");return c.innerHTML=r.trim(),s((i=c)?Array.from(i.childNodes):[],r=>o(r));var i},i={a:1,b:1,c:1};const e=1;export default()=>{const{a:r,b:s,c:o}=i;return[c(' <div class="os-host"> <div class="os-resize-observer-host"></div> <div class="os-padding"> <div class="os-viewport"> <div class="os-content"> fdfhdfgh </div> </div> </div> <div class="os-scrollbar os-scrollbar-horizontal"> <div class="os-scrollbar-track"> <div class="os-scrollbar-handle"></div> </div> </div> <div class="os-scrollbar os-scrollbar-vertical"> <div class="os-scrollbar-track"> <div class="os-scrollbar-handle"></div> </div> </div> <div class="os-scrollbar-corner"></div> </div>'),r,s,o]};export{e as a};
+110
View File
@@ -0,0 +1,110 @@
var OverlayScrollbars = function (exports) {
'use strict';
function isNumber(obj) {
return typeof obj === 'number';
}
function isFunction(obj) {
return typeof obj === 'function';
}
function isArray(obj) {
return Array.isArray(obj);
}
function isArrayLike(obj) {
var length = !!obj && obj.length;
return isArray(obj) || !isFunction(obj) && isNumber(length) && length > -1 && length % 1 == 0;
}
var keys = function keys(obj) {
return Object.keys(obj);
};
function each(source, callback) {
if (isArrayLike(source)) {
for (var i = 0; i < source.length; i++) {
if (callback(source[i], i, source) === false) {
break;
}
}
} else if (source) {
each(keys(source), function (key) {
return callback(source[key], key, source);
});
}
return source;
}
var contents = function contents(elm) {
return elm ? Array.from(elm.childNodes) : [];
};
var removeElements = function removeElements(nodes) {
if (isArrayLike(nodes)) {
each(Array.from(nodes), function (e) {
return removeElements(e);
});
} else if (nodes) {
var parentNode = nodes.parentNode;
if (parentNode) {
parentNode.removeChild(nodes);
}
}
};
var createDiv = function createDiv() {
return document.createElement('div');
};
var createDOM = function createDOM(html) {
var createdDiv = createDiv();
createdDiv.innerHTML = html.trim();
return each(contents(createdDiv), function (elm) {
return removeElements(elm);
});
};
var abc = {
a: 1,
b: 1,
c: 1
};
var index = function index() {
var a = abc.a,
b = abc.b,
c = abc.c;
return [createDOM('\
<div class="os-host">\
<div class="os-resize-observer-host"></div>\
<div class="os-padding">\
<div class="os-viewport">\
<div class="os-content">\
fdfhdfgh\
</div>\
</div>\
</div>\
<div class="os-scrollbar os-scrollbar-horizontal">\
<div class="os-scrollbar-track">\
<div class="os-scrollbar-handle"></div>\
</div>\
</div>\
<div class="os-scrollbar os-scrollbar-vertical">\
<div class="os-scrollbar-track">\
<div class="os-scrollbar-handle"></div>\
</div>\
</div>\
<div class="os-scrollbar-corner"></div>\
</div>'), a, b, c];
};
var a = 1;
exports.a = a;
exports.default = index;
return exports;
}({});
//# sourceMappingURL=overlayscrollbars.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
var OverlayScrollbars=function(r){"use strict";function s(r){var s=!!r&&r.length;return function(r){return Array.isArray(r)}(r)||!function(r){return"function"==typeof r}(r)&&function(r){return"number"==typeof r}(s)&&s>-1&&s%1==0}function o(r,i){if(s(r))for(var n=0;n<r.length&&!1!==i(r[n],n,r);n++);else r&&o((a=r,Object.keys(a)),(function(s){return i(r[s],s,r)}));var a;return r}var i=function(r){var i,n=document.createElement("div");return n.innerHTML=r.trim(),o((i=n)?Array.from(i.childNodes):[],(function(r){return function r(i){if(s(i))o(Array.from(i),(function(s){return r(s)}));else if(i){var n=i.parentNode;n&&n.removeChild(i)}}(r)}))},n=1,a=1,e=1;return r.a=1,r.default=function(){var r=n,s=a,o=e;return[i(' <div class="os-host"> <div class="os-resize-observer-host"></div> <div class="os-padding"> <div class="os-viewport"> <div class="os-content"> fdfhdfgh </div> </div> </div> <div class="os-scrollbar os-scrollbar-horizontal"> <div class="os-scrollbar-track"> <div class="os-scrollbar-handle"></div> </div> </div> <div class="os-scrollbar os-scrollbar-vertical"> <div class="os-scrollbar-track"> <div class="os-scrollbar-handle"></div> </div> </div> <div class="os-scrollbar-corner"></div> </div>'),r,s,o]},r}({});
+5 -7
View File
@@ -1,16 +1,14 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="description" content="Server Syncing API Code Challenge" /> <meta name="description" content="Server Syncing API Code Challenge" />
<title>Server Syncing API</title> <title>Server Syncing API</title>
</head> </head>
<body> <body>
<div id="hi">hi</div> <div id="hi">hi</div>
<script type="text/javascript" src="./dist/overlayscrollbars.js"></script> <script type="text/javascript" src="./dist/overlayscrollbars.js"></script>
</body> </body>
</html>
</html>
+19 -19
View File
@@ -1,22 +1,22 @@
{ {
"version": "0.0.1", "version": "0.0.1",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
"@types/jquery": { "@types/jquery": {
"version": "3.5.0", "version": "3.5.0",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.0.tgz", "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.0.tgz",
"integrity": "sha512-C7qQUjpMWDUNYQRTXsP5nbYYwCwwgy84yPgoTT7fPN69NH92wLeCtFaMsWeolJD1AF/6uQw3pYt62rzv83sMmw==", "integrity": "sha512-C7qQUjpMWDUNYQRTXsP5nbYYwCwwgy84yPgoTT7fPN69NH92wLeCtFaMsWeolJD1AF/6uQw3pYt62rzv83sMmw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/sizzle": "*" "@types/sizzle": "*"
} }
}, },
"@types/sizzle": { "@types/sizzle": {
"version": "2.3.2", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
"integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==", "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
"dev": true "dev": true
}
} }
}
} }
+3 -9
View File
@@ -1,11 +1,5 @@
{ {
"private": true, "private": true,
"description": "OverlayScrollbars version 2", "description": "OverlayScrollbars version 2",
"version": "0.0.1", "version": "0.0.1"
"peerDependencies": {
"jquery": "^3.5.1"
},
"devDependencies": {
"@types/jquery": "^3.5.0"
}
} }
@@ -1,3 +1,3 @@
import { jsAPI } from 'core/compatibility/vendors'; import { jsAPI } from 'core/compatibility/vendors';
export const resizeObserver: any | undefined = jsAPI('ResizeObserver'); export const resizeObserver: any | undefined = jsAPI('ResizeObserver');
@@ -1,7 +1,7 @@
export const mouseButton: (event: MouseEvent) => number = (event) => { export const mouseButton: (event: MouseEvent) => number = (event) => {
const button: number = event.button; const { button } = event;
if (!event.which && button !== undefined) if (!event.which && button !== undefined) {
return (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0))); return button & 1 ? 1 : button & 2 ? 3 : button & 4 ? 2 : 0; // eslint-disable-line no-bitwise
else }
return event.which; return event.which;
} };
@@ -1,4 +1,3 @@
export * from 'core/compatibility/vendors'; export * from 'core/compatibility/vendors';
export * from 'core/compatibility/apis'; export * from 'core/compatibility/apis';
export * from 'core/compatibility/events'; export * from 'core/compatibility/events';
@@ -1,14 +1,10 @@
import { each } from 'core/utils'; import { each, hasOwnProperty } from 'core/utils';
import { createDiv } from 'core/dom'; import { createDiv } from 'core/dom';
const firstLetterToUpper: (str: string) => string = (str) => { const firstLetterToUpper: (str: string) => string = (str) => str.charAt(0).toUpperCase() + str.slice(1);
return str.charAt(0).toUpperCase() + str.slice(1); const getDummyStyle: () => CSSStyleDeclaration = () => createDiv().style;
}
const getDummyStyle: () => CSSStyleDeclaration = () => {
return createDiv().style;
}
//https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix // https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix
export const cssPrefixes: ReadonlyArray<string> = ['-webkit-', '-moz-', '-o-', '-ms-']; export const cssPrefixes: ReadonlyArray<string> = ['-webkit-', '-moz-', '-o-', '-ms-'];
export const jsPrefixes: ReadonlyArray<string> = ['WebKit', 'Moz', 'O', 'MS', 'webkit', 'moz', 'o', 'ms']; export const jsPrefixes: ReadonlyArray<string> = ['WebKit', 'Moz', 'O', 'MS', 'webkit', 'moz', 'o', 'ms'];
@@ -21,79 +17,82 @@ export const cssCache: { [key: string]: string } = {};
* @param name The name of the CSS property which shall be get. * @param name The name of the CSS property which shall be get.
*/ */
export const cssProperty: (name: string) => string | undefined = (name) => { export const cssProperty: (name: string) => string | undefined = (name) => {
let result: string | undefined = cssCache[name]; let result: string | undefined = cssCache[name];
if (cssCache.hasOwnProperty(name)) if (hasOwnProperty(cssCache, name)) {
return result;
const uppercasedName: string = firstLetterToUpper(name);
const elmStyle: CSSStyleDeclaration = getDummyStyle();
each(cssPrefixes, (prefix: string) => {
const prefixWithoutDashes: string = prefix.replace(/-/g, '');
const resultPossibilities: Array<string> = [
name, //transition
prefix + name, //-webkit-transition
prefixWithoutDashes + uppercasedName, //webkitTransition
firstLetterToUpper(prefixWithoutDashes) + uppercasedName //WebkitTransition
];
result = resultPossibilities.find((resultPossibility: string) => elmStyle[resultPossibility] !== undefined);
return !result;
});
cssCache[name] = result;
return result; return result;
} }
const uppercasedName: string = firstLetterToUpper(name);
const elmStyle: CSSStyleDeclaration = getDummyStyle();
each(cssPrefixes, (prefix: string) => {
const prefixWithoutDashes: string = prefix.replace(/-/g, '');
const resultPossibilities: Array<string> = [
name, // transition
prefix + name, // -webkit-transition
prefixWithoutDashes + uppercasedName, // webkitTransition
firstLetterToUpper(prefixWithoutDashes) + uppercasedName, // WebkitTransition
];
result = resultPossibilities.find((resultPossibility: string) => elmStyle[resultPossibility] !== undefined);
return !result;
});
cssCache[name] = result;
return result;
};
/** /**
* Get the name of the given CSS property value(s), with vendor prefix if it isn't supported wuthout, or undefined if no value is supported. * Get the name of the given CSS property value(s), with vendor prefix if it isn't supported wuthout, or undefined if no value is supported.
* @param property The CSS property to which the CSS property value(s) belong. * @param property The CSS property to which the CSS property value(s) belong.
* @param values The value(s) separated by spaces which shall be get. * @param values The value(s) separated by spaces which shall be get.
* @param suffix A suffix which is added to each value in case the value is a function or something else more advanced. * @param suffix A suffix which is added to each value in case the value is a function or something else more advanced.
*/ */
export const cssPropertyValue: (property: string, values: string, suffix?: string) => string | undefined = (property, values, suffix) => { export const cssPropertyValue: (property: string, values: string, suffix?: string) => string | undefined = (property, values, suffix) => {
const name: string = property + ' ' + values; const name = `${property} ${values}`;
let result: string | undefined = cssCache[name]; let result: string | undefined = cssCache[name];
if (cssCache.hasOwnProperty(name)) if (hasOwnProperty(cssCache, name)) {
return result;
const dummyStyle: CSSStyleDeclaration = getDummyStyle();
const possbleValues: Array<string> = values.split(' ');
const preparedSuffix: string = suffix || '';
const cssPrefixesWithFirstEmpty = [''].concat(cssPrefixes);
each(possbleValues, (possibleValue: string) => {
each(cssPrefixesWithFirstEmpty, (prefix: string) => {
const prop = prefix + possibleValue;
dummyStyle.cssText = property + ':' + prop + preparedSuffix;
if (dummyStyle.length) {
result = prop;
return false;
}
});
return !result;
});
cssCache[name] = result;
return result; return result;
} }
const dummyStyle: CSSStyleDeclaration = getDummyStyle();
const possbleValues: Array<string> = values.split(' ');
const preparedSuffix: string = suffix || '';
const cssPrefixesWithFirstEmpty = [''].concat(cssPrefixes);
each(possbleValues, (possibleValue: string) => {
each(cssPrefixesWithFirstEmpty, (prefix: string) => {
const prop = prefix + possibleValue;
dummyStyle.cssText = `${property}:${prop}${preparedSuffix}`;
if (dummyStyle.length) {
result = prop;
return false;
}
});
return !result;
});
cssCache[name] = result;
return result;
};
/** /**
* Get the requested JS function, object or constructor with vendor prefix if it isn't supported without or undefined if unsupported. * Get the requested JS function, object or constructor with vendor prefix if it isn't supported without or undefined if unsupported.
* @param name The name of the JS function, object or constructor. * @param name The name of the JS function, object or constructor.
*/ */
export const jsAPI: (name: string) => any = (name) => { export const jsAPI: (name: string) => any = (name) => {
let result: any = jsCache[name] || window[name]; let result: any = jsCache[name] || window[name];
if (jsCache.hasOwnProperty(name)) if (hasOwnProperty(jsCache, name)) {
return result;
each(jsPrefixes, (prefix: string) => {
result = result || window[prefix + firstLetterToUpper(name)];
return !result;
});
jsCache[name] = result;
return result; return result;
} }
each(jsPrefixes, (prefix: string) => {
result = result || window[prefix + firstLetterToUpper(name)];
return !result;
});
jsCache[name] = result;
return result;
};
@@ -6,10 +6,11 @@
* @param value The value of the attribute which shall be set. * @param value The value of the attribute which shall be set.
*/ */
export const attr: (elm: Element, attrName: string, value?: string) => string | null | void = (elm, attrName, value) => { export const attr: (elm: Element, attrName: string, value?: string) => string | null | void = (elm, attrName, value) => {
if (value === undefined) if (value === undefined) {
return elm.getAttribute(attrName); return elm.getAttribute(attrName);
elm.setAttribute(attrName, value); }
} elm.setAttribute(attrName, value);
};
/** /**
* Removes the given attribute from the given element. * Removes the given attribute from the given element.
@@ -17,8 +18,8 @@ export const attr: (elm: Element, attrName: string, value?: string) => string |
* @param attrName The attribute name. * @param attrName The attribute name.
*/ */
export const removeAttr: (elm: Element, attrName: string) => void = (elm, attrName) => { export const removeAttr: (elm: Element, attrName: string) => void = (elm, attrName) => {
elm.removeAttribute(attrName); elm.removeAttribute(attrName);
} };
/** /**
* Gets or sets the scrollLeft value of the given element depending whether the value attribute is given. * Gets or sets the scrollLeft value of the given element depending whether the value attribute is given.
@@ -26,10 +27,11 @@ export const removeAttr: (elm: Element, attrName: string) => void = (elm, attrNa
* @param value The scrollLeft value which shall be set. * @param value The scrollLeft value which shall be set.
*/ */
export const scrollLeft: (elm: HTMLElement, value?: number) => number | void = (elm, value) => { export const scrollLeft: (elm: HTMLElement, value?: number) => number | void = (elm, value) => {
if (value === undefined) if (value === undefined) {
return elm.scrollLeft; return elm.scrollLeft;
elm.scrollLeft = value; }
} elm.scrollLeft = value;
};
/** /**
* Gets or sets the scrollTop value of the given element depending whether the value attribute is given. * Gets or sets the scrollTop value of the given element depending whether the value attribute is given.
@@ -37,10 +39,11 @@ export const scrollLeft: (elm: HTMLElement, value?: number) => number | void = (
* @param value The scrollTop value which shall be set. * @param value The scrollTop value which shall be set.
*/ */
export const scrollTop: (elm: HTMLElement, value?: number) => number | void = (elm, value) => { export const scrollTop: (elm: HTMLElement, value?: number) => number | void = (elm, value) => {
if (value === undefined) if (value === undefined) {
return elm.scrollTop; return elm.scrollTop;
elm.scrollTop = value; }
} elm.scrollTop = value;
};
/** /**
* Gets or sets the value of the given input element depending whether the value attribute is given. * Gets or sets the value of the given input element depending whether the value attribute is given.
@@ -48,7 +51,8 @@ export const scrollTop: (elm: HTMLElement, value?: number) => number | void = (e
* @param value The value which shall be set. * @param value The value which shall be set.
*/ */
export const val: (elm: HTMLInputElement, value?: string) => string | void = (elm, value) => { export const val: (elm: HTMLInputElement, value?: string) => string | void = (elm, value) => {
if (value === undefined) if (value === undefined) {
return elm.value; return elm.value;
elm.value = value; }
} elm.value = value;
};
@@ -1,15 +1,13 @@
import { isString } from 'core/utils/types'; import { isString } from 'core/utils/types';
const rnothtmlwhite: RegExp = (/[^\x20\t\r\n\f]+/g); const rnothtmlwhite = /[^\x20\t\r\n\f]+/g;
/** /**
* Check whether the given element has the given class name. * Check whether the given element has the given class name.
* @param elm The element. * @param elm The element.
* @param className The class name. * @param className The class name.
*/ */
export const hasClass: (elm: Element, className: string) => boolean = (elm, className) => { export const hasClass: (elm: Element, className: string) => boolean = (elm, className) => elm.classList.contains(className);
return elm.classList.contains(className);
}
/** /**
* Adds the given class name(s) to the given element. * Adds the given class name(s) to the given element.
@@ -17,15 +15,16 @@ export const hasClass: (elm: Element, className: string) => boolean = (elm, clas
* @param className The class name(s) which shall be added. (separated by spaces) * @param className The class name(s) which shall be added. (separated by spaces)
*/ */
export const addClass: (elm: Element, className: string) => void = (elm, className) => { export const addClass: (elm: Element, className: string) => void = (elm, className) => {
let clazz: string; let clazz: string;
let i: number = 0; let i = 0;
if (isString(className)) { if (isString(className)) {
const classes: Array<string> = className.match(rnothtmlwhite) || []; const classes: Array<string> = className.match(rnothtmlwhite) || [];
while ((clazz = classes[i++])) while ((clazz = classes[i++])) {
elm.classList.add(clazz); elm.classList.add(clazz);
} }
} }
};
/** /**
* Removes the given class name(s) from the given element. * Removes the given class name(s) from the given element.
@@ -33,15 +32,16 @@ export const addClass: (elm: Element, className: string) => void = (elm, classNa
* @param className The class name(s) which shall be removed. (separated by spaces) * @param className The class name(s) which shall be removed. (separated by spaces)
*/ */
export const removeClass: (elm: Element, className: string) => void = (elm, className) => { export const removeClass: (elm: Element, className: string) => void = (elm, className) => {
let clazz: string; let clazz: string;
let i: number = 0; let i = 0;
if (isString(className)) { if (isString(className)) {
const classes: Array<string> = className.match(rnothtmlwhite) || []; const classes: Array<string> = className.match(rnothtmlwhite) || [];
while ((clazz = classes[i++])) while ((clazz = classes[i++])) {
elm.classList.remove(clazz); elm.classList.remove(clazz);
} }
} }
};
/** /**
* Adds or removes the given class name(s) from the given element depending on the given condition. * Adds or removes the given class name(s) from the given element depending on the given condition.
@@ -50,10 +50,9 @@ export const removeClass: (elm: Element, className: string) => void = (elm, clas
* @param className The class name(s) which shall be added or removed. (separated by spaces) * @param className The class name(s) which shall be added or removed. (separated by spaces)
*/ */
export const conditionalClass: (elm: Element, className: string, condition: boolean) => void = (elm, className, condition) => { export const conditionalClass: (elm: Element, className: string, condition: boolean) => void = (elm, className, condition) => {
if (condition) { if (condition) {
addClass(elm, className); addClass(elm, className);
} } else {
else { removeClass(elm, className);
removeClass(elm, className); }
} };
}
@@ -1,14 +1,12 @@
import { each } from 'core/utils/arrays'; import { each } from 'core/utils/array';
import { contents } from 'core/dom/traversal'; import { contents } from 'core/dom/traversal';
import { removeElements } from 'core/dom/manipulation'; import { removeElements } from 'core/dom/manipulation';
export const createDiv: () => HTMLDivElement = () => { export const createDiv: () => HTMLDivElement = () => document.createElement('div');
return document.createElement('div');
}
export const createDOM: (html: string) => ReadonlyArray<Node> = (html) => { export const createDOM: (html: string) => ReadonlyArray<Node> = (html) => {
const elm = createDiv(); const createdDiv = createDiv();
elm.innerHTML = html.trim(); createdDiv.innerHTML = html.trim();
return each(contents(elm), (elm) => removeElements(elm)); return each(contents(createdDiv), (elm) => removeElements(elm));
} };
@@ -1,7 +1,7 @@
export * from 'core/dom/attributes'; export * from 'core/dom/attribute';
export * from 'core/dom/classes'; export * from 'core/dom/class';
export * from 'core/dom/create'; export * from 'core/dom/create';
export * from 'core/dom/style'; export * from 'core/dom/style';
export * from 'core/dom/manipulation'; export * from 'core/dom/manipulation';
export * from 'core/dom/offset'; export * from 'core/dom/offset';
export * from 'core/dom/traversal'; export * from 'core/dom/traversal';
@@ -1,91 +1,101 @@
import { isArrayLike, isHTMLElement } from 'core/utils/types'; import { isArrayLike } from 'core/utils/types';
import { each } from 'core/utils/arrays'; import { each } from 'core/utils/array';
import { parent } from 'core/dom/traversal'; import { parent } from 'core/dom/traversal';
type NodeCollection = ArrayLike<Node> | Node | undefined | null; type NodeCollection = ArrayLike<Node> | Node | undefined | null;
/** /**
* Inserts Nodes before the given preferredAnchor element. * Inserts Nodes before the given preferredAnchor element.
* @param parent The parent of the preferredAnchor element or the element which shall be the parent of the inserted Nodes. * @param parentElm The parent of the preferredAnchor element or the element which shall be the parent of the inserted Nodes.
* @param preferredAnchor The element before which the Nodes shall be inserted or null if the elements shall be appended at the end. * @param preferredAnchor The element before which the Nodes shall be inserted or null if the elements shall be appended at the end.
* @param insertedElms The Nodes which shall be inserted. * @param insertedElms The Nodes which shall be inserted.
*/ */
const before: (parent: Node | null, preferredAnchor: Node | null, insertedElms: NodeCollection) => void = (parent, preferredAnchor, insertedElms) => { const before: (parentElm: Node | null, preferredAnchor: Node | null, insertedElms: NodeCollection) => void = (
if (insertedElms) { parentElm,
let anchor: Node | null = preferredAnchor; preferredAnchor,
let fragment: DocumentFragment | Node | undefined | null; insertedElms,
) => {
if (insertedElms) {
let anchor: Node | null = preferredAnchor;
let fragment: DocumentFragment | Node | undefined | null;
// parent must be defined // parent must be defined
if (parent) { if (parentElm) {
if (isArrayLike(insertedElms)) { if (isArrayLike(insertedElms)) {
fragment = document.createDocumentFragment(); fragment = document.createDocumentFragment();
// append all insertedElms to the fragment and if one of these is the anchor, change the anchor // append all insertedElms to the fragment and if one of these is the anchor, change the anchor
each(insertedElms, (insertedElm) => { each(insertedElms, (insertedElm) => {
if (insertedElm === anchor) { if (insertedElm === anchor) {
anchor = insertedElm.previousSibling; anchor = insertedElm.previousSibling;
} }
fragment!.appendChild(insertedElm); fragment!.appendChild(insertedElm);
}); });
} } else {
else { fragment = insertedElms;
fragment = insertedElms; }
}
// if the preferred anchor isn't null set it to a valid anchor // if the preferred anchor isn't null set it to a valid anchor
if (preferredAnchor) { if (preferredAnchor) {
if (!anchor) { if (!anchor) {
anchor = parent.firstChild; anchor = parentElm.firstChild;
} } else if (anchor !== preferredAnchor) {
else if (anchor !== preferredAnchor) { anchor = anchor.nextSibling;
anchor = anchor.nextSibling;
}
}
parent.insertBefore(fragment, anchor);
} }
}
parentElm.insertBefore(fragment, anchor);
} }
} }
};
/** /**
* Appends the given children at the end of the given Node. * Appends the given children at the end of the given Node.
* @param node The Node to which the children shall be appended. * @param node The Node to which the children shall be appended.
* @param children The Nodes which shall be appended. * @param children The Nodes which shall be appended.
*/ */
export const appendChildren: (node: Node | null, children: NodeCollection) => void = (node, children) => { before(node, null, children) }; export const appendChildren: (node: Node | null, children: NodeCollection) => void = (node, children) => {
before(node, null, children);
};
/** /**
* Prepends the given children at the start of the given Node. * Prepends the given children at the start of the given Node.
* @param node The Node to which the children shall be prepended. * @param node The Node to which the children shall be prepended.
* @param children The Nodes which shall be prepended. * @param children The Nodes which shall be prepended.
*/ */
export const prependChildren: (node: Node | null, children: NodeCollection) => void = (node, children) => { before(node, node && node.firstChild, children) }; export const prependChildren: (node: Node | null, children: NodeCollection) => void = (node, children) => {
before(node, node && node.firstChild, children);
};
/** /**
* Inserts the given Nodes before the given Node. * Inserts the given Nodes before the given Node.
* @param node The Node before which the given Nodes shall be inserted. * @param node The Node before which the given Nodes shall be inserted.
* @param insertedNodes The Nodes which shall be inserted. * @param insertedNodes The Nodes which shall be inserted.
*/ */
export const insertBefore: (node: Node | null, insertedNodes: NodeCollection) => void = (node, insertedNodes) => { before(parent(node), node, insertedNodes) }; export const insertBefore: (node: Node | null, insertedNodes: NodeCollection) => void = (node, insertedNodes) => {
before(parent(node), node, insertedNodes);
};
/** /**
* Inserts the given Nodes after the given Node. * Inserts the given Nodes after the given Node.
* @param node The Node after which the given Nodes shall be inserted. * @param node The Node after which the given Nodes shall be inserted.
* @param insertedNodes The Nodes which shall be inserted. * @param insertedNodes The Nodes which shall be inserted.
*/ */
export const insertAfter: (node: Node | null, insertedNodes: NodeCollection) => void = (node, insertedNodes) => { before(parent(node), node && node.nextSibling, insertedNodes) }; export const insertAfter: (node: Node | null, insertedNodes: NodeCollection) => void = (node, insertedNodes) => {
before(parent(node), node && node.nextSibling, insertedNodes);
};
/** /**
* Removes the given Nodes from their parent. * Removes the given Nodes from their parent.
* @param nodes The Nodes which shall be removed. * @param nodes The Nodes which shall be removed.
*/ */
export const removeElements: (nodes: NodeCollection) => void = (nodes) => { export const removeElements: (nodes: NodeCollection) => void = (nodes) => {
if (isArrayLike(nodes)) { if (isArrayLike(nodes)) {
each(Array.from(nodes), (e) => removeElements(e)); each(Array.from(nodes), (e) => removeElements(e));
} else if (nodes) {
const { parentNode } = nodes;
if (parentNode) {
parentNode.removeChild(nodes);
} }
else if (nodes) { }
const parentNode = nodes.parentNode; };
if (parentNode)
parentNode.removeChild(nodes);
}
}
@@ -1,14 +1,12 @@
export const offset = (elm: HTMLElement) => { export const offset = (elm: HTMLElement) => {
const rect = elm.getBoundingClientRect(); const rect = elm.getBoundingClientRect();
return { return {
top: rect.top + window.pageXOffset, top: rect.top + window.pageXOffset,
left: rect.left + window.pageYOffset left: rect.left + window.pageYOffset,
}; };
} };
export const position = (elm: HTMLElement) => { export const position = (elm: HTMLElement) => ({
return { top: elm.offsetTop,
top: elm.offsetTop, left: elm.offsetLeft,
left: elm.offsetLeft });
};
}
@@ -1,62 +1,57 @@
import { keys } from 'core/utils/object';
import { isString, isNumber, isUndefined } from 'core/utils/types'; import { isString, isNumber, isUndefined } from 'core/utils/types';
type cssStyleObj = { [key: string]: string | number }; type cssStyleObj = { [key: string]: string | number };
const cssNumber = { const cssNumber = {
animationIterationCount: true, animationIterationCount: true,
columnCount: true, columnCount: true,
fillOpacity: true, fillOpacity: true,
flexGrow: true, flexGrow: true,
flexShrink: true, flexShrink: true,
fontWeight: true, fontWeight: true,
lineHeight: true, lineHeight: true,
opacity: true, opacity: true,
order: true, order: true,
orphans: true, orphans: true,
widows: true, widows: true,
zIndex: true, zIndex: true,
zoom: true zoom: true,
}; };
const setCSSVal: (elm: HTMLElement, prop: string, val: string | number) => void = (elm, prop, val) => { const parseCSSVal: (prop: string, val: string | number) => string | number = (prop, val) =>
try { !cssNumber[prop.toLowerCase()] && isNumber(val) ? `${val}px` : val;
if (elm.style[prop] !== undefined) {
elm.style[prop] = parseCSSVal(prop, val);
}
} catch (e) { }
}
const parseCSSVal: (prop: string, val: string | number) => string | number = (prop, val) => { const setCSSVal: (elm: HTMLElement, prop: string, val: string | number) => void = (elm, prop, val) => {
return !cssNumber[prop.toLowerCase()] && isNumber(val) ? val + 'px' : val; try {
} if (elm.style[prop] !== undefined) {
elm.style[prop] = parseCSSVal(prop, val);
}
} catch (e) {}
};
export function style(elm: HTMLElement, styles: string | cssStyleObj): string; export function style(elm: HTMLElement, styles: string | cssStyleObj): string;
export function style(elm: HTMLElement, styles: string | cssStyleObj, val: string | number): void; export function style(elm: HTMLElement, styles: string | cssStyleObj, val: string | number): void;
export function style(elm: HTMLElement, styles: string | cssStyleObj, val?: string | number): string | void { export function style(elm: HTMLElement, styles: string | cssStyleObj, val?: string | number): string | void {
const getCptStyle: Function = window.getComputedStyle; const getCptStyle = window.getComputedStyle;
if (isString(styles)) { if (isString(styles)) {
if (isUndefined(val)) { if (isUndefined(val)) {
const cptStyle: CSSStyleDeclaration = getCptStyle(elm, null); const cptStyle: CSSStyleDeclaration = getCptStyle(elm, null);
//https://bugzilla.mozilla.org/show_bug.cgi?id=548397 can be null sometimes if iframe with display: none (firefox only!) // https://bugzilla.mozilla.org/show_bug.cgi?id=548397 can be null sometimes if iframe with display: none (firefox only!)
return cptStyle != null ? cptStyle.getPropertyValue(styles) : elm.style[styles]; return cptStyle != null ? cptStyle.getPropertyValue(styles) : elm.style[styles];
}
else {
setCSSVal(elm, styles, val);
}
}
else {
for (const key in styles)
setCSSVal(elm, key, styles[key]);
} }
setCSSVal(elm, styles, val);
} else {
keys(styles).forEach((key) => setCSSVal(elm, key, styles[key]));
}
} }
export const hide: (elm: HTMLElement) => void = (elm) => { export const hide: (elm: HTMLElement) => void = (elm) => {
elm.style.display = 'none'; elm.style.display = 'none';
} };
export const show: (elm: HTMLElement) => void = (elm) => { export const show: (elm: HTMLElement) => void = (elm) => {
elm.style.display = 'block'; elm.style.display = 'block';
} };
@@ -1,52 +1,50 @@
import { each } from 'core/utils/arrays'; import { each } from 'core/utils/array';
const elementIsVisible: (elm: HTMLElement) => boolean = (elm) => { const elementIsVisible: (elm: HTMLElement) => boolean = (elm) => !!(elm.offsetWidth || elm.offsetHeight || elm.getClientRects().length);
return !!(elm.offsetWidth || elm.offsetHeight || elm.getClientRects().length);
}
export const find: (selector: string, elm?: Element | null) => ReadonlyArray<Element> = (selector, elm?) => { export const find: (selector: string, elm?: Element | null) => ReadonlyArray<Element> = (selector, elm?) => {
const arr: Array<Element> = []; const arr: Array<Element> = [];
each((elm || document).querySelectorAll(selector), (e: Element) => { each((elm || document).querySelectorAll(selector), (e: Element) => {
arr.push(e); arr.push(e);
}); });
return arr; return arr;
} };
export const findFirst: (selector: string, elm?: Element | null) => Element | null = (selector, elm?) => { export const findFirst: (selector: string, elm?: Element | null) => Element | null = (selector, elm?) => (elm || document).querySelector(selector);
return (elm || document).querySelector(selector);
}
export const is: (elm: Element | null, selector: string) => boolean = (elm, selector) => { export const is: (elm: Element | null, selector: string) => boolean = (elm, selector) => {
if (elm) { if (elm) {
if (selector === ':visible') if (selector === ':visible') {
return elementIsVisible(elm as HTMLElement); return elementIsVisible(elm as HTMLElement);
if (selector === ':hidden')
return !elementIsVisible(elm as HTMLElement);
if (elm.matches(selector))
return true;
} }
return false; if (selector === ':hidden') {
} return !elementIsVisible(elm as HTMLElement);
}
if (elm.matches(selector)) {
return true;
}
}
return false;
};
export const children: (elm: Element | null, selector?: string) => ReadonlyArray<Element> = (elm, selector?) => { export const children: (elm: Element | null, selector?: string) => ReadonlyArray<Element> = (elm, selector?) => {
const children: Array<Element> = []; const childs: Array<Element> = [];
each(elm && elm.children, (child: Element) => { each(elm && elm.children, (child: Element) => {
if (selector) { if (selector) {
if (child.matches(selector)) if (child.matches(selector)) {
children.push(child); childs.push(child);
} }
else } else {
children.push(child); childs.push(child);
}); }
});
return children; return childs;
} };
export const contents: (elm: Element | null) => ReadonlyArray<ChildNode> = (elm) => { export const contents: (elm: Element | null) => ReadonlyArray<ChildNode> = (elm) => (elm ? Array.from<ChildNode>(elm.childNodes) : []);
return elm ? Array.from<ChildNode>(elm.childNodes) : [];
}
export const parent: (elm: Node | null) => Node | null = (elm) => elm ? elm.parentElement : null; export const parent: (elm: Node | null) => Node | null = (elm) => (elm ? elm.parentElement : null);
@@ -1,2 +1,2 @@
export * from 'core/options/validation'; export * from 'core/options/validation';
export * from 'core/options/transformation'; export * from 'core/options/transformation';
@@ -1,6 +1,6 @@
import { OptionsTemplate, OptionsAndOptionsTemplate, PlainObject, OptionsTemplateTypes } from "core/typings"; import { OptionsTemplate, OptionsAndOptionsTemplate, PlainObject, OptionsTemplateTypes } from 'core/typings';
import { isArray, isObject } from "core/utils/types"; import { isArray, isObject } from 'core/utils/types';
import { each } from "core/utils/arrays"; import { each, keys } from 'core/utils';
/** /**
* Transforms the given OptionsAndOptionsTemplate<T> object to its corresponding generic (T) Object or its corresponding Template object. * Transforms the given OptionsAndOptionsTemplate<T> object to its corresponding generic (T) Object or its corresponding Template object.
@@ -8,19 +8,26 @@ import { each } from "core/utils/arrays";
* @param toTemplate True if the given OptionsAndOptionsTemplate<T> shall be converted to its corresponding Template object. * @param toTemplate True if the given OptionsAndOptionsTemplate<T> shall be converted to its corresponding Template object.
*/ */
export function transform<T extends Required<T>>(optionsWithOptionsTemplate: OptionsAndOptionsTemplate<T>): T; export function transform<T extends Required<T>>(optionsWithOptionsTemplate: OptionsAndOptionsTemplate<T>): T;
export function transform<T extends Required<T>>(optionsWithOptionsTemplate: OptionsAndOptionsTemplate<T>, toTemplate: true | void): OptionsTemplate<T>; export function transform<T extends Required<T>>(
export function transform<T extends Required<T>>(optionsWithOptionsTemplate: OptionsAndOptionsTemplate<T>, toTemplate?: true | void): OptionsTemplate<T> | T { optionsWithOptionsTemplate: OptionsAndOptionsTemplate<T>,
const result: any = {}; toTemplate: true | void,
): OptionsTemplate<T>;
export function transform<T extends Required<T>>(
optionsWithOptionsTemplate: OptionsAndOptionsTemplate<T>,
toTemplate?: true | void,
): OptionsTemplate<T> | T {
const result: any = {};
each(Object.keys(optionsWithOptionsTemplate), (key: Extract<keyof T, string>) => { each(keys(optionsWithOptionsTemplate), (key: Extract<keyof T, string>) => {
const val: PlainObject | OptionsTemplateTypes | Array<OptionsTemplateTypes> = optionsWithOptionsTemplate[key]; const val: PlainObject | OptionsTemplateTypes | Array<OptionsTemplateTypes> = optionsWithOptionsTemplate[key];
/* istanbul ignore else */ /* istanbul ignore else */
if (isArray(val)) if (isArray(val)) {
result[key] = val[toTemplate ? 1 : 0]; result[key] = val[toTemplate ? 1 : 0];
else if (isObject(val)) } else if (isObject(val)) {
result[key] = transform(val as OptionsAndOptionsTemplate<typeof val>, toTemplate); result[key] = transform(val as OptionsAndOptionsTemplate<typeof val>, toTemplate);
}); }
});
return result; return result;
}; }
@@ -1,8 +1,16 @@
import { each, indexOf } from 'core/utils/arrays'; import { each, indexOf, hasOwnProperty, keys } from 'core/utils';
import { type, isArray, isUndefined, isEmptyObject, isPlainObject, isString } from 'core/utils/types'; import { type, isArray, isUndefined, isEmptyObject, isPlainObject, isString } from 'core/utils/types';
import { PlainObject, OptionsTemplate, OptionsTemplateTypes, OptionsTemplateType, OptionsValidated, Func, OptionsValidatedResult } from 'core/typings'; import {
PlainObject,
OptionsTemplate,
OptionsTemplateTypes,
OptionsTemplateType,
OptionsValidated,
Func,
OptionsValidatedResult,
} from 'core/typings';
const stringify = JSON.stringify; const { stringify } = JSON;
/** /**
* A prefix and suffix tuple which serves as recognition pattern for template types. * A prefix and suffix tuple which serves as recognition pattern for template types.
@@ -13,18 +21,13 @@ const templateTypePrefixSuffix: readonly [string, string] = ['__TPL_', '_TYPE__'
* Key = normal type string * Key = normal type string
* value = template type string * value = template type string
*/ */
const optionsTemplateTypes: OptionsTemplateTypesDictionary = [ const optionsTemplateTypes: OptionsTemplateTypesDictionary = ['boolean', 'number', 'string', 'array', 'object', 'function', 'null'].reduce(
'boolean', (result, item) => {
'number',
'string',
'array',
'object',
'function',
'null'
].reduce((result, item) => {
result[item] = templateTypePrefixSuffix[0] + item + templateTypePrefixSuffix[1]; result[item] = templateTypePrefixSuffix[0] + item + templateTypePrefixSuffix[1];
return result; return result;
}, {} as OptionsTemplateTypesDictionary); },
{} as OptionsTemplateTypesDictionary,
);
/** /**
* Validates the given options object according to the given template object and returns a object which looks like: * Validates the given options object according to the given template object and returns a object which looks like:
@@ -35,7 +38,7 @@ const optionsTemplateTypes: OptionsTemplateTypesDictionary = [
* @param options The options object which shall be validated. * @param options The options object which shall be validated.
* @param template The template according to which the options object shall be validated. * @param template The template according to which the options object shall be validated.
* @param optionsDiff When provided the returned validated object will only have properties which are different to this objects properties. * @param optionsDiff When provided the returned validated object will only have properties which are different to this objects properties.
* Example (assume all properties are valid to the template): * Example (assume all properties are valid to the template):
* Options object : { a: 'a', b: 'b', c: 'c' } * Options object : { a: 'a', b: 'b', c: 'c' }
* optionsDiff object : { a: 'a', b: 'b', c: undefined } * optionsDiff object : { a: 'a', b: 'b', c: undefined }
* Returned validated object : { c: 'c' } * Returned validated object : { c: 'c' }
@@ -44,80 +47,87 @@ const optionsTemplateTypes: OptionsTemplateTypesDictionary = [
* @param doWriteErrors True if errors shall be logged into the console, false otherwise. * @param doWriteErrors True if errors shall be logged into the console, false otherwise.
* @param propPath The propertyPath which lead to this object. (used for error logging) * @param propPath The propertyPath which lead to this object. (used for error logging)
*/ */
const validateRecursive = function <T extends PlainObject>(options: T, template: OptionsTemplate<Required<T>>, optionsDiff: OptionsValidated<T>, doWriteErrors?: boolean, propPath?: string): OptionsValidatedResult<T> { const validateRecursive = function <T extends PlainObject>(
const validatedOptions: OptionsValidated<T> = {}; options: T,
const optionsCopy: T = Object.assign({}, options); template: OptionsTemplate<Required<T>>,
const props = Object.keys(template).filter(prop => options.hasOwnProperty(prop)); optionsDiff: OptionsValidated<T>,
doWriteErrors?: boolean,
propPath?: string,
): OptionsValidatedResult<T> {
const validatedOptions: OptionsValidated<T> = {};
const optionsCopy: T = { ...options };
const props = keys(template).filter((prop) => hasOwnProperty(options, prop));
each(props, (prop: Extract<keyof T, string>) => { each(props, (prop: Extract<keyof T, string>) => {
const optionsDiffValue: any = isUndefined(optionsDiff[prop]) ? {} : optionsDiff[prop]; const optionsDiffValue: any = isUndefined(optionsDiff[prop]) ? {} : optionsDiff[prop];
const optionsValue: any = options[prop]; const optionsValue: any = options[prop];
const templateValue: PlainObject | string | OptionsTemplateTypes | Array<OptionsTemplateTypes> = template[prop]; const templateValue: PlainObject | string | OptionsTemplateTypes | Array<OptionsTemplateTypes> = template[prop];
const templateIsComplex = isPlainObject(templateValue); const templateIsComplex = isPlainObject(templateValue);
const propPrefix = propPath ? propPath + '.' : ''; const propPrefix = propPath ? `${propPath}.` : '';
//if the template has a object as value, it means that the options are complex (verschachtelt) // if the template has a object as value, it means that the options are complex (verschachtelt)
if (templateIsComplex && isPlainObject(optionsValue)) { if (templateIsComplex && isPlainObject(optionsValue)) {
const validatedResult = validateRecursive(optionsValue, templateValue as PlainObject, optionsDiffValue, doWriteErrors, propPrefix + prop); const validatedResult = validateRecursive(optionsValue, templateValue as PlainObject, optionsDiffValue, doWriteErrors, propPrefix + prop);
validatedOptions[prop] = validatedResult.validated; validatedOptions[prop] = validatedResult.validated;
optionsCopy[prop] = validatedResult.foreign as any; optionsCopy[prop] = validatedResult.foreign as any;
each([optionsCopy, validatedOptions], (value) => { each([optionsCopy, validatedOptions], (value) => {
if (isEmptyObject(value[prop])) { if (isEmptyObject(value[prop])) {
delete value[prop]; delete value[prop];
}
});
} }
else if (!templateIsComplex) { });
let isValid = false; } else if (!templateIsComplex) {
const errorEnumStrings: Array<string> = []; let isValid = false;
const errorPossibleTypes: Array<string> = []; const errorEnumStrings: Array<string> = [];
const optionsValueType = type(optionsValue); const errorPossibleTypes: Array<string> = [];
const templateValueArr: Array<string | OptionsTemplateTypes> = !isArray(templateValue) ? [templateValue as string | OptionsTemplateTypes] : templateValue as Array<OptionsTemplateTypes>; const optionsValueType = type(optionsValue);
const templateValueArr: Array<string | OptionsTemplateTypes> = !isArray(templateValue)
? [templateValue as string | OptionsTemplateTypes]
: (templateValue as Array<OptionsTemplateTypes>);
each(templateValueArr, (currTemplateType) => { each(templateValueArr, (currTemplateType) => {
//if currType value isn't inside possibleTemplateTypes we assume its a enum string value // if currType value isn't inside possibleTemplateTypes we assume its a enum string value
const isEnumString = indexOf(Object.values(optionsTemplateTypes), currTemplateType) < 0; const isEnumString = indexOf(Object.values(optionsTemplateTypes), currTemplateType) < 0;
if (isEnumString && isString(optionsValue)) { if (isEnumString && isString(optionsValue)) {
//split it into a array which contains all possible values for example: ["yes", "no", "maybe"] // split it into a array which contains all possible values for example: ["yes", "no", "maybe"]
const enumStringSplit = currTemplateType.split(' '); const enumStringSplit = currTemplateType.split(' ');
isValid = !!enumStringSplit.find(possibility => possibility === optionsValue); isValid = !!enumStringSplit.find((possibility) => possibility === optionsValue);
// build error message // build error message
errorEnumStrings.push(...enumStringSplit); errorEnumStrings.push(...enumStringSplit);
} } else {
else { isValid = optionsTemplateTypes[optionsValueType] === currTemplateType;
isValid = optionsTemplateTypes[optionsValueType] === currTemplateType;
}
// build error message
errorPossibleTypes.push(isEnumString ? optionsTemplateTypes.string : currTemplateType);
// continue if invalid, break if valid
return !isValid;
});
if (isValid) {
const doStringifyComparison = isArray(optionsValue) || isPlainObject(optionsValue);
if (doStringifyComparison ? stringify(optionsValue) !== stringify(optionsDiffValue) : optionsValue !== optionsDiffValue) {
validatedOptions[prop] = optionsValue;
}
}
else if (doWriteErrors) {
console.warn(`The option "${propPrefix}${prop}" wasn't set, because it doesn't accept the type [ ${optionsValueType.toUpperCase()} ] with the value of "${optionsValue}".\r\n` +
`Accepted types are: [ ${errorPossibleTypes.join(', ').toUpperCase()} ].\r\n` +
(errorEnumStrings.length > 0 ? `\r\nValid strings are: [ ${errorEnumStrings.join(', ')} ].` : ''))
}
delete optionsCopy[prop];
} }
});
return { // build error message
foreign: optionsCopy, errorPossibleTypes.push(isEnumString ? optionsTemplateTypes.string : currTemplateType);
validated: validatedOptions
}; // continue if invalid, break if valid
return !isValid;
});
if (isValid) {
const doStringifyComparison = isArray(optionsValue) || isPlainObject(optionsValue);
if (doStringifyComparison ? stringify(optionsValue) !== stringify(optionsDiffValue) : optionsValue !== optionsDiffValue) {
validatedOptions[prop] = optionsValue;
}
} else if (doWriteErrors) {
console.warn(
`${
`The option "${propPrefix}${prop}" wasn't set, because it doesn't accept the type [ ${optionsValueType.toUpperCase()} ] with the value of "${optionsValue}".\r\n` +
`Accepted types are: [ ${errorPossibleTypes.join(', ').toUpperCase()} ].\r\n`
}${errorEnumStrings.length > 0 ? `\r\nValid strings are: [ ${errorEnumStrings.join(', ')} ].` : ''}`,
);
}
delete optionsCopy[prop];
}
});
return {
foreign: optionsCopy,
validated: validatedOptions,
};
}; };
/** /**
@@ -129,7 +139,7 @@ const validateRecursive = function <T extends PlainObject>(options: T, template:
* @param options The options object which shall be validated. * @param options The options object which shall be validated.
* @param template The template according to which the options object shall be validated. * @param template The template according to which the options object shall be validated.
* @param optionsDiff When provided the returned validated object will only have properties which are different to this objects properties. * @param optionsDiff When provided the returned validated object will only have properties which are different to this objects properties.
* Example (assume all properties are valid to the template): * Example (assume all properties are valid to the template):
* Options object : { a: 'a', b: 'b', c: 'c' } * Options object : { a: 'a', b: 'b', c: 'c' }
* optionsDiff object : { a: 'a', b: 'b', c: undefined } * optionsDiff object : { a: 'a', b: 'b', c: undefined }
* Returned validated object : { c: 'c' } * Returned validated object : { c: 'c' }
@@ -137,28 +147,32 @@ const validateRecursive = function <T extends PlainObject>(options: T, template:
* Without the optionsDiff object the returned validated object would be: { a: 'a', b: 'b', c: 'c' } * Without the optionsDiff object the returned validated object would be: { a: 'a', b: 'b', c: 'c' }
* @param doWriteErrors True if errors shall be logged into the console, false otherwise. * @param doWriteErrors True if errors shall be logged into the console, false otherwise.
*/ */
const validate = function <T extends PlainObject>(options: T, template: OptionsTemplate<Required<T>>, optionsDiff?: OptionsValidated<T>, doWriteErrors?: boolean): OptionsValidatedResult<T> { const validate = function <T extends PlainObject>(
/* options: T,
template: OptionsTemplate<Required<T>>,
optionsDiff?: OptionsValidated<T>,
doWriteErrors?: boolean,
): OptionsValidatedResult<T> {
/*
if (!isEmptyObject(foreign) && doWriteErrors) if (!isEmptyObject(foreign) && doWriteErrors)
console.warn(`The following options are discarded due to invalidity:\r\n ${window.JSON.stringify(foreign, null, 2)}`); console.warn(`The following options are discarded due to invalidity:\r\n ${window.JSON.stringify(foreign, null, 2)}`);
//add values, which aren't specified in the template, to the finished validated object to prevent them from being discarded //add values, which aren't specified in the template, to the finished validated object to prevent them from being discarded
if (keepForeignProps) { if (keepForeignProps) {
Object.assign(result.validated, foreign); Object.assign(result.validated, foreign);
} }
*/ */
return validateRecursive(options, template, optionsDiff || {}, doWriteErrors || false); return validateRecursive(options, template, optionsDiff || {}, doWriteErrors || false);
}; };
export { validate, optionsTemplateTypes }; export { validate, optionsTemplateTypes };
type OptionsTemplateTypesDictionary = { type OptionsTemplateTypesDictionary = {
readonly boolean: OptionsTemplateType<boolean>; readonly boolean: OptionsTemplateType<boolean>;
readonly number: OptionsTemplateType<number>; readonly number: OptionsTemplateType<number>;
readonly string: OptionsTemplateType<string>; readonly string: OptionsTemplateType<string>;
readonly array: OptionsTemplateType<Array<any>>; readonly array: OptionsTemplateType<Array<any>>;
readonly object: OptionsTemplateType<object>; readonly object: OptionsTemplateType<object>; // eslint-disable-line @typescript-eslint/ban-types
readonly function: OptionsTemplateType<Func>; readonly function: OptionsTemplateType<Func>;
readonly null: OptionsTemplateType<null>; readonly null: OptionsTemplateType<null>;
} };
+32 -18
View File
@@ -5,32 +5,46 @@ export type Func = (this: any, ...args: any[]) => any;
export type OptionsTemplateType<T extends OptionsTemplateNativeTypes> = ExtractPropsKey<OptionsTemplateTypeMap, T>; export type OptionsTemplateType<T extends OptionsTemplateNativeTypes> = ExtractPropsKey<OptionsTemplateTypeMap, T>;
export type OptionsTemplateTypes = keyof OptionsTemplateTypeMap; export type OptionsTemplateTypes = keyof OptionsTemplateTypeMap;
export type OptionsTemplateNativeTypes = OptionsTemplateTypeMap[keyof OptionsTemplateTypeMap]; export type OptionsTemplateNativeTypes = OptionsTemplateTypeMap[keyof OptionsTemplateTypeMap];
export type OptionsTemplateValue<T extends OptionsTemplateNativeTypes = string> = T extends string ? string extends T ? OptionsTemplateValueNonEnum<T> : string : OptionsTemplateValueNonEnum<T>; export type OptionsTemplateValue<T extends OptionsTemplateNativeTypes = string> = T extends string
? string extends T
? OptionsTemplateValueNonEnum<T>
: string
: OptionsTemplateValueNonEnum<T>;
export type OptionsTemplate<T extends Required<T>> = { export type OptionsTemplate<T extends Required<T>> = {
[P in keyof T]: PlainObject extends T[P] ? OptionsTemplate<Required<T[P]>> : T[P] extends OptionsTemplateNativeTypes ? OptionsTemplateValue<T[P]> : never [P in keyof T]: PlainObject extends T[P]
? OptionsTemplate<Required<T[P]>>
: T[P] extends OptionsTemplateNativeTypes
? OptionsTemplateValue<T[P]>
: never;
}; };
export type OptionsValidated<T> = { export type OptionsValidated<T> = {
[P in keyof T]?: OptionsValidated<T[P]>; [P in keyof T]?: OptionsValidated<T[P]>;
}; };
export type OptionsValidatedResult<T> = { export type OptionsValidatedResult<T> = {
readonly foreign: PlainObject; readonly foreign: PlainObject;
readonly validated: OptionsValidated<T>; readonly validated: OptionsValidated<T>;
} };
// Options With Options Template Typings: // Options With Options Template Typings:
export type OptionsAndOptionsTemplateValue<T extends OptionsTemplateNativeTypes> = [T, OptionsTemplateValue<T>]; export type OptionsAndOptionsTemplateValue<T extends OptionsTemplateNativeTypes> = [T, OptionsTemplateValue<T>];
export type OptionsAndOptionsTemplate<T extends Required<T>> = { export type OptionsAndOptionsTemplate<T extends Required<T>> = {
[P in keyof T]: PlainObject extends T[P] ? OptionsAndOptionsTemplate<Required<T[P]>> : T[P] extends OptionsTemplateNativeTypes ? OptionsAndOptionsTemplateValue<T[P]> : never [P in keyof T]: PlainObject extends T[P]
} ? OptionsAndOptionsTemplate<Required<T[P]>>
: T[P] extends OptionsTemplateNativeTypes
? OptionsAndOptionsTemplateValue<T[P]>
: never;
};
type OptionsTemplateTypeMap = { type OptionsTemplateTypeMap = {
'__TPL_boolean_TYPE__': boolean; __TPL_boolean_TYPE__: boolean;
'__TPL_number_TYPE__': number; __TPL_number_TYPE__: number;
'__TPL_string_TYPE__': string; __TPL_string_TYPE__: string;
'__TPL_array_TYPE__': Array<any> __TPL_array_TYPE__: Array<any>;
'__TPL_function_TYPE__': Func __TPL_function_TYPE__: Func;
'__TPL_null_TYPE__': null; __TPL_null_TYPE__: null;
'__TPL_object_TYPE__': object; __TPL_object_TYPE__: object; // eslint-disable-line @typescript-eslint/ban-types
} };
type ExtractPropsKey<T, TProps extends T[keyof T]> = { type ExtractPropsKey<T, TProps extends T[keyof T]> = {
[P in keyof T]: TProps extends T[P] ? P : never; [P in keyof T]: TProps extends T[P] ? P : never;
}[keyof T]; }[keyof T];
type OptionsTemplateValueNonEnum<T extends OptionsTemplateNativeTypes> = OptionsTemplateType<T> | [OptionsTemplateType<T>, ...Array<OptionsTemplateTypes>]; type OptionsTemplateValueNonEnum<T extends OptionsTemplateNativeTypes> =
| OptionsTemplateType<T>
| [OptionsTemplateType<T>, ...Array<OptionsTemplateTypes>];
@@ -0,0 +1,52 @@
import { keys } from 'core/utils/object';
import { isArrayLike } from 'core/utils/types';
import { PlainObject } from 'core/typings';
/**
* Iterates through a array or object
* @param arrayLikeOrObject The array or object through which shall be iterated.
* @param callback The function which is responsible for the iteration.
* If the function returns true its treated like a "continue" statement.
* If the function returns false its treated like a "break" statement.
*/
export function each<T>(
array: Array<T> | ReadonlyArray<T>,
callback: (value: T, indexOrKey: number, source: Array<T>) => boolean | void,
): Array<T> | ReadonlyArray<T>;
export function each<T>(
array: Array<T> | ReadonlyArray<T> | null,
callback: (value: T, indexOrKey: number, source: Array<T>) => boolean | void,
): Array<T> | ReadonlyArray<T> | null;
export function each<T>(
arrayLikeObject: ArrayLike<T>,
callback: (value: T, indexOrKey: number, source: ArrayLike<T>) => boolean | void,
): ArrayLike<T>;
export function each<T>(
arrayLikeObject: ArrayLike<T> | null,
callback: (value: T, indexOrKey: number, source: ArrayLike<T>) => boolean | void,
): ArrayLike<T> | null;
export function each(obj: PlainObject, callback: (value: any, indexOrKey: string, source: PlainObject) => boolean | void): PlainObject;
export function each(obj: PlainObject | null, callback: (value: any, indexOrKey: string, source: PlainObject) => boolean | void): PlainObject | null;
export function each<T>(
source: ArrayLike<T> | PlainObject | null,
callback: (value: T | any, indexOrKey: any, source: any) => boolean | void,
): Array<T> | ReadonlyArray<T> | ArrayLike<T> | PlainObject | null {
if (isArrayLike(source)) {
for (let i = 0; i < source.length; i++) {
if (callback(source[i], i, source) === false) {
break;
}
}
} else if (source) {
each(keys(source), (key) => callback(source[key], key, source));
}
return source;
}
/**
* Returns the index of the given inside the given array or -1 if the given item isn't part of the given array.
* @param arr The array.
* @param item The item.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
*/
export const indexOf: <T = any>(arr: Array<T>, item: T, fromIndex?: number) => number = (arr, item, fromIndex) => arr.indexOf(item, fromIndex);
@@ -1,44 +0,0 @@
import { isArrayLike } from 'core/utils/types';
import { PlainObject } from 'core/typings';
/**
* Iterates through a array or object
* @param arrayLikeOrObject The array or object through which shall be iterated.
* @param callback The function which is responsible for the iteration.
* If the function returns true its treated like a "continue" statement.
* If the function returns false its treated like a "break" statement.
*/
export function each<T>(array: Array<T> | ReadonlyArray<T>, callback: (value: T, indexOrKey: number, source: Array<T>) => boolean | void): Array<T> | ReadonlyArray<T>;
export function each<T>(array: Array<T> | ReadonlyArray<T> | null, callback: (value: T, indexOrKey: number, source: Array<T>) => boolean | void): Array<T> | ReadonlyArray<T> | null;
export function each<T>(arrayLikeObject: ArrayLike<T>, callback: (value: T, indexOrKey: number, source: ArrayLike<T>) => boolean | void): ArrayLike<T>;
export function each<T>(arrayLikeObject: ArrayLike<T> | null, callback: (value: T, indexOrKey: number, source: ArrayLike<T>) => boolean | void): ArrayLike<T> | null;
export function each(obj: PlainObject, callback: (value: any, indexOrKey: string, source: PlainObject) => boolean | void): PlainObject;
export function each(obj: PlainObject | null, callback: (value: any, indexOrKey: string, source: PlainObject) => boolean | void): PlainObject | null;
export function each<T>(source: ArrayLike<T> | PlainObject | null, callback: (value: T | any, indexOrKey: any, source: any) => boolean | void): Array<T> | ReadonlyArray<T> | ArrayLike<T> | PlainObject | null {
let i: number | string = 0;
if (isArrayLike(source)) {
for (; i < source.length; i++) {
if (callback(source[i], i, source) === false)
break;
}
}
else if (source) {
for (i in source) {
if (callback(source[i], i, source) === false)
break;
}
}
return source;
};
/**
* Returns the index of the given inside the given array or -1 if the given item isn't part of the given array.
* @param arr The array.
* @param item The item.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
*/
export const indexOf: <T = any>(arr: Array<T>, item: T, fromIndex?: number) => number = (arr, item, fromIndex) => {
return arr.indexOf(item, fromIndex);
}
@@ -1,5 +1,5 @@
import { isArray, isFunction, isPlainObject, isNull } from 'core/utils/types'; import { isArray, isFunction, isPlainObject, isNull } from 'core/utils/types';
import { each } from 'core/utils/arrays'; import { each } from 'core/utils/array';
// https://github.com/jquery/jquery/blob/master/src/core.js#L116 // https://github.com/jquery/jquery/blob/master/src/core.js#L116
export function extend<T, U>(target: T, object1: U): T & U; export function extend<T, U>(target: T, object1: U): T & U;
@@ -7,53 +7,62 @@ export function extend<T, U, V>(target: T, object1: U, object2: V): T & U & V;
export function extend<T, U, V, W>(target: T, object1: U, object2: V, object3: W): T & U & V & W; export function extend<T, U, V, W>(target: T, object1: U, object2: V, object3: W): T & U & V & W;
export function extend<T, U, V, W, X>(target: T, object1: U, object2: V, object3: W, object4: X): T & U & V & W & X; export function extend<T, U, V, W, X>(target: T, object1: U, object2: V, object3: W, object4: X): T & U & V & W & X;
export function extend<T, U, V, W, X, Y>(target: T, object1: U, object2: V, object3: W, object4: X, object5: Y): T & U & V & W & X & Y; export function extend<T, U, V, W, X, Y>(target: T, object1: U, object2: V, object3: W, object4: X, object5: Y): T & U & V & W & X & Y;
export function extend<T, U, V, W, X, Y, Z>(target: T, object1?: U, object2?: V, object3?: W, object4?: X, object5?: Y, object6?: Z): T & U & V & W & X & Y & Z { export function extend<T, U, V, W, X, Y, Z>(
const sources: Array<any> = [object1, object2, object3, object4, object5, object6]; target: T,
object1?: U,
object2?: V,
object3?: W,
object4?: X,
object5?: Y,
object6?: Z,
): T & U & V & W & X & Y & Z {
/* eslint-disable no-restricted-syntax, guard-for-in */
const sources: Array<any> = [object1, object2, object3, object4, object5, object6];
// Handle case when target is a string or something (possible in deep copy) // Handle case when target is a string or something (possible in deep copy)
if ((typeof target !== "object" || isNull(target)) && !isFunction(target)) { if ((typeof target !== 'object' || isNull(target)) && !isFunction(target)) {
target = {} as T; target = {} as T;
} }
each(sources, (source) => { each(sources, (source) => {
// Only deal with non-null/undefined values // Only deal with non-null/undefined values
if (source != null) { if (source != null) {
// Extend the base object
for (const name in source) {
const copy: any = source[name];
// Extend the base object // Prevent Object.prototype pollution
for (const name in source) { // Prevent never-ending loop
const copy: any = source[name]; if (name === '__proto__' || target === copy) {
continue;
// Prevent Object.prototype pollution
// Prevent never-ending loop
if (name === "__proto__" || target === copy) {
continue;
}
const copyIsArray = isArray(copy);
// Recurse if we're merging plain objects or arrays
if (copy && (isPlainObject(copy) || copyIsArray)) {
const src = target[name];
let clone: any = src;
// Ensure proper type for the source value
if (copyIsArray && !isArray(src)) {
clone = [];
} else if (!copyIsArray && !isPlainObject(src)) {
clone = {};
}
// Never move original objects, clone them
target[name] = extend(clone, copy) as any;
// Don't bring in undefined values
} else if (copy !== undefined) {
target[name] = copy;
}
}
} }
});
// Return the modified object const copyIsArray = isArray(copy);
return target as any;
} // Recurse if we're merging plain objects or arrays
if (copy && (isPlainObject(copy) || copyIsArray)) {
const src = target[name];
let clone: any = src;
// Ensure proper type for the source value
if (copyIsArray && !isArray(src)) {
clone = [];
} else if (!copyIsArray && !isPlainObject(src)) {
clone = {};
}
// Never move original objects, clone them
target[name] = extend(clone, copy) as any;
// Don't bring in undefined values
} else if (copy !== undefined) {
target[name] = copy;
}
}
}
});
// Return the modified object
return target as any;
/* eslint-enable */
}
@@ -1,3 +1,4 @@
export * from 'core/utils/arrays'; export * from 'core/utils/array';
export * from 'core/utils/object';
export * from 'core/utils/extend'; export * from 'core/utils/extend';
export * from 'core/utils/types'; export * from 'core/utils/types';
@@ -0,0 +1,13 @@
/**
* Determines whether the passed object has a property with the passed name.
* @param obj The object.
* @param prop The name of the property.
*/
export const hasOwnProperty: (obj: any, prop: string | number | symbol) => boolean = (obj: any, prop: string | number | symbol) =>
Object.prototype.hasOwnProperty.call(obj, prop);
/**
* Returns the names of the enumerable string properties and methods of an object.
* @param obj The object of which the properties shall be returned.
*/
export const keys: (obj: any) => Array<string> = (obj: any) => Object.keys(obj);
@@ -1,88 +1,89 @@
import { PlainObject } from 'core/typings'; import { PlainObject } from 'core/typings';
export const type: (obj: any) => string = (obj) => { export const type: (obj: any) => string = (obj) => {
if (obj === undefined) if (obj === undefined) return `${obj}`;
return obj + ''; if (obj === null) return `${obj}`;
if (obj === null) return Object.prototype.toString
return obj + ''; .call(obj)
return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase(); .replace(/^\[object (.+)\]$/, '$1')
} .toLowerCase();
export function isNumber(obj: any): obj is number {
return typeof obj === 'number';
}; };
export function isNumber(obj: any): obj is number {
return typeof obj === 'number';
}
export function isString(obj: any): obj is string { export function isString(obj: any): obj is string {
return typeof obj === 'string'; return typeof obj === 'string';
} }
export function isBoolean(obj: any): obj is boolean { export function isBoolean(obj: any): obj is boolean {
return typeof obj === 'boolean'; return typeof obj === 'boolean';
} }
export function isObject(obj: any): boolean { export function isFunction(obj: any): obj is (...args: Array<unknown>) => unknown {
return typeof obj === 'object' && !isArray(obj) && !isNull(obj); return typeof obj === 'function';
}
export function isFunction(obj: any): obj is Function {
return typeof obj === 'function';
} }
export function isUndefined(obj: any): obj is undefined { export function isUndefined(obj: any): obj is undefined {
return obj === undefined; return obj === undefined;
} }
export function isNull(obj: any): obj is null { export function isNull(obj: any): obj is null {
return obj === null; return obj === null;
} }
export function isArray(obj: any): obj is Array<any> { export function isArray(obj: any): obj is Array<any> {
return Array.isArray(obj); return Array.isArray(obj);
} }
export function isObject(obj: any): boolean {
return typeof obj === 'object' && !isArray(obj) && !isNull(obj);
}
/** /**
* Returns true if the given object is array like, false otherwise. * Returns true if the given object is array like, false otherwise.
* @param obj The Object * @param obj The Object
*/ */
export function isArrayLike<T extends PlainObject = any>(obj: any): obj is ArrayLike<T> { export function isArrayLike<T extends PlainObject = any>(obj: any): obj is ArrayLike<T> {
const length = !!obj && obj.length; const length = !!obj && obj.length;
return isArray(obj) || (!isFunction(obj) && isNumber(length) && length > -1 && length % 1 == 0); return isArray(obj) || (!isFunction(obj) && isNumber(length) && length > -1 && length % 1 == 0); // eslint-disable-line eqeqeq
} }
/** /**
* Returns true if the given object is a "plain" (e.g. { key: value }) object, false otherwise. * Returns true if the given object is a "plain" (e.g. { key: value }) object, false otherwise.
* @param obj The Object. * @param obj The Object.
*/ */
export function isPlainObject<T = any>(obj: any): obj is PlainObject<T> { export function isPlainObject<T = any>(obj: any): obj is PlainObject<T> {
if (!obj || !isObject(obj) || type(obj) !== 'object') if (!obj || !isObject(obj) || type(obj) !== 'object') return false;
return false;
let key; let key;
const proto = 'prototype'; const proto = 'prototype';
const hasOwnProperty = Object[proto].hasOwnProperty; const { hasOwnProperty } = Object[proto];
const hasOwnConstructor = hasOwnProperty.call(obj, 'constructor'); const hasOwnConstructor = hasOwnProperty.call(obj, 'constructor');
const hasIsPrototypeOf = obj.constructor && obj.constructor[proto] && hasOwnProperty.call(obj.constructor[proto], 'isPrototypeOf'); const hasIsPrototypeOf = obj.constructor && obj.constructor[proto] && hasOwnProperty.call(obj.constructor[proto], 'isPrototypeOf');
if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) { if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
return false; return false;
} }
for (key in obj) { /**/ } /* eslint-disable no-restricted-syntax */
for (key in obj) {
/**/
}
/* eslint-enable */
return isUndefined(key) || hasOwnProperty.call(obj, key); return isUndefined(key) || hasOwnProperty.call(obj, key);
}; }
/** /**
* Checks whether the given object is a HTMLElement. * Checks whether the given object is a HTMLElement.
* @param obj The object which shall be checked. * @param obj The object which shall be checked.
*/ */
export function isHTMLElement(obj: any): obj is HTMLElement { export function isHTMLElement(obj: any): obj is HTMLElement {
const instaceOfRightHandSide = window.HTMLElement; const instaceOfRightHandSide = window.HTMLElement;
const doInstanceOf = isObject(instaceOfRightHandSide) || isFunction(instaceOfRightHandSide); const doInstanceOf = isObject(instaceOfRightHandSide) || isFunction(instaceOfRightHandSide);
return !!( return !!(doInstanceOf ? obj instanceof instaceOfRightHandSide : obj && isObject(obj) && obj.nodeType === 1 && isString(obj.nodeName));
doInstanceOf ? obj instanceof instaceOfRightHandSide : (obj && isObject(obj) && obj.nodeType === 1 && isString(obj.nodeName))
);
} }
/** /**
@@ -90,7 +91,8 @@ export function isHTMLElement(obj: any): obj is HTMLElement {
* @param obj The Object. * @param obj The Object.
*/ */
export function isEmptyObject(obj: any): boolean { export function isEmptyObject(obj: any): boolean {
for (let name in obj) /* eslint-disable no-restricted-syntax, guard-for-in */
return false; for (const name in obj) return false;
return true; return true;
}; /* eslint-enable */
}
+18 -10
View File
@@ -1,6 +1,5 @@
import { createDOM } from 'core/dom'; import { createDOM } from 'core/dom';
import j from 'jquery';
/* /*
export * from 'core/compatibility'; export * from 'core/compatibility';
export * from 'core/utils'; export * from 'core/utils';
@@ -10,14 +9,16 @@ export * from 'instances';
*/ */
const abc = { const abc = {
a: 1, a: 1,
b: 1, b: 1,
c: 1, c: 1,
} };
export default () => { export default () => {
const { a, b, c } = abc; const { a, b, c } = abc;
return [createDOM(`\ return [
createDOM(
'\
<div class="os-host">\ <div class="os-host">\
<div class="os-resize-observer-host"></div>\ <div class="os-resize-observer-host"></div>\
<div class="os-padding">\ <div class="os-padding">\
@@ -38,5 +39,12 @@ export default () => {
</div>\ </div>\
</div>\ </div>\
<div class="os-scrollbar-corner"></div>\ <div class="os-scrollbar-corner"></div>\
</div>`), j('div'), a, b, c]; </div>',
}; ),
a,
b,
c,
];
};
export const a = 1;
+21 -23
View File
@@ -7,46 +7,44 @@ const targetInstanceMap: WeakMap<Element, any> = new WeakMap();
* @param osInstance The OverlayScrollbars instance. * @param osInstance The OverlayScrollbars instance.
*/ */
export const addInstance: (target: Element, osInstance: any) => void = (target, osInstance) => { export const addInstance: (target: Element, osInstance: any) => void = (target, osInstance) => {
targetInstanceMap.set(target, osInstance); targetInstanceMap.set(target, osInstance);
targets.add(target); targets.add(target);
} };
/** /**
* Removes a OverlayScrollbars instance from the given element. * Removes a OverlayScrollbars instance from the given element.
* @param target The element from which its OverlayScrollbars instance shall be removed. * @param target The element from which its OverlayScrollbars instance shall be removed.
*/ */
export const removeInstance: (target: Element) => void = (target) => { export const removeInstance: (target: Element) => void = (target) => {
targetInstanceMap.delete(target); targetInstanceMap.delete(target);
targets.delete(target); targets.delete(target);
} };
/** /**
* Gets the OverlayScrollbars from the given element or undefined if it doesn't have one. * Gets the OverlayScrollbars from the given element or undefined if it doesn't have one.
* @param target The element of which its OverlayScrollbars instance shall be get. * @param target The element of which its OverlayScrollbars instance shall be get.
*/ */
export const getInstance: (target: Element) => any = (target) => { export const getInstance: (target: Element) => any = (target) => targetInstanceMap.get(target);
return targetInstanceMap.get(target);
}
/** /**
* Gets a Map which represents all active OverayScrollbars instances. * Gets a Map which represents all active OverayScrollbars instances.
* The Key is the ekement and the value is the instance. * The Key is the ekement and the value is the instance.
*/ */
export const allInstances: () => ReadonlyMap<Element, any> = () => { export const allInstances: () => ReadonlyMap<Element, any> = () => {
const validTargetInstanceMap: Map<Element, any> = new Map(); const validTargetInstanceMap: Map<Element, any> = new Map();
targets.forEach((target: Element) => { targets.forEach((target: Element) => {
/* istanbul ignore else */ /* istanbul ignore else */
if (targetInstanceMap.has(target)) { if (targetInstanceMap.has(target)) {
validTargetInstanceMap.set(target, targetInstanceMap.get(target)) validTargetInstanceMap.set(target, targetInstanceMap.get(target));
} }
}); });
targets.clear(); targets.clear();
validTargetInstanceMap.forEach((instance: any, validTarget: Element) => { validTargetInstanceMap.forEach((instance: any, validTarget: Element) => {
targets.add(validTarget); targets.add(validTarget);
}); });
return validTargetInstanceMap; return validTargetInstanceMap;
} };
+57 -58
View File
@@ -1,6 +1,6 @@
import { OptionsTemplate, OptionsTemplateValue, OptionsAndOptionsTemplateValue, OptionsAndOptionsTemplate, Func } from "core/typings"; import { OptionsTemplate, OptionsTemplateValue, OptionsAndOptionsTemplateValue, OptionsAndOptionsTemplate, Func } from 'core/typings';
import { optionsTemplateTypes as oTypes, transform } from "core/options"; import { optionsTemplateTypes as oTypes, transform } from 'core/options';
import { OverlayScrollbars } from "typings"; import { ResizeBehavior, OverflowBehavior, VisibilityBehavior, AutoHideBehavior, Options } from 'typings';
const classNameAllowedValues: OptionsTemplateValue<string | null> = [oTypes.string, oTypes.null]; const classNameAllowedValues: OptionsTemplateValue<string | null> = [oTypes.string, oTypes.null];
const numberAllowedValues: OptionsTemplateValue<number> = oTypes.number; const numberAllowedValues: OptionsTemplateValue<number> = oTypes.number;
@@ -9,15 +9,15 @@ const stringArrayNullAllowedValues: OptionsTemplateValue<string | Array<string>
const booleanTrueTemplate: OptionsAndOptionsTemplateValue<boolean> = [true, oTypes.boolean]; const booleanTrueTemplate: OptionsAndOptionsTemplateValue<boolean> = [true, oTypes.boolean];
const booleanFalseTemplate: OptionsAndOptionsTemplateValue<boolean> = [false, oTypes.boolean]; const booleanFalseTemplate: OptionsAndOptionsTemplateValue<boolean> = [false, oTypes.boolean];
const callbackTemplate: OptionsAndOptionsTemplateValue<Func | null> = [null, [oTypes.function, oTypes.null]]; const callbackTemplate: OptionsAndOptionsTemplateValue<Func | null> = [null, [oTypes.function, oTypes.null]];
const resizeAllowedValues: OptionsTemplateValue<OverlayScrollbars.ResizeBehavior> = 'none both horizontal vertical'; const resizeAllowedValues: OptionsTemplateValue<ResizeBehavior> = 'none both horizontal vertical';
const overflowBehaviorAllowedValues: OptionsTemplateValue<OverlayScrollbars.OverflowBehavior> = 'visible-hidden visible-scroll scroll hidden'; const overflowBehaviorAllowedValues: OptionsTemplateValue<OverflowBehavior> = 'visible-hidden visible-scroll scroll hidden';
const scrollbarsVisibilityAllowedValues: OptionsTemplateValue<OverlayScrollbars.VisibilityBehavior> = 'visible hidden auto'; const scrollbarsVisibilityAllowedValues: OptionsTemplateValue<VisibilityBehavior> = 'visible hidden auto';
const scrollbarsAutoHideAllowedValues: OptionsTemplateValue<OverlayScrollbars.AutoHideBehavior> = 'never scroll leavemove'; const scrollbarsAutoHideAllowedValues: OptionsTemplateValue<AutoHideBehavior> = 'never scroll leavemove';
/** /**
* A object which serves as "default options object" and "options template object". * A object which serves as "default options object" and "options template object".
* I combined these two into one object so that I don't have to define two separate big objects, instead I define one big object. * I combined these two into one object so that I don't have to define two separate big objects, instead I define one big object.
* *
* The property value is a tuple: * The property value is a tuple:
* the first value is the default value * the first value is the default value
* the second value is the template value * the second value is the template value
@@ -29,54 +29,53 @@ const scrollbarsAutoHideAllowedValues: OptionsTemplateValue<OverlayScrollbars.Au
* Property "a" has a default value of 'default' and it can be a string or null * Property "a" has a default value of 'default' and it can be a string or null
* Property "b" has a default value of 250 and it can be number * Property "b" has a default value of 250 and it can be number
*/ */
const defaultOptionsWithTemplate: OptionsAndOptionsTemplate<Required<OverlayScrollbars.Options>> = { const defaultOptionsWithTemplate: OptionsAndOptionsTemplate<Required<Options>> = {
className: ['os-theme-dark', classNameAllowedValues], //null || string className: ['os-theme-dark', classNameAllowedValues], // null || string
resize: ['none', resizeAllowedValues], //none || both || horizontal || vertical || n || b || h || v resize: ['none', resizeAllowedValues], // none || both || horizontal || vertical || n || b || h || v
sizeAutoCapable: booleanTrueTemplate, //true || false sizeAutoCapable: booleanTrueTemplate, // true || false
clipAlways: booleanTrueTemplate, //true || false clipAlways: booleanTrueTemplate, // true || false
normalizeRTL: booleanTrueTemplate, //true || false normalizeRTL: booleanTrueTemplate, // true || false
paddingAbsolute: booleanFalseTemplate, //true || false paddingAbsolute: booleanFalseTemplate, // true || false
autoUpdate: [null, booleanNullAllowedValues], //true || false || null autoUpdate: [null, booleanNullAllowedValues], // true || false || null
autoUpdateInterval: [33, numberAllowedValues], //number autoUpdateInterval: [33, numberAllowedValues], // number
updateOnLoad: [['img'], stringArrayNullAllowedValues], //string || array || null updateOnLoad: [['img'], stringArrayNullAllowedValues], // string || array || null
nativeScrollbarsOverlaid: { nativeScrollbarsOverlaid: {
showNativeScrollbars: booleanFalseTemplate, //true || false showNativeScrollbars: booleanFalseTemplate, // true || false
initialize: booleanFalseTemplate //true || false initialize: booleanFalseTemplate, // true || false
}, },
overflowBehavior: { overflowBehavior: {
x: ['scroll', overflowBehaviorAllowedValues], //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s x: ['scroll', overflowBehaviorAllowedValues], // visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s
y: ['scroll', overflowBehaviorAllowedValues] //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s y: ['scroll', overflowBehaviorAllowedValues], // visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s
}, },
scrollbars: { scrollbars: {
visibility: ['auto', scrollbarsVisibilityAllowedValues], //visible || hidden || auto || v || h || a visibility: ['auto', scrollbarsVisibilityAllowedValues], // visible || hidden || auto || v || h || a
autoHide: ['never', scrollbarsAutoHideAllowedValues], //never || scroll || leave || move || n || s || l || m autoHide: ['never', scrollbarsAutoHideAllowedValues], // never || scroll || leave || move || n || s || l || m
autoHideDelay: [800, numberAllowedValues], //number autoHideDelay: [800, numberAllowedValues], // number
dragScrolling: booleanTrueTemplate, //true || false dragScrolling: booleanTrueTemplate, // true || false
clickScrolling: booleanFalseTemplate, //true || false clickScrolling: booleanFalseTemplate, // true || false
touchSupport: booleanTrueTemplate, //true || false touchSupport: booleanTrueTemplate, // true || false
snapHandle: booleanFalseTemplate //true || false snapHandle: booleanFalseTemplate, // true || false
}, },
textarea: { textarea: {
dynWidth: booleanFalseTemplate, //true || false dynWidth: booleanFalseTemplate, // true || false
dynHeight: booleanFalseTemplate, //true || false dynHeight: booleanFalseTemplate, // true || false
inheritedAttrs: [['style', 'class'], stringArrayNullAllowedValues], //string || array || null inheritedAttrs: [['style', 'class'], stringArrayNullAllowedValues], // string || array || null
}, },
callbacks: { callbacks: {
onInitialized: callbackTemplate, //null || function onInitialized: callbackTemplate, // null || function
onInitializationWithdrawn: callbackTemplate, //null || function onInitializationWithdrawn: callbackTemplate, // null || function
onDestroyed: callbackTemplate, //null || function onDestroyed: callbackTemplate, // null || function
onScrollStart: callbackTemplate, //null || function onScrollStart: callbackTemplate, // null || function
onScroll: callbackTemplate, //null || function onScroll: callbackTemplate, // null || function
onScrollStop: callbackTemplate, //null || function onScrollStop: callbackTemplate, // null || function
onOverflowChanged: callbackTemplate, //null || function onOverflowChanged: callbackTemplate, // null || function
onOverflowAmountChanged: callbackTemplate, //null || function onOverflowAmountChanged: callbackTemplate, // null || function
onDirectionChanged: callbackTemplate, //null || function onDirectionChanged: callbackTemplate, // null || function
onContentSizeChanged: callbackTemplate, //null || function onContentSizeChanged: callbackTemplate, // null || function
onHostSizeChanged: callbackTemplate, //null || function onHostSizeChanged: callbackTemplate, // null || function
onUpdated: callbackTemplate //null || function onUpdated: callbackTemplate, // null || function
} },
} };
export const optionsTemplate: OptionsTemplate<Required<OverlayScrollbars.Options>> = transform(defaultOptionsWithTemplate, true);
export const defaultOptions: OverlayScrollbars.Options = transform(defaultOptionsWithTemplate);
export const optionsTemplate: OptionsTemplate<Required<Options>> = transform(defaultOptionsWithTemplate, true);
export const defaultOptions: Options = transform(defaultOptionsWithTemplate);
+442 -334
View File
@@ -1,369 +1,477 @@
export namespace OverlayScrollbars { export type ResizeBehavior = 'none' | 'both' | 'horizontal' | 'vertical';
export type ResizeBehavior = "none" | "both" | "horizontal" | "vertical";
export type OverflowBehavior = "hidden" | "scroll" | "visible-hidden" | "visible-scroll"; export type OverflowBehavior = 'hidden' | 'scroll' | 'visible-hidden' | 'visible-scroll';
export type VisibilityBehavior = "visible" | "hidden" | "auto"; export type VisibilityBehavior = 'visible' | 'hidden' | 'auto';
export type AutoHideBehavior = "never" | "scroll" | "leave" | "move"; export type AutoHideBehavior = 'never' | 'scroll' | 'leave' | 'move';
export type ScrollBehavior = "always" | "ifneeded" | "never"; export type ScrollBehavior = 'always' | 'ifneeded' | 'never';
export type BlockBehavior = "begin" | "end" | "center" | "nearest"; export type BasicEventCallback = (this: any) => void;
export type Easing = string | null | undefined; export type ScrollEventCallback = (this: any, args?: UIEvent) => void;
export type Margin = number | boolean; export type OverflowChangedCallback = (this: any, args?: OverflowChangedArgs) => void;
export type Position = number | string; export type OverflowAmountChangedCallback = (this: any, args?: OverflowAmountChangedArgs) => void;
export type Extensions = string | ReadonlyArray<string> | { [extensionName: string]: {} }; export type DirectionChangedCallback = (this: any, args?: DirectionChangedArgs) => void;
export type BasicEventCallback = (this: OverlayScrollbars) => void; export type SizeChangedCallback = (this: any, args?: SizeChangedArgs) => void;
export type ScrollEventCallback = (this: OverlayScrollbars, args?: UIEvent) => void; export type UpdatedCallback = (this: any, args?: UpdatedArgs) => void;
export type OverflowChangedCallback = (this: OverlayScrollbars, args?: OverflowChangedArgs) => void; export interface Options {
className?: string | null;
export type OverflowAmountChangedCallback = (this: OverlayScrollbars, args?: OverflowAmountChangedArgs) => void; resize?: ResizeBehavior;
sizeAutoCapable?: boolean;
export type DirectionChangedCallback = (this: OverlayScrollbars, args?: DirectionChangedArgs) => void; clipAlways?: boolean;
normalizeRTL?: boolean;
export type SizeChangedCallback = (this: OverlayScrollbars, args?: SizeChangedArgs) => void; paddingAbsolute?: boolean;
autoUpdate?: boolean | null;
export type UpdatedCallback = (this: OverlayScrollbars, args?: UpdatedArgs) => void; autoUpdateInterval?: number;
updateOnLoad?: string | ReadonlyArray<string> | null;
export type Coordinates = { x?: Position; y?: Position } nativeScrollbarsOverlaid?: {
| { l?: Position; t?: Position } showNativeScrollbars?: boolean;
| { left?: Position; top?: Position } initialize?: boolean;
| [Position, Position] };
| Position overflowBehavior?: {
| HTMLElement x?: OverflowBehavior;
| { y?: OverflowBehavior;
el: HTMLElement; };
scroll?: ScrollBehavior | { x?: ScrollBehavior; y?: ScrollBehavior } | [ScrollBehavior, ScrollBehavior]; scrollbars?: {
block?: BlockBehavior | { x?: BlockBehavior; y?: BlockBehavior } | [BlockBehavior, BlockBehavior]; visibility?: VisibilityBehavior;
margin?: Margin autoHide?: AutoHideBehavior;
| { autoHideDelay?: number;
top?: Margin; dragScrolling?: boolean;
right?: Margin; clickScrolling?: boolean;
bottom?: Margin; touchSupport?: boolean;
left?: Margin; snapHandle?: boolean;
} };
| [Margin, Margin] textarea?: {
| [Margin, Margin, Margin, Margin]; dynWidth?: boolean;
}; dynHeight?: boolean;
inheritedAttrs?: string | ReadonlyArray<string> | null;
export interface OverflowChangedArgs { };
x: boolean; callbacks?: {
y: boolean; onInitialized?: BasicEventCallback | null;
xScrollable: boolean; onInitializationWithdrawn?: BasicEventCallback | null;
yScrollable: boolean; onDestroyed?: BasicEventCallback | null;
clipped: boolean; onScrollStart?: ScrollEventCallback | null;
} onScroll?: ScrollEventCallback | null;
onScrollStop?: ScrollEventCallback | null;
export interface OverflowAmountChangedArgs { onOverflowChanged?: OverflowChangedCallback | null;
x: number; onOverflowAmountChanged?: OverflowAmountChangedCallback | null;
y: number; onDirectionChanged?: DirectionChangedCallback | null;
} onContentSizeChanged?: SizeChangedCallback | null;
onHostSizeChanged?: SizeChangedCallback | null;
export interface DirectionChangedArgs { onUpdated?: UpdatedCallback | null;
isRTL: number; };
dir: string;
}
export interface SizeChangedArgs {
width: number;
height: number;
}
export interface UpdatedArgs {
forced: boolean;
}
export interface Options {
className?: string | null;
resize?: ResizeBehavior;
sizeAutoCapable?: boolean;
clipAlways?: boolean;
normalizeRTL?: boolean;
paddingAbsolute?: boolean;
autoUpdate?: boolean | null;
autoUpdateInterval?: number;
updateOnLoad?: string | ReadonlyArray<string> | null;
nativeScrollbarsOverlaid?: {
showNativeScrollbars?: boolean;
initialize?: boolean;
};
overflowBehavior?: {
x?: OverflowBehavior;
y?: OverflowBehavior;
};
scrollbars?: {
visibility?: VisibilityBehavior;
autoHide?: AutoHideBehavior;
autoHideDelay?: number;
dragScrolling?: boolean;
clickScrolling?: boolean;
touchSupport?: boolean;
snapHandle?: boolean;
};
textarea?: {
dynWidth?: boolean;
dynHeight?: boolean;
inheritedAttrs?: string | ReadonlyArray<string> | null;
};
callbacks?: {
onInitialized?: BasicEventCallback | null;
onInitializationWithdrawn?: BasicEventCallback | null;
onDestroyed?: BasicEventCallback | null;
onScrollStart?: ScrollEventCallback | null;
onScroll?: ScrollEventCallback | null;
onScrollStop?: ScrollEventCallback | null;
onOverflowChanged?: OverflowChangedCallback | null;
onOverflowAmountChanged?: OverflowAmountChangedCallback | null;
onDirectionChanged?: DirectionChangedCallback | null;
onContentSizeChanged?: SizeChangedCallback | null;
onHostSizeChanged?: SizeChangedCallback | null;
onUpdated?: UpdatedCallback | null;
};
}
export interface ScrollInfo {
position: {
x: number;
y: number;
};
ratio: {
x: number;
y: number;
};
max: {
x: number;
y: number;
};
handleOffset: {
x: number;
y: number;
};
handleLength: {
x: number;
y: number;
};
handleLengthRatio: {
x: number;
y: number;
};
trackLength: {
x: number;
y: number;
};
snappedHandleOffset: {
x: number;
y: number;
};
isRTL: boolean;
isRTLNormalized: boolean;
}
export interface Elements {
target: HTMLElement;
host: HTMLElement;
padding: HTMLElement;
viewport: HTMLElement;
content: HTMLElement;
scrollbarHorizontal: {
scrollbar: HTMLElement;
track: HTMLElement;
handle: HTMLElement;
};
scrollbarVertical: {
scrollbar: HTMLElement;
track: HTMLElement;
handle: HTMLElement;
};
scrollbarCorner: HTMLElement;
}
export interface State {
destroyed: boolean;
sleeping: boolean;
autoUpdate: boolean;
widthAuto: boolean;
heightAuto: boolean;
documentMixed: boolean;
padding: {
t: number;
r: number;
b: number;
l: number;
};
overflowAmount: {
x: number;
y: number;
};
hideOverflow: {
x: boolean;
y: boolean;
xs: boolean;
ys: boolean;
};
hasOverflow: {
x: boolean;
y: boolean;
};
contentScrollSize: {
width: number;
height: number;
};
viewportSize: {
width: number;
height: number;
};
hostSize: {
width: number;
height: number;
};
}
export interface Extension {
contract(global: any): boolean;
added(options?: {}): void;
removed(): void;
on(callbackName: string, callbackArgs?: UIEvent | OverflowChangedArgs | OverflowAmountChangedArgs | DirectionChangedArgs | SizeChangedArgs | UpdatedArgs): void;
}
export interface ExtensionInfo {
name: string;
extensionFactory: (this: OverlayScrollbars, defaultOptions: {}, compatibility: Compatibility, framework: any) => Extension;
defaultOptions?: {};
}
export interface Globals {
defaultOptions: {};
autoUpdateLoop: boolean;
autoUpdateRecommended: boolean;
supportMutationObserver: boolean;
supportResizeObserver: boolean;
supportPassiveEvents: boolean;
supportTransform: boolean;
supportTransition: boolean;
restrictedMeasuring: boolean;
nativeScrollbarStyling: boolean;
cssCalc: string | null;
nativeScrollbarSize: {
x: number;
y: number;
};
nativeScrollbarIsOverlaid: {
x: boolean;
y: boolean;
};
overlayScrollbarDummySize: {
x: number;
y: number;
};
rtlScrollBehavior: {
i: boolean;
n: boolean;
};
}
export interface Compatibility {
wW(): number;
wH(): number;
mO(): any;
rO(): any;
rAF(): (callback: (...args: any[]) => any) => number;
cAF(): (requestID: number) => void;
now(): number;
stpP(event: Event): void;
prvD(event: Event): void;
page(event: MouseEvent): { x: number, y: number };
mBtn(event: MouseEvent): number;
inA<T>(item: T, array: T[]): number;
isA(obj: any): boolean;
type(obj: any): string;
bind(func: (...args: any[]) => any, thisObj: any, ...args: any[]): any;
}
} }
export interface OverflowChangedArgs {
x: boolean;
y: boolean;
xScrollable: boolean;
yScrollable: boolean;
clipped: boolean;
}
export interface OverflowAmountChangedArgs {
x: number;
y: number;
}
export interface DirectionChangedArgs {
isRTL: number;
dir: string;
}
export interface SizeChangedArgs {
width: number;
height: number;
}
export interface UpdatedArgs {
forced: boolean;
}
/*
export namespace OverlayScrollbars {
export type ResizeBehavior = 'none' | 'both' | 'horizontal' | 'vertical';
export type OverflowBehavior = 'hidden' | 'scroll' | 'visible-hidden' | 'visible-scroll';
export type VisibilityBehavior = 'visible' | 'hidden' | 'auto';
export type AutoHideBehavior = 'never' | 'scroll' | 'leave' | 'move';
export type ScrollBehavior = 'always' | 'ifneeded' | 'never';
export type BlockBehavior = 'begin' | 'end' | 'center' | 'nearest';
export type Easing = string | null | undefined;
export type Margin = number | boolean;
export type Position = number | string;
export type Extensions = string | ReadonlyArray<string> | { [extensionName: string]: {} };
export type BasicEventCallback = (this: OverlayScrollbars) => void;
export type ScrollEventCallback = (this: OverlayScrollbars, args?: UIEvent) => void;
export type OverflowChangedCallback = (this: OverlayScrollbars, args?: OverflowChangedArgs) => void;
export type OverflowAmountChangedCallback = (this: OverlayScrollbars, args?: OverflowAmountChangedArgs) => void;
export type DirectionChangedCallback = (this: OverlayScrollbars, args?: DirectionChangedArgs) => void;
export type SizeChangedCallback = (this: OverlayScrollbars, args?: SizeChangedArgs) => void;
export type UpdatedCallback = (this: OverlayScrollbars, args?: UpdatedArgs) => void;
export type Coordinates =
| { x?: Position; y?: Position }
| { l?: Position; t?: Position }
| { left?: Position; top?: Position }
| [Position, Position]
| Position
| HTMLElement
| {
el: HTMLElement;
scroll?: ScrollBehavior | { x?: ScrollBehavior; y?: ScrollBehavior } | [ScrollBehavior, ScrollBehavior];
block?: BlockBehavior | { x?: BlockBehavior; y?: BlockBehavior } | [BlockBehavior, BlockBehavior];
margin?:
| Margin
| {
top?: Margin;
right?: Margin;
bottom?: Margin;
left?: Margin;
}
| [Margin, Margin]
| [Margin, Margin, Margin, Margin];
};
export interface OverflowChangedArgs {
x: boolean;
y: boolean;
xScrollable: boolean;
yScrollable: boolean;
clipped: boolean;
}
export interface OverflowAmountChangedArgs {
x: number;
y: number;
}
export interface DirectionChangedArgs {
isRTL: number;
dir: string;
}
export interface SizeChangedArgs {
width: number;
height: number;
}
export interface UpdatedArgs {
forced: boolean;
}
export interface Options {
className?: string | null;
resize?: ResizeBehavior;
sizeAutoCapable?: boolean;
clipAlways?: boolean;
normalizeRTL?: boolean;
paddingAbsolute?: boolean;
autoUpdate?: boolean | null;
autoUpdateInterval?: number;
updateOnLoad?: string | ReadonlyArray<string> | null;
nativeScrollbarsOverlaid?: {
showNativeScrollbars?: boolean;
initialize?: boolean;
};
overflowBehavior?: {
x?: OverflowBehavior;
y?: OverflowBehavior;
};
scrollbars?: {
visibility?: VisibilityBehavior;
autoHide?: AutoHideBehavior;
autoHideDelay?: number;
dragScrolling?: boolean;
clickScrolling?: boolean;
touchSupport?: boolean;
snapHandle?: boolean;
};
textarea?: {
dynWidth?: boolean;
dynHeight?: boolean;
inheritedAttrs?: string | ReadonlyArray<string> | null;
};
callbacks?: {
onInitialized?: BasicEventCallback | null;
onInitializationWithdrawn?: BasicEventCallback | null;
onDestroyed?: BasicEventCallback | null;
onScrollStart?: ScrollEventCallback | null;
onScroll?: ScrollEventCallback | null;
onScrollStop?: ScrollEventCallback | null;
onOverflowChanged?: OverflowChangedCallback | null;
onOverflowAmountChanged?: OverflowAmountChangedCallback | null;
onDirectionChanged?: DirectionChangedCallback | null;
onContentSizeChanged?: SizeChangedCallback | null;
onHostSizeChanged?: SizeChangedCallback | null;
onUpdated?: UpdatedCallback | null;
};
}
export interface ScrollInfo {
position: {
x: number;
y: number;
};
ratio: {
x: number;
y: number;
};
max: {
x: number;
y: number;
};
handleOffset: {
x: number;
y: number;
};
handleLength: {
x: number;
y: number;
};
handleLengthRatio: {
x: number;
y: number;
};
trackLength: {
x: number;
y: number;
};
snappedHandleOffset: {
x: number;
y: number;
};
isRTL: boolean;
isRTLNormalized: boolean;
}
export interface Elements {
target: HTMLElement;
host: HTMLElement;
padding: HTMLElement;
viewport: HTMLElement;
content: HTMLElement;
scrollbarHorizontal: {
scrollbar: HTMLElement;
track: HTMLElement;
handle: HTMLElement;
};
scrollbarVertical: {
scrollbar: HTMLElement;
track: HTMLElement;
handle: HTMLElement;
};
scrollbarCorner: HTMLElement;
}
export interface State {
destroyed: boolean;
sleeping: boolean;
autoUpdate: boolean;
widthAuto: boolean;
heightAuto: boolean;
documentMixed: boolean;
padding: {
t: number;
r: number;
b: number;
l: number;
};
overflowAmount: {
x: number;
y: number;
};
hideOverflow: {
x: boolean;
y: boolean;
xs: boolean;
ys: boolean;
};
hasOverflow: {
x: boolean;
y: boolean;
};
contentScrollSize: {
width: number;
height: number;
};
viewportSize: {
width: number;
height: number;
};
hostSize: {
width: number;
height: number;
};
}
export interface Extension {
contract(global: any): boolean;
added(options?: {}): void;
removed(): void;
on(
callbackName: string,
callbackArgs?: UIEvent | OverflowChangedArgs | OverflowAmountChangedArgs | DirectionChangedArgs | SizeChangedArgs | UpdatedArgs,
): void;
}
export interface ExtensionInfo {
name: string;
extensionFactory: (this: OverlayScrollbars, defaultOptions: {}, compatibility: Compatibility, framework: any) => Extension;
defaultOptions?: {};
}
export interface Globals {
defaultOptions: {};
autoUpdateLoop: boolean;
autoUpdateRecommended: boolean;
supportMutationObserver: boolean;
supportResizeObserver: boolean;
supportPassiveEvents: boolean;
supportTransform: boolean;
supportTransition: boolean;
restrictedMeasuring: boolean;
nativeScrollbarStyling: boolean;
cssCalc: string | null;
nativeScrollbarSize: {
x: number;
y: number;
};
nativeScrollbarIsOverlaid: {
x: boolean;
y: boolean;
};
overlayScrollbarDummySize: {
x: number;
y: number;
};
rtlScrollBehavior: {
i: boolean;
n: boolean;
};
}
export interface Compatibility {
wW(): number;
wH(): number;
mO(): any;
rO(): any;
rAF(): (callback: (...args: any[]) => any) => number;
cAF(): (requestID: number) => void;
now(): number;
stpP(event: Event): void;
prvD(event: Event): void;
page(event: MouseEvent): { x: number; y: number };
mBtn(event: MouseEvent): number;
inA<T>(item: T, array: T[]): number;
isA(obj: any): boolean;
type(obj: any): string;
bind(func: (...args: any[]) => any, thisObj: any, ...args: any[]): any;
}
}
interface OverlayScrollbars { interface OverlayScrollbars {
options(): OverlayScrollbars.Options; options(): OverlayScrollbars.Options;
options(options: OverlayScrollbars.Options): void; options(options: OverlayScrollbars.Options): void;
options(optionName: string): any; options(optionName: string): any;
options(optionName: string, optionValue: {} | null): void; options(optionName: string, optionValue: {} | null): void;
update(force?: boolean): void; update(force?: boolean): void;
sleep(): void; sleep(): void;
scroll(): OverlayScrollbars.ScrollInfo; scroll(): OverlayScrollbars.ScrollInfo;
scroll( scroll(
coordinates: OverlayScrollbars.Coordinates, coordinates: OverlayScrollbars.Coordinates,
duration?: number, duration?: number,
easing?: OverlayScrollbars.Easing | { x?: OverlayScrollbars.Easing; y?: OverlayScrollbars.Easing } | [OverlayScrollbars.Easing, OverlayScrollbars.Easing], easing?:
complete?: (...args: any[]) => any | OverlayScrollbars.Easing
): void; | { x?: OverlayScrollbars.Easing; y?: OverlayScrollbars.Easing }
scroll(coordinates: OverlayScrollbars.Coordinates, options: {}): void; | [OverlayScrollbars.Easing, OverlayScrollbars.Easing],
complete?: (...args: any[]) => any,
): void;
scroll(coordinates: OverlayScrollbars.Coordinates, options: {}): void;
scrollStop(): OverlayScrollbars; scrollStop(): OverlayScrollbars;
getElements(): OverlayScrollbars.Elements; getElements(): OverlayScrollbars.Elements;
getElements(elementName: string): any; getElements(elementName: string): any;
getState(): OverlayScrollbars.State; getState(): OverlayScrollbars.State;
getState(stateProperty: string): any; getState(stateProperty: string): any;
destroy(): void; destroy(): void;
ext(): {}; ext(): {};
ext(extensionName: string): OverlayScrollbars.Extension; ext(extensionName: string): OverlayScrollbars.Extension;
addExt(extensionName: string, options: {}): OverlayScrollbars.Extension; addExt(extensionName: string, options: {}): OverlayScrollbars.Extension;
removeExt(extensionName: string): boolean; removeExt(extensionName: string): boolean;
} }
interface OverlayScrollbarsStatic { interface OverlayScrollbarsStatic {
( (element: HTMLElement | Element, options: OverlayScrollbars.Options, extensions?: OverlayScrollbars.Extensions): OverlayScrollbars;
element: HTMLElement | Element, (element: HTMLElement | Element | null): OverlayScrollbars | undefined;
options: OverlayScrollbars.Options,
extensions?: OverlayScrollbars.Extensions
): OverlayScrollbars;
(
element: HTMLElement | Element | null
): OverlayScrollbars | undefined;
( (elements: NodeListOf<Element> | ReadonlyArray<Element>, options: OverlayScrollbars.Options, extensions?: OverlayScrollbars.Extensions):
elements: NodeListOf<Element> | ReadonlyArray<Element>, | OverlayScrollbars
options: OverlayScrollbars.Options, | OverlayScrollbars[]
extensions?: OverlayScrollbars.Extensions | undefined;
): OverlayScrollbars | OverlayScrollbars[] | undefined; (elements: NodeListOf<Element> | ReadonlyArray<Element>, filter?: string | ((element: Element, instance: OverlayScrollbars) => boolean)):
( | OverlayScrollbars
elements: NodeListOf<Element> | ReadonlyArray<Element>, | OverlayScrollbars[]
filter?: string | ((element: Element, instance: OverlayScrollbars) => boolean) | undefined;
): OverlayScrollbars | OverlayScrollbars[] | undefined;
globals(): OverlayScrollbars.Globals; globals(): OverlayScrollbars.Globals;
defaultOptions(): OverlayScrollbars.Options; defaultOptions(): OverlayScrollbars.Options;
defaultOptions(newDefaultOptions: OverlayScrollbars.Options): void; defaultOptions(newDefaultOptions: OverlayScrollbars.Options): void;
extension(): { [index: number]: OverlayScrollbars.ExtensionInfo; length: number }; extension(): {
extension(extensionName: string): OverlayScrollbars.ExtensionInfo; [index: number]: OverlayScrollbars.ExtensionInfo;
extension( length: number;
extensionName: string, };
extensionFactory: (this: OverlayScrollbars, defaultOptions: {}, extension(extensionName: string): OverlayScrollbars.ExtensionInfo;
compatibility: OverlayScrollbars.Compatibility, framework: any) => OverlayScrollbars.Extension, extension(
defaultOptions?: {} extensionName: string,
): void; extensionFactory: (
extension(extensionName: string, extensionFactory: null | undefined): void; this: OverlayScrollbars,
defaultOptions: {},
compatibility: OverlayScrollbars.Compatibility,
framework: any,
) => OverlayScrollbars.Extension,
defaultOptions?: {},
): void;
extension(extensionName: string, extensionFactory: null | undefined): void;
valid(osInstance: any): boolean; valid(osInstance: any): boolean;
} }
*/
@@ -1,87 +1,87 @@
import { jsAPI, cssProperty, cssPropertyValue } from 'core/compatibility/vendors'; import { jsAPI, cssProperty, cssPropertyValue } from 'core/compatibility/vendors';
describe('vendors', () => { describe('vendors', () => {
describe('jsAPI', () => { describe('jsAPI', () => {
test('gets MutationObserver', () => { test('gets MutationObserver', () => {
const mutationObserver = jsAPI('MutationObserver'); const mutationObserver = jsAPI('MutationObserver');
expect(mutationObserver).toBe(MutationObserver); expect(mutationObserver).toBe(MutationObserver);
});
test('gets requestAnimationFrame', () => {
const rAF = jsAPI('requestAnimationFrame');
expect(rAF).toBe(requestAnimationFrame);
});
test('gets undefined', () => {
const apiWhichDontExist = jsAPI('apiWhichDontExist');
expect(apiWhichDontExist).toBeUndefined();
});
test('cache is used', () => {
const name = 'CacheTestJsAPIWhichDontExists';
const fn = () => { };
window[name] = fn;
expect(jsAPI(name)).toBe(fn);
delete window[name];
expect(jsAPI(name)).toBe(fn);
});
}); });
describe('cssProperty', () => { test('gets requestAnimationFrame', () => {
test('gets transform', () => { const rAF = jsAPI('requestAnimationFrame');
const transform = cssProperty('transform'); expect(rAF).toBe(requestAnimationFrame);
expect(transform).not.toBeUndefined();
});
test('gets undefined', () => {
const propWhichDontExist = cssProperty('propWhichDontExist');
expect(propWhichDontExist).toBeUndefined();
});
test('cache is used', () => {
const spy = jest.spyOn(Document.prototype, 'createElement');
cssProperty('cachePropWhichDontExist');
expect(spy).toBeCalledTimes(1);
cssProperty('cachePropWhichDontExist');
expect(spy).toBeCalledTimes(1);
});
}); });
describe('cssPropertyValue', () => { test('gets undefined', () => {
test('gets calc', () => { const apiWhichDontExist = jsAPI('apiWhichDontExist');
const calc = cssPropertyValue('width', 'calc', '(1px)'); expect(apiWhichDontExist).toBeUndefined();
expect(calc).not.toBeUndefined();
});
test('gets calc as second value', () => {
const calc = cssPropertyValue('width', 'nonexistend-calc calc', '(1px)');
expect(calc).not.toBeUndefined();
});
test('gets undefined', () => {
const nonexistend = cssPropertyValue('width', 'nonexistend');
expect(nonexistend).toBeUndefined();
});
test('cache is used', () => {
let expectedCalledTimes = 0;
const spy = jest.spyOn(Document.prototype, 'createElement');
const run = (propName: string, propValue: string) => {
expectedCalledTimes++;
cssPropertyValue(propName, propValue);
expect(spy).toBeCalledTimes(expectedCalledTimes);
cssPropertyValue(propName, propValue);
expect(spy).toBeCalledTimes(expectedCalledTimes);
}
run('width', 'cacheNonexistendValue');
run('height', 'cacheNonexistendValue');
run('width', 'cacheNonexistendValue cacheNonexistendValue2');
run('height', 'cacheNonexistendValue cacheNonexistendValue2');
});
}); });
});
test('cache is used', () => {
const name = 'CacheTestJsAPIWhichDontExists';
const fn = () => {};
window[name] = fn;
expect(jsAPI(name)).toBe(fn);
delete window[name];
expect(jsAPI(name)).toBe(fn);
});
});
describe('cssProperty', () => {
test('gets transform', () => {
const transform = cssProperty('transform');
expect(transform).not.toBeUndefined();
});
test('gets undefined', () => {
const propWhichDontExist = cssProperty('propWhichDontExist');
expect(propWhichDontExist).toBeUndefined();
});
test('cache is used', () => {
const spy = jest.spyOn(Document.prototype, 'createElement');
cssProperty('cachePropWhichDontExist');
expect(spy).toBeCalledTimes(1);
cssProperty('cachePropWhichDontExist');
expect(spy).toBeCalledTimes(1);
});
});
describe('cssPropertyValue', () => {
test('gets calc', () => {
const calc = cssPropertyValue('width', 'calc', '(1px)');
expect(calc).not.toBeUndefined();
});
test('gets calc as second value', () => {
const calc = cssPropertyValue('width', 'nonexistend-calc calc', '(1px)');
expect(calc).not.toBeUndefined();
});
test('gets undefined', () => {
const nonexistend = cssPropertyValue('width', 'nonexistend');
expect(nonexistend).toBeUndefined();
});
test('cache is used', () => {
let expectedCalledTimes = 0;
const spy = jest.spyOn(Document.prototype, 'createElement');
const run = (propName: string, propValue: string) => {
expectedCalledTimes++;
cssPropertyValue(propName, propValue);
expect(spy).toBeCalledTimes(expectedCalledTimes);
cssPropertyValue(propName, propValue);
expect(spy).toBeCalledTimes(expectedCalledTimes);
};
run('width', 'cacheNonexistendValue');
run('height', 'cacheNonexistendValue');
run('width', 'cacheNonexistendValue cacheNonexistendValue2');
run('height', 'cacheNonexistendValue cacheNonexistendValue2');
});
});
});
@@ -1,97 +1,97 @@
import { attr, removeAttr, val, scrollLeft, scrollTop } from 'core/dom/attributes'; import { attr, removeAttr, val, scrollLeft, scrollTop } from 'core/dom/attribute';
const testElm = document.body; const testElm = document.body;
const setAttribute = (name: string, value: string) => { const setAttribute = (name: string, value: string) => {
testElm.setAttribute(name, value); testElm.setAttribute(name, value);
}; };
const setScrollLeft = (value: number) => { const setScrollLeft = (value: number) => {
testElm.scrollLeft = value; testElm.scrollLeft = value;
}; };
const setScrollTop = (value: number) => { const setScrollTop = (value: number) => {
testElm.scrollTop = value; testElm.scrollTop = value;
}; };
const removeAttribute = (name: string) => { const removeAttribute = (name: string) => {
testElm.removeAttribute(name); testElm.removeAttribute(name);
}; };
describe('dom attributes', () => { describe('dom attributes', () => {
describe('attr', () => { describe('attr', () => {
test('get', () => { test('get', () => {
const attrName = 'data-test-get'; const attrName = 'data-test-get';
setAttribute(attrName, '123'); setAttribute(attrName, '123');
expect(attr(testElm, attrName)).toBe('123'); expect(attr(testElm, attrName)).toBe('123');
setAttribute(attrName, 'abc'); setAttribute(attrName, 'abc');
expect(attr(testElm, attrName)).toBe('abc'); expect(attr(testElm, attrName)).toBe('abc');
removeAttribute(attrName); removeAttribute(attrName);
});
test('set', () => {
const attrName = 'data-test-set';
attr(testElm, attrName, '123');
expect(attr(testElm, attrName)).toBe('123');
attr(testElm, attrName, 'abc');
expect(attr(testElm, attrName)).toBe('abc');
removeAttribute(attrName);
});
}); });
describe('scrollLeft', () => { test('set', () => {
test('get', () => { const attrName = 'data-test-set';
setScrollLeft(100);
expect(scrollLeft(testElm)).toBe(100);
setScrollLeft(0);
});
test('set', () => { attr(testElm, attrName, '123');
scrollLeft(testElm, 100); expect(attr(testElm, attrName)).toBe('123');
expect(scrollLeft(testElm)).toBe(100);
setScrollLeft(0); attr(testElm, attrName, 'abc');
}); expect(attr(testElm, attrName)).toBe('abc');
removeAttribute(attrName);
});
});
describe('scrollLeft', () => {
test('get', () => {
setScrollLeft(100);
expect(scrollLeft(testElm)).toBe(100);
setScrollLeft(0);
}); });
describe('scrollTop', () => { test('set', () => {
test('get', () => { scrollLeft(testElm, 100);
setScrollTop(100); expect(scrollLeft(testElm)).toBe(100);
expect(scrollTop(testElm)).toBe(100); setScrollLeft(0);
setScrollTop(0); });
}); });
test('set', () => { describe('scrollTop', () => {
scrollTop(testElm, 100); test('get', () => {
expect(scrollTop(testElm)).toBe(100); setScrollTop(100);
setScrollTop(0); expect(scrollTop(testElm)).toBe(100);
}); setScrollTop(0);
}); });
describe('val', () => { test('set', () => {
const input = document.createElement('input'); scrollTop(testElm, 100);
expect(scrollTop(testElm)).toBe(100);
setScrollTop(0);
});
});
test('get', () => { describe('val', () => {
input.value = 'hi'; const input = document.createElement('input');
expect(val(input)).toBe('hi');
input.value = '';
});
test('set', () => { test('get', () => {
val(input, 'hi2'); input.value = 'hi';
expect(val(input)).toBe('hi2'); expect(val(input)).toBe('hi');
val(input, ''); input.value = '';
expect(val(input)).toBe('');
});
}); });
test('remove attribute', () => { test('set', () => {
const attrName = 'data-test-remove'; val(input, 'hi2');
expect(val(input)).toBe('hi2');
setAttribute(attrName, '123'); val(input, '');
removeAttr(testElm, attrName); expect(val(input)).toBe('');
expect(attr(testElm, attrName)).toBeNull();
}); });
}); });
test('remove attribute', () => {
const attrName = 'data-test-remove';
setAttribute(attrName, '123');
removeAttr(testElm, attrName);
expect(attr(testElm, attrName)).toBeNull();
});
});
@@ -1,85 +1,83 @@
import { addClass, removeClass, hasClass, conditionalClass } from 'core/dom/classes'; import { addClass, removeClass, hasClass, conditionalClass } from 'core/dom/class';
const testElm = document.body; const testElm = document.body;
const removeAllClassNames = () => { const removeAllClassNames = () => {
while (testElm.classList.length > 0) { while (testElm.classList.length > 0) {
const classToRemove = testElm.classList.item(0); const classToRemove = testElm.classList.item(0);
if (classToRemove) { if (classToRemove) {
testElm.classList.remove(classToRemove); testElm.classList.remove(classToRemove);
}
} }
}
}; };
const hasClassName = (className: string) => { const hasClassName = (className: string) => testElm.classList.contains(className);
return testElm.classList.contains(className);
};
describe('dom class names', () => { describe('dom class names', () => {
afterEach(() => { afterEach(() => {
removeAllClassNames(); removeAllClassNames();
}); });
test('add none', () => { test('add none', () => {
addClass(testElm, ''); addClass(testElm, '');
// @ts-ignore // @ts-ignore
addClass(testElm, null); addClass(testElm, null);
// @ts-ignore // @ts-ignore
addClass(testElm, 2); addClass(testElm, 2);
expect(testElm.classList.length).toBe(0); expect(testElm.classList.length).toBe(0);
}); });
test('add single', () => { test('add single', () => {
addClass(testElm, 'test-class'); addClass(testElm, 'test-class');
expect(hasClassName('test-class')).toBe(true); expect(hasClassName('test-class')).toBe(true);
}); });
test('add multiple', () => { test('add multiple', () => {
addClass(testElm, 'test-class test-class2'); addClass(testElm, 'test-class test-class2');
expect(hasClassName('test-class')).toBe(true); expect(hasClassName('test-class')).toBe(true);
expect(hasClassName('test-class2')).toBe(true); expect(hasClassName('test-class2')).toBe(true);
}); });
test('remove none', () => { test('remove none', () => {
addClass(testElm, 'test-class'); addClass(testElm, 'test-class');
removeClass(testElm, ''); removeClass(testElm, '');
// @ts-ignore // @ts-ignore
removeClass(testElm, null); removeClass(testElm, null);
// @ts-ignore // @ts-ignore
removeClass(testElm, 2); removeClass(testElm, 2);
expect(testElm.classList.length).toBe(1); expect(testElm.classList.length).toBe(1);
}); });
test('remove single', () => { test('remove single', () => {
addClass(testElm, 'test-class'); addClass(testElm, 'test-class');
expect(hasClassName('test-class')).toBe(true); expect(hasClassName('test-class')).toBe(true);
removeClass(testElm, 'test-class'); removeClass(testElm, 'test-class');
expect(hasClassName('test-class')).toBe(false); expect(hasClassName('test-class')).toBe(false);
}); });
test('remove multiple', () => { test('remove multiple', () => {
addClass(testElm, 'test-class test-class2'); addClass(testElm, 'test-class test-class2');
removeClass(testElm, 'test-class test-class2'); removeClass(testElm, 'test-class test-class2');
expect(hasClassName('test-class')).toBe(false); expect(hasClassName('test-class')).toBe(false);
expect(hasClassName('test-class2')).toBe(false); expect(hasClassName('test-class2')).toBe(false);
}); });
test('has', () => { test('has', () => {
addClass(testElm, 'test-class'); addClass(testElm, 'test-class');
expect(hasClass(testElm, 'test-class')).toBe(true); expect(hasClass(testElm, 'test-class')).toBe(true);
}); });
test('conditional single', () => { test('conditional single', () => {
conditionalClass(testElm, 'test-class', true) conditionalClass(testElm, 'test-class', true);
expect(hasClass(testElm, 'test-class')).toBe(true); expect(hasClass(testElm, 'test-class')).toBe(true);
conditionalClass(testElm, 'test-class', false) conditionalClass(testElm, 'test-class', false);
expect(hasClass(testElm, 'test-class')).toBe(false); expect(hasClass(testElm, 'test-class')).toBe(false);
}); });
test('conditional multiple', () => { test('conditional multiple', () => {
conditionalClass(testElm, 'test-class test-class2', true) conditionalClass(testElm, 'test-class test-class2', true);
expect(hasClass(testElm, 'test-class')).toBe(true); expect(hasClass(testElm, 'test-class')).toBe(true);
expect(hasClass(testElm, 'test-class2')).toBe(true); expect(hasClass(testElm, 'test-class2')).toBe(true);
conditionalClass(testElm, 'test-class test-class2', false) conditionalClass(testElm, 'test-class test-class2', false);
expect(hasClass(testElm, 'test-class')).toBe(false); expect(hasClass(testElm, 'test-class')).toBe(false);
expect(hasClass(testElm, 'test-class2')).toBe(false); expect(hasClass(testElm, 'test-class2')).toBe(false);
}); });
}); });
@@ -2,73 +2,74 @@ import { each } from 'core/utils';
import { createDiv, createDOM } from 'core/dom/create'; import { createDiv, createDOM } from 'core/dom/create';
const slotElm = document.body; const slotElm = document.body;
const testHTML = '<div id="parent" class="parent-class"><div id="child" class="child-class"></div></div><p>2</p><input type="text" value="3"></input>'; const testHTML =
'<div id="parent" class="parent-class"><div id="child" class="child-class"></div></div><p>2</p><input type="text" value="3"></input>';
describe('dom create', () => { describe('dom create', () => {
afterEach(() => { afterEach(() => {
slotElm.innerHTML = ''; slotElm.innerHTML = '';
});
describe('createDiv', () => {
test('correct element tag', () => {
const createdDiv = createDiv();
expect(createdDiv.tagName.toLowerCase()).toBe('div');
}); });
describe('createDiv', () => { test('no class names', () => {
test('correct element tag', () => { const createdDiv = createDiv();
const createdDiv = createDiv(); expect(createdDiv.classList.length).toBe(0);
expect(createdDiv.tagName.toLowerCase()).toBe('div');
});
test('no class names', () => {
const createdDiv = createDiv();
expect(createdDiv.classList.length).toBe(0);
});
test('no style', () => {
const createdDiv = createDiv();
expect(createdDiv.style.length).toBe(0);
});
test('not in document', () => {
const createdDiv = createDiv();
expect(createdDiv.parentElement).toBe(null);
});
}); });
describe('createDOM', () => { test('no style', () => {
test('correct elements length', () => { const createdDiv = createDiv();
const dom = createDOM(testHTML); expect(createdDiv.style.length).toBe(0);
expect(dom.length).toBe(3);
});
test('elements arent child of any element', () => {
const dom = createDOM(testHTML);
each(dom, (elm) => {
expect(elm.parentElement).toBe(null);
});
});
test('elements are created correctly', () => {
const dom = createDOM(testHTML);
each(dom, (elm) => {
slotElm.append(elm);
});
const parentElm = slotElm.querySelector('#parent');
const childElm = slotElm.querySelector('#child');
const pElm = slotElm.querySelector('p');
const inputElm = slotElm.querySelector('input');
expect(parentElm).toBeDefined();
expect(childElm).toBeDefined();
expect(pElm).toBeDefined();
expect(inputElm).toBeDefined();
expect(parentElm?.parentElement).toBe(slotElm);
expect(pElm?.parentElement).toBe(slotElm);
expect(inputElm?.parentElement).toBe(slotElm);
expect(childElm?.parentElement).toBe(parentElm);
expect(parentElm?.classList.contains('parent-class')).toBeTruthy();
expect(childElm?.classList.contains('child-class')).toBeTruthy();
expect(pElm?.textContent).toBe('2');
expect(inputElm?.value).toBe('3');
expect(inputElm?.getAttribute('type')).toBe('text');
});
}); });
});
test('not in document', () => {
const createdDiv = createDiv();
expect(createdDiv.parentElement).toBe(null);
});
});
describe('createDOM', () => {
test('correct elements length', () => {
const dom = createDOM(testHTML);
expect(dom.length).toBe(3);
});
test('elements arent child of any element', () => {
const dom = createDOM(testHTML);
each(dom, (elm) => {
expect(elm.parentElement).toBe(null);
});
});
test('elements are created correctly', () => {
const dom = createDOM(testHTML);
each(dom, (elm) => {
slotElm.append(elm);
});
const parentElm = slotElm.querySelector('#parent');
const childElm = slotElm.querySelector('#child');
const pElm = slotElm.querySelector('p');
const inputElm = slotElm.querySelector('input');
expect(parentElm).toBeDefined();
expect(childElm).toBeDefined();
expect(pElm).toBeDefined();
expect(inputElm).toBeDefined();
expect(parentElm?.parentElement).toBe(slotElm);
expect(pElm?.parentElement).toBe(slotElm);
expect(inputElm?.parentElement).toBe(slotElm);
expect(childElm?.parentElement).toBe(parentElm);
expect(parentElm?.classList.contains('parent-class')).toBeTruthy();
expect(childElm?.classList.contains('child-class')).toBeTruthy();
expect(pElm?.textContent).toBe('2');
expect(inputElm?.value).toBe('3');
expect(inputElm?.getAttribute('type')).toBe('text');
});
});
});
@@ -3,347 +3,352 @@ import { each, isArray, isHTMLElement } from 'core/utils';
const slotElm = document.body; const slotElm = document.body;
const fillSlotElm = () => { const fillSlotElm = () => {
const content = [createDiv(), createDiv(), createDiv(), createDiv(), createDiv()]; const content = [createDiv(), createDiv(), createDiv(), createDiv(), createDiv()];
content.forEach((elm, i) => { content.forEach((elm, i) => {
elm.setAttribute('id', i.toString()); elm.setAttribute('id', i.toString());
slotElm.append(elm); slotElm.append(elm);
}); });
}; };
const clearSlotElm = () => { const clearSlotElm = () => {
contents(slotElm).forEach(elm => { contents(slotElm).forEach((elm) => {
elm.remove(); elm.remove();
}); });
}; };
const compareToNative = (target: Node, method: string, snapshot: Array<Node>, elms: Element | Node | Array<Element> | Array<Node>, compareIds: boolean = false) => { const compareToNative = (
if (!compareIds) { target: Node,
if (!isArray(elms)) { method: string,
elms = [elms]; snapshot: Array<Node>,
} elms: Element | Node | Array<Element> | Array<Node>,
elms.forEach(e => { compareIds = false,
if (isHTMLElement(e)) ) => {
e.remove(); if (!compareIds) {
}); if (!isArray(elms)) {
target[method](...elms); elms = [elms];
expect(Array.from(slotElm.childNodes)).toEqual(snapshot);
} }
else { elms.forEach((e) => {
clearSlotElm(); if (isHTMLElement(e)) {
fillSlotElm(); e.remove();
}
});
target[method](...elms);
expect(Array.from(slotElm.childNodes)).toEqual(snapshot);
} else {
clearSlotElm();
fillSlotElm();
if (!isArray(elms)) {
if (!isArray(elms)) { elms = [elms];
elms = [elms];
}
const realElms: Array<Element> = [];
elms.forEach((elm) => {
slotElm.childNodes.forEach((child) => {
if (isHTMLElement(child)) {
if (isHTMLElement(elm) && child.getAttribute('id') === elm.getAttribute('id')) {
realElms.push(child);
}
if (compareIds && target !== slotElm && isHTMLElement(target) && child.getAttribute('id') === target.getAttribute('id')) {
target = child;
}
}
})
});
target[method](...realElms);
const mapIds = (elm: Node) => isHTMLElement(elm) ? elm.getAttribute('id') || '' : '';
const snapshotIdArr: Array<string> = snapshot.map(mapIds);
const elmsIdArr: Array<string> = Array.from(slotElm.childNodes).map(mapIds);
expect(JSON.stringify(elmsIdArr)).toEqual(JSON.stringify(snapshotIdArr));
} }
const realElms: Array<Element> = [];
elms.forEach((elm) => {
slotElm.childNodes.forEach((child) => {
if (isHTMLElement(child)) {
if (isHTMLElement(elm) && child.getAttribute('id') === elm.getAttribute('id')) {
realElms.push(child);
}
if (compareIds && target !== slotElm && isHTMLElement(target) && child.getAttribute('id') === target.getAttribute('id')) {
target = child;
}
}
});
});
target[method](...realElms);
const mapIds = (elm: Node) => (isHTMLElement(elm) ? elm.getAttribute('id') || '' : '');
const snapshotIdArr: Array<string> = snapshot.map(mapIds);
const elmsIdArr: Array<string> = Array.from(slotElm.childNodes).map(mapIds);
expect(JSON.stringify(elmsIdArr)).toEqual(JSON.stringify(snapshotIdArr));
}
}; };
describe('dom manipulation', () => { describe('dom manipulation', () => {
beforeEach(() => fillSlotElm()); beforeEach(() => fillSlotElm());
afterEach(() => clearSlotElm()); afterEach(() => clearSlotElm());
describe('appendChildren', () => { describe('appendChildren', () => {
test('single created', () => { test('single created', () => {
const createdDiv = createDiv(); const createdDiv = createDiv();
const childNodes = slotElm.childNodes; const { childNodes } = slotElm;
const length = childNodes.length; const { length } = childNodes;
appendChildren(slotElm, createdDiv); appendChildren(slotElm, createdDiv);
expect(createdDiv).toBe(childNodes[childNodes.length - 1]); expect(createdDiv).toBe(childNodes[childNodes.length - 1]);
expect(childNodes.length).toBe(length + 1); expect(childNodes.length).toBe(length + 1);
compareToNative(slotElm, 'append', Array.from(childNodes), createdDiv); compareToNative(slotElm, 'append', Array.from(childNodes), createdDiv);
});
test('multiple created', () => {
const createdDivs = [createDiv(), createDiv(), createDiv()];
const childNodes = slotElm.childNodes;
const length = childNodes.length;
appendChildren(slotElm, createdDivs);
expect(createdDivs[0]).toBe(childNodes[childNodes.length - 3]);
expect(createdDivs[1]).toBe(childNodes[childNodes.length - 2]);
expect(createdDivs[2]).toBe(childNodes[childNodes.length - 1]);
expect(childNodes.length).toBe(length + createdDivs.length);
compareToNative(slotElm, 'append', Array.from(childNodes), createdDivs);
});
test('single existing', () => {
const childNodes = slotElm.childNodes;
const elm = childNodes[1];
appendChildren(slotElm, elm);
expect(elm).toBe(childNodes[childNodes.length - 1]);
compareToNative(slotElm, 'append', Array.from(childNodes), elm, true);
});
test('multiple existing', () => {
const childNodes = slotElm.childNodes;
const elms = [childNodes[1], childNodes[0], childNodes[2]];
appendChildren(slotElm, elms);
expect(elms[0]).toBe(childNodes[childNodes.length - 3]);
expect(elms[1]).toBe(childNodes[childNodes.length - 2]);
expect(elms[2]).toBe(childNodes[childNodes.length - 1]);
compareToNative(slotElm, 'append', Array.from(childNodes), elms, true);
});
test('none', () => {
const childNodes = slotElm.childNodes;
const length = childNodes.length;
appendChildren(slotElm, null);
appendChildren(null, childNodes);
expect(childNodes.length).toBe(length);
});
}); });
describe('prependChildren', () => { test('multiple created', () => {
test('single created', () => { const createdDivs = [createDiv(), createDiv(), createDiv()];
const createdDiv = createDiv(); const { childNodes } = slotElm;
const childNodes = slotElm.childNodes; const { length } = childNodes;
const length = childNodes.length;
prependChildren(slotElm, createdDiv); appendChildren(slotElm, createdDivs);
expect(createdDiv).toBe(childNodes[0]); expect(createdDivs[0]).toBe(childNodes[childNodes.length - 3]);
expect(childNodes.length).toBe(length + 1); expect(createdDivs[1]).toBe(childNodes[childNodes.length - 2]);
expect(createdDivs[2]).toBe(childNodes[childNodes.length - 1]);
expect(childNodes.length).toBe(length + createdDivs.length);
compareToNative(slotElm, 'prepend', Array.from(childNodes), createdDiv); compareToNative(slotElm, 'append', Array.from(childNodes), createdDivs);
});
test('multiple created', () => {
const createdDivs = [createDiv(), createDiv(), createDiv()];
const childNodes = slotElm.childNodes;
const length = childNodes.length;
prependChildren(slotElm, createdDivs);
expect(createdDivs[0]).toBe(childNodes[0]);
expect(createdDivs[1]).toBe(childNodes[1]);
expect(createdDivs[2]).toBe(childNodes[2]);
expect(childNodes.length).toBe(length + createdDivs.length);
compareToNative(slotElm, 'prepend', Array.from(childNodes), createdDivs);
});
test('single existing', () => {
const childNodes = slotElm.childNodes;
const elm = childNodes[1];
prependChildren(slotElm, elm);
expect(elm).toBe(childNodes[0]);
compareToNative(slotElm, 'prepend', Array.from(childNodes), elm, true);
});
test('multiple existing', () => {
const childNodes = slotElm.childNodes;
const elms = [childNodes[1], childNodes[0], childNodes[2]];
prependChildren(slotElm, elms);
expect(elms[0]).toBe(childNodes[0]);
expect(elms[1]).toBe(childNodes[1]);
expect(elms[2]).toBe(childNodes[2]);
compareToNative(slotElm, 'prepend', Array.from(childNodes), elms, true);
});
test('none', () => {
const childNodes = slotElm.childNodes;
const length = childNodes.length;
prependChildren(slotElm, null);
prependChildren(null, childNodes);
expect(childNodes.length).toBe(length);
});
}); });
describe('insertBefore', () => { test('single existing', () => {
test('single created', () => { const { childNodes } = slotElm;
const createdDiv = createDiv(); const elm = childNodes[1];
const childNodes = slotElm.childNodes;
const length = childNodes.length;
const target = childNodes[1];
insertBefore(target, createdDiv); appendChildren(slotElm, elm);
expect(createdDiv).toBe(childNodes[1]); expect(elm).toBe(childNodes[childNodes.length - 1]);
expect(childNodes.length).toBe(length + 1);
compareToNative(target, 'before', Array.from(childNodes), createdDiv); compareToNative(slotElm, 'append', Array.from(childNodes), elm, true);
});
test('multiple created', () => {
const createdDivs = [createDiv(), createDiv(), createDiv()];
const childNodes = slotElm.childNodes;
const length = childNodes.length;
const target = childNodes[1];
insertBefore(target, createdDivs);
expect(createdDivs[0]).toBe(childNodes[1]);
expect(createdDivs[1]).toBe(childNodes[2]);
expect(createdDivs[2]).toBe(childNodes[3]);
expect(childNodes.length).toBe(length + createdDivs.length);
compareToNative(target, 'before', Array.from(childNodes), createdDivs);
});
test('single existing', () => {
const childNodes = slotElm.childNodes;
const target = childNodes[1];
const elm = childNodes[2];
insertBefore(target, elm);
expect(elm).toBe(childNodes[1]);
compareToNative(target, 'before', Array.from(childNodes), elm, true);
});
test('multiple existing', () => {
const childNodes = slotElm.childNodes;
const target = childNodes[1];
const elms = [childNodes[4], childNodes[1], childNodes[2]];
insertBefore(target, elms);
expect(elms[0]).toBe(childNodes[1]);
expect(elms[1]).toBe(childNodes[2]);
expect(elms[2]).toBe(childNodes[3]);
compareToNative(target, 'before', Array.from(childNodes), elms, true);
});
test('none', () => {
const childNodes = slotElm.childNodes;
const length = childNodes.length;
insertBefore(slotElm, null);
insertBefore(null, childNodes);
expect(childNodes.length).toBe(length);
});
}); });
describe('insertAfter', () => { test('multiple existing', () => {
test('single created', () => { const { childNodes } = slotElm;
const createdDiv = createDiv(); const elms = [childNodes[1], childNodes[0], childNodes[2]];
const childNodes = slotElm.childNodes;
const length = childNodes.length;
const target = childNodes[1];
insertAfter(target, createdDiv); appendChildren(slotElm, elms);
expect(createdDiv).toBe(childNodes[2]); expect(elms[0]).toBe(childNodes[childNodes.length - 3]);
expect(childNodes.length).toBe(length + 1); expect(elms[1]).toBe(childNodes[childNodes.length - 2]);
expect(elms[2]).toBe(childNodes[childNodes.length - 1]);
compareToNative(target, 'after', Array.from(childNodes), createdDiv); compareToNative(slotElm, 'append', Array.from(childNodes), elms, true);
});
test('multiple created', () => {
const createdDivs = [createDiv(), createDiv(), createDiv()];
const childNodes = slotElm.childNodes;
const length = childNodes.length;
const target = childNodes[1];
insertAfter(target, createdDivs);
expect(createdDivs[0]).toBe(childNodes[2]);
expect(createdDivs[1]).toBe(childNodes[3]);
expect(createdDivs[2]).toBe(childNodes[4]);
expect(childNodes.length).toBe(length + createdDivs.length);
compareToNative(target, 'after', Array.from(childNodes), createdDivs);
});
test('single existing', () => {
const childNodes = slotElm.childNodes;
const target = childNodes[1];
const elm = childNodes[0];
insertAfter(target, elm);
expect(elm).toBe(childNodes[1]);
compareToNative(target, 'after', Array.from(childNodes), elm, true);
});
test('multiple existing', () => {
const childNodes = slotElm.childNodes;
const target = childNodes[1];
const elms = [childNodes[4], childNodes[1], childNodes[2]];
insertAfter(target, elms);
expect(elms[0]).toBe(childNodes[1]);
expect(elms[1]).toBe(childNodes[2]);
expect(elms[2]).toBe(childNodes[3]);
compareToNative(target, 'after', Array.from(childNodes), elms, true);
});
test('none', () => {
const childNodes = slotElm.childNodes;
const length = childNodes.length;
insertAfter(slotElm, null);
insertAfter(null, childNodes);
expect(childNodes.length).toBe(length);
});
}); });
describe('removeElm', () => { test('none', () => {
test('single created', () => { const { childNodes } = slotElm;
const createdDiv = createDiv(); const { length } = childNodes;
expect(createdDiv.parentElement).toBeNull();
removeElements(createdDiv);
});
test('multiple created', () => { appendChildren(slotElm, null);
const createdDivs: Array<HTMLElement> = [createDiv(), createDiv(), createDiv(), createDiv()]; appendChildren(null, childNodes);
each(createdDivs, (createdDiv: HTMLElement) => {
expect(createdDiv.parentElement).toBeNull();
});
removeElements(createdDivs);
});
test('single existing', () => { expect(childNodes.length).toBe(length);
const childNodes = slotElm.childNodes;
const length = childNodes.length;
expect(length).not.toBe(0);
removeElements(childNodes[0]);
expect(childNodes.length).toBe(length - 1);
});
test('multiple existing', () => {
const childNodes = slotElm.childNodes;
expect(childNodes.length).not.toBe(0)
removeElements(childNodes);
expect(childNodes.length).toBe(0);
});
test('none', () => {
// @ts-ignore
removeElements(null);
});
}); });
}); });
describe('prependChildren', () => {
test('single created', () => {
const createdDiv = createDiv();
const { childNodes } = slotElm;
const { length } = childNodes;
prependChildren(slotElm, createdDiv);
expect(createdDiv).toBe(childNodes[0]);
expect(childNodes.length).toBe(length + 1);
compareToNative(slotElm, 'prepend', Array.from(childNodes), createdDiv);
});
test('multiple created', () => {
const createdDivs = [createDiv(), createDiv(), createDiv()];
const { childNodes } = slotElm;
const { length } = childNodes;
prependChildren(slotElm, createdDivs);
expect(createdDivs[0]).toBe(childNodes[0]);
expect(createdDivs[1]).toBe(childNodes[1]);
expect(createdDivs[2]).toBe(childNodes[2]);
expect(childNodes.length).toBe(length + createdDivs.length);
compareToNative(slotElm, 'prepend', Array.from(childNodes), createdDivs);
});
test('single existing', () => {
const { childNodes } = slotElm;
const elm = childNodes[1];
prependChildren(slotElm, elm);
expect(elm).toBe(childNodes[0]);
compareToNative(slotElm, 'prepend', Array.from(childNodes), elm, true);
});
test('multiple existing', () => {
const { childNodes } = slotElm;
const elms = [childNodes[1], childNodes[0], childNodes[2]];
prependChildren(slotElm, elms);
expect(elms[0]).toBe(childNodes[0]);
expect(elms[1]).toBe(childNodes[1]);
expect(elms[2]).toBe(childNodes[2]);
compareToNative(slotElm, 'prepend', Array.from(childNodes), elms, true);
});
test('none', () => {
const { childNodes } = slotElm;
const { length } = childNodes;
prependChildren(slotElm, null);
prependChildren(null, childNodes);
expect(childNodes.length).toBe(length);
});
});
describe('insertBefore', () => {
test('single created', () => {
const createdDiv = createDiv();
const { childNodes } = slotElm;
const { length } = childNodes;
const target = childNodes[1];
insertBefore(target, createdDiv);
expect(createdDiv).toBe(childNodes[1]);
expect(childNodes.length).toBe(length + 1);
compareToNative(target, 'before', Array.from(childNodes), createdDiv);
});
test('multiple created', () => {
const createdDivs = [createDiv(), createDiv(), createDiv()];
const { childNodes } = slotElm;
const { length } = childNodes;
const target = childNodes[1];
insertBefore(target, createdDivs);
expect(createdDivs[0]).toBe(childNodes[1]);
expect(createdDivs[1]).toBe(childNodes[2]);
expect(createdDivs[2]).toBe(childNodes[3]);
expect(childNodes.length).toBe(length + createdDivs.length);
compareToNative(target, 'before', Array.from(childNodes), createdDivs);
});
test('single existing', () => {
const { childNodes } = slotElm;
const target = childNodes[1];
const elm = childNodes[2];
insertBefore(target, elm);
expect(elm).toBe(childNodes[1]);
compareToNative(target, 'before', Array.from(childNodes), elm, true);
});
test('multiple existing', () => {
const { childNodes } = slotElm;
const target = childNodes[1];
const elms = [childNodes[4], childNodes[1], childNodes[2]];
insertBefore(target, elms);
expect(elms[0]).toBe(childNodes[1]);
expect(elms[1]).toBe(childNodes[2]);
expect(elms[2]).toBe(childNodes[3]);
compareToNative(target, 'before', Array.from(childNodes), elms, true);
});
test('none', () => {
const { childNodes } = slotElm;
const { length } = childNodes;
insertBefore(slotElm, null);
insertBefore(null, childNodes);
expect(childNodes.length).toBe(length);
});
});
describe('insertAfter', () => {
test('single created', () => {
const createdDiv = createDiv();
const { childNodes } = slotElm;
const { length } = childNodes;
const target = childNodes[1];
insertAfter(target, createdDiv);
expect(createdDiv).toBe(childNodes[2]);
expect(childNodes.length).toBe(length + 1);
compareToNative(target, 'after', Array.from(childNodes), createdDiv);
});
test('multiple created', () => {
const createdDivs = [createDiv(), createDiv(), createDiv()];
const { childNodes } = slotElm;
const { length } = childNodes;
const target = childNodes[1];
insertAfter(target, createdDivs);
expect(createdDivs[0]).toBe(childNodes[2]);
expect(createdDivs[1]).toBe(childNodes[3]);
expect(createdDivs[2]).toBe(childNodes[4]);
expect(childNodes.length).toBe(length + createdDivs.length);
compareToNative(target, 'after', Array.from(childNodes), createdDivs);
});
test('single existing', () => {
const { childNodes } = slotElm;
const target = childNodes[1];
const elm = childNodes[0];
insertAfter(target, elm);
expect(elm).toBe(childNodes[1]);
compareToNative(target, 'after', Array.from(childNodes), elm, true);
});
test('multiple existing', () => {
const { childNodes } = slotElm;
const target = childNodes[1];
const elms = [childNodes[4], childNodes[1], childNodes[2]];
insertAfter(target, elms);
expect(elms[0]).toBe(childNodes[1]);
expect(elms[1]).toBe(childNodes[2]);
expect(elms[2]).toBe(childNodes[3]);
compareToNative(target, 'after', Array.from(childNodes), elms, true);
});
test('none', () => {
const { childNodes } = slotElm;
const { length } = childNodes;
insertAfter(slotElm, null);
insertAfter(null, childNodes);
expect(childNodes.length).toBe(length);
});
});
describe('removeElm', () => {
test('single created', () => {
const createdDiv = createDiv();
expect(createdDiv.parentElement).toBeNull();
removeElements(createdDiv);
});
test('multiple created', () => {
const createdDivs: Array<HTMLElement> = [createDiv(), createDiv(), createDiv(), createDiv()];
each(createdDivs, (createdDiv: HTMLElement) => {
expect(createdDiv.parentElement).toBeNull();
});
removeElements(createdDivs);
});
test('single existing', () => {
const { childNodes } = slotElm;
const { length } = childNodes;
expect(length).not.toBe(0);
removeElements(childNodes[0]);
expect(childNodes.length).toBe(length - 1);
});
test('multiple existing', () => {
const { childNodes } = slotElm;
expect(childNodes.length).not.toBe(0);
removeElements(childNodes);
expect(childNodes.length).toBe(0);
});
test('none', () => {
// @ts-ignore
removeElements(null);
});
});
});
@@ -4,210 +4,210 @@ const slotElm = document.body;
const testHTML = '<div id="parent" class="div-class"><div id="child" class="div-class"></div></div><p>2</p><input type="text" value="3"></input>abc'; const testHTML = '<div id="parent" class="div-class"><div id="child" class="div-class"></div></div><p>2</p><input type="text" value="3"></input>abc';
describe('dom traversal', () => { describe('dom traversal', () => {
beforeEach(() => { beforeEach(() => {
slotElm.innerHTML = testHTML; slotElm.innerHTML = testHTML;
}); });
afterEach(() => { afterEach(() => {
slotElm.innerHTML = ''; slotElm.innerHTML = '';
});
describe('find', () => {
test('by class', () => {
const divClass = find('.div-class');
expect(divClass.length).toBe(2);
expect(divClass[1].parentElement).toBe(divClass[0]);
}); });
describe('find', () => { test('by id', () => {
test('by class', () => { const parentId = find('#parent');
const divClass = find('.div-class');
expect(divClass.length).toBe(2); expect(parentId.length).toBe(1);
expect(divClass[1].parentElement).toBe(divClass[0]); expect(parentId[0]).toBe(document.querySelector('#parent'));
});
test('by id', () => {
const parentId = find('#parent');
expect(parentId.length).toBe(1);
expect(parentId[0]).toBe(document.querySelector('#parent'));
});
test('all', () => {
const all = find('*');
const allNative = document.querySelectorAll('*');
expect(all.length).toBe(allNative.length);
expect(Array.from(all)).toEqual(Array.from(allNative));
});
test('all with defined parent', () => {
const all = find('*', document.querySelector('#parent'));
const allNative = document.querySelector('#parent')?.querySelectorAll('*');
expect(all.length).toBe(allNative?.length);
expect(Array.from(all)).toEqual(Array.from(allNative!));
});
test('all with null parent', () => {
const all = find('*', null);
const allNative = document.querySelectorAll('*');
expect(all.length).toBe(allNative.length);
expect(Array.from(all)).toEqual(Array.from(allNative!));
});
test('non-existent', () => {
const nonExistent = find('#non-existent');
expect(nonExistent.length).toBe(0);
});
}); });
describe('findFirst', () => { test('all', () => {
test('by class', () => { const all = find('*');
const divClass = findFirst('.div-class'); const allNative = document.querySelectorAll('*');
expect(divClass).toBe(document.querySelector('.div-class')); expect(all.length).toBe(allNative.length);
}); expect(Array.from(all)).toEqual(Array.from(allNative));
test('by id', () => {
const parentId = findFirst('#parent');
expect(parentId).toBe(document.querySelector('#parent'));
});
test('all', () => {
const all = findFirst('*');
const allNative = document.querySelector('*');
expect(all).toBe(allNative);
});
test('all with defined parent', () => {
const all = findFirst('*', document.querySelector('#parent'));
const allNative = document.querySelector('#parent')?.querySelector('*');
expect(all).toBe(allNative);
});
test('all with null parent', () => {
const all = findFirst('*', null);
const allNative = document.querySelector('*');
expect(all).toBe(allNative);
});
test('non-existent', () => {
const nonExistent = findFirst('#non-existent');
expect(nonExistent).toBe(null);
});
}); });
describe('is', () => { test('all with defined parent', () => {
test('tag', () => { const all = find('*', document.querySelector('#parent'));
expect(is(findFirst('input'), 'input')).toBe(true); const allNative = document.querySelector('#parent')?.querySelectorAll('*');
expect(is(findFirst('body'), 'body')).toBe(true);
expect(is(findFirst('div'), 'div')).toBe(true);
expect(is(findFirst('input'), 'body')).toBe(false); expect(all.length).toBe(allNative?.length);
expect(is(findFirst('body'), 'input')).toBe(false); expect(Array.from(all)).toEqual(Array.from(allNative));
expect(is(findFirst('div'), 'head')).toBe(false);
});
test('id', () => {
expect(is(findFirst('#parent'), '#parent')).toBe(true);
expect(is(findFirst('#child'), '#parent')).toBe(false);
});
test('class', () => {
expect(is(findFirst('.div-class'), '.div-class')).toBe(true);
expect(is(findFirst('.div-class'), '.other-class')).toBe(false);
});
test('visibility', () => {
expect(is(findFirst('.div-class'), ':visible')).toBe(false);
expect(is(findFirst('.div-class'), ':hidden')).toBe(true);
});
test('created', () => {
const div = createDiv();
expect(div.parentNode).toBeNull();
expect(is(div, 'div')).toBe(true);
expect(is(div, 'body')).toBe(false);
expect(is(div, 'input')).toBe(false);
expect(is(div, 'head')).toBe(false);
expect(is(div, '#parent')).toBe(false);
expect(is(div, '#parent')).toBe(false);
expect(is(div, '.div-class')).toBe(false);
expect(is(div, '.other-class')).toBe(false);
expect(is(div, ':visible')).toBe(false);
expect(is(div, ':hidden')).toBe(true);
});
test('none', () => {
expect(is(null, 'body')).toBe(false);
expect(is(null, 'input')).toBe(false);
expect(is(null, 'head')).toBe(false);
expect(is(null, '#parent')).toBe(false);
expect(is(null, '#parent')).toBe(false);
expect(is(null, '.div-class')).toBe(false);
expect(is(null, '.other-class')).toBe(false);
expect(is(null, ':visible')).toBe(false);
expect(is(null, ':hidden')).toBe(false);
});
}); });
describe('children', () => { test('all with null parent', () => {
test('available element', () => { const all = find('*', null);
const childs = children(document.body); const allNative = document.querySelectorAll('*');
expect(childs.length).toBe(document.body.children.length); expect(all.length).toBe(allNative.length);
expect(childs).toEqual(Array.from(document.body.children)); expect(Array.from(all)).toEqual(Array.from(allNative));
});
test('unavailable element', () => {
const childs = children(null);
expect(childs.length).toEqual(0);
});
test('with selector', () => {
const childs = children(document.body, 'input');
expect(childs.length).toBe(1);
expect(childs[0]).toBe(findFirst('input'));
});
}); });
describe('contents', () => { test('non-existent', () => {
test('available element', () => { const nonExistent = find('#non-existent');
const childs = contents(document.body);
expect(childs.length).toBe(document.body.childNodes.length); expect(nonExistent.length).toBe(0);
expect(childs).toEqual(Array.from(document.body.childNodes)); });
}); });
test('unavailable element', () => { describe('findFirst', () => {
const childs = contents(null); test('by class', () => {
const divClass = findFirst('.div-class');
expect(childs.length).toEqual(0); expect(divClass).toBe(document.querySelector('.div-class'));
});
}); });
describe('parent', () => { test('by id', () => {
test('available element', () => { const parentId = findFirst('#parent');
const p = parent(document.body);
expect(p).toBe(document.body.parentElement); expect(parentId).toBe(document.querySelector('#parent'));
});
test('unavailable element', () => {
const p = parent(null);
expect(p).toBeNull();
});
}); });
});
test('all', () => {
const all = findFirst('*');
const allNative = document.querySelector('*');
expect(all).toBe(allNative);
});
test('all with defined parent', () => {
const all = findFirst('*', document.querySelector('#parent'));
const allNative = document.querySelector('#parent')?.querySelector('*');
expect(all).toBe(allNative);
});
test('all with null parent', () => {
const all = findFirst('*', null);
const allNative = document.querySelector('*');
expect(all).toBe(allNative);
});
test('non-existent', () => {
const nonExistent = findFirst('#non-existent');
expect(nonExistent).toBe(null);
});
});
describe('is', () => {
test('tag', () => {
expect(is(findFirst('input'), 'input')).toBe(true);
expect(is(findFirst('body'), 'body')).toBe(true);
expect(is(findFirst('div'), 'div')).toBe(true);
expect(is(findFirst('input'), 'body')).toBe(false);
expect(is(findFirst('body'), 'input')).toBe(false);
expect(is(findFirst('div'), 'head')).toBe(false);
});
test('id', () => {
expect(is(findFirst('#parent'), '#parent')).toBe(true);
expect(is(findFirst('#child'), '#parent')).toBe(false);
});
test('class', () => {
expect(is(findFirst('.div-class'), '.div-class')).toBe(true);
expect(is(findFirst('.div-class'), '.other-class')).toBe(false);
});
test('visibility', () => {
expect(is(findFirst('.div-class'), ':visible')).toBe(false);
expect(is(findFirst('.div-class'), ':hidden')).toBe(true);
});
test('created', () => {
const div = createDiv();
expect(div.parentNode).toBeNull();
expect(is(div, 'div')).toBe(true);
expect(is(div, 'body')).toBe(false);
expect(is(div, 'input')).toBe(false);
expect(is(div, 'head')).toBe(false);
expect(is(div, '#parent')).toBe(false);
expect(is(div, '#parent')).toBe(false);
expect(is(div, '.div-class')).toBe(false);
expect(is(div, '.other-class')).toBe(false);
expect(is(div, ':visible')).toBe(false);
expect(is(div, ':hidden')).toBe(true);
});
test('none', () => {
expect(is(null, 'body')).toBe(false);
expect(is(null, 'input')).toBe(false);
expect(is(null, 'head')).toBe(false);
expect(is(null, '#parent')).toBe(false);
expect(is(null, '#parent')).toBe(false);
expect(is(null, '.div-class')).toBe(false);
expect(is(null, '.other-class')).toBe(false);
expect(is(null, ':visible')).toBe(false);
expect(is(null, ':hidden')).toBe(false);
});
});
describe('children', () => {
test('available element', () => {
const childs = children(document.body);
expect(childs.length).toBe(document.body.children.length);
expect(childs).toEqual(Array.from(document.body.children));
});
test('unavailable element', () => {
const childs = children(null);
expect(childs.length).toEqual(0);
});
test('with selector', () => {
const childs = children(document.body, 'input');
expect(childs.length).toBe(1);
expect(childs[0]).toBe(findFirst('input'));
});
});
describe('contents', () => {
test('available element', () => {
const childs = contents(document.body);
expect(childs.length).toBe(document.body.childNodes.length);
expect(childs).toEqual(Array.from(document.body.childNodes));
});
test('unavailable element', () => {
const childs = contents(null);
expect(childs.length).toEqual(0);
});
});
describe('parent', () => {
test('available element', () => {
const p = parent(document.body);
expect(p).toBe(document.body.parentElement);
});
test('unavailable element', () => {
const p = parent(null);
expect(p).toBeNull();
});
});
});
@@ -1,77 +1,77 @@
import { OptionsTemplate, OptionsAndOptionsTemplate, PlainObject } from "core/typings"; import { OptionsTemplate, OptionsAndOptionsTemplate, PlainObject } from 'core/typings';
import { optionsTemplateTypes as oTypes, transform } from "core/options"; import { optionsTemplateTypes as oTypes, transform } from 'core/options';
type TestOptionsObj = { propA: 'propA', null: null }; type TestOptionsObj = { propA: 'propA'; null: null };
type TestOptionsEnum = 'A' | 'B' | 'C'; type TestOptionsEnum = 'A' | 'B' | 'C';
type TestOptions = { type TestOptions = {
str?: string; str?: string;
strArrNull?: string | Array<string> | null; strArrNull?: string | Array<string> | null;
nullbool?: boolean | null; nullbool?: boolean | null;
nested?: { nested?: {
num?: number; num?: number;
switch?: boolean; switch?: boolean;
abc?: TestOptionsEnum;
};
obj?: TestOptionsObj | null;
abc?: TestOptionsEnum; abc?: TestOptionsEnum;
arr?: Array<any>; };
func?: () => void; obj?: TestOptionsObj | null;
} abc?: TestOptionsEnum;
arr?: Array<any>;
func?: () => void;
};
type DeepRequired<T> = { type DeepRequired<T> = {
[P in keyof T]-?: PlainObject extends T[P] ? DeepRequired<T[P]> : T[P]; [P in keyof T]-?: PlainObject extends T[P] ? DeepRequired<T[P]> : T[P];
}; };
const options: DeepRequired<TestOptions> = { const options: DeepRequired<TestOptions> = {
str: 'hi', str: 'hi',
strArrNull: null, strArrNull: null,
nullbool: true, nullbool: true,
nested: { nested: {
num: 1, num: 1,
switch: false, switch: false,
abc: 'B', abc: 'B',
}, },
obj: { propA: 'propA', null: null }, obj: { propA: 'propA', null: null },
abc: 'A', abc: 'A',
arr: [1, 2, 3], arr: [1, 2, 3],
func: () => { } func: () => {},
} };
const optionsTemplate: OptionsTemplate<Required<TestOptions>> = { const optionsTemplate: OptionsTemplate<Required<TestOptions>> = {
str: oTypes.string, str: oTypes.string,
strArrNull: [oTypes.string, oTypes.array, oTypes.null], strArrNull: [oTypes.string, oTypes.array, oTypes.null],
nullbool: [oTypes.boolean, oTypes.null], nullbool: [oTypes.boolean, oTypes.null],
nested: { nested: {
num: oTypes.number, num: oTypes.number,
switch: oTypes.boolean, switch: oTypes.boolean,
abc: 'A B C',
},
obj: [oTypes.object, oTypes.null],
abc: 'A B C', abc: 'A B C',
arr: oTypes.array, },
func: oTypes.function, obj: [oTypes.object, oTypes.null],
} abc: 'A B C',
arr: oTypes.array,
func: oTypes.function,
};
const optionsAndOptionsTemplate: OptionsAndOptionsTemplate<Required<TestOptions>> = { const optionsAndOptionsTemplate: OptionsAndOptionsTemplate<Required<TestOptions>> = {
str: [options.str, optionsTemplate.str], str: [options.str, optionsTemplate.str],
strArrNull: [options.strArrNull, optionsTemplate.strArrNull], strArrNull: [options.strArrNull, optionsTemplate.strArrNull],
nullbool: [options.nullbool, optionsTemplate.nullbool], nullbool: [options.nullbool, optionsTemplate.nullbool],
nested: { nested: {
num: [options.nested.num, optionsTemplate.nested.num], num: [options.nested.num, optionsTemplate.nested.num],
switch: [options.nested.switch, optionsTemplate.nested.switch], switch: [options.nested.switch, optionsTemplate.nested.switch],
abc: [options.nested.abc, optionsTemplate.nested.abc], abc: [options.nested.abc, optionsTemplate.nested.abc],
}, },
obj: [options.obj, optionsTemplate.obj], obj: [options.obj, optionsTemplate.obj],
abc: [options.abc, optionsTemplate.abc], abc: [options.abc, optionsTemplate.abc],
arr: [options.arr, optionsTemplate.arr], arr: [options.arr, optionsTemplate.arr],
func: [options.func, optionsTemplate.func] func: [options.func, optionsTemplate.func],
}; };
describe('options and options template object transformation', () => { describe('options and options template object transformation', () => {
test('transforms correctly into options object', () => { test('transforms correctly into options object', () => {
expect(transform(optionsAndOptionsTemplate)).toEqual(options); expect(transform(optionsAndOptionsTemplate)).toEqual(options);
}); });
test('transforms correctly into template object', () => { test('transforms correctly into template object', () => {
expect(transform(optionsAndOptionsTemplate, true)).toEqual(optionsTemplate); expect(transform(optionsAndOptionsTemplate, true)).toEqual(optionsTemplate);
}); });
}); });
@@ -2,369 +2,438 @@ import { validate, optionsTemplateTypes as oTypes } from 'core/options';
import { extend, isEmptyObject } from 'core/utils'; import { extend, isEmptyObject } from 'core/utils';
import { OptionsTemplate } from 'core/typings'; import { OptionsTemplate } from 'core/typings';
type TestOptionsObj = { propA: 'propA', null: null }; type TestOptionsObj = { propA: 'propA'; null: null };
type TestOptionsEnum = 'A' | 'B' | 'C'; type TestOptionsEnum = 'A' | 'B' | 'C';
type TestOptions = { type TestOptions = {
str?: string; str?: string;
strArrNull?: string | Array<string> | null; strArrNull?: string | Array<string> | null;
nullbool?: boolean | null; nullbool?: boolean | null;
nested?: { nested?: {
num?: number; num?: number;
switch?: boolean; switch?: boolean;
abc?: TestOptionsEnum;
};
obj?: TestOptionsObj | null;
abc?: TestOptionsEnum; abc?: TestOptionsEnum;
arr?: Array<any>; };
func?: () => void; obj?: TestOptionsObj | null;
} abc?: TestOptionsEnum;
arr?: Array<any>;
func?: () => void;
};
const options: TestOptions = { const options: TestOptions = {
str: 'hi', str: 'hi',
strArrNull: null, strArrNull: null,
nullbool: true, nullbool: true,
nested: { nested: {
num: 1, num: 1,
switch: false, switch: false,
abc: 'B', abc: 'B',
}, },
obj: { propA: 'propA', null: null }, obj: { propA: 'propA', null: null },
abc: 'A', abc: 'A',
arr: [1, 2, 3], arr: [1, 2, 3],
func: () => { } func: () => {},
} };
const template: OptionsTemplate<Required<TestOptions>> = { const template: OptionsTemplate<Required<TestOptions>> = {
str: oTypes.string, str: oTypes.string,
strArrNull: [oTypes.string, oTypes.array, oTypes.null], strArrNull: [oTypes.string, oTypes.array, oTypes.null],
nullbool: [oTypes.boolean, oTypes.null], nullbool: [oTypes.boolean, oTypes.null],
nested: { nested: {
num: oTypes.number, num: oTypes.number,
switch: oTypes.boolean, switch: oTypes.boolean,
abc: 'A B C',
},
obj: [oTypes.object, oTypes.null],
abc: 'A B C', abc: 'A B C',
arr: oTypes.array, },
func: oTypes.function, obj: [oTypes.object, oTypes.null],
} abc: 'A B C',
arr: oTypes.array,
func: oTypes.function,
};
describe('options validation', () => { describe('options validation', () => {
describe('object return & mutation', () => { describe('object return & mutation', () => {
test('foreign properties wont affect validated object', () => { test('foreign properties wont affect validated object', () => {
const foreignObj = { foreignProp: 'foreign', foreignDeep: { a: 'A', b: 'B' } }; const foreignObj = {
const modifiedOptions = extend({}, options, { nested: foreignObj }, foreignObj); foreignProp: 'foreign',
const result = validate(modifiedOptions, template); foreignDeep: { a: 'A', b: 'B' },
const { validated } = result; };
const modifiedOptions = extend({}, options, { nested: foreignObj }, foreignObj);
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).toEqual(options); expect(validated).toEqual(options);
});
test('passed objects arent mutated', () => {
const clonedOptions = extend({}, options);
validate(clonedOptions, template, clonedOptions);
expect(clonedOptions).toEqual(options);
});
test('passed object isnt returned object', () => {
const clonedOptions = extend({}, options);
const result = validate(clonedOptions, template);
expect(result.validated).not.toBe(clonedOptions);
});
}); });
describe('foreign property return', () => { test('passed objects arent mutated', () => {
test('return no foreign property', () => { const clonedOptions = extend({}, options);
const result = validate(options, template); validate(clonedOptions, template, clonedOptions);
expect(isEmptyObject(result.foreign)).toBe(true); expect(clonedOptions).toEqual(options);
});
test('return signle non-object foreign property', () => {
const foreignObj = { foreignProp: 'foreign' };
const modifiedOptions = extend({}, options, foreignObj);
const result = validate(modifiedOptions, template);
const { foreign } = result;
expect(foreign).toEqual(foreignObj);
});
test('return complex foreign properties', () => {
const foreignObj = { foreignProp: 'foreign', foreignDeep: { a: 'A', b: 'B' } };
const modifiedOptions = extend({}, options, foreignObj);
const result = validate(modifiedOptions, template);
const { foreign } = result;
expect(foreign).toEqual(foreignObj);
});
test('return nested complex foreign properties', () => {
const foreignObj = { foreignProp: 'foreign', foreignDeep: { a: 'A', b: 'B' } };
const modifiedOptions = extend({}, options, { nested: foreignObj }, foreignObj);
const result = validate(modifiedOptions, template);
const { foreign } = result;
expect(foreign.nested).toEqual(foreignObj);
delete foreign.nested;
expect(foreign).toEqual(foreignObj);
});
}); });
describe('diff property return', () => { test('passed object isnt returned object', () => {
test('one value changed', () => { const clonedOptions = extend({}, options);
const modifiedOptions = extend({}, options, { str: 'newvaluetest' }); const result = validate(clonedOptions, template);
const result = validate(modifiedOptions, template, options);
const { validated } = result;
expect(validated.str).toBe('newvaluetest'); expect(result.validated).not.toBe(clonedOptions);
delete validated.str; });
expect(isEmptyObject(validated)).toBe(true); });
});
test('multiple values changed', () => { describe('foreign property return', () => {
const modifiedOptions = extend({}, options, { str: 'newvaluetest', nullbool: null }); test('return no foreign property', () => {
const result = validate(modifiedOptions, template, options); const result = validate(options, template);
const { validated } = result;
expect(validated.str).toBe('newvaluetest'); expect(isEmptyObject(result.foreign)).toBe(true);
expect(validated.nullbool).toBe(null);
delete validated.str;
delete validated.nullbool;
expect(isEmptyObject(validated)).toBe(true);
});
test('one nested value changed', () => {
const modifiedOptions = extend({}, options, { nested: { num: -1293 } });
const result = validate(modifiedOptions, template, options);
const { validated } = result;
expect(validated.nested?.num).toBe(-1293);
delete validated.nested?.num;
expect(isEmptyObject(validated.nested)).toBe(true);
delete validated.nested;
expect(isEmptyObject(validated)).toBe(true);
});
test('multiple nested values changed', () => {
const modifiedOptions = extend({}, options, { nested: { num: -1293, abc: 'C' } });
const result = validate(modifiedOptions, template, options);
const { validated } = result;
expect(validated.nested?.num).toBe(-1293);
expect(validated.nested?.abc).toBe('C');
delete validated.nested?.num;
delete validated.nested?.abc;
expect(isEmptyObject(validated.nested)).toBe(true);
delete validated.nested;
expect(isEmptyObject(validated)).toBe(true);
});
test('various values changed', () => {
const newFunc = () => { };
const modifiedOptions = extend({}, options, { str: 'newstrvalue', func: newFunc, abc: 'C', nested: { num: -1293, abc: 'C' } });
const result = validate(modifiedOptions, template, options);
const { validated } = result;
expect(validated.str).toBe('newstrvalue');
expect(validated.func).toBe(newFunc);
expect(validated.abc).toBe('C');
delete validated.str;
delete validated.func;
delete validated.abc;
expect(validated.nested?.num).toBe(-1293);
expect(validated.nested?.abc).toBe('C');
delete validated.nested?.num;
delete validated.nested?.abc;
expect(isEmptyObject(validated.nested)).toBe(true);
delete validated.nested;
expect(isEmptyObject(validated)).toBe(true);
});
test('various values changed with foreign properties', () => {
const foreignObj = { foreignProp: 'foreign', foreignDeep: { a: 'A', b: 'B' } };
const newFunc = () => { };
const modifiedOptions = extend({}, options, { str: 'newstrvalue', func: newFunc, abc: 'C', nested: { num: -1293, abc: 'C' } }, foreignObj, { nested: foreignObj });
const result = validate(modifiedOptions, template, options);
const { validated } = result;
expect(validated.str).toBe('newstrvalue');
expect(validated.func).toBe(newFunc);
expect(validated.abc).toBe('C');
delete validated.str;
delete validated.func;
delete validated.abc;
expect(validated.nested?.num).toBe(-1293);
expect(validated.nested?.abc).toBe('C');
delete validated.nested?.num;
delete validated.nested?.abc;
expect(isEmptyObject(validated.nested)).toBe(true);
delete validated.nested;
expect(isEmptyObject(validated)).toBe(true);
});
}); });
describe('value validity', () => { test('return signle non-object foreign property', () => {
test('single value doesnt match template', () => { const foreignObj = { foreignProp: 'foreign' };
const modifiedOptions = extend({}, options, { str: 1 }); const modifiedOptions = extend({}, options, foreignObj);
const result = validate(modifiedOptions, template); const result = validate(modifiedOptions, template);
const { validated } = result; const { foreign } = result;
expect(validated).not.toHaveProperty('str'); expect(foreign).toEqual(foreignObj);
});
test('single enum value doesnt match template', () => {
const modifiedOptions = extend({}, options, { abc: 'testval' });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('abc');
});
test('multiple values dont match template', () => {
const modifiedOptions = extend({}, options, { str: 1, abc: 'testval', nullbool: 'string' });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('str');
expect(validated).not.toHaveProperty('abc');
expect(validated).not.toHaveProperty('nullbool');
});
test('single nested value dont match template', () => {
const modifiedOptions = extend({}, options, { nested: { num: 'hi' } });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated.nested).not.toHaveProperty('num');
});
test('single nested enum value dont match template', () => {
const modifiedOptions = extend({}, options, { nested: { abc: 'testabc' } });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated.nested).not.toHaveProperty('abc');
});
test('multiple nested values dont match template', () => {
const modifiedOptions = extend({}, options, { nested: { num: 'hi', abc: 'testabc' } });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated.nested).not.toHaveProperty('num');
expect(validated.nested).not.toHaveProperty('abc');
});
test('all nested values dont match template', () => {
const modifiedOptions = extend({}, options, { nested: { num: 'hi', abc: 'testabc', switch: 1 } });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('nested');
});
test('all nested values dont match template with foreign property', () => {
const modifiedOptions = extend({}, options, { nested: { foreign: 'foreign', num: 'hi', abc: 'testabc', switch: 1 } });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('nested');
});
test('various values dont match template', () => {
const modifiedOptions = extend({}, options, { nested: { switch: null }, obj: 1, abc: 'testest', func: {} });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated.nested).not.toHaveProperty('switch');
expect(validated).not.toHaveProperty('obj');
expect(validated).not.toHaveProperty('abc');
expect(validated).not.toHaveProperty('func');
});
test('various values dont match template with foreign properties', () => {
const foreignObj = { foreignProp: 'foreign', foreignDeep: { a: 'A', b: 'B' } };
const modifiedOptions = extend({}, options, { nested: { switch: null }, obj: 1, abc: 'testest', func: {} }, foreignObj, { nested: foreignObj });
const result = validate(modifiedOptions, template);
const { validated, foreign } = result;
expect(foreign.nested).toEqual(foreignObj);
delete foreign.nested;
expect(foreign).toEqual(foreignObj);
expect(validated.nested).not.toHaveProperty('switch');
expect(validated).not.toHaveProperty('obj');
expect(validated).not.toHaveProperty('abc');
expect(validated).not.toHaveProperty('func');
});
test('nested object is string', () => {
const modifiedOptions = extend({}, options, { nested: 'string' });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('nested');
});
test('nested object is null', () => {
const modifiedOptions = extend({}, options, { nested: null });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('nested');
});
test('nested object is undefined', () => {
const modifiedOptions = extend({}, options);
modifiedOptions.nested = undefined;
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('nested');
});
}); });
describe('error logging', () => { test('return complex foreign properties', () => {
test('dont log error if nothing is wrong', () => { const foreignObj = {
const warn = console.warn; foreignProp: 'foreign',
console.warn = jest.fn(); foreignDeep: { a: 'A', b: 'B' },
};
const modifiedOptions = extend({}, options, foreignObj);
const result = validate(modifiedOptions, template);
const { foreign } = result;
validate(options, template, {}, true); expect(foreign).toEqual(foreignObj);
expect(console.warn).not.toBeCalled();
console.warn = warn;
});
test('dont log error if something is wrong and flag is false', () => {
const warn = console.warn;
console.warn = jest.fn();
const modifiedOptions = extend({}, options, { str: 1 });
validate(modifiedOptions, template, {}, false);
expect(console.warn).not.toBeCalled();
console.warn = warn;
});
test('log error if something is wrong and flag is true', () => {
const warn = console.warn;
console.warn = jest.fn();
// str must be string
validate(extend({}, options, { str: 1 }), template, {}, true);
expect(console.warn).toBeCalledTimes(1);
// abc must be A | B | C
validate(extend({}, options, { abc: 'some string' }), template, {}, true);
expect(console.warn).toBeCalledTimes(2);
// everthing OK
validate(extend({}, options, { abc: 'C' }), template, {}, true);
expect(console.warn).toBeCalledTimes(2);
console.warn = warn;
});
}); });
});
test('return nested complex foreign properties', () => {
const foreignObj = {
foreignProp: 'foreign',
foreignDeep: { a: 'A', b: 'B' },
};
const modifiedOptions = extend({}, options, { nested: foreignObj }, foreignObj);
const result = validate(modifiedOptions, template);
const { foreign } = result;
expect(foreign.nested).toEqual(foreignObj);
delete foreign.nested;
expect(foreign).toEqual(foreignObj);
});
});
describe('diff property return', () => {
test('one value changed', () => {
const modifiedOptions = extend({}, options, { str: 'newvaluetest' });
const result = validate(modifiedOptions, template, options);
const { validated } = result;
expect(validated.str).toBe('newvaluetest');
delete validated.str;
expect(isEmptyObject(validated)).toBe(true);
});
test('multiple values changed', () => {
const modifiedOptions = extend({}, options, {
str: 'newvaluetest',
nullbool: null,
});
const result = validate(modifiedOptions, template, options);
const { validated } = result;
expect(validated.str).toBe('newvaluetest');
expect(validated.nullbool).toBe(null);
delete validated.str;
delete validated.nullbool;
expect(isEmptyObject(validated)).toBe(true);
});
test('one nested value changed', () => {
const modifiedOptions = extend({}, options, { nested: { num: -1293 } });
const result = validate(modifiedOptions, template, options);
const { validated } = result;
expect(validated.nested?.num).toBe(-1293);
delete validated.nested?.num;
expect(isEmptyObject(validated.nested)).toBe(true);
delete validated.nested;
expect(isEmptyObject(validated)).toBe(true);
});
test('multiple nested values changed', () => {
const modifiedOptions = extend({}, options, {
nested: { num: -1293, abc: 'C' },
});
const result = validate(modifiedOptions, template, options);
const { validated } = result;
expect(validated.nested?.num).toBe(-1293);
expect(validated.nested?.abc).toBe('C');
delete validated.nested?.num;
delete validated.nested?.abc;
expect(isEmptyObject(validated.nested)).toBe(true);
delete validated.nested;
expect(isEmptyObject(validated)).toBe(true);
});
test('various values changed', () => {
const newFunc = () => {};
const modifiedOptions = extend({}, options, {
str: 'newstrvalue',
func: newFunc,
abc: 'C',
nested: { num: -1293, abc: 'C' },
});
const result = validate(modifiedOptions, template, options);
const { validated } = result;
expect(validated.str).toBe('newstrvalue');
expect(validated.func).toBe(newFunc);
expect(validated.abc).toBe('C');
delete validated.str;
delete validated.func;
delete validated.abc;
expect(validated.nested?.num).toBe(-1293);
expect(validated.nested?.abc).toBe('C');
delete validated.nested?.num;
delete validated.nested?.abc;
expect(isEmptyObject(validated.nested)).toBe(true);
delete validated.nested;
expect(isEmptyObject(validated)).toBe(true);
});
test('various values changed with foreign properties', () => {
const foreignObj = {
foreignProp: 'foreign',
foreignDeep: { a: 'A', b: 'B' },
};
const newFunc = () => {};
const modifiedOptions = extend(
{},
options,
{
str: 'newstrvalue',
func: newFunc,
abc: 'C',
nested: { num: -1293, abc: 'C' },
},
foreignObj,
{ nested: foreignObj },
);
const result = validate(modifiedOptions, template, options);
const { validated } = result;
expect(validated.str).toBe('newstrvalue');
expect(validated.func).toBe(newFunc);
expect(validated.abc).toBe('C');
delete validated.str;
delete validated.func;
delete validated.abc;
expect(validated.nested?.num).toBe(-1293);
expect(validated.nested?.abc).toBe('C');
delete validated.nested?.num;
delete validated.nested?.abc;
expect(isEmptyObject(validated.nested)).toBe(true);
delete validated.nested;
expect(isEmptyObject(validated)).toBe(true);
});
});
describe('value validity', () => {
test('single value doesnt match template', () => {
const modifiedOptions = extend({}, options, { str: 1 });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('str');
});
test('single enum value doesnt match template', () => {
const modifiedOptions = extend({}, options, { abc: 'testval' });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('abc');
});
test('multiple values dont match template', () => {
const modifiedOptions = extend({}, options, {
str: 1,
abc: 'testval',
nullbool: 'string',
});
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('str');
expect(validated).not.toHaveProperty('abc');
expect(validated).not.toHaveProperty('nullbool');
});
test('single nested value dont match template', () => {
const modifiedOptions = extend({}, options, { nested: { num: 'hi' } });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated.nested).not.toHaveProperty('num');
});
test('single nested enum value dont match template', () => {
const modifiedOptions = extend({}, options, {
nested: { abc: 'testabc' },
});
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated.nested).not.toHaveProperty('abc');
});
test('multiple nested values dont match template', () => {
const modifiedOptions = extend({}, options, {
nested: { num: 'hi', abc: 'testabc' },
});
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated.nested).not.toHaveProperty('num');
expect(validated.nested).not.toHaveProperty('abc');
});
test('all nested values dont match template', () => {
const modifiedOptions = extend({}, options, {
nested: { num: 'hi', abc: 'testabc', switch: 1 },
});
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('nested');
});
test('all nested values dont match template with foreign property', () => {
const modifiedOptions = extend({}, options, {
nested: {
foreign: 'foreign',
num: 'hi',
abc: 'testabc',
switch: 1,
},
});
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('nested');
});
test('various values dont match template', () => {
const modifiedOptions = extend({}, options, {
nested: { switch: null },
obj: 1,
abc: 'testest',
func: {},
});
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated.nested).not.toHaveProperty('switch');
expect(validated).not.toHaveProperty('obj');
expect(validated).not.toHaveProperty('abc');
expect(validated).not.toHaveProperty('func');
});
test('various values dont match template with foreign properties', () => {
const foreignObj = {
foreignProp: 'foreign',
foreignDeep: { a: 'A', b: 'B' },
};
const modifiedOptions = extend(
{},
options,
{
nested: { switch: null },
obj: 1,
abc: 'testest',
func: {},
},
foreignObj,
{ nested: foreignObj },
);
const result = validate(modifiedOptions, template);
const { validated, foreign } = result;
expect(foreign.nested).toEqual(foreignObj);
delete foreign.nested;
expect(foreign).toEqual(foreignObj);
expect(validated.nested).not.toHaveProperty('switch');
expect(validated).not.toHaveProperty('obj');
expect(validated).not.toHaveProperty('abc');
expect(validated).not.toHaveProperty('func');
});
test('nested object is string', () => {
const modifiedOptions = extend({}, options, { nested: 'string' });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('nested');
});
test('nested object is null', () => {
const modifiedOptions = extend({}, options, { nested: null });
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('nested');
});
test('nested object is undefined', () => {
const modifiedOptions = extend({}, options);
modifiedOptions.nested = undefined;
const result = validate(modifiedOptions, template);
const { validated } = result;
expect(validated).not.toHaveProperty('nested');
});
});
describe('error logging', () => {
test('dont log error if nothing is wrong', () => {
const { warn } = console;
console.warn = jest.fn();
validate(options, template, {}, true);
expect(console.warn).not.toBeCalled();
console.warn = warn;
});
test('dont log error if something is wrong and flag is false', () => {
const { warn } = console;
console.warn = jest.fn();
const modifiedOptions = extend({}, options, { str: 1 });
validate(modifiedOptions, template, {}, false);
expect(console.warn).not.toBeCalled();
console.warn = warn;
});
test('log error if something is wrong and flag is true', () => {
const { warn } = console;
console.warn = jest.fn();
// str must be string
validate(extend({}, options, { str: 1 }), template, {}, true);
expect(console.warn).toBeCalledTimes(1);
// abc must be A | B | C
validate(extend({}, options, { abc: 'some string' }), template, {}, true);
expect(console.warn).toBeCalledTimes(2);
// everthing OK
validate(extend({}, options, { abc: 'C' }), template, {}, true);
expect(console.warn).toBeCalledTimes(2);
console.warn = warn;
});
});
});
@@ -1,176 +1,179 @@
import { each, indexOf } from 'core/utils/arrays'; import { each, indexOf } from 'core/utils/array';
describe('array utilities', () => { describe('array utilities', () => {
describe('each', () => { describe('each', () => {
describe('each through Array', () => { describe('each through Array', () => {
test('returns input', () => { test('returns input', () => {
const arr = [1, 2, 3]; const arr = [1, 2, 3];
expect(each(arr, () => { })).toBe(arr); expect(each(arr, () => {})).toBe(arr);
}); });
test('correct times', () => { test('correct times', () => {
const arr = [1, 2, 3]; const arr = [1, 2, 3];
const eachCallback = jest.fn(); const eachCallback = jest.fn();
each(arr, eachCallback); each(arr, eachCallback);
expect(eachCallback).toBeCalledTimes(arr.length); expect(eachCallback).toBeCalledTimes(arr.length);
}); });
test('correct callback values', () => { test('correct callback values', () => {
const arr = [1, 2, 3]; const arr = [1, 2, 3];
each(arr, (value, index, src) => { each(arr, (value, index, src) => {
expect(value).toBe(arr[index]); expect(value).toBe(arr[index]);
expect(arr).toBe(src); expect(arr).toBe(src);
}); });
}); });
test('return false equals break', () => { test('return false equals break', () => {
const arr = [1, 2, 3]; const arr = [1, 2, 3];
const testFunc = jest.fn(); const testFunc = jest.fn();
each(arr, () => { each(arr, () => {
testFunc(); testFunc();
return false; return false;
});
expect(testFunc).toBeCalledTimes(1);
});
test('return true equals continue', () => {
const arr = [1, 2, 3];
const testFunc = jest.fn();
each(arr, (value, index) => {
if (index === 0)
return true;
testFunc();
});
expect(testFunc).toBeCalledTimes(arr.length - 1);
});
}); });
describe('each through Object', () => { expect(testFunc).toBeCalledTimes(1);
test('returns input', () => { });
const obj = {
a: 1,
b: 2,
c: 3
};
expect(each(obj, () => { })).toBe(obj);
});
test('correct times', () => { test('return true equals continue', () => {
const obj = { const arr = [1, 2, 3];
a: 1, const testFunc = jest.fn();
b: 2,
c: 3
};
const eachCallback = jest.fn();
each(obj, eachCallback); each(arr, (value, index) => {
expect(eachCallback).toBeCalledTimes(Object.keys(obj).length); if (index === 0) {
}); return true;
}
test('correct callback values', () => { testFunc();
const obj = {
a: 1,
b: 2,
c: 3
};
each(obj, (value, key, src) => {
expect(value).toBe(obj[key]);
expect(obj).toBe(src);
});
});
test('return false equals break', () => {
const obj = {
a: 1,
b: 2,
c: 3
};
const testFunc = jest.fn();
each(obj, () => {
testFunc();
return false;
});
expect(testFunc).toBeCalledTimes(1);
});
test('return true equals continue', () => {
const obj = {
a: 1,
b: 2,
c: 3
};
const testFunc = jest.fn();
let index = -1;
each(obj, (value) => {
index++;
if (index === 0)
return true;
testFunc();
});
expect(testFunc).toBeCalledTimes(Object.keys(obj).length - 1);
});
}); });
describe('each through ArrayLike Object', () => { expect(testFunc).toBeCalledTimes(arr.length - 1);
test('returns input', () => { });
const arrLikeObj = document.querySelectorAll('*');
expect(each(arrLikeObj, () => { })).toBe(arrLikeObj);
});
test('correct times', () => {
const arrLikeObj = document.querySelectorAll('*');
const eachCallback = jest.fn();
each(arrLikeObj, eachCallback);
expect(eachCallback).toBeCalledTimes(arrLikeObj.length);
});
test('correct callback values', () => {
const arrLikeObj = document.querySelectorAll('*');
each(arrLikeObj, (value, index, src) => {
expect(value).toBe(arrLikeObj[index]);
expect(src).toBe(arrLikeObj);
});
});
test('return false equals break', () => {
const arrLikeObj = document.querySelectorAll('*');
const testFunc = jest.fn();
each(arrLikeObj, () => {
testFunc();
return false;
});
expect(testFunc).toBeCalledTimes(1);
});
test('return true equals continue', () => {
const arrLikeObj = document.querySelectorAll('*');
const testFunc = jest.fn();
each(arrLikeObj, (value, index) => {
if (index === 0)
return true;
testFunc();
});
expect(testFunc).toBeCalledTimes(arrLikeObj.length - 1);
});
});
}); });
test('indexOf', () => { describe('each through Object', () => {
const idx = indexOf([1, 2, 3], 2); test('returns input', () => {
expect(idx).toBe(1); const obj = {
a: 1,
b: 2,
c: 3,
};
expect(each(obj, () => {})).toBe(obj);
});
test('correct times', () => {
const obj = {
a: 1,
b: 2,
c: 3,
};
const eachCallback = jest.fn();
each(obj, eachCallback);
expect(eachCallback).toBeCalledTimes(Object.keys(obj).length);
});
test('correct callback values', () => {
const obj = {
a: 1,
b: 2,
c: 3,
};
each(obj, (value, key, src) => {
expect(value).toBe(obj[key]);
expect(obj).toBe(src);
});
});
test('return false equals break', () => {
const obj = {
a: 1,
b: 2,
c: 3,
};
const testFunc = jest.fn();
each(obj, () => {
testFunc();
return false;
});
expect(testFunc).toBeCalledTimes(1);
});
test('return true equals continue', () => {
const obj = {
a: 1,
b: 2,
c: 3,
};
const testFunc = jest.fn();
let index = -1;
each(obj, () => {
index++;
if (index === 0) {
return true;
}
testFunc();
});
expect(testFunc).toBeCalledTimes(Object.keys(obj).length - 1);
});
}); });
});
describe('each through ArrayLike Object', () => {
test('returns input', () => {
const arrLikeObj = document.querySelectorAll('*');
expect(each(arrLikeObj, () => {})).toBe(arrLikeObj);
});
test('correct times', () => {
const arrLikeObj = document.querySelectorAll('*');
const eachCallback = jest.fn();
each(arrLikeObj, eachCallback);
expect(eachCallback).toBeCalledTimes(arrLikeObj.length);
});
test('correct callback values', () => {
const arrLikeObj = document.querySelectorAll('*');
each(arrLikeObj, (value, index, src) => {
expect(value).toBe(arrLikeObj[index]);
expect(src).toBe(arrLikeObj);
});
});
test('return false equals break', () => {
const arrLikeObj = document.querySelectorAll('*');
const testFunc = jest.fn();
each(arrLikeObj, () => {
testFunc();
return false;
});
expect(testFunc).toBeCalledTimes(1);
});
test('return true equals continue', () => {
const arrLikeObj = document.querySelectorAll('*');
const testFunc = jest.fn();
each(arrLikeObj, (value, index) => {
if (index === 0) {
return true;
}
testFunc();
});
expect(testFunc).toBeCalledTimes(arrLikeObj.length - 1);
});
});
});
test('indexOf', () => {
const idx = indexOf([1, 2, 3], 2);
expect(idx).toBe(1);
});
});
@@ -1,148 +1,144 @@
import { extend } from 'core/utils/extend'; import { extend } from 'core/utils/extend';
import { isPlainObject } from 'core/utils/types'; import { isPlainObject } from 'core/utils/types';
//type DeepPartial<T> = T extends object ? { [K in keyof T]?: DeepPartial<T[K]> } : T // type DeepPartial<T> = T extends object ? { [K in keyof T]?: DeepPartial<T[K]> } : T
type Deep = { type Deep = {
foo?: { foo?: {
bar?: boolean, bar?: boolean;
baz?: boolean baz?: boolean;
}, };
foo2?: Document foo2?: Document;
}; };
type Settings = { type Settings = {
xnumber0?: null, xnumber0?: null;
xnumber1?: number | null, xnumber1?: number | null;
xnumber2?: number | null, xnumber2?: number | null;
xstring1?: string, xstring1?: string;
xstring2?: string, xstring2?: string;
xxx?: string xxx?: string;
}; };
type NestedArray = { type NestedArray = {
arr: Array<any> | object arr: Array<any> | object;
}; };
//https://github.com/jquery/jquery/blob/master/test/unit/core.js#L965 // https://github.com/jquery/jquery/blob/master/test/unit/core.js#L965
describe('extend', () => { describe('extend', () => {
test('equals object assign', () => { test('equals object assign', () => {
let settings: Settings = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" }; let settings: Settings = { xnumber1: 5, xnumber2: 7, xstring1: 'peter', xstring2: 'pan' };
const options: Settings = { xnumber2: 1, xstring2: "x", xxx: "newstring" }; const options: Settings = { xnumber2: 1, xstring2: 'x', xxx: 'newstring' };
const optionsCopy: Settings = { xnumber2: 1, xstring2: "x", xxx: "newstring" }; const optionsCopy: Settings = { xnumber2: 1, xstring2: 'x', xxx: 'newstring' };
const merged: Settings = { xnumber1: 5, xnumber2: 1, xstring1: "peter", xstring2: "x", xxx: "newstring" }; const merged: Settings = { xnumber1: 5, xnumber2: 1, xstring1: 'peter', xstring2: 'x', xxx: 'newstring' };
extend(settings, options); extend(settings, options);
expect(settings).toEqual(merged); expect(settings).toEqual(merged);
expect(options).toEqual(optionsCopy); expect(options).toEqual(optionsCopy);
extend(settings, null, options); extend(settings, null, options);
expect(settings).toEqual(merged); expect(settings).toEqual(merged);
expect(options).toEqual(optionsCopy); expect(options).toEqual(optionsCopy);
const deep1: Deep = { foo: { bar: true } };
const deep2: Deep = { foo: { baz: true }, foo2: document };
const deep2copy: Deep = { foo: { baz: true }, foo2: document };
const deepmerged: Deep = { foo: { bar: true, baz: true }, foo2: document };
const deep1: Deep = { foo: { bar: true } }; extend(deep1, deep2);
const deep2: Deep = { foo: { baz: true }, foo2: document }; expect(deep1.foo).toEqual(deepmerged.foo);
const deep2copy: Deep = { foo: { baz: true }, foo2: document }; expect(deep2.foo).toEqual(deep2copy.foo);
const deepmerged: Deep = { foo: { bar: true, baz: true }, foo2: document }; expect(deep1.foo2).toBe(document);
extend(deep1, deep2); const arr = [1, 2, 3];
expect(deep1.foo).toEqual(deepmerged.foo); const nestedArray: NestedArray = { arr };
expect(deep2.foo).toEqual(deep2copy.foo);
expect(deep1.foo2).toBe(document);
expect(extend({}, nestedArray).arr).not.toBe(arr);
expect(Array.isArray(extend({ arr: {} }, nestedArray).arr)).toBeTruthy();
expect(Array.isArray(extend({ arr: {} }, nestedArray).arr)).toBeTruthy();
expect(isPlainObject(extend({ arr }, { arr: {} }).arr)).toBeTruthy();
const arr = [1, 2, 3]; let empty: { foo?: any } = {};
const nestedArray: NestedArray = { arr: arr }; const optionsWithLength = { foo: { length: -1 } };
expect(extend({}, nestedArray).arr).not.toBe(arr); extend(empty, optionsWithLength);
expect(Array.isArray(extend({ arr: {} }, nestedArray).arr)).toBeTruthy(); expect(empty.foo).toEqual(optionsWithLength.foo);
expect(Array.isArray(extend({ arr: {} }, nestedArray).arr)).toBeTruthy();
expect(isPlainObject(extend({ arr: arr }, { arr: {} }).arr)).toBeTruthy();
let empty = {}; empty = {};
const optionsWithLength = { "foo": { "length": -1 } }; const optionsWithDate = { foo: { date: new Date() } };
extend(empty, optionsWithDate);
expect(empty.foo).toEqual(optionsWithDate.foo);
extend(empty, optionsWithLength); /** @constructor */
expect(empty["foo"]).toEqual(optionsWithLength["foo"]); const MyKlass = function () {};
// @ts-ignore
const customObject = new MyKlass();
const optionsWithCustomObject = { foo: { date: customObject } };
empty = {};
empty = {}; extend(empty, optionsWithCustomObject);
const optionsWithDate = { "foo": { "date": new Date() } }; expect(empty.foo && empty.foo.date === customObject).toBeTruthy();
// Makes the class a little more realistic
MyKlass.prototype = { someMethod() {} };
empty = {};
extend(empty, optionsWithDate); extend(empty, optionsWithCustomObject);
expect(empty["foo"]).toEqual(optionsWithDate["foo"]); expect(empty.foo && empty.foo.date === customObject).toBeTruthy();
/** @constructor */ const MyNumber = Number;
const myKlass = function () { };
// @ts-ignore
const customObject = new myKlass();
const optionsWithCustomObject = { "foo": { "date": customObject } };
empty = {};
extend(empty, optionsWithCustomObject); let ret: any = extend({ foo: 4 }, { foo: new MyNumber(5) });
expect(empty["foo"] && empty["foo"]["date"] === customObject).toBeTruthy(); expect(parseInt(ret.foo?.toString() as string, 10) === 5).toBeTruthy();
// Makes the class a little more realistic let nullUndef = extend({}, options, { xnumber2: null });
myKlass.prototype = { "someMethod": function () { } }; expect(nullUndef.xnumber2).toBe(null);
empty = {};
extend(empty, optionsWithCustomObject); // @ts-ignore
expect(empty["foo"] && empty["foo"]["date"] === customObject).toBeTruthy(); nullUndef = extend({}, options, { xnumber2: undefined });
expect(nullUndef.xnumber2).toBe(options.xnumber2);
const MyNumber = Number; // @ts-ignore
nullUndef = extend({}, options, { xnumber0: null });
expect(nullUndef.xnumber0).toBe(null);
var ret: any = extend({ foo: 4 }, { foo: new MyNumber(5) }); const target = {};
expect(parseInt(ret.foo?.toString() as string, 10) === 5).toBeTruthy(); const recursive = { foo: target, bar: 5 };
let nullUndef = extend({}, options, { xnumber2: null }); extend(target, recursive);
expect(nullUndef.xnumber2).toBe(null); expect(target).toEqual({ bar: 5 });
// @ts-ignore ret = extend({ foo: [] }, { foo: [0] });
nullUndef = extend({}, options, { xnumber2: undefined }); expect(ret.foo?.length).toBe(1);
expect(nullUndef.xnumber2).toBe(options.xnumber2);
// @ts-ignore ret = extend({ foo: '1,2,3' }, { foo: [1, 2, 3] });
nullUndef = extend({}, options, { xnumber0: null }); expect(typeof ret.foo !== 'string').toBeTruthy();
expect(nullUndef.xnumber0).toBe(null);
const target = {}; ret = extend({ foo: 'bar' }, { foo: null });
const recursive = { foo: target, bar: 5 }; expect(typeof ret.foo !== 'undefined').toBeTruthy();
extend(target, recursive); const obj = { foo: null };
expect(target).toEqual({ bar: 5 }); extend(obj, { foo: 'notnull' });
expect(obj.foo).toBe('notnull');
ret = extend({ foo: [] }, { foo: [0] }); const func: { (): void; key?: string } = () => {};
expect(ret.foo?.length).toBe(1); extend(func, { key: 'value' });
expect(func.key).toBe('value');
ret = extend({ foo: "1,2,3" }, { foo: [1, 2, 3] }); const defaults = { xnumber1: 5, xnumber2: 7, xstring1: 'peter', xstring2: 'pan' };
expect(typeof ret.foo !== "string").toBeTruthy(); const defaultsCopy = { xnumber1: 5, xnumber2: 7, xstring1: 'peter', xstring2: 'pan' };
const options1 = { xnumber2: 1, xstring2: 'x' };
const options1Copy = { xnumber2: 1, xstring2: 'x' };
const options2 = { xstring2: 'xx', xxx: 'newstringx' };
const options2Copy = { xstring2: 'xx', xxx: 'newstringx' };
const merged2 = { xnumber1: 5, xnumber2: 1, xstring1: 'peter', xstring2: 'xx', xxx: 'newstringx' };
ret = extend({ foo: "bar" }, { foo: null }); settings = extend({}, defaults, options1, options2);
expect(typeof ret.foo !== "undefined").toBeTruthy(); expect(settings).toEqual(merged2);
expect(defaults).toEqual(defaultsCopy);
expect(options1).toEqual(options1Copy);
expect(options2).toEqual(options2Copy);
const obj = { foo: null }; expect(extend('', { foo: 1 })).toEqual({ foo: 1 });
extend(obj, { foo: "notnull" }); expect(extend(null, { foo: null, deep: { foo: null } })).toEqual({ foo: null, deep: { foo: null } });
expect(obj.foo).toBe("notnull"); expect(extend(12, { foo: 1, deep: { foo: null, text: '' } })).toEqual({ foo: 1, deep: { foo: null, text: '' } });
});
const func: { (): void, key?: string } = () => { }; });
extend(func, { key: "value" });
expect(func.key).toBe("value");
const defaults = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" };
const defaultsCopy = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" };
const options1 = { xnumber2: 1, xstring2: "x" };
const options1Copy = { xnumber2: 1, xstring2: "x" };
const options2 = { xstring2: "xx", xxx: "newstringx" };
const options2Copy = { xstring2: "xx", xxx: "newstringx" };
const merged2 = { xnumber1: 5, xnumber2: 1, xstring1: "peter", xstring2: "xx", xxx: "newstringx" };
settings = extend({}, defaults, options1, options2);
expect(settings).toEqual(merged2);
expect(defaults).toEqual(defaultsCopy);
expect(options1).toEqual(options1Copy);
expect(options2).toEqual(options2Copy);
expect(extend('', { foo: 1 })).toEqual({ foo: 1 });
expect(extend(null, { foo: null, deep: { foo: null } })).toEqual({ foo: null, deep: { foo: null } });
expect(extend(12, { foo: 1, deep: { foo: null, text: '' } })).toEqual({ foo: 1, deep: { foo: null, text: '' } });
});
});
@@ -1,216 +1,229 @@
import { type, isNumber, isString, isBoolean, isFunction, isArray, isObject, isUndefined, isNull, isArrayLike, isPlainObject, isEmptyObject, isHTMLElement } from 'core/utils/types'; import {
type,
isNumber,
isString,
isBoolean,
isFunction,
isArray,
isObject,
isUndefined,
isNull,
isArrayLike,
isPlainObject,
isEmptyObject,
isHTMLElement,
} from 'core/utils/types';
const testfn = function () { }; const testfn = function () {};
const testfnAsync = async function () { }; const testfnAsync = async function () {};
const typeNameValueMap = { const typeNameValueMap = {
null: null, null: null,
undefined: undefined, undefined,
void0: void 0, void0: void 0,
infinity: Infinity, infinity: Infinity,
number: 0, number: 0,
string: '0', string: '0',
booleanTrue: true, booleanTrue: true,
booleanFalse: false, booleanFalse: false,
function: testfn, function: testfn,
functionAsync: testfnAsync, functionAsync: testfnAsync,
functionArrow: () => { }, functionArrow: () => {},
functionArrowAsync: async () => { }, functionArrowAsync: async () => {},
functionConstructor: new (testfn as any)(), functionConstructor: new (testfn as any)(),
arrayEmpty: [], arrayEmpty: [],
objectEmpty: {}, objectEmpty: {},
array: [1, 2, 3], array: [1, 2, 3],
object: { a: 1, b: 2, c: 3 }, object: { a: 1, b: 2, c: 3 },
objectCreate: Object.create(null), objectCreate: Object.create(null),
arrayLikeObject: { 0: 0, 1: 1, 2: 2, length: 3 }, arrayLikeObject: { 0: 0, 1: 1, 2: 2, length: 3 },
newNumber: new Number(0), newNumber: new Number(0),
newString: new String('0'), newString: new String('0'),
newBoolean: new Boolean(false), newBoolean: new Boolean(false),
newFunction: new Function(''), newFunction: new Function(''),
newArray: new Array(), newArray: [],
document: document, document,
window: window, window,
body: document.body, body: document.body,
querySelectorAll: document.querySelectorAll('*'), querySelectorAll: document.querySelectorAll('*'),
}; };
const testTypeFn = (typeFunc: Function, expectedTypeNameValueResultMap: any) => { const testTypeFn = (typeFunc: Function, expectedTypeNameValueResultMap: any) => {
Object.keys(typeNameValueMap).forEach(comparisonKey => { Object.keys(typeNameValueMap).forEach((comparisonKey) => {
const comparisonValue = typeNameValueMap[comparisonKey]; const comparisonValue = typeNameValueMap[comparisonKey];
const result = typeFunc(comparisonValue); const result = typeFunc(comparisonValue);
if (expectedTypeNameValueResultMap.hasOwnProperty(comparisonKey)) { if (expectedTypeNameValueResultMap.hasOwnProperty(comparisonKey)) {
const todoComparisonValue = expectedTypeNameValueResultMap[comparisonKey]; const todoComparisonValue = expectedTypeNameValueResultMap[comparisonKey];
expect(result + comparisonKey).toBe(todoComparisonValue + comparisonKey); expect(result + comparisonKey).toBe(todoComparisonValue + comparisonKey);
} } else {
else { expect(result + comparisonKey).toBe(false + comparisonKey);
expect(result + comparisonKey).toBe(false + comparisonKey); }
} });
});
}; };
describe('types', () => { describe('types', () => {
test('type', () => { test('type', () => {
expect(type(undefined)).toBe("undefined"); expect(type(undefined)).toBe('undefined');
expect(type(null)).toBe("null"); expect(type(null)).toBe('null');
expect(type(true)).toBe("boolean"); expect(type(true)).toBe('boolean');
expect(type(new Boolean())).toBe("boolean"); expect(type(new Boolean())).toBe('boolean');
expect(type(3)).toBe("number"); expect(type(3)).toBe('number');
expect(type(new Number(3))).toBe("number"); expect(type(new Number(3))).toBe('number');
expect(type("test")).toBe("string"); expect(type('test')).toBe('string');
expect(type(new String("test"))).toBe("string"); expect(type(new String('test'))).toBe('string');
expect(type(function () { })).toBe("function"); expect(type(function () {})).toBe('function');
expect(type([])).toBe("array"); expect(type([])).toBe('array');
expect(type(new Array())).toBe("array"); expect(type([])).toBe('array');
expect(type(new Date())).toBe("date"); expect(type(new Date())).toBe('date');
expect(type(new Error())).toBe("error"); expect(type(new Error())).toBe('error');
expect(type(Symbol())).toBe("symbol"); expect(type(Symbol())).toBe('symbol');
expect(type(Object(Symbol()))).toBe("symbol"); expect(type(Object(Symbol()))).toBe('symbol');
expect(type(/test/)).toBe("regexp"); expect(type(/test/)).toBe('regexp');
});
test('isNumber', () => {
testTypeFn(isNumber, {
number: true,
infinity: true,
newNumber: false, // new Number() not a number is ok
});
});
test('isString', () => {
testTypeFn(isString, {
string: true,
newString: false, // new String() not a string is ok
});
});
test('isBoolean', () => {
testTypeFn(isBoolean, {
booleanTrue: true,
booleanFalse: true,
newBoolean: false, // new Boolean() not a boolean is ok
});
});
test('isFunction', () => {
testTypeFn(isFunction, {
function: true,
functionAsync: true,
functionArrow: true,
functionArrowAsync: true,
newFunction: true,
});
});
test('isArray', () => {
testTypeFn(isArray, {
array: true,
arrayEmpty: true,
newArray: true,
});
});
test('isObject', () => {
testTypeFn(isObject, {
object: true,
objectEmpty: true,
objectCreate: true,
document: true,
window: true,
body: true,
querySelectorAll: true,
functionConstructor: true,
arrayLikeObject: true,
// is ok since nobody does this
newNumber: true,
newString: true,
newBoolean: true,
});
});
test('isUndefined', () => {
testTypeFn(isUndefined, {
undefined: true,
void0: true,
});
});
test('isNull', () => {
testTypeFn(isNull, {
null: true,
});
});
test('isArrayLike', () => {
testTypeFn(isArrayLike, {
array: true,
arrayEmpty: true,
arrayLikeObject: true,
querySelectorAll: true,
string: true,
newString: true,
newArray: true,
// is ok I guess...
window: true,
});
});
test('isPlainObject', () => {
testTypeFn(isPlainObject, {
object: true,
objectEmpty: true,
objectCreate: true,
arrayLikeObject: true,
});
});
test('isEmptyObject', () => {
testTypeFn(isEmptyObject, {
objectEmpty: true,
objectCreate: true,
arrayEmpty: true,
newNumber: true,
newBoolean: true,
newFunction: true,
newArray: true,
null: true,
undefined: true,
booleanTrue: true,
booleanFalse: true,
void0: true,
number: true,
infinity: true,
functionConstructor: true,
function: true,
functionAsync: true,
functionArrow: true,
functionArrowAsync: true,
});
});
test('isHTMLElement', () => {
const temp = window.HTMLElement;
testTypeFn(isHTMLElement, {
body: true,
});
Array.from(document.querySelectorAll('*')).forEach((elm) => {
expect(isHTMLElement(elm)).toBeTruthy();
}); });
test('isNumber', () => { delete window.HTMLElement;
testTypeFn(isNumber, { // @ts-ignore
number: true, window.HTMLElement = null;
infinity: true,
newNumber: false // new Number() not a number is ok testTypeFn(isHTMLElement, {
}); body: true,
});
Array.from(document.querySelectorAll('*')).forEach((elm) => {
expect(isHTMLElement(elm)).toBeTruthy();
}); });
test('isString', () => { window.HTMLElement = temp;
testTypeFn(isString, { });
string: true, });
newString: false // new String() not a string is ok
});
});
test('isBoolean', () => {
testTypeFn(isBoolean, {
booleanTrue: true,
booleanFalse: true,
newBoolean: false // new Boolean() not a boolean is ok
});
});
test('isFunction', () => {
testTypeFn(isFunction, {
function: true,
functionAsync: true,
functionArrow: true,
functionArrowAsync: true,
newFunction: true
});
});
test('isArray', () => {
testTypeFn(isArray, {
array: true,
arrayEmpty: true,
newArray: true,
});
});
test('isObject', () => {
testTypeFn(isObject, {
object: true,
objectEmpty: true,
objectCreate: true,
document: true,
window: true,
body: true,
querySelectorAll: true,
functionConstructor: true,
arrayLikeObject: true,
// is ok since nobody does this
newNumber: true,
newString: true,
newBoolean: true,
});
});
test('isUndefined', () => {
testTypeFn(isUndefined, {
undefined: true,
void0: true,
});
});
test('isNull', () => {
testTypeFn(isNull, {
null: true,
});
});
test('isArrayLike', () => {
testTypeFn(isArrayLike, {
array: true,
arrayEmpty: true,
arrayLikeObject: true,
querySelectorAll: true,
string: true,
newString: true,
newArray: true,
// is ok I guess...
window: true,
});
});
test('isPlainObject', () => {
testTypeFn(isPlainObject, {
object: true,
objectEmpty: true,
objectCreate: true,
arrayLikeObject: true,
});
});
test('isEmptyObject', () => {
testTypeFn(isEmptyObject, {
objectEmpty: true,
objectCreate: true,
arrayEmpty: true,
newNumber: true,
newBoolean: true,
newFunction: true,
newArray: true,
null: true,
undefined: true,
booleanTrue: true,
booleanFalse: true,
void0: true,
number: true,
infinity: true,
functionConstructor: true,
function: true,
functionAsync: true,
functionArrow: true,
functionArrowAsync: true,
});
});
test('isHTMLElement', () => {
const temp = window.HTMLElement;
testTypeFn(isHTMLElement, {
body: true
});
Array.from(document.querySelectorAll('*')).forEach((elm) => {
expect(isHTMLElement(elm)).toBeTruthy();
});
delete window.HTMLElement;
// @ts-ignore
window.HTMLElement = null;
testTypeFn(isHTMLElement, {
body: true
});
Array.from(document.querySelectorAll('*')).forEach((elm) => {
expect(isHTMLElement(elm)).toBeTruthy();
});
window.HTMLElement = temp;
});
});
@@ -4,26 +4,26 @@ const testElm = document.body;
const testInstance = { value: 'value' }; const testInstance = { value: 'value' };
describe('instances', () => { describe('instances', () => {
afterEach(() => { afterEach(() => {
removeInstance(testElm); removeInstance(testElm);
}); });
test('add instance', () => { test('add instance', () => {
addInstance(testElm, testInstance); addInstance(testElm, testInstance);
expect(allInstances().size).toBe(1); expect(allInstances().size).toBe(1);
}); });
test('remove instance', () => { test('remove instance', () => {
addInstance(testElm, testInstance); addInstance(testElm, testInstance);
removeInstance(testElm); removeInstance(testElm);
expect(allInstances().size).toBe(0); expect(allInstances().size).toBe(0);
}); });
test('get instance', () => { test('get instance', () => {
addInstance(testElm, testInstance); addInstance(testElm, testInstance);
expect(getInstance(testElm)).toBe(testInstance); expect(getInstance(testElm)).toBe(testInstance);
}); });
}); });
@@ -2,8 +2,8 @@ import { validate } from 'core/options';
import { defaultOptions, optionsTemplate } from 'options'; import { defaultOptions, optionsTemplate } from 'options';
describe('options', () => { describe('options', () => {
test('default options matching the options template', () => { test('default options matching the options template', () => {
const { validated } = validate(defaultOptions, optionsTemplate); const { validated } = validate(defaultOptions, optionsTemplate);
expect(validated).toEqual(defaultOptions); expect(validated).toEqual(defaultOptions);
}); });
}); });

Some files were not shown because too many files have changed in this diff Show More