Skip to content

Commit dde57b3

Browse files
committed
🐛 Fix Enter not starting a new line in code editors
- Chromium 150 (Blockbench 5.2) inserts <br> on Enter, which CodeJar drops from its value - Insert line breaks as `\n` text instead, in every CodeJar editor - Fixes #535
1 parent 8f7b451 commit dde57b3

4 files changed

Lines changed: 55 additions & 2 deletions

File tree

‎src/panels/textDisplayElement/textDisplayElement.svelte‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script lang="ts" module>
22
import { CodeJar } from '@novacbn/svelte-codejar'
33
import { TextDisplay } from '../../outliner/textDisplay'
4+
import { insertLineBreakAsText } from '../../util/codeJar'
45
import { localize as translate } from '../../util/lang'
56
import { Stopwatch } from '../../util/stopwatch'
67
import {
@@ -117,7 +118,11 @@
117118
class="toolbar text-display-text-toolbar"
118119
style={!!selected ? 'margin-bottom: 16px;' : 'visibility:hidden; height: 0px;'}
119120
>
120-
<div class="content codejar-container" on:keydown={onKeydown}>
121+
<div
122+
class="content codejar-container"
123+
on:keydown={onKeydown}
124+
on:beforeinput={insertLineBreakAsText}
125+
>
121126
<CodeJar
122127
bind:element={codeJarElement}
123128
syntax="snbtTextComponent"

‎src/svelteComponents/customCodeJar.svelte‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script lang="ts">
22
import { CodeJar } from '@novacbn/svelte-codejar'
3+
import { insertLineBreakAsText } from '../util/codeJar'
34
45
interface Props {
56
value: string
@@ -55,7 +56,7 @@
5556
})
5657
</script>
5758

58-
<div class="content codejar-container" onkeydown={onKeydown}>
59+
<div class="content codejar-container" onkeydown={onKeydown} onbeforeinput={insertLineBreakAsText}>
5960
<CodeJar
6061
bind:element={codeJarElement}
6162
{syntax}

‎src/tests/ui-behaviour.test.ts‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,30 @@ describe('UI behaviour', () => {
146146
expect(await blockbench.dialog().isOpen()).toBe(false)
147147
})
148148
})
149+
150+
describe('code editors', () => {
151+
it('Enter starts a new line in the On-Summon Function editor', async () => {
152+
await blockbench.newProject(BLUEPRINT_FORMAT_ID)
153+
await blockbench.action('animated_java:action/blueprint-settings').trigger()
154+
await blockbench.evaluate(() => {
155+
;(globalThis as any).Dialog.open.sidebar.setPage('eventFunctions')
156+
})
157+
await blockbench.waitFor(() => document.querySelector('.dialog pre[contenteditable]'))
158+
await blockbench.page.click('.dialog pre[contenteditable]')
159+
160+
const { keyboard } = blockbench.page
161+
await keyboard.type('tag @s add a')
162+
await keyboard.press('Enter')
163+
await keyboard.type('tag @s add b')
164+
await keyboard.press('Enter')
165+
await keyboard.type('say hi')
166+
await blockbench.dialog().cancel()
167+
168+
expect(
169+
await blockbench.evaluate(
170+
() => (globalThis as any).Project.animated_java.on_summon_function
171+
)
172+
).toBe('tag @s add a\ntag @s add b\nsay hi')
173+
})
174+
})
149175
})

‎src/util/codeJar.ts‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* `beforeinput` handler that inserts native line breaks into a CodeJar editor as `\n` text.
3+
*
4+
* Chromium 150+ (Blockbench 5.2+) inserts `<br>` on Enter, even in `plaintext-only` `<pre>`
5+
* editors, and CodeJar reads its value from `textContent`, which drops `<br>`.
6+
*/
7+
export function insertLineBreakAsText(event: InputEvent) {
8+
if (event.inputType !== 'insertLineBreak' && event.inputType !== 'insertParagraph') return
9+
const selection = getSelection()
10+
if (!(event.target instanceof HTMLElement) || !selection?.rangeCount) return
11+
12+
const afterCursor = document.createRange()
13+
afterCursor.selectNodeContents(event.target)
14+
const { endContainer, endOffset } = selection.getRangeAt(0)
15+
afterCursor.setStart(endContainer, endOffset)
16+
17+
event.preventDefault()
18+
// A trailing `\n` doesn't render as a new line in a <pre>, so pad it with a second one.
19+
// The caret lands between them, since the browser can't place it after a trailing `\n`.
20+
document.execCommand('insertHTML', false, afterCursor.toString() === '' ? '\n\n' : '\n')
21+
}

0 commit comments

Comments
 (0)