Skip to content

Commit

Permalink
feat: custom delimiters
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Sep 14, 2021
1 parent efdb5b3 commit eda903c
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 7 deletions.
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ <h2>Tests</h2>
<li><a href="/tests/pre.html">v-pre</a></li>
<li><a href="/tests/reactive.html">reactive</a></li>
<li><a href="/tests/multi-mount.html">Multi mount</a></li>
<li><a href="/tests/custom-delimiters.html">Custom delimiters</a></li>
</ul>

<style>
Expand Down
12 changes: 12 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,23 @@ import { createContext } from './context'
import { toDisplayString } from './directives/text'
import { nextTick } from './scheduler'

const escapeRegex = (str: string) =>
str.replace(/[-.*+?^${}()|[\]\/\\]/g, '\\$&')

export const createApp = (initialData?: any) => {
// root context
const ctx = createContext()
if (initialData) {
ctx.scope = reactive(initialData)

// handle custom delimiters
if (initialData.$delimiters) {
const [open, close] = (ctx.delimiters = initialData.$delimiters)
ctx.delimitersRE = new RegExp(
escapeRegex(open) + '([^]+?)' + escapeRegex(close),
'g'
)
}
}

// global internal helpers
Expand Down
15 changes: 11 additions & 4 deletions src/context.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { effect as rawEffect, reactive, ReactiveEffect } from '@vue/reactivity'
import {
effect as rawEffect,
reactive,
ReactiveEffectRunner
} from '@vue/reactivity'
import { Block } from './block'
import { Directive } from './directives'
import { queueJob } from './scheduler'
import { inOnce } from './walk'

export interface Context {
key?: any
scope: Record<string, any>
dirs: Record<string, Directive>
blocks: Block[]
effect: typeof rawEffect
effects: ReactiveEffect[]
effects: ReactiveEffectRunner[]
cleanups: (() => void)[]
delimiters: [string, string]
delimitersRE: RegExp
}

export const createContext = (parent?: Context): Context => {
Expand All @@ -22,12 +27,14 @@ export const createContext = (parent?: Context): Context => {
effects: [],
blocks: [],
cleanups: [],
delimiters: ['{{', '}}'],
delimitersRE: /\{\{([^]+?)\}\}/g,
effect: (fn) => {
if (inOnce) {
queueJob(fn)
return fn as any
}
const e: ReactiveEffect = rawEffect(fn, {
const e: ReactiveEffectRunner = rawEffect(fn, {
scheduler: () => queueJob(e)
})
ctx.effects.push(e)
Expand Down
5 changes: 2 additions & 3 deletions src/walk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { Context, createScopedContext } from './context'

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

export let inOnce = false

Expand Down Expand Up @@ -82,11 +81,11 @@ export const walk = (node: Node, ctx: Context): ChildNode | null | void => {
} else if (type === 3) {
// Text
const data = (node as Text).data
if (data.includes('{{')) {
if (data.includes(ctx.delimiters[0])) {
let segments: string[] = []
let lastIndex = 0
let match
while ((match = interpolationRE.exec(data))) {
while ((match = ctx.delimitersRE.exec(data))) {
const leading = data.slice(lastIndex, match.index)
if (leading) segments.push(JSON.stringify(leading))
segments.push(`$s(${match[1]})`)
Expand Down
11 changes: 11 additions & 0 deletions tests/custom-delimiters.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script type="module">
import { createApp } from '../src'
createApp({
$delimiters: ['${', '}']
}).mount()
</script>

<div v-scope="{ count: 1 }">
<p>count is ${ count }!</p>
<button @click="count++">increase</button>
</div>

0 comments on commit eda903c

Please sign in to comment.