Skip to content

Commit 0dffbfc

Browse files
authored
Nicer ast view (#693)
* simplify * shuffle code around * nicer AST view * simplify * check
1 parent 0c6b619 commit 0dffbfc

File tree

2 files changed

+68
-67
lines changed

2 files changed

+68
-67
lines changed

packages/repl/src/lib/Output/AstNode.svelte

Lines changed: 67 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -9,52 +9,34 @@
99
interface Props {
1010
key?: string;
1111
value: Ast;
12-
collapsed?: boolean;
1312
path_nodes?: Ast[];
1413
autoscroll?: boolean;
14+
depth?: number;
1515
}
1616
17-
let {
18-
key = '',
19-
value,
20-
collapsed = $bindable(true),
21-
path_nodes = [],
22-
autoscroll = true
23-
}: Props = $props();
17+
let { key = '', value, path_nodes = [], autoscroll = true, depth = 0 }: Props = $props();
2418
2519
const { toggleable } = get_repl_context();
2620
21+
let root = depth === 0;
22+
let open = $state(root);
23+
2724
let list_item_el = $state() as HTMLLIElement;
2825
29-
let is_root = $derived(path_nodes[0] === value);
3026
let is_leaf = $derived(path_nodes[path_nodes.length - 1] === value);
31-
let is_ast_array = $derived(Array.isArray(value));
32-
let is_collapsable = $derived(value && typeof value === 'object');
27+
let is_array = $derived(Array.isArray(value));
28+
let is_primitive = $derived(value === null || typeof value !== 'object');
3329
let is_markable = $derived(
34-
is_collapsable &&
30+
!is_primitive &&
3531
'start' in value &&
3632
'end' in value &&
3733
typeof value.start === 'number' &&
3834
typeof value.end === 'number'
3935
);
4036
let key_text = $derived(key ? `${key}:` : '');
4137
42-
let preview_text = $state('');
43-
44-
$effect(() => {
45-
if (!is_collapsable || !collapsed) return;
46-
47-
if (is_ast_array) {
48-
if (!('length' in value)) return;
49-
50-
preview_text = `[ ${value.length} element${value.length === 1 ? '' : 's'} ]`;
51-
} else {
52-
preview_text = `{ ${Object.keys(value).join(', ')} }`;
53-
}
54-
});
55-
5638
$effect(() => {
57-
collapsed = !path_nodes.includes(value);
39+
open = path_nodes.includes(value);
5840
});
5941
6042
$effect(() => {
@@ -95,36 +77,59 @@
9577

9678
<li
9779
bind:this={list_item_el}
98-
class:marked={!is_root && is_leaf}
80+
class:marked={!root && is_leaf}
9981
onmouseover={handle_mark_text}
10082
onfocus={handle_mark_text}
10183
onmouseleave={handle_unmark_text}
10284
>
103-
{#if !is_root && is_collapsable}
104-
<button class="ast-toggle" class:open={!collapsed} onclick={() => (collapsed = !collapsed)}>
105-
{key_text}
106-
</button>
107-
{:else if key_text}
108-
<span>{key_text}</span>
109-
{/if}
110-
{#if is_collapsable}
111-
{#if collapsed && !is_root}
112-
<button class="preview" onclick={() => (collapsed = !collapsed)}>
113-
{preview_text}
114-
</button>
115-
{:else}
116-
<span>{is_ast_array ? '[' : '{'}</span>
85+
{#if is_primitive || (is_array && value.length === 0)}
86+
<span class="value">
87+
{#if key_text}
88+
<span>{key_text}</span>
89+
{/if}
90+
91+
{#if value == undefined}
92+
<span class="token comment">{String(value)}</span>
93+
{:else}
94+
<span class="token {typeof value}">
95+
{JSON.stringify(value)}
96+
</span>
97+
{/if}
98+
</span>
99+
{:else}
100+
<details bind:open>
101+
<summary>
102+
{#if key}
103+
<span class="key">{key}</span>:
104+
{/if}
105+
106+
{#if is_array}
107+
[{#if !open}
108+
<span class="token comment">...</span>]
109+
<span class="token comment">({value.length})</span>
110+
{/if}
111+
{:else}
112+
{#if value.type}
113+
<span class="token comment">{value.type}</span>
114+
{/if}
115+
{'{'}{#if !open}<span class="token comment">...</span>}{/if}
116+
{/if}
117+
</summary>
118+
117119
<ul>
118120
{#each Object.entries(value) as [k, v]}
119-
<AstNode key={is_ast_array ? '' : k} value={v} {path_nodes} {autoscroll} />
121+
<AstNode
122+
key={is_array ? undefined : k}
123+
value={v}
124+
{path_nodes}
125+
{autoscroll}
126+
depth={depth + 1}
127+
/>
120128
{/each}
121129
</ul>
122-
<span>{is_ast_array ? ']' : '}'}</span>
123-
{/if}
124-
{:else}
125-
<span class="token {typeof value}">
126-
{JSON.stringify(value)}
127-
</span>
130+
131+
<span>{is_array ? ']' : '}'}</span>
132+
</details>
128133
{/if}
129134
</li>
130135

@@ -143,26 +148,18 @@
143148
background-color: var(--sk-highlight-color);
144149
}
145150
146-
button {
147-
&:hover {
148-
text-decoration: underline;
149-
}
150-
}
151-
152-
.ast-toggle {
151+
summary {
153152
position: relative;
154-
}
153+
display: block;
154+
cursor: pointer;
155155
156-
.ast-toggle::before {
157-
content: '\25B6';
158-
position: absolute;
159-
bottom: 0;
160-
left: -1.3rem;
161-
opacity: 0.7;
162-
}
156+
.key {
157+
text-decoration: underline;
158+
}
163159
164-
.ast-toggle.open::before {
165-
content: '\25BC';
160+
&:hover .key {
161+
text-decoration: underline;
162+
}
166163
}
167164
168165
.token {
@@ -176,4 +173,8 @@
176173
.token.number {
177174
color: var(--sk-code-number);
178175
}
176+
177+
.token.comment {
178+
color: var(--sk-code-comment);
179+
}
179180
</style>

packages/repl/src/lib/Output/AstView.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
<code>
6666
{#if typeof ast === 'object'}
6767
<ul>
68-
<AstNode value={ast} {path_nodes} {autoscroll} collapsed={false} />
68+
<AstNode value={ast} {path_nodes} {autoscroll} />
6969
</ul>
7070
{:else}
7171
<p>No AST available</p>

0 commit comments

Comments
 (0)