Skip to content

Commit

Permalink
reverted back to old toPath and vueSet code
Browse files Browse the repository at this point in the history
  • Loading branch information
bhoriuchi committed Jan 28, 2018
1 parent eb8b5f7 commit a443311
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 150 deletions.
77 changes: 28 additions & 49 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,39 +23,25 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de

var invalidKey = /^\d|[^a-zA-Z0-9_]/gm;
var intKey = /^\d+$/;
var charCodeOfDot = '.'.charCodeAt(0);
var reEscapeChar = /\\(\\)?/g;
var rePropName = RegExp(
// Match anything that isn't a dot or bracket.
'[^.[\\]]+' + '|' +
// Or match property names within brackets.
'\\[(?:' +
// Match a non-string expression.
'([^"\'].*)' + '|' +
// Or match strings (supports escaping characters).
'(["\'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2' + ')\\]' + '|' +
// Or match "" as the space between consecutive dots or empty brackets.
'(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))', 'g');

// modified from lodash - /~https://github.com/lodash/lodash
function toPath(string) {
if (Array.isArray(string)) {
return string;
}
var result = [];
if (string.charCodeAt(0) === charCodeOfDot) {
result.push('');
}
string.replace(rePropName, function (match, expression, quote, subString) {
var key = match;
if (quote) {
key = subString.replace(reEscapeChar, '$1');
} else if (expression) {
key = expression.trim();
}
result.push(key);

function isNumberLike(value) {
return String(value).match(/^\d+$/);
}

function toPath(pathString) {
if (Array.isArray(pathString)) return pathString;
if (typeof pathString === 'number') return [pathString];
pathString = String(pathString);

// taken from lodash - /~https://github.com/lodash/lodash
var pathRx = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(\.|\[\])(?:\4|$))/g;
var pathArray = [];

pathString.replace(pathRx, function (match, number, quote, string) {
pathArray.push(quote ? string : number !== undefined ? Number(number) : match);
return pathArray[pathArray.length - 1];
});
return result;
return pathArray;
}

function noop() {}
Expand Down Expand Up @@ -141,7 +127,7 @@ function getPaths(object) {
function _get(obj, path, defaultValue) {
try {
var o = obj;
var fields = Array.isArray(path) ? path : toPath(path);
var fields = toPath(path);
while (fields.length) {
var prop = fields.shift();
o = o[prop];
Expand Down Expand Up @@ -231,23 +217,16 @@ function buildVuexModel(vm, vuexPath, options) {
return model;
}

function vueSet(object, path, value) {
try {
var parts = toPath(path);
var obj = object;
while (parts.length) {
var key = parts.shift();
if (!parts.length) {
_vue2.default.set(obj, key, value);
} else if (!hasOwnProperty(obj, key) || obj[key] === null) {
_vue2.default.set(obj, key, typeof key === 'number' ? [] : {});
}
obj = obj[key];
}
return object;
} catch (err) {
throw deepsetError('vueSet unable to set object (' + err.message + ')');
function vueSet(obj, path, value) {
var fields = Array.isArray(path) ? path : toPath(path);
var prop = fields.shift();

if (!fields.length) return _vue2.default.set(obj, prop, value);
if (!hasOwnProperty(obj, prop) || obj[prop] === null) {
var objVal = fields.length >= 1 && isNumberLike(fields[0]) ? [] : {};
_vue2.default.set(obj, prop, objVal);
}
vueSet(obj[prop], fields, value);
}

function vuexSet(path, value) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue-deepset",
"version": "0.6.2",
"version": "0.6.3",
"description": "Deep set Vue.js objects",
"main": "index.js",
"scripts": {
Expand Down
87 changes: 37 additions & 50 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,31 @@ import Vue from 'vue'

const invalidKey = /^\d|[^a-zA-Z0-9_]/gm
const intKey = /^\d+$/
const charCodeOfDot = '.'.charCodeAt(0)
const reEscapeChar = /\\(\\)?/g
const rePropName = RegExp(
// Match anything that isn't a dot or bracket.
'[^.[\\]]+' + '|' +
// Or match property names within brackets.
'\\[(?:' +
// Match a non-string expression.
'([^"\'].*)' + '|' +
// Or match strings (supports escaping characters).
'(["\'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2' +
')\\]' + '|' +
// Or match "" as the space between consecutive dots or empty brackets.
'(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))'
, 'g')

// modified from lodash - /~https://github.com/lodash/lodash
function toPath (string) {
if (Array.isArray(string)) {
return string
}
const result = []
if (string.charCodeAt(0) === charCodeOfDot) {
result.push('')
}
string.replace(rePropName, (match, expression, quote, subString) => {
let key = match
if (quote) {
key = subString.replace(reEscapeChar, '$1')
} else if (expression) {
key = expression.trim()
}
result.push(key)
function isNumberLike(value) {
return String(value).match(/^\d+$/);
}

function toPath (pathString) {
if (Array.isArray(pathString)) return pathString
if (typeof pathString === 'number') return [ pathString ]
pathString = String(pathString)

// taken from lodash - /~https://github.com/lodash/lodash
let pathRx = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(\.|\[\])(?:\4|$))/g
let pathArray = []

pathString.replace(pathRx, (match, number, quote, string) => {
pathArray.push(
quote
? string
: number !== undefined
? Number(number)
: match
)
return pathArray[pathArray.length - 1]
})
return result
return pathArray
}

function noop () {}
Expand Down Expand Up @@ -120,7 +110,7 @@ function getPaths (object, current = '', paths = []) {
function get (obj, path, defaultValue) {
try {
let o = obj
const fields = Array.isArray(path) ? path : toPath(path)
const fields = toPath(path)
while (fields.length) {
const prop = fields.shift()
o = o[prop]
Expand Down Expand Up @@ -204,23 +194,20 @@ function buildVuexModel (vm, vuexPath, options) {
return model
}

export function vueSet (object, path, value) {
try {
const parts = toPath(path)
let obj = object
while (parts.length) {
const key = parts.shift()
if (!parts.length) {
Vue.set(obj, key, value)
} else if (!hasOwnProperty(obj, key) || obj[key] === null) {
Vue.set(obj, key, typeof key === 'number' ? [] : {})
}
obj = obj[key]
}
return object
} catch (err) {
throw deepsetError(`vueSet unable to set object (${err.message})`)
export function vueSet (obj, path, value) {
let fields = Array.isArray(path)
? path
: toPath(path)
let prop = fields.shift()

if (!fields.length) return Vue.set(obj, prop, value)
if (!hasOwnProperty(obj, prop) || obj[prop] === null) {
const objVal = fields.length >= 1 && isNumberLike(fields[0])
? []
: {}
Vue.set(obj, prop, objVal)
}
vueSet(obj[prop], fields, value)
}

export function vuexSet (path, value) {
Expand Down
97 changes: 97 additions & 0 deletions test/issue12.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Reproduce issue 12</title>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<script src="../vue-deepset.js"></script>
</head>
<body>
<div id="app">
<div>
<div>
<h1>Books info</h1>
<template v-for="(book, bookIndex) in libraryModel['books']">
<div>
<h3>{{book.title}}</h3>
<template v-for="(fan, fanIndex) in book.fans">
Name:<input v-model.trim="libraryModel[`books[${bookIndex}].fans[${fanIndex}].name`]" />
Comments:<input type="number" v-model.number="libraryModel[`books[${bookIndex}].fans[${fanIndex}].comments`]" />
<br/>
</template>
</div>
</template>
</div>
<pre v-text="libraryModel"></pre>
</div>
</div>

<script>
Vue.use(VueDeepSet)
var store = new Vuex.Store({
state: {
user: {
id: 1,
name: 'rey'
}
},
mutations: VueDeepSet.extendMutation()
})
var app = new Vue({
el: '#app',
store,
created () {
this.$store.registerModule(['BooksModule'], {
namespaced: true,
state: {
library: {
id: 1,
address: 'Some place in my mind',
books: [
{
title: 'Vuejs for fun',
fans: [
{
id: 1,
name: 'FooBarnatic',
comments: 2
},
{
id: 2,
name: 'BazManiac',
comments: 10
}
]
},
{
title: 'vue-deepset the nice way',
fans: [
{
id: 1,
name: 'FooBarnatic',
comments: 35
},
{
id: 2,
name: 'BazManiac',
comments: 50
}
]
}
]
}
}
});
},
computed: {
libraryModel() {
return this.$deepModel('BooksModule.library');
}
}
})
</script>

</body>
</html>
Loading

0 comments on commit a443311

Please sign in to comment.