Skip to content

Commit 24124b7

Browse files
committed
add handling of events
1 parent d1e57af commit 24124b7

File tree

2 files changed

+124
-33
lines changed

2 files changed

+124
-33
lines changed

src/index.js

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
// https://github.com/justin-schroeder/arrow-js/blob/31c1861075aabe29b67620b58a33c7fecb209c8f/src/html.ts#L166C1-L166C23
22
const delimiter = '➳❍'
3-
const bookend = '❍⇚'
43
const delimiterComment = `<!--${delimiter}-->`
4+
5+
//FIXME: Don't really need to handle
6+
const bookend = '❍⇚'
57
const bookendComment = `<!--${bookend}-->`
68

9+
const eventRegex = /(@)(\w+)=["']$/
10+
711
export function renderToString(template) {
812
const isT = 'isT' in template
913

@@ -17,41 +21,55 @@ export function renderToString(template) {
1721

1822
let htmlString = renderResult[0]
1923
const expressions = renderResult[1]
20-
if (expressions.length > 0) {
21-
expressions.forEach(expressionInstance => {
22-
const isExpressionReactive = expressionInstance && expressionInstance.e
23-
const isExpressionPartial = isExpressionReactive.isT
24-
25-
if (!isExpressionReactive) {
26-
htmlString = htmlString.replace(delimiterComment, expressionInstance())
27-
return
28-
}
24+
const evntsOnIndex = []
25+
let index = -1
2926

30-
if (isExpressionPartial) {
31-
htmlString = htmlString.replace(
32-
delimiterComment,
33-
renderToString(expressionInstance.e)
34-
)
35-
return
36-
}
27+
if (!expressions.length) return htmlString
3728

38-
const watcherReturn = expressionInstance.e()
29+
return htmlString.replace(
30+
new RegExp(delimiterComment, 'g'),
31+
(...matchers) => {
32+
const str = matchers[0]
33+
const matchedAt = matchers[1]
34+
const matchedString = matchers[2]
35+
index += 1
3936

40-
if (
41-
typeof watcherReturn !== 'object' &&
42-
typeof watcherReturn !== 'function'
43-
) {
44-
htmlString = htmlString.replace(delimiterComment, watcherReturn)
45-
return
37+
const beforeDelim = matchedString.slice(0, matchedAt)
38+
const immediatelyFollowed = eventRegex.test(beforeDelim)
39+
if (immediatelyFollowed) {
40+
return str
4641
}
42+
return interpolateExpressions(str, expressions[index])
43+
}
44+
)
45+
}
4746

48-
if (watcherReturn && watcherReturn.isT) {
49-
const _nestedHtmlString = renderToString(watcherReturn)
50-
htmlString = htmlString.replace(delimiterComment, _nestedHtmlString)
51-
return
52-
}
53-
})
47+
function interpolateExpressions(htmlString, expressionInstance) {
48+
const isExpressionReactive = expressionInstance && expressionInstance.e
49+
const isExpressionPartial = isExpressionReactive.isT
50+
51+
if (!isExpressionReactive) {
52+
return htmlString.replace(delimiterComment, expressionInstance())
53+
}
54+
55+
if (isExpressionPartial) {
56+
return htmlString.replace(
57+
delimiterComment,
58+
renderToString(expressionInstance.e)
59+
)
5460
}
5561

56-
return htmlString
62+
const watcherReturn = expressionInstance.e()
63+
64+
if (
65+
typeof watcherReturn !== 'object' &&
66+
typeof watcherReturn !== 'function'
67+
) {
68+
return htmlString.replace(delimiterComment, watcherReturn)
69+
}
70+
71+
if (watcherReturn && watcherReturn.isT) {
72+
const _nestedHtmlString = renderToString(watcherReturn)
73+
return htmlString.replace(delimiterComment, _nestedHtmlString)
74+
}
5775
}

tests/basic.test.js

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ test('variable', async () => {
2323
assert.is(out, '<p>hello world</p>')
2424
})
2525

26-
test('reactive variable', async () => {
26+
test('reactive variable type string', async () => {
2727
const rVar = reactive({ message: 'hello world' })
2828
const tmp = html`<p>${rVar.message}</p>`
2929
const out = renderToString(tmp)
3030
assert.is(out, '<p>hello world</p>')
3131
})
3232

33-
test('reactive variable nested', async () => {
33+
test('reactive variable type number', async () => {
3434
const pageState = reactive({
3535
count: 0,
3636
})
@@ -120,4 +120,77 @@ test('Mix match partials and', async () => {
120120
)
121121
})
122122

123+
test('events', async () => {
124+
const rVar = reactive({ count: 0 })
125+
const final = html`<button @click="${() => rVar.count + 1}">
126+
${rVar.count}
127+
</button>`
128+
129+
const out = renderToString(final)
130+
131+
await inlineSnapshot(
132+
out,
133+
`<button @click="<!--➳❍-->">
134+
0
135+
</button>`
136+
)
137+
})
138+
139+
test('multiple events', async () => {
140+
const rVar = reactive({ count: 0 })
141+
const final = html`<button
142+
@click="${() => rVar.count + 1}"
143+
@focus="${() => console.log('focus!')}"
144+
>
145+
${rVar.count}
146+
</button>`
147+
148+
const out = renderToString(final)
149+
150+
await inlineSnapshot(
151+
out,
152+
`<button
153+
@click="<!--➳❍-->"
154+
@focus="<!--➳❍-->"
155+
>
156+
0
157+
</button>`
158+
)
159+
})
160+
161+
test('nested events', async () => {
162+
const rVar = reactive({ count: 0 })
163+
const partial = html`
164+
<input
165+
@focus="${() => {
166+
console.log('input focused')
167+
}}"
168+
/>
169+
`
170+
const final = html`<button
171+
value="${() => rVar.count + 1}"
172+
@click="${() => rVar.count + 1}"
173+
@focus="${() => console.log('focus!')}"
174+
>
175+
${rVar.count} ${partial}
176+
</button>`
177+
178+
const out = renderToString(final)
179+
180+
await inlineSnapshot(
181+
out,
182+
`<button
183+
value="1"
184+
@click="<!--➳❍-->"
185+
@focus="<!--➳❍-->"
186+
>
187+
0
188+
<input
189+
@focus="<!--➳❍-->"
190+
/>
191+
192+
</button>`
193+
)
194+
})
195+
123196
test.run()

0 commit comments

Comments
 (0)