@@ -100,3 +100,79 @@ function formatFrameForVite(frame) {
100
100
. map ( ( line ) => ( line . match ( / ^ \s + \^ / ) ? ' ' + line : ' ' + line . replace ( ':' , ' | ' ) ) )
101
101
. join ( '\n' ) ;
102
102
}
103
+
104
+ /**
105
+ * @param {import('svelte/types/compiler/interfaces').Warning & Error } err a svelte compiler error, which is a mix of Warning and an error
106
+ * @param {string } originalCode
107
+ * @param {import('../index.js').Arrayable<import('svelte/types/compiler/preprocess').PreprocessorGroup> } [preprocessors]
108
+ */
109
+ export function enhanceCompileError ( err , originalCode , preprocessors ) {
110
+ preprocessors = arraify ( preprocessors ?? [ ] ) ;
111
+
112
+ /** @type {string[] } */
113
+ const additionalMessages = [ ] ;
114
+
115
+ // Handle incorrect TypeScript usage
116
+ if ( err . code === 'parse-error' ) {
117
+ // Reference from Svelte: https://github.com/sveltejs/svelte/blob/800f6c076be5dd87dd4d2e9d66c59b973d54d84b/packages/svelte/src/compiler/preprocess/index.js#L262
118
+ const scriptRe = / < s c r i p t ( \s [ ^ ] * ?) ? (?: > ( [ ^ ] * ?) < \/ s c r i p t > | \/ > ) / gi;
119
+ const errIndex = err . pos ?? - 1 ;
120
+
121
+ let m ;
122
+ while ( ( m = scriptRe . exec ( originalCode ) ) ) {
123
+ const matchStart = m . index ;
124
+ const matchEnd = matchStart + m [ 0 ] . length ;
125
+ const isErrorInScript = matchStart <= errIndex && errIndex <= matchEnd ;
126
+ if ( isErrorInScript ) {
127
+ // Warn missing lang="ts"
128
+ const hasLangTs = m [ 1 ] ?. includes ( 'lang="ts"' ) ;
129
+ if ( ! hasLangTs ) {
130
+ additionalMessages . push ( 'Did you forget to add lang="ts" to your script tag?' ) ;
131
+ }
132
+ // Warn missing script preprocessor
133
+ if ( preprocessors . every ( ( p ) => p . script == null ) ) {
134
+ const preprocessorType = hasLangTs ? 'TypeScript' : 'script' ;
135
+ additionalMessages . push (
136
+ `Did you forget to add a ${ preprocessorType } preprocessor? See https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/preprocess.md for more information.`
137
+ ) ;
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ // Handle incorrect CSS preprocessor usage
144
+ if ( err . code === 'css-syntax-error' ) {
145
+ const styleRe = / < s t y l e ( \s [ ^ ] * ?) ? (?: > ( [ ^ ] * ?) < \/ s t y l e > | \/ > ) / gi;
146
+
147
+ let m ;
148
+ while ( ( m = styleRe . exec ( originalCode ) ) ) {
149
+ // Warn missing lang attribute
150
+ if ( ! m [ 1 ] ?. includes ( 'lang=' ) ) {
151
+ additionalMessages . push ( 'Did you forget to add a lang attribute to your style tag?' ) ;
152
+ }
153
+ // Warn missing style preprocessor
154
+ if (
155
+ preprocessors . every ( ( p ) => p . style == null || p . name === 'inject-scope-everything-rule' )
156
+ ) {
157
+ const preprocessorType = m [ 1 ] ?. match ( / l a n g = " ( .+ ?) " / ) ?. [ 1 ] ?? 'style' ;
158
+ additionalMessages . push (
159
+ `Did you forget to add a ${ preprocessorType } preprocessor? See https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/preprocess.md for more information.`
160
+ ) ;
161
+ }
162
+ }
163
+ }
164
+
165
+ if ( additionalMessages . length ) {
166
+ err . message += '\n\n- ' + additionalMessages . join ( '\n- ' ) ;
167
+ }
168
+
169
+ return err ;
170
+ }
171
+
172
+ /**
173
+ * @param {T | T[] } value
174
+ * @template T
175
+ */
176
+ function arraify ( value ) {
177
+ return Array . isArray ( value ) ? value : [ value ] ;
178
+ }
0 commit comments