Skip to content

Commit 1fbcbbc

Browse files
AlexanderBelokonAlexander
and
Alexander
authored
feat(content): improve reactivity (#688)
* fix: properly treat falsy values in context * feat: added reactivity and event support * feat: added v-model support for custom components Co-authored-by: Alexander <aab.sandash@protonmail.com>
1 parent 881f6d4 commit 1fbcbbc

File tree

1 file changed

+40
-8
lines changed

1 file changed

+40
-8
lines changed

packages/content/templates/nuxt-content.js

+40-8
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,51 @@ const info = require('property-information')
22

33
const rootKeys = ['class-name', 'class', 'style']
44

5-
function propsToData (props, doc) {
5+
const rxOn = /^@|^v-on:/
6+
const rxBind = /^:|^v-bind:/
7+
const rxModel = /^v-model/
8+
const nativeInputs = ['select', 'textarea', 'input']
9+
10+
function evalInContext (code, context) {
11+
return new Function("with(this) { return (" + code + ") }").call(context)
12+
}
13+
14+
function propsToData (node, doc) {
15+
const { tag, props } = node
616
return Object.keys(props).reduce(function (data, key) {
717
const k = key.replace(/.*:/, '')
818
let obj = rootKeys.includes(k) ? data : data.attrs
919
const value = props[key]
1020
const { attribute } = info.find(info.html, key)
11-
12-
if (key === 'v-bind') {
13-
const val = value in doc ? doc[value] : eval(`(${value})`)
21+
const native = nativeInputs.includes(tag)
22+
23+
if (rxModel.test(key) && value in doc && !native) {
24+
const mods = key.replace(rxModel, '')
25+
.split('.')
26+
.filter(d => d)
27+
.reduce((d, k) => (d[k] = true, d), {})
28+
29+
// As of yet we don't resolve custom v-model field/event names from components
30+
const field = 'value'
31+
const event = mods.lazy ? 'change' : 'input'
32+
const processor =
33+
mods.number ? (d => +d) :
34+
mods.trim ? (d => d.trim()) :
35+
d => d
36+
37+
obj[field] = evalInContext(value, doc)
38+
data.on = data.on || {}
39+
data.on[event] = e => doc[value] = processor(e)
40+
} else if (key === 'v-bind') {
41+
const val = value in doc ? doc[value] : evalInContext(value, doc)
1442
obj = Object.assign(obj, val)
15-
} else if (key.indexOf(':') === 0 || key.indexOf('v-bind:') === 0) {
16-
key = key.replace('v-bind:', '').replace(':', '')
17-
obj[key] = value in doc ? doc[value] : eval(`(${value})`)
43+
} else if (rxOn.test(key)) {
44+
key = key.replace(rxOn, '')
45+
data.on = data.on || {}
46+
data.on[key] = evalInContext(value, doc)
47+
} else if (rxBind.test(key)) {
48+
key = key.replace(rxBind, '')
49+
obj[key] = value in doc ? doc[value] : evalInContext(value, doc)
1850
} else if (Array.isArray(value)) {
1951
obj[attribute] = value.join(' ')
2052
} else {
@@ -56,7 +88,7 @@ function processNode (node, h, doc) {
5688
}
5789

5890
const slotData = slotsToData(node || {}, h, doc)
59-
const propData = propsToData(node.props, doc)
91+
const propData = propsToData(node || {}, doc)
6092
const data = Object.assign({}, slotData, propData)
6193

6294
/**

0 commit comments

Comments
 (0)