first commit

This commit is contained in:
DanielRamirezGe
2020-01-14 20:43:08 -06:00
parent 3557894f7f
commit 5eecfbf6cd
26326 changed files with 2434803 additions and 0 deletions
+110
View File
@@ -0,0 +1,110 @@
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [3.1.0](https://github.com/alexsasharegan/vue-functional-data-merge/compare/v3.0.1...v3.1.0) (2019-06-01)
### Features
* vue compliant style string parsing ([#9](https://github.com/alexsasharegan/vue-functional-data-merge/issues/9)) ([e7d640b](https://github.com/alexsasharegan/vue-functional-data-merge/commit/e7d640b)), closes [/github.com/vuejs/vue/blob/dev/src/platforms/web/util/style.js#L5-L16](https://github.com/alexsasharegan/vue-functional-data-merge/issues/L5-L16)
### [3.0.1](https://github.com/alexsasharegan/vue-functional-data-merge/compare/v3.0.0...v3.0.1) (2019-06-01)
### Bug Fixes
* split on first ':' char ([40e06c5](https://github.com/alexsasharegan/vue-functional-data-merge/commit/40e06c5))
## [3.0.0](https://github.com/alexsasharegan/vue-functional-data-merge/compare/v2.0.7...v3.0.0) (2019-06-01)
### Bug Fixes
* remove unnecessary code ([9c9f3ce](https://github.com/alexsasharegan/vue-functional-data-merge/commit/9c9f3ce))
* update tests for latest jest version ([1e4f2f0](https://github.com/alexsasharegan/vue-functional-data-merge/commit/1e4f2f0))
### Features
* parse & merge style strings ([6894fa7](https://github.com/alexsasharegan/vue-functional-data-merge/commit/6894fa7))
### BREAKING CHANGES
* parsing strings into style objects changes the output and rendered style behavior in components
<a name="2.0.7"></a>
## [2.0.7](https://github.com/alexsasharegan/vue-functional-data-merge/compare/v2.0.6...v2.0.7) (2018-09-07)
<a name="2.0.6"></a>
## [2.0.6](https://github.com/alexsasharegan/vue-functional-data-merge/compare/v2.0.5...v2.0.6) (2018-03-17)
<a name="2.0.5"></a>
## [2.0.5](https://github.com/alexsasharegan/vue-functional-data-merge/compare/v2.0.4...v2.0.5) (2018-03-01)
<a name="2.0.4"></a>
## [2.0.4](https://github.com/alexsasharegan/vue-functional-data-merge/compare/v2.0.3...v2.0.4) (2018-01-16)
### Bug Fixes
* **#5:** handle initial state nullables on nested props ([#6](https://github.com/alexsasharegan/vue-functional-data-merge/issues/6)) ([2b78c54](https://github.com/alexsasharegan/vue-functional-data-merge/commit/2b78c54)), closes [#5](https://github.com/alexsasharegan/vue-functional-data-merge/issues/5) [#5](https://github.com/alexsasharegan/vue-functional-data-merge/issues/5)
<a name="2.0.3"></a>
## [2.0.3](https://github.com/alexsasharegan/vue-functional-data-merge/compare/v2.0.2...v2.0.3) (2017-12-09)
<a name="2.0.2"></a>
## [2.0.2](https://github.com/alexsasharegan/vue-functional-data-merge/compare/v2.0.1...v2.0.2) (2017-11-26)
### Bug Fixes
* transpile for of stmts ([5048b40](https://github.com/alexsasharegan/vue-functional-data-merge/commit/5048b40))
<a name="2.0.1"></a>
## [2.0.1](https://github.com/alexsasharegan/vue-functional-data-merge/compare/v2.0.0...v2.0.1) (2017-11-26)
### Bug Fixes
* mv obj spread to index signature typing & use arguments only ([c087a4f](https://github.com/alexsasharegan/vue-functional-data-merge/commit/c087a4f))
<a name="2.0.0"></a>
# [2.0.0](https://github.com/alexsasharegan/vue-functional-data-merge/compare/v1.0.7...v2.0.0) (2017-11-26)
### Bug Fixes
* **#2:** don't copy level 1 obj refs ([28bb545](https://github.com/alexsasharegan/vue-functional-data-merge/commit/28bb545))
### Features
* add testing & bench, fix issue [#2](https://github.com/alexsasharegan/vue-functional-data-merge/issues/2), refactor ([e978c7f](https://github.com/alexsasharegan/vue-functional-data-merge/commit/e978c7f))
### BREAKING CHANGES
* default export has been removed in favor of named export
* right-most arguments were not originally given precedence in all cases. This has been fixed.
+22
View File
@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2017 Alex Regan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+3
View File
@@ -0,0 +1,3 @@
import { VNodeData } from "vue";
declare function mergeData(...vNodeData: VNodeData[]): VNodeData;
export { mergeData };
+2
View File
@@ -0,0 +1,2 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var __assign=function(){return(__assign=Object.assign||function(e){for(var t,a=1,r=arguments.length;a<r;a++)for(var s in t=arguments[a])Object.prototype.hasOwnProperty.call(t,s)&&(e[s]=t[s]);return e}).apply(this,arguments)},pattern={kebab:/-(\w)/g,styleProp:/:(.*)/,styleList:/;(?![^(]*\))/g};function camelReplace(e,t){return t?t.toUpperCase():""}function camelCase(e){return e.replace(pattern.kebab,camelReplace)}function parseStyle(e){for(var t={},a=0,r=e.split(pattern.styleList);a<r.length;a++){var s=r[a].split(pattern.styleProp),c=s[0],n=s[1];(c=c.trim())&&("string"==typeof n&&(n=n.trim()),t[camelCase(c)]=n)}return t}function mergeData(){for(var e,t,a={},r=arguments.length;r--;)for(var s=0,c=Object.keys(arguments[r]);s<c.length;s++)switch(e=c[s]){case"class":case"style":case"directives":if(Array.isArray(a[e])||(a[e]=[]),"style"===e){var n=void 0;n=Array.isArray(arguments[r].style)?arguments[r].style:[arguments[r].style];for(var o=0;o<n.length;o++){var l=n[o];"string"==typeof l&&(n[o]=parseStyle(l))}arguments[r].style=n}a[e]=a[e].concat(arguments[r][e]);break;case"staticClass":if(!arguments[r][e])break;void 0===a[e]&&(a[e]=""),a[e]&&(a[e]+=" "),a[e]+=arguments[r][e].trim();break;case"on":case"nativeOn":a[e]||(a[e]={});for(var i=0,p=Object.keys(arguments[r][e]||{});i<p.length;i++)t=p[i],a[e][t]?a[e][t]=[].concat(a[e][t],arguments[r][e][t]):a[e][t]=arguments[r][e][t];break;case"attrs":case"props":case"domProps":case"scopedSlots":case"staticStyle":case"hook":case"transition":a[e]||(a[e]={}),a[e]=__assign({},arguments[r][e],a[e]);break;case"slot":case"key":case"ref":case"tag":case"show":case"keepAlive":default:a[e]||(a[e]=arguments[r][e])}return a}exports.mergeData=mergeData;
//# sourceMappingURL=lib.common.js.map
File diff suppressed because one or more lines are too long
+2
View File
@@ -0,0 +1,2 @@
var e=function(){return(e=Object.assign||function(e){for(var t,r=1,s=arguments.length;r<s;r++)for(var a in t=arguments[r])Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e}).apply(this,arguments)},t={kebab:/-(\w)/g,styleProp:/:(.*)/,styleList:/;(?![^(]*\))/g};function r(e,t){return t?t.toUpperCase():""}function s(e){for(var s,a={},c=0,o=e.split(t.styleList);c<o.length;c++){var n=o[c].split(t.styleProp),i=n[0],l=n[1];(i=i.trim())&&("string"==typeof l&&(l=l.trim()),a[(s=i,s.replace(t.kebab,r))]=l)}return a}function a(){for(var t,r,a={},c=arguments.length;c--;)for(var o=0,n=Object.keys(arguments[c]);o<n.length;o++)switch(t=n[o]){case"class":case"style":case"directives":if(Array.isArray(a[t])||(a[t]=[]),"style"===t){var i=void 0;i=Array.isArray(arguments[c].style)?arguments[c].style:[arguments[c].style];for(var l=0;l<i.length;l++){var y=i[l];"string"==typeof y&&(i[l]=s(y))}arguments[c].style=i}a[t]=a[t].concat(arguments[c][t]);break;case"staticClass":if(!arguments[c][t])break;void 0===a[t]&&(a[t]=""),a[t]&&(a[t]+=" "),a[t]+=arguments[c][t].trim();break;case"on":case"nativeOn":a[t]||(a[t]={});for(var p=0,f=Object.keys(arguments[c][t]||{});p<f.length;p++)r=f[p],a[t][r]?a[t][r]=[].concat(a[t][r],arguments[c][t][r]):a[t][r]=arguments[c][t][r];break;case"attrs":case"props":case"domProps":case"scopedSlots":case"staticStyle":case"hook":case"transition":a[t]||(a[t]={}),a[t]=e({},arguments[c][t],a[t]);break;case"slot":case"key":case"ref":case"tag":case"show":case"keepAlive":default:a[t]||(a[t]=arguments[c][t])}return a}export{a as mergeData};
//# sourceMappingURL=lib.esm.js.map
File diff suppressed because one or more lines are too long
+2
View File
@@ -0,0 +1,2 @@
var mergeData=function(e){"use strict";var t=function(){return(t=Object.assign||function(e){for(var t,r=1,a=arguments.length;r<a;r++)for(var s in t=arguments[r])Object.prototype.hasOwnProperty.call(t,s)&&(e[s]=t[s]);return e}).apply(this,arguments)},r={kebab:/-(\w)/g,styleProp:/:(.*)/,styleList:/;(?![^(]*\))/g};function a(e,t){return t?t.toUpperCase():""}function s(e){for(var t,s={},c=0,n=e.split(r.styleList);c<n.length;c++){var o=n[c].split(r.styleProp),i=o[0],l=o[1];(i=i.trim())&&("string"==typeof l&&(l=l.trim()),s[(t=i,t.replace(r.kebab,a))]=l)}return s}return e.mergeData=function(){for(var e,r,a={},c=arguments.length;c--;)for(var n=0,o=Object.keys(arguments[c]);n<o.length;n++)switch(e=o[n]){case"class":case"style":case"directives":if(Array.isArray(a[e])||(a[e]=[]),"style"===e){var i=void 0;i=Array.isArray(arguments[c].style)?arguments[c].style:[arguments[c].style];for(var l=0;l<i.length;l++){var y=i[l];"string"==typeof y&&(i[l]=s(y))}arguments[c].style=i}a[e]=a[e].concat(arguments[c][e]);break;case"staticClass":if(!arguments[c][e])break;void 0===a[e]&&(a[e]=""),a[e]&&(a[e]+=" "),a[e]+=arguments[c][e].trim();break;case"on":case"nativeOn":a[e]||(a[e]={});for(var f=0,p=Object.keys(arguments[c][e]||{});f<p.length;f++)r=p[f],a[e][r]?a[e][r]=[].concat(a[e][r],arguments[c][e][r]):a[e][r]=arguments[c][e][r];break;case"attrs":case"props":case"domProps":case"scopedSlots":case"staticStyle":case"hook":case"transition":a[e]||(a[e]={}),a[e]=t({},arguments[c][e],a[e]);break;case"slot":case"key":case"ref":case"tag":case"show":case"keepAlive":default:a[e]||(a[e]=arguments[c][e])}return a},e}({});
//# sourceMappingURL=lib.js.map
File diff suppressed because one or more lines are too long
+110
View File
@@ -0,0 +1,110 @@
{
"_from": "vue-functional-data-merge@^3.1.0",
"_id": "vue-functional-data-merge@3.1.0",
"_inBundle": false,
"_integrity": "sha512-leT4kdJVQyeZNY1kmnS1xiUlQ9z1B/kdBFCILIjYYQDqZgLqCLa0UhjSSeRX6c3mUe6U5qYeM8LrEqkHJ1B4LA==",
"_location": "/vue-functional-data-merge",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "vue-functional-data-merge@^3.1.0",
"name": "vue-functional-data-merge",
"escapedName": "vue-functional-data-merge",
"rawSpec": "^3.1.0",
"saveSpec": null,
"fetchSpec": "^3.1.0"
},
"_requiredBy": [
"/bootstrap-vue"
],
"_resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz",
"_shasum": "08a7797583b7f35680587f8a1d51d729aa1dc657",
"_spec": "vue-functional-data-merge@^3.1.0",
"_where": "/home/george/citwa/red_de_investigacion_front/first/node_modules/bootstrap-vue",
"author": {
"name": "Alex Regan",
"email": "alex.joseph.regan@gmail.com",
"url": "https://github.com/alexsasharegan"
},
"bugs": {
"url": "https://github.com/alexsasharegan/vue-functional-data-merge/issues"
},
"bundleDependencies": false,
"dependencies": {},
"deprecated": false,
"description": "Vue.js util for intelligently merging data passed to functional components.",
"devDependencies": {
"@types/benchmark": "^1.0.31",
"@types/jest": "^24.0.13",
"benchmark": "^2.1.4",
"coveralls": "^3.0.3",
"cross-env": "^5.2.0",
"jest": "^24.8.0",
"lodash": "^4.17.11",
"prettier": "^1.17.1",
"rollup": "^1.13.1",
"rollup-plugin-terser": "^5.0.0",
"rollup-plugin-typescript2": "^0.21.1",
"rollup-plugin-uglify": "^6.0.2",
"standard-version": "^6.0.1",
"ts-jest": "^24.0.2",
"typescript": "^3.5.1",
"uglify-es": "^3.3.9",
"vue": "^2.6.10"
},
"files": [
"dist",
"src"
],
"homepage": "https://github.com/alexsasharegan/vue-functional-data-merge#readme",
"jest": {
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"transform": {
"\\.(ts|tsx)$": "ts-jest"
},
"testMatch": [
"**/__tests__/*.(ts|js)",
"**/?(*.)(spec|test).(js|ts)"
],
"coverageDirectory": "coverage",
"collectCoverage": true
},
"keywords": [
"vue",
"vuejs",
"functional",
"components",
"vue",
"util"
],
"license": "MIT",
"main": "dist/lib.common.js",
"module": "dist/lib.esm.js",
"name": "vue-functional-data-merge",
"repository": {
"type": "git",
"url": "git+https://github.com/alexsasharegan/vue-functional-data-merge.git"
},
"scripts": {
"bench": "node benchmark/",
"build": "cross-env NODE_ENV=production npm run rollup",
"coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
"fmt": "prettier --config ./.prettierrc --write {__test__,src}/**/*.{ts,js}",
"postrelease": "git push --follow-tags origin master && npm publish",
"prebuild": "scripts/clean.js",
"prepublishOnly": "npm run build",
"prerelease": "npm run build && npm test",
"release": "standard-version",
"rollup": "rollup -c",
"size": "cat dist/lib.esm.js | wc -c",
"size:gzip": "gzip -c dist/lib.esm.js | wc -c",
"test": "jest --verbose --coverage"
},
"types": "dist/index.d.ts",
"version": "3.1.0"
}
+254
View File
@@ -0,0 +1,254 @@
# vue-functional-data-merge
[![npm](https://img.shields.io/npm/v/vue-functional-data-merge.svg?style=for-the-badge)](https://img.shields.io/npm/v/vue-functional-data-merge)
[![npm downloads](https://img.shields.io/npm/dt/vue-functional-data-merge.svg?style=for-the-badge)](https://www.npmjs.com/package/vue-functional-data-merge)
[![GitHub stars](https://img.shields.io/github/stars/alexsasharegan/vue-functional-data-merge.svg?style=for-the-badge)](https://github.com/alexsasharegan/vue-functional-data-merge/stargazers)
[![GitHub issues](https://img.shields.io/github/issues/alexsasharegan/vue-functional-data-merge.svg?style=for-the-badge)](https://github.com/alexsasharegan/vue-functional-data-merge/issues)
[![Travis](https://img.shields.io/travis/alexsasharegan/vue-functional-data-merge.svg?style=for-the-badge)](https://github.com/alexsasharegan/vue-functional-data-merge)
[![Coverage Status](https://img.shields.io/coveralls/github/alexsasharegan/vue-functional-data-merge.svg?style=for-the-badge)](https://coveralls.io/github/alexsasharegan/vue-functional-data-merge)
[![GitHub license](https://img.shields.io/github/license/alexsasharegan/vue-functional-data-merge.svg?style=for-the-badge)](https://github.com/alexsasharegan/vue-functional-data-merge/blob/master/LICENSE.md)
Vue.js util for intelligently merging data passed to functional components. (1K
=> 0.5K gzipped)
- [Getting Started](#getting-started)
- [Why do I need this util?](#why-do-i-need-this-util)
- [Scoped Styles](#scoped-styles)
- [Performance](#performance)
## Getting Started
Load the util from npm:
```sh
# NPM:
npm i vue-functional-data-merge
# Yarn:
yarn add vue-functional-data-merge
```
Now import and use it in your functional component declaration:
```js
// MyFunctionalComponent.js
// ESM
import { mergeData } from "vue-functional-data-merge";
// Common JS
const { mergeData } = require("vue-functional-data-merge/dist/lib.common.js");
export default {
name: "my-functional-component",
functional: true,
props: ["foo", "bar", "baz"],
render(h, { props, data, children }) {
const componentData = {
staticClass: "fn-component", // concatenates all static classes
class: {
// object|Array|string all get merged and preserved
active: props.foo,
"special-class": props.bar,
},
attrs: {
id: "my-functional-component", // now overrides any id placed on the component
},
on: {
// Event handlers are merged to an array of handlers at each event.
// The last data object passed to `mergeData` will have it's event handlers called first.
// Right-most arguments are prepended to event handler array.
click(e) {
alert(props.baz);
},
},
};
return h("div", mergeData(data, componentData), children);
},
};
```
## Why do I need this util?
When writing functional Vue components, the render function receives a
`context.data` object
([see vue docs](https://vuejs.org/v2/guide/render-function.html#Functional-Components)).
This object that contains the entire data object passed to the component (the
shape of which
[can be found here](https://vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth)).
In order to write flexible components, the data object used to create the
component must be merged with the data received. If not, only the properties
defined by the component will be rendered.
Consider this example:
```js
// MyBtn.js
export default {
name: "my-btn",
props: ["variant"],
functional: true,
render(h, { props, children }) {
return h(
"button",
{
staticClass: "btn",
class: [`btn-${props.variant}`],
attrs: { type: "button" },
},
children
);
},
};
```
This exports a functional button component that applies a base `.btn` class and
a `.btn-<variant>` class based on the `variant` prop passed to the component.
It's just a simple wrapper around some Bootstrap styling to make repetitive
usage simpler. Usage would look like this:
```html
<template>
<form>
<input type="text" placeholder="Name" required>
<input type="email" placeholder="email" required>
<my-btn variant="primary" type="submit" id="form-submit-btn" @click="onClick">Submit</my-btn>
</form>
</template>
```
We've used our Bootstrap button component in a form and conveniently applied the
`primary` variant, but we also wanted to change the button `type` from `button`
to `submit`, give it an `id`, and attach a click handler. This won't work
because we haven't passed the attributes, listeners, etc. to the create element
call in the component's render function.
To fix this, we might extract out props, merge listeners/attributes, etc. This
works well, but gets verbose fast when attempting to support all dom attributes,
event listeners, etc. One might think to simply use Object spread or
`Object.assign` to solve this like so:
```js
return h("button", { ...context.data, ...componentData }, children);
```
Now when we try to add any dom attributes, Object spread is essentially
performing something like this:
```js
Object.assign(
{},
{
props: { variant: "primary" },
attrs: { id: "form-submit-btn", type: "submit" }
on: { click: onClick }
},
{
staticClass: "btn",
class: [`btn-${props.variant}`],
attrs: { type: "button" },
on: {
click() {
alert("Hello from MyBtn!")
}
}
}
)
```
The component data will wipe out all the context's `attrs` and `on` handlers as
`Object.assign` merges these properties. This is where the `mergeData` util can
help you. It will dig into the nested properties of the `context.data` and apply
different merge strategies for each data property. `mergeData` works like a
nested `Object.assign` in that the util has a variadic argument length&mdash;you
can pass any number of arguments to it, and they will all be merged from left to
right (the right most arguments taking merge priority). You don't have to pass a
new target object as the first argument, as the return value will always be a
fresh object.
## Scoped Styles
You may run into cases where you are using a functional component in another
component with scoped styles. This would look something like this:
```html
<template>
<button class="my-class">
<slot></slot>
</button>
</template>
<style scoped>
.my-class {
text-align: center;
}
</style>
```
This will generate data attributes on the component elements and the css
selector.
```html
<style>
.my-class[data-v-f3f3eg9] {
text-align: center;
}
</style>
<button data-v-f3f3eg9 class="my-class">
Click me!
</button>
```
When a parent component with scoped styles makes use of a functional component,
the data attribute won't be passed down automatically. Instead, you must pull
this attribute out manually and add it to the `VNodeData` used in a render
function's `createElement` call. Doing this requires reaching into Vue
internals, which can be risky due to the private nature of the API and its
potential to change. For that reason, this is not supported in this util.
However, this util can make that manual merging easier by conforming to the
`VNodeData` shape required by `mergeData` and Vue itself. Here is an example of
a helper function to manually extract a parent's style scope id and
conditionally apply it in the functional component's render function.
```js
const FunctionalComponent = {
functional: true,
render(createElement, context) {
let { parent, data, children } = context;
let componentData = { class: "my-class" };
return createElement(
"button",
mergeData(data, getScopedStyleData(parent), componentData),
children
);
},
};
/**
* @param {Vue} parent
* @returns {VNodeData}
*/
export function getScopedStyleData(parent) {
let data = { attrs: {} };
if (parent.$options._scopeId) {
data.attrs[`data-v-${parent.$options._scopeId}`] = "";
}
return data;
}
```
## Performance
This util was written with performance in mind. Since functional components are
perfect for components that are stateless and have many nodes rendered, the
`mergeData` util is expected to be called extensively. As such, minimal variable
allocations are made as well as minimal internal function calls _(for loops are
preferred over `map`, `reduce`, & `forEach` to avoid adding stack frames)_.
TypeScript is used with Vue typings to ensure the most accurate merge strategy
for each property of the `context.data` object. You can run the benchmark
yourself, but simple merges run at ~1,000,000 ops/sec and complex merges at
~400,000 ops/sec.
+151
View File
@@ -0,0 +1,151 @@
import { VNodeData } from "vue";
const pattern = {
kebab: /-(\w)/g,
styleProp: /:(.*)/,
styleList: /;(?![^(]*\))/g,
} as const;
function camelReplace(_substr: string, match: string) {
return match ? match.toUpperCase() : "";
}
function camelCase(str: string) {
return str.replace(pattern.kebab, camelReplace);
}
function parseStyle(style: string) {
let styleMap: Record<string, any> = {};
for (let s of style.split(pattern.styleList)) {
let [key, val] = s.split(pattern.styleProp);
key = key.trim();
if (!key) {
continue;
}
// May be undefined if the `key: value` pair is incomplete.
if (typeof val === "string") {
val = val.trim();
}
styleMap[camelCase(key)] = val;
}
return styleMap;
}
/**
* Intelligently merges data for createElement.
* Merges arguments left to right, preferring the right argument.
* Returns new VNodeData object.
*/
function mergeData(...vNodeData: VNodeData[]): VNodeData;
function mergeData(): VNodeData {
let mergeTarget: VNodeData & Record<string, any> = {};
let i: number = arguments.length;
let prop: string;
let event: string;
// Allow for variadic argument length.
while (i--) {
// Iterate through the data properties and execute merge strategies
// Object.keys eliminates need for hasOwnProperty call
for (prop of Object.keys(arguments[i])) {
switch (prop) {
// Array merge strategy (array concatenation)
case "class":
case "style":
case "directives":
if (!Array.isArray(mergeTarget[prop])) {
mergeTarget[prop] = [];
}
if (prop === "style") {
let style: any[];
if (Array.isArray(arguments[i].style)) {
style = arguments[i].style;
} else {
style = [arguments[i].style];
}
for (let j = 0; j < style.length; j++) {
let s = style[j];
if (typeof s === "string") {
style[j] = parseStyle(s);
}
}
arguments[i].style = style;
}
// Repackaging in an array allows Vue runtime
// to merge class/style bindings regardless of type.
mergeTarget[prop] = mergeTarget[prop].concat(arguments[i][prop]);
break;
// Space delimited string concatenation strategy
case "staticClass":
if (!arguments[i][prop]) {
break;
}
if (mergeTarget[prop] === undefined) {
mergeTarget[prop] = "";
}
if (mergeTarget[prop]) {
// Not an empty string, so concatenate
mergeTarget[prop] += " ";
}
mergeTarget[prop] += arguments[i][prop].trim();
break;
// Object, the properties of which to merge via array merge strategy (array concatenation).
// Callback merge strategy merges callbacks to the beginning of the array,
// so that the last defined callback will be invoked first.
// This is done since to mimic how Object.assign merging
// uses the last given value to assign.
case "on":
case "nativeOn":
if (!mergeTarget[prop]) {
mergeTarget[prop] = {};
}
for (event of Object.keys(arguments[i][prop] || {})) {
// Concat function to array of functions if callback present.
if (mergeTarget[prop][event]) {
// Insert current iteration data in beginning of merged array.
mergeTarget[prop][event] = [].concat(
mergeTarget[prop][event],
arguments[i][prop][event]
);
} else {
// Straight assign.
mergeTarget[prop][event] = arguments[i][prop][event];
}
}
break;
// Object merge strategy
case "attrs":
case "props":
case "domProps":
case "scopedSlots":
case "staticStyle":
case "hook":
case "transition":
if (!mergeTarget[prop]) {
mergeTarget[prop] = {};
}
mergeTarget[prop] = { ...arguments[i][prop], ...mergeTarget[prop] };
break;
// Reassignment strategy (no merge)
case "slot":
case "key":
case "ref":
case "tag":
case "show":
case "keepAlive":
default:
if (!mergeTarget[prop]) {
mergeTarget[prop] = arguments[i][prop];
}
}
}
}
return mergeTarget;
}
export { mergeData };