Skip to content

Commit 010e6f2

Browse files
author
Rich Harris
committed
show inline diagnostics (#17)
1 parent c1e1e58 commit 010e6f2

File tree

8 files changed

+108
-6
lines changed

8 files changed

+108
-6
lines changed

content/tutorial/common/src/__client.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,14 @@ if (import.meta.hot) {
118118
'*'
119119
);
120120
});
121+
122+
import.meta.hot.on('svelte:warnings', (data) => {
123+
parent.postMessage(
124+
{
125+
type: 'warnings',
126+
data
127+
},
128+
'*'
129+
);
130+
});
121131
}

content/tutorial/common/svelte.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ const config = {
55
// Don't do this in your own apps unless you know what you're doing!
66
// See https://kit.svelte.dev/docs/configuration#csrf for more info.
77
csrf: false
8+
},
9+
10+
vitePlugin: {
11+
experimental: {
12+
sendWarningsToBrowser: true
13+
}
814
}
915
};
1016

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"@codemirror/lang-html": "^6.4.2",
3939
"@codemirror/lang-javascript": "^6.1.4",
4040
"@codemirror/language": "^6.6.0",
41+
"@codemirror/lint": "^6.2.0",
4142
"@codemirror/state": "^6.2.0",
4243
"@codemirror/view": "^6.9.2",
4344
"@fontsource/roboto-mono": "^4.5.10",

pnpm-lock.yaml

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

src/routes/tutorial/[slug]/Editor.svelte

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
import { html } from '@codemirror/lang-html';
1111
import { svelte } from '@replit/codemirror-lang-svelte';
1212
import { tags } from '@lezer/highlight';
13-
import { HighlightStyle } from '@codemirror/language';
14-
import { syntaxHighlighting } from '@codemirror/language';
13+
import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
14+
import { setDiagnostics } from '@codemirror/lint';
1515
import { afterNavigate } from '$app/navigation';
16-
import { files, selected_file, selected_name, update_file } from './state.js';
16+
import { files, selected_file, selected_name, update_file, warnings } from './state.js';
1717
import './codemirror.css';
1818
1919
// TODO add more styles (selection ranges, etc)
@@ -40,8 +40,31 @@
4040
/** @type {import('@codemirror/view').EditorView} */
4141
let editor_view;
4242
43+
/** @type {import('@codemirror/state').EditorState | undefined} */
44+
let current_state;
45+
4346
$: if (editor_view && $selected_name) {
4447
select_state($selected_name);
48+
49+
const current_warnings = $warnings[$selected_name];
50+
51+
if (current_warnings) {
52+
const diagnostics = current_warnings.map((warning) => {
53+
/** @type {import('@codemirror/lint').Diagnostic} */
54+
const diagnostic = {
55+
from: warning.start.character,
56+
to: warning.end.character,
57+
severity: 'warning',
58+
message: warning.message
59+
};
60+
61+
return diagnostic;
62+
});
63+
64+
const transaction = setDiagnostics(editor_view.state, diagnostics);
65+
66+
editor_view.dispatch(transaction);
67+
}
4568
}
4669
4770
/** @param {string} $selected_name */
@@ -75,6 +98,8 @@
7598
editor_states.set(file.name, state);
7699
}
77100
101+
current_state = state;
102+
78103
if (editor_view) {
79104
editor_view.setState(state);
80105
}
@@ -114,6 +139,8 @@
114139
// keep `editor_states` updated so that undo/redo history is preserved for files independently
115140
editor_states.set($selected_file.name, editor_view.state);
116141
}
142+
143+
current_state = editor_view.state;
117144
}
118145
});
119146
@@ -129,6 +156,9 @@
129156
afterNavigate(() => {
130157
editor_states.clear();
131158
select_state($selected_name);
159+
160+
// clear warnings
161+
warnings.set({});
132162
});
133163
</script>
134164

src/routes/tutorial/[slug]/Output.svelte

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import Chrome from './Chrome.svelte';
66
import Loading from './Loading.svelte';
77
import { base, error, logs, progress, subscribe } from './adapter';
8+
import { warnings } from './state';
89
910
/** @type {import('$lib/types').Exercise} */
1011
export let exercise;
@@ -61,6 +62,11 @@
6162
}, 1000);
6263
} else if (e.data.type === 'ping-pause') {
6364
clearTimeout(timeout);
65+
} else if (e.data.type === 'warnings') {
66+
warnings.update(($warnings) => ({
67+
...$warnings,
68+
[e.data.data.normalizedFilename]: e.data.data.allWarnings
69+
}));
6470
}
6571
}
6672

src/routes/tutorial/[slug]/codemirror.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,28 @@
4949
color: var(--sk-text-2);
5050
}
5151

52+
.cm-editor .cm-tooltip {
53+
border: none;
54+
border-radius: 2px;
55+
overflow: hidden;
56+
margin: 0.4rem 0;
57+
filter: drop-shadow(1px 2px 5px rgba(0,0,0,0.1));
58+
}
59+
.cm-editor .cm-tooltip-hover {}
60+
.cm-editor .cm-tooltip-below {}
61+
.cm-editor .cm-tooltip-lint {}
62+
.cm-editor .cm-tooltip-section {}
63+
.cm-editor .cm-diagnostic {
64+
border: none;
65+
padding: 0.2rem 0.8rem;
66+
}
67+
.cm-editor .cm-diagnostic-warning {
68+
/* background: hsl(36, 100%, 32%); */
69+
background: hsl(39, 100%, 10%);
70+
}
71+
.cm-editor .cm-diagnosticText {}
72+
73+
5274
@media (prefers-color-scheme: dark) {
5375
.cm-editor .cm-activeLineGutter {
5476
background-color: var(--sk-back-3);
@@ -57,4 +79,8 @@
5779
.cm-editor .cm-activeLine {
5880
background-color: var(--sk-back-2);
5981
}
82+
83+
.cm-editor .cm-diagnostic-warning {
84+
background: hsl(39, 100%, 20%);
85+
}
6086
}

src/routes/tutorial/[slug]/state.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,34 @@
11
import { derived, writable } from 'svelte/store';
22
import * as adapter from './adapter.js';
33

4-
/** @type {import('svelte/store').Writable<import('$lib/types').Stub[]>} */
4+
/**
5+
* @template T
6+
* @typedef {import('svelte/store').Writable<T>} Writable<T>
7+
*/
8+
9+
// TODO would be nice if svelte exported this type (maybe it does already?)
10+
/**
11+
* @typedef {{
12+
* code: string;
13+
* start: { line: number, column: number, character: number };
14+
* end: { line: number, column: number, character: number };
15+
* pos: number;
16+
* filename: string;
17+
* frame: string;
18+
* message: string;
19+
* }} CompilerWarning
20+
*/
21+
22+
/** @type {Writable<import('$lib/types').Stub[]>} */
523
export const files = writable([]);
624

7-
/** @type {import('svelte/store').Writable<Record<string, import('$lib/types').Stub>>} */
25+
/** @type {Writable<Record<string, import('$lib/types').Stub>>} */
826
export const solution = writable({});
927

10-
/** @type {import('svelte/store').Writable<string | null>} */
28+
/** @type {Writable<Record<string, CompilerWarning[]>>} */
29+
export const warnings = writable({});
30+
31+
/** @type {Writable<string | null>} */
1132
export const selected_name = writable(null);
1233

1334
export const selected_file = derived([files, selected_name], ([$files, $selected_name]) => {

0 commit comments

Comments
 (0)