Skip to content

Commit 61d076c

Browse files
authored
Fancy playground editor (#498)
* Factor out Editor component. * Use Ace editor. * Working tests using Ace editor. * Styling.
1 parent fc26dc5 commit 61d076c

File tree

6 files changed

+133
-32
lines changed

6 files changed

+133
-32
lines changed

web-playground/e2e/sample-tester.test.ts

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ describe('test all grammars with puppeteer', () => {
9090
const button = await page.$('#formatButton') ?? fail('Did not find button');
9191
await button.click();
9292

93-
await waitForOutput(page, "#output");
9493
const output = await readOutput();
9594

9695
// Useful for debugging:
@@ -110,7 +109,6 @@ async function testInputFile(input: string, expected: string, query: string, lan
110109
const button = await page.$('#formatButton') ?? fail('Did not find button');
111110
await button.click();
112111

113-
await waitForOutput(page, "#output");
114112
const output = await readOutput();
115113

116114
// Useful for debugging:
@@ -120,38 +118,37 @@ async function testInputFile(input: string, expected: string, query: string, lan
120118
}
121119

122120
async function setTextarea(selector: string, text: string) {
123-
let textInput = await page.$(selector) ?? fail('Did not find text area');
121+
let textInput = await page.$(selector) ?? fail('Did not find text input control');
122+
let textAreaSelector = `${selector} textarea`;
124123

125124
// Clear the text area first, otherwise the following doesn't work.
126-
await textInput.click({ clickCount: 3 });
125+
await textInput.click();
126+
await page.keyboard.down('ControlLeft')
127+
await page.keyboard.press('KeyA')
128+
await page.keyboard.up('ControlLeft')
127129
await textInput.press('Backspace');
128130

129131
// Quick way to enter text into a field. See https://github.com/puppeteer/puppeteer/issues/4192
130132
await page.evaluate((selector, text) => {
131133
(<HTMLInputElement>document.querySelector(selector)).value = text;
132-
}, selector, text);
134+
}, textAreaSelector, text);
133135

134136
// Without this hack, the textarea simply won't get updated.
135137
await page.keyboard.type("X");
136138
await textInput.press('Backspace');
137139
}
138140

139141
async function readOutput() {
140-
const outputElement = await page.$("#output");
141-
return await page.evaluate(element => element?.textContent, outputElement);
142-
}
143-
144-
const waitForOutput = async (
145-
page: Page,
146-
selector: string,
147-
options: FrameWaitForFunctionOptions = { polling: "mutation", timeout: 30000 }
148-
) => {
149-
const el = typeof selector === "string" ?
150-
(await page.waitForSelector(selector)) : selector;
142+
const outputSelector = "#rawOutput";
143+
const el = await page.waitForSelector(outputSelector);
151144

152-
return page.waitForFunction(
145+
// Wait for useful output.
146+
await page.waitForFunction(
153147
el => el?.textContent !== "" && el?.textContent !== "Formatting ...",
154-
options,
148+
{ polling: "mutation", timeout: 30000 },
155149
el
156150
);
157-
};
151+
152+
const outputElement = await page.$(outputSelector);
153+
return await page.evaluate(element => element?.textContent, outputElement);
154+
}

web-playground/package-lock.json

Lines changed: 73 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web-playground/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
"private": true,
55
"homepage": "/playground",
66
"dependencies": {
7+
"ace-builds": "^1.22.0",
78
"react": "^18.2.0",
9+
"react-ace": "^10.1.0",
810
"react-dom": "^18.2.0"
911
},
1012
"devDependencies": {
@@ -52,4 +54,4 @@
5254
"last 1 safari version"
5355
]
5456
}
55-
}
57+
}

web-playground/src/App.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,7 @@ button:not(:disabled) {
8282
border-color: #c792fa;
8383
color: #212529;
8484
}
85+
86+
.hidden {
87+
display: none;
88+
}

web-playground/src/App.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ReactElement, useCallback, useEffect, useRef, useState } from "react";
2+
import Editor from "./components/editor";
23
import useDebounce from "./hooks/useDebounce";
34
import languages from './samples/languages_export';
45
import init, {
@@ -142,15 +143,16 @@ function App() {
142143
<div className="columns">
143144
<div className="column">
144145
<h1>Query</h1>
145-
<textarea id="query" value={query} onChange={e => setQuery(e.target.value)} />
146+
<Editor id="query" value={query} onChange={s => setQuery(s)} placeholder="Enter your query here ..." />
146147
</div>
147148
<div className="column">
148149
<h1>Input</h1>
149-
<textarea id="input" value={input} onChange={e => setInput(e.target.value)} />
150+
<Editor id="input" value={input} onChange={s => setInput(s)} placeholder="Enter your input here ..." />
150151
</div>
151152
<div className="column">
152153
<h1>Output</h1>
153-
<textarea id="output" value={output} readOnly></textarea>
154+
<Editor id="output" value={output} readOnly placeholder="The formatted code will appear here ..." />
155+
<textarea id="rawOutput" value={output} readOnly className="hidden"></textarea>
154156
</div>
155157
</div>
156158
</div>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import AceEditor from "react-ace";
2+
3+
import "ace-builds/src-noconflict/ext-language_tools";
4+
import "ace-builds/src-noconflict/mode-plain_text";
5+
import "ace-builds/src-noconflict/theme-clouds.js";
6+
7+
export default function Editor(props: {
8+
id: string,
9+
value: string,
10+
placeholder: string,
11+
readOnly?: boolean,
12+
onChange?: (value: string) => void
13+
}) {
14+
return (
15+
<AceEditor
16+
mode="plain_text"
17+
theme="clouds"
18+
name={props.id}
19+
value={props.value}
20+
placeholder={props.placeholder}
21+
readOnly={props.readOnly}
22+
onChange={props.onChange}
23+
width="100%"
24+
height="100%"
25+
tabSize={2}
26+
enableBasicAutocompletion={true}
27+
enableLiveAutocompletion={true}
28+
enableSnippets={true}
29+
/>
30+
)
31+
}
32+

0 commit comments

Comments
 (0)