Skip to content

Commit 778b92f

Browse files
yyx990803Lostlover
authored andcommitted
fix: allow more enumerated values for contenteditable
close vuejs#9397
1 parent 6afd96f commit 778b92f

File tree

4 files changed

+25
-12
lines changed

4 files changed

+25
-12
lines changed

src/platforms/web/runtime/modules/attrs.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
getXlinkProp,
1515
isBooleanAttr,
1616
isEnumeratedAttr,
17-
isFalsyAttrValue
17+
isFalsyAttrValue,
18+
convertEnumeratedValue
1819
} from 'web/util/index'
1920

2021
function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {
@@ -75,7 +76,7 @@ function setAttr (el: Element, key: string, value: any) {
7576
el.setAttribute(key, value)
7677
}
7778
} else if (isEnumeratedAttr(key)) {
78-
el.setAttribute(key, isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true')
79+
el.setAttribute(key, convertEnumeratedValue(key, value))
7980
} else if (isXlink(key)) {
8081
if (isFalsyAttrValue(value)) {
8182
el.removeAttributeNS(xlinkNS, getXlinkProp(key))

src/platforms/web/server/modules/attrs.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
import {
1212
isBooleanAttr,
1313
isEnumeratedAttr,
14-
isFalsyAttrValue
14+
isFalsyAttrValue,
15+
convertEnumeratedValue
1516
} from 'web/util/attrs'
1617

1718
import { isSSRUnsafeAttr } from 'web/server/util'
@@ -54,7 +55,7 @@ export function renderAttr (key: string, value: string): string {
5455
return ` ${key}="${key}"`
5556
}
5657
} else if (isEnumeratedAttr(key)) {
57-
return ` ${key}="${isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true'}"`
58+
return ` ${key}="${escape(convertEnumeratedValue(key, value))}"`
5859
} else if (!isFalsyAttrValue(value)) {
5960
return ` ${key}="${escape(String(value))}"`
6061
}

src/platforms/web/util/attrs.js

+11
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ export const mustUseProp = (tag: string, type: ?string, attr: string): boolean =
1919

2020
export const isEnumeratedAttr = makeMap('contenteditable,draggable,spellcheck')
2121

22+
const isValidContentEditableValue = makeMap('events,caret,typing,plaintext-only')
23+
24+
export const convertEnumeratedValue = (key: string, value: any) => {
25+
return isFalsyAttrValue(value) || value === 'false'
26+
? 'false'
27+
// allow arbitrary string value for contenteditable
28+
: key === 'contenteditable' && isValidContentEditableValue(value)
29+
? value
30+
: 'true'
31+
}
32+
2233
export const isBooleanAttr = makeMap(
2334
'allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,' +
2435
'default,defaultchecked,defaultmuted,defaultselected,defer,disabled,' +

test/unit/features/directives/bind.spec.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -69,25 +69,25 @@ describe('Directive v-bind', () => {
6969

7070
it('enumerated attr', done => {
7171
const vm = new Vue({
72-
template: '<div><span :draggable="foo">hello</span></div>',
72+
template: '<div><span :contenteditable="foo">hello</span></div>',
7373
data: { foo: true }
7474
}).$mount()
75-
expect(vm.$el.firstChild.getAttribute('draggable')).toBe('true')
76-
vm.foo = 'again'
75+
expect(vm.$el.firstChild.getAttribute('contenteditable')).toBe('true')
76+
vm.foo = 'plaintext-only' // allow special values
7777
waitForUpdate(() => {
78-
expect(vm.$el.firstChild.getAttribute('draggable')).toBe('true')
78+
expect(vm.$el.firstChild.getAttribute('contenteditable')).toBe('plaintext-only')
7979
vm.foo = null
8080
}).then(() => {
81-
expect(vm.$el.firstChild.getAttribute('draggable')).toBe('false')
81+
expect(vm.$el.firstChild.getAttribute('contenteditable')).toBe('false')
8282
vm.foo = ''
8383
}).then(() => {
84-
expect(vm.$el.firstChild.getAttribute('draggable')).toBe('true')
84+
expect(vm.$el.firstChild.getAttribute('contenteditable')).toBe('true')
8585
vm.foo = false
8686
}).then(() => {
87-
expect(vm.$el.firstChild.getAttribute('draggable')).toBe('false')
87+
expect(vm.$el.firstChild.getAttribute('contenteditable')).toBe('false')
8888
vm.foo = 'false'
8989
}).then(() => {
90-
expect(vm.$el.firstChild.getAttribute('draggable')).toBe('false')
90+
expect(vm.$el.firstChild.getAttribute('contenteditable')).toBe('false')
9191
}).then(done)
9292
})
9393

0 commit comments

Comments
 (0)