Skip to content

Commit bc89f92

Browse files
committed
✨ support .property shorthand (refs #39)
1 parent 69934be commit bc89f92

File tree

7 files changed

+1324
-8
lines changed

7 files changed

+1324
-8
lines changed

docs/ast.md

+1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ interface VDirectiveKey <: Node {
150150
- The `name` property doesn't have `v-` prefix. It's dropped.
151151
- The `argument` property is a `VExpressionContainer` node if it's a [dynamic argument].
152152
- In the shorthand of `v-bind` case, the `name.name` property is `"bind"` and the `name.rawName` property is `":"`.
153+
- In the shorthand of `v-bind` with `.prop` modifier case, the `name.name` property is `"bind"` and the `name.rawName` property is `"."` and the `modifiers` property includes a `VIdentifier` node of `"prop"`.
153154
- In the shorthand of `v-on` case, the `name.name` property is `"on"` and the `name.rawName` property is `@`.
154155
- In the shorthand of `v-slot` case, the `name.name` property is `"slot"` and the `name.rawName` property is `#`.
155156
- Otherwise, `shorthand` property is always `false`.

src/html/parser.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import {
4747
} from "./intermediate-tokenizer"
4848
import { Tokenizer } from "./tokenizer"
4949

50-
const DIRECTIVE_NAME = /^(?:v-|[:@#]).*[^.:@#]$/u
50+
const DIRECTIVE_NAME = /^(?:v-|[.:@#]).*[^.:@#]$/u
5151
const DT_DD = /^d[dt]$/u
5252
const DUMMY_PARENT: any = Object.freeze({})
5353

src/template/index.ts

+29-7
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ import {
3434
parseSlotScopeExpression,
3535
} from "../script"
3636

37-
const shorthandSign = /^[:@#]/u
38-
const shorthandNameMap = { ":": "bind", "@": "on", "#": "slot" }
37+
const shorthandSign = /^[.:@#]/u
38+
const shorthandNameMap = { ":": "bind", ".": "bind", "@": "on", "#": "slot" }
3939

4040
/**
4141
* Get the belonging document of the given node.
@@ -101,7 +101,11 @@ function parseDirectiveKeyStatically(node: VIdentifier): VDirectiveKey {
101101
}
102102
let i = 0
103103

104-
function createIdentifier(start: number, end: number): VIdentifier {
104+
function createIdentifier(
105+
start: number,
106+
end: number,
107+
name?: string,
108+
): VIdentifier {
105109
return {
106110
type: "VIdentifier",
107111
parent: directiveKey,
@@ -110,16 +114,15 @@ function parseDirectiveKeyStatically(node: VIdentifier): VDirectiveKey {
110114
start: { column: column + start, line },
111115
end: { column: column + end, line },
112116
},
113-
name: text.slice(start, end),
117+
name: name || text.slice(start, end),
114118
rawName: rawText.slice(start, end),
115119
}
116120
}
117121

118122
// Parse.
119123
if (shorthandSign.test(text)) {
120-
const sign = text[0] as ":" | "@" | "#"
121-
directiveKey.name = createIdentifier(0, 1)
122-
directiveKey.name.name = shorthandNameMap[sign]
124+
const sign = text[0] as ":" | "." | "@" | "#"
125+
directiveKey.name = createIdentifier(0, 1, shorthandNameMap[sign])
123126
i = 1
124127
} else {
125128
const colon = text.indexOf(":")
@@ -133,6 +136,7 @@ function parseDirectiveKeyStatically(node: VIdentifier): VDirectiveKey {
133136
.slice(i)
134137
.split(".")
135138
.map(modifierName => {
139+
//TODO: generate syntax error if modifierName.length === 0.
136140
const modifier = createIdentifier(i, i + modifierName.length)
137141
i += modifierName.length + 1
138142
return modifier
@@ -145,9 +149,23 @@ function parseDirectiveKeyStatically(node: VIdentifier): VDirectiveKey {
145149
}
146150
directiveKey.modifiers = modifiers
147151

152+
if (directiveKey.name.rawName === "." && !modifiers.some(isPropModifier)) {
153+
const pos = (directiveKey.argument || directiveKey.name).range[1]
154+
const propModifier = createIdentifier(pos, pos, "prop")
155+
modifiers.unshift(propModifier)
156+
}
157+
148158
return directiveKey
149159
}
150160

161+
/**
162+
* Check whether a given identifier node is `prop` or not.
163+
* @param node The identifier node to check.
164+
*/
165+
function isPropModifier(node: VIdentifier): boolean {
166+
return node.name === "prop"
167+
}
168+
151169
/**
152170
* Parse the tokens of a given key node.
153171
* @param node The key node to parse.
@@ -193,6 +211,10 @@ function parseDirectiveKeyTokens(node: VDirectiveKey): Token[] {
193211

194212
let lastNode = (argument as VIdentifier | null) || name
195213
for (const modifier of modifiers) {
214+
if (modifier.rawName === "") {
215+
continue
216+
}
217+
196218
tokens.push(
197219
{
198220
type: "Punctuator",

0 commit comments

Comments
 (0)