Skip to content

Commit eda903c

Browse files
committed
feat: custom delimiters
1 parent efdb5b3 commit eda903c

File tree

5 files changed

+37
-7
lines changed

5 files changed

+37
-7
lines changed

index.html

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ <h2>Tests</h2>
2424
<li><a href="/tests/pre.html">v-pre</a></li>
2525
<li><a href="/tests/reactive.html">reactive</a></li>
2626
<li><a href="/tests/multi-mount.html">Multi mount</a></li>
27+
<li><a href="/tests/custom-delimiters.html">Custom delimiters</a></li>
2728
</ul>
2829

2930
<style>

src/app.ts

+12
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,23 @@ import { createContext } from './context'
55
import { toDisplayString } from './directives/text'
66
import { nextTick } from './scheduler'
77

8+
const escapeRegex = (str: string) =>
9+
str.replace(/[-.*+?^${}()|[\]\/\\]/g, '\\$&')
10+
811
export const createApp = (initialData?: any) => {
912
// root context
1013
const ctx = createContext()
1114
if (initialData) {
1215
ctx.scope = reactive(initialData)
16+
17+
// handle custom delimiters
18+
if (initialData.$delimiters) {
19+
const [open, close] = (ctx.delimiters = initialData.$delimiters)
20+
ctx.delimitersRE = new RegExp(
21+
escapeRegex(open) + '([^]+?)' + escapeRegex(close),
22+
'g'
23+
)
24+
}
1325
}
1426

1527
// global internal helpers

src/context.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
1-
import { effect as rawEffect, reactive, ReactiveEffect } from '@vue/reactivity'
1+
import {
2+
effect as rawEffect,
3+
reactive,
4+
ReactiveEffectRunner
5+
} from '@vue/reactivity'
26
import { Block } from './block'
37
import { Directive } from './directives'
48
import { queueJob } from './scheduler'
59
import { inOnce } from './walk'
6-
710
export interface Context {
811
key?: any
912
scope: Record<string, any>
1013
dirs: Record<string, Directive>
1114
blocks: Block[]
1215
effect: typeof rawEffect
13-
effects: ReactiveEffect[]
16+
effects: ReactiveEffectRunner[]
1417
cleanups: (() => void)[]
18+
delimiters: [string, string]
19+
delimitersRE: RegExp
1520
}
1621

1722
export const createContext = (parent?: Context): Context => {
@@ -22,12 +27,14 @@ export const createContext = (parent?: Context): Context => {
2227
effects: [],
2328
blocks: [],
2429
cleanups: [],
30+
delimiters: ['{{', '}}'],
31+
delimitersRE: /\{\{([^]+?)\}\}/g,
2532
effect: (fn) => {
2633
if (inOnce) {
2734
queueJob(fn)
2835
return fn as any
2936
}
30-
const e: ReactiveEffect = rawEffect(fn, {
37+
const e: ReactiveEffectRunner = rawEffect(fn, {
3138
scheduler: () => queueJob(e)
3239
})
3340
ctx.effects.push(e)

src/walk.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { Context, createScopedContext } from './context'
1111

1212
const dirRE = /^(?:v-|:|@)/
1313
const modifierRE = /\.([\w-]+)/g
14-
const interpolationRE = /\{\{([^]+?)\}\}/g
1514

1615
export let inOnce = false
1716

@@ -82,11 +81,11 @@ export const walk = (node: Node, ctx: Context): ChildNode | null | void => {
8281
} else if (type === 3) {
8382
// Text
8483
const data = (node as Text).data
85-
if (data.includes('{{')) {
84+
if (data.includes(ctx.delimiters[0])) {
8685
let segments: string[] = []
8786
let lastIndex = 0
8887
let match
89-
while ((match = interpolationRE.exec(data))) {
88+
while ((match = ctx.delimitersRE.exec(data))) {
9089
const leading = data.slice(lastIndex, match.index)
9190
if (leading) segments.push(JSON.stringify(leading))
9291
segments.push(`$s(${match[1]})`)

tests/custom-delimiters.html

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script type="module">
2+
import { createApp } from '../src'
3+
createApp({
4+
$delimiters: ['${', '}']
5+
}).mount()
6+
</script>
7+
8+
<div v-scope="{ count: 1 }">
9+
<p>count is ${ count }!</p>
10+
<button @click="count++">increase</button>
11+
</div>

0 commit comments

Comments
 (0)