Skip to content

Commit deaaf47

Browse files
enhance(playground): メタデータを確認できるように・シンタックスエラー時のUX改善
1 parent ba7db02 commit deaaf47

File tree

1 file changed

+81
-7
lines changed

1 file changed

+81
-7
lines changed

.vitepress/pages/Playground.vue

+81-7
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@
99
<div :class="[$style.playgroundPaneRoot, $style.playgroundEditorPane]">
1010
<div :class="$style.playgroundPaneHeader">
1111
<div :class="$style.playgroundResultActionsLeft">
12-
<button :class="$style.playgroundButton" @click="replaceWithFizzbuzz">Fizzbuzz</button>
12+
<button :class="$style.playgroundButton" :disabled="editorLoading" @click="replaceWithFizzbuzz">Fizzbuzz</button>
1313
</div>
1414
<div :class="$style.playgroundResultActionsRight">
1515
<button :class="$style.playgroundButton" :disabled="!isRunning" @click="abort">Abort</button>
16-
<button :class="[$style.playgroundButton, $style.playgroundButtonPrimary]" @click="run">Run</button>
16+
<button :class="[$style.playgroundButton, $style.playgroundButtonPrimary]" :disabled="editorLoading" @click="run">Run</button>
1717
</div>
1818
</div>
1919

2020
<div :class="$style.playgroundEditorRoot">
21-
<div :class="$style.playgroundEditorScroller">
21+
<div :class="$style.playgroundEditorScroller" :inert="editorLoading">
2222
<div :class="[$style.highlight, $style.playgroundEditorHighlight]" v-html="editorHtml"></div>
2323
<textarea
2424
ref="inputEl"
@@ -31,6 +31,9 @@
3131
:class="$style.playgroundEditorTextarea"
3232
></textarea>
3333
</div>
34+
<div v-if="editorLoading" :class="$style.playgroundEditorLoading">
35+
<div>Loading...</div>
36+
</div>
3437
</div>
3538
</div>
3639
<div :class="$style.playgroundPaneRoot">
@@ -40,6 +43,8 @@
4043
<label for="output">Output</label>
4144
<input type="radio" id="ast" v-model="resultTab" value="ast">
4245
<label for="ast">AST</label>
46+
<input type="radio" id="metadata" v-model="resultTab" value="metadata">
47+
<label for="metadata">Metadata</label>
4348
</div>
4449
<div :class="$style.playgroundResultActionsRight">
4550
<button :class="[$style.playgroundButton]" @click="clearLog">Clear</button>
@@ -59,7 +64,19 @@
5964
>{{ log.text }}</div>
6065
</div>
6166
<div v-else-if="resultTab === 'ast'" :class="$style.playgroundResultContent">
62-
<div :class="$style.highlight" v-html="astHtml"></div>
67+
<div v-if="isSyntaxError" class="danger custom-block">
68+
<p class="custom-block-title">Syntax Error</p>
69+
<p>See Output tab for details</p>
70+
</div>
71+
<div v-else :class="$style.highlight" v-html="astHtml"></div>
72+
</div>
73+
<div v-else-if="resultTab === 'metadata'" :class="$style.playgroundResultContent">
74+
<div v-if="isSyntaxError" class="danger custom-block">
75+
<p class="custom-block-title">Syntax Error</p>
76+
<p>See Output tab for details</p>
77+
</div>
78+
<div v-else-if="metadata" :class="$style.highlight" v-html="metadataHtml"></div>
79+
<div v-else>No metadata</div>
6380
</div>
6481
</div>
6582
</div>
@@ -85,9 +102,10 @@ const fizzbuzz = `for (let i, 100) {
85102
\t\telse i
86103
}`;
87104
88-
const resultTab = ref<'output' | 'ast'>('output');
105+
const resultTab = ref<'output' | 'ast' | 'metadata'>('output');
89106
90107
//#region Editor
108+
const editorLoading = ref(true);
91109
const inputEl = useTemplateRef('inputEl');
92110
const code = ref(fizzbuzz);
93111
const editorHtml = ref('');
@@ -159,23 +177,35 @@ const logs = ref<{
159177
}[]>([]);
160178
const logEl = useTemplateRef('logEl');
161179
180+
const isSyntaxError = ref(false);
181+
162182
const ast = ref<Ast.Node[] | null>(null);
163183
const astHtml = ref('');
164184
185+
const metadata = ref<unknown>(null);
186+
const metadataHtml = ref('');
187+
165188
function parse() {
189+
isSyntaxError.value = false;
190+
166191
if (parser != null) {
167192
try {
168193
const _ast = parser.parse(code.value);
169194
logs.value = [];
170195
ast.value = _ast;
196+
197+
const meta = Interpreter.collectMetadata(_ast);
198+
metadata.value = meta?.get(null) ?? null;
171199
} catch (err) {
172200
if (err instanceof errors.AiScriptError) {
173201
logs.value = [{
174202
text: `[SyntaxError] ${err.name}: ${err.message}`,
175203
type: 'error',
176204
}];
205+
isSyntaxError.value = true;
177206
}
178207
ast.value = null;
208+
metadata.value = null;
179209
}
180210
} else {
181211
ast.value = null;
@@ -299,6 +329,8 @@ const updateHash = useThrottle((d: HashData) => {
299329
//#endregion
300330
301331
onMounted(async () => {
332+
const loadStartedAt = Date.now();
333+
302334
await init();
303335
initAiScriptEnv();
304336
@@ -324,7 +356,12 @@ onMounted(async () => {
324356
}, { immediate: true });
325357
326358
watch(ast, async (newAst) => {
327-
if (highlighter && newAst != null) {
359+
if (highlighter) {
360+
if (newAst == null) {
361+
astHtml.value = '';
362+
return;
363+
}
364+
328365
astHtml.value = highlighter.codeToHtml(JSON.stringify(newAst, null, 2), {
329366
lang: 'json',
330367
themes: {
@@ -334,7 +371,31 @@ onMounted(async () => {
334371
defaultColor: false,
335372
});
336373
}
337-
});
374+
}, { immediate: true });
375+
376+
watch(metadata, async (newMetadata) => {
377+
if (highlighter) {
378+
if (newMetadata == null) {
379+
metadataHtml.value = '';
380+
return;
381+
}
382+
383+
metadataHtml.value = highlighter.codeToHtml(JSON.stringify(newMetadata, null, 2), {
384+
lang: 'json',
385+
themes: {
386+
light: 'github-light',
387+
dark: 'github-dark',
388+
},
389+
defaultColor: false,
390+
});
391+
}
392+
}, { immediate: true });
393+
394+
const loadEndedAt = Date.now();
395+
396+
setTimeout(() => {
397+
editorLoading.value = false;
398+
}, Math.max(0, 500 - (loadEndedAt - loadStartedAt)));
338399
});
339400
340401
onUnmounted(() => {
@@ -388,6 +449,19 @@ onUnmounted(() => {
388449
overflow: scroll;
389450
}
390451
452+
.playgroundEditorLoading {
453+
position: absolute;
454+
top: 0;
455+
left: 0;
456+
right: 0;
457+
bottom: 0;
458+
background-color: rgba(255, 255, 255, 0.5);
459+
z-index: 1;
460+
display: flex;
461+
justify-content: center;
462+
align-items: center;
463+
}
464+
391465
.playgroundEditorScroller {
392466
position: relative;
393467
padding: 24px 36px;

0 commit comments

Comments
 (0)