@@ -5,6 +5,10 @@ import * as yootils from 'yootils';
55import { escape_html , get_depth } from '../../../utils.js' ;
66import { ready } from '../common/index.js' ;
77
8+ /**
9+ * @typedef {import("../../../../routes/tutorial/[slug]/state.js").CompilerWarning } CompilerWarning
10+ */
11+
812const converter = new AnsiToHtml ( {
913 fg : 'var(--sk-text-3)'
1014} ) ;
@@ -17,9 +21,10 @@ let vm;
1721 * @param {import('svelte/store').Writable<Error | null> } error
1822 * @param {import('svelte/store').Writable<{ value: number, text: string }> } progress
1923 * @param {import('svelte/store').Writable<string[]> } logs
24+ * @param {import('svelte/store').Writable<Record<string, CompilerWarning[]>> } warnings
2025 * @returns {Promise<import('$lib/types').Adapter> }
2126 */
22- export async function create ( base , error , progress , logs ) {
27+ export async function create ( base , error , progress , logs , warnings ) {
2328 if ( / s a f a r i / i. test ( navigator . userAgent ) && ! / c h r o m e / i. test ( navigator . userAgent ) ) {
2429 throw new Error ( 'WebContainers are not supported by Safari' ) ;
2530 }
@@ -45,12 +50,40 @@ export async function create(base, error, progress, logs) {
4550 }
4651 } ) ;
4752
53+ /** @type {Record<string, CompilerWarning[]> } */
54+ let $warnings ;
55+ warnings . subscribe ( ( value ) => $warnings = value ) ;
56+
57+ /** @type {any } */
58+ let timeout ;
59+
60+ /** @param {number } msec */
61+ function schedule_to_update_warning ( msec ) {
62+ clearTimeout ( timeout ) ;
63+ timeout = setTimeout ( ( ) => warnings . set ( $warnings ) , msec ) ;
64+ }
65+
4866 const log_stream = ( ) =>
4967 new WritableStream ( {
5068 write ( chunk ) {
5169 if ( chunk === '\x1B[1;1H' ) {
5270 // clear screen
5371 logs . set ( [ ] ) ;
72+
73+ } else if ( chunk ?. startsWith ( 'svelte:warnings:' ) ) {
74+ /** @type {CompilerWarning } */
75+ const warn = JSON . parse ( chunk . slice ( 16 ) ) ;
76+ const current = $warnings [ warn . filename ] ;
77+
78+ if ( ! current ) {
79+ $warnings [ warn . filename ] = [ warn ] ;
80+ // the exact same warning may be given multiple times in a row
81+ } else if ( ! current . some ( ( s ) => ( s . code === warn . code && s . pos === warn . pos ) ) ) {
82+ current . push ( warn ) ;
83+ }
84+
85+ schedule_to_update_warning ( 100 ) ;
86+
5487 } else {
5588 const log = converter . toHtml ( escape_html ( chunk ) ) . replace ( / \n / g, '<br>' ) ;
5689 logs . update ( ( $logs ) => [ ...$logs , log ] ) ;
@@ -154,6 +187,17 @@ export async function create(base, error, progress, logs) {
154187 ...force_delete
155188 ] ;
156189
190+ // initialize warnings of written files
191+ to_write
192+ . filter ( ( stub ) => stub . type === 'file' && $warnings [ stub . name ] )
193+ . forEach ( ( stub ) => $warnings [ stub . name ] = [ ] ) ;
194+ // remove warnings of deleted files
195+ to_delete
196+ . filter ( ( stubname ) => $warnings [ stubname ] )
197+ . forEach ( ( stubname ) => delete $warnings [ stubname ] ) ;
198+
199+ warnings . set ( $warnings ) ;
200+
157201 current_stubs = stubs_to_map ( stubs ) ;
158202
159203 // For some reason, server-ready is fired again when the vite dev server is restarted.
@@ -221,6 +265,10 @@ export async function create(base, error, progress, logs) {
221265
222266 tree [ basename ] = to_file ( file ) ;
223267
268+ // initialize warnings of this file
269+ $warnings [ file . name ] = [ ] ;
270+ schedule_to_update_warning ( 100 ) ;
271+
224272 await vm . mount ( root ) ;
225273
226274 current_stubs . set ( file . name , file ) ;
0 commit comments