svelte-docinfo 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Locating a Svelte component's script tags: its instance `<script>` and its
3
+ * `<script module>`.
4
+ *
5
+ * Svelte takes a `<script>` for one of those only at the top level of the
6
+ * file. Nested in an element, a block, or `<svelte:head>` it's an ordinary
7
+ * element (a JSON-LD block, an inline analytics snippet), and its content says
8
+ * nothing about the component. So finding the tags takes two steps: a regex
9
+ * scan for candidates (`scanScriptTags`), then a decision about which of
10
+ * them are top-level (`findScriptTags`).
11
+ *
12
+ * @internal
13
+ *
14
+ * @module
15
+ */
16
+ /** A located script tag: parsed attributes, content, and where the content starts in the source. */
17
+ export interface SvelteScriptTag {
18
+ /** Opening-tag attributes; bare attributes (`module`) map to `true`. */
19
+ attributes: Map<string, string | true>;
20
+ content: string;
21
+ /** Offset of `content` within the source, for mapping script positions to original lines. */
22
+ start: number;
23
+ }
24
+ /** A script tag the scan matched, before anything has decided whether it's top-level. */
25
+ export interface ScannedScriptTag extends SvelteScriptTag {
26
+ /** Offset of the tag's opening `<`, which is where Svelte's parser places the script. */
27
+ open: number;
28
+ /** Offset just past the tag's closing `>`. */
29
+ end: number;
30
+ /**
31
+ * Whether the scan alone proves the tag top-level, with no parser: see
32
+ * `scanScriptTags` for the proof and its conditions.
33
+ */
34
+ provenTopLevel: boolean;
35
+ }
36
+ /**
37
+ * Scan Svelte source for script tags with content, in source order, and mark
38
+ * the ones the scan itself proves top-level.
39
+ *
40
+ * The scan is syntactic and knows nothing about nesting, so it returns nested
41
+ * tags too; `findScriptTags` is the function that answers which are the
42
+ * component's. Limits: whitespace around an attribute `=` makes a tag
43
+ * unmatchable (Svelte rejects one of those spellings, and svelte2tsx matches
44
+ * neither), and `</script>` in a string literal ends the content early.
45
+ *
46
+ * **`provenTopLevel`** holds for a tag when everything from the start of the
47
+ * file to it is whitespace, complete HTML comments, and earlier script tags
48
+ * that are themselves proven. Svelte's parser reads each of those at the root
49
+ * and comes back to the root: whitespace is text, a comment runs to the first
50
+ * `-->`, and a top-level script runs from its opening tag to the first
51
+ * `</script>`, the same extents the regex matched. So it meets this tag at the
52
+ * root, where a `<script>` is the instance or module script.
53
+ *
54
+ * Anything that would need more than that argument leaves the tag unproven,
55
+ * along with every tag after it:
56
+ *
57
+ * - any other text or markup before the tag: a `<style>`,
58
+ * `<svelte:options>`, an unterminated comment, what's left over when a
59
+ * `</script>` in a string ended an earlier match early, and tags the regex
60
+ * doesn't match (`<SCRIPT>`, a spelling with whitespace around `=`)
61
+ * - a self-closing `<script />`, which Svelte's parser rejects at the top
62
+ * level
63
+ * - attributes outside `UNAMBIGUOUS_ATTRIBUTES_MATCHER`
64
+ */
65
+ export declare const scanScriptTags: (svelteSource: string) => Array<ScannedScriptTag>;
66
+ /**
67
+ * A script tag is a module script when it carries a `module` attribute
68
+ * (Svelte 5) or `context="module"` (Svelte 4) — Svelte's `read_script` test,
69
+ * minus its error paths. `module` inside an attribute *value* doesn't count.
70
+ */
71
+ export declare const isModuleScript: (attributes: Map<string, string | true>) => boolean;
72
+ /** The part of Svelte's parsed root that `findScriptTags` reads. */
73
+ export interface SvelteTemplateScripts {
74
+ /** The instance script, at the offset of its opening `<`. */
75
+ instance?: {
76
+ start: number;
77
+ } | null;
78
+ /** The module script, at the offset of its opening `<`. */
79
+ module?: {
80
+ start: number;
81
+ } | null;
82
+ }
83
+ /**
84
+ * Parses a Svelte source whose script and style content is blanked, and says
85
+ * where its top-level scripts are. Throws when the source doesn't parse.
86
+ */
87
+ export type ParseSvelteTemplate = (blankedSource: string) => SvelteTemplateScripts;
88
+ /**
89
+ * How `findScriptTags` decided which tags are top-level:
90
+ *
91
+ * - `'scan'` — the scan proved every tag top-level (`provenTopLevel`), so
92
+ * nothing was parsed
93
+ * - `'parser'` — Svelte's parser said which tags are the instance and module
94
+ * scripts
95
+ * - `'unparsed'` — the parser threw, and every matched tag is returned
96
+ */
97
+ export type ScriptTagsDecision = 'scan' | 'parser' | 'unparsed';
98
+ /** What `findScriptTags` returns. */
99
+ export interface FoundScriptTags {
100
+ /** The component's script tags, in source order. */
101
+ tags: Array<SvelteScriptTag>;
102
+ decidedBy: ScriptTagsDecision;
103
+ }
104
+ /** Options for `findScriptTags`. */
105
+ export interface FindScriptTagsOptions {
106
+ /**
107
+ * Take the scan's proof when it covers every tag, without parsing.
108
+ * `false` sends every source with a tag to the parser.
109
+ *
110
+ * @default true
111
+ */
112
+ scanProof?: boolean;
113
+ /** The parser asked about tags the scan can't prove. Defaults to Svelte's. */
114
+ parseTemplate?: ParseSvelteTemplate;
115
+ }
116
+ /**
117
+ * Find a component's script tags: the `<script>` tags at the top level of the
118
+ * source, in source order. A `<script>` nested in an element, a block, or
119
+ * `<svelte:head>` isn't one, matching Svelte, which reads only a top-level
120
+ * tag as the instance or module script.
121
+ *
122
+ * `scanScriptTags` finds the candidates. When it proves every one of them
123
+ * top-level, which covers the usual component with its scripts ahead of the
124
+ * template, that's the answer. Otherwise Svelte's parser decides: the source
125
+ * is parsed with script and style content blanked, and the tags at the
126
+ * offsets of the root's `instance` and `module` are kept. svelte2tsx parses
127
+ * the same blanked source, but demotes only the tags the parser reads as
128
+ * nested elements, so a tag spelled inside an expression string or an
129
+ * attribute value is still a script to it and isn't one here.
130
+ *
131
+ * Limits: a `</script>` or `</style>` inside a string or comment ends that
132
+ * tag's blanked content early, and what's left over is parsed as template.
133
+ * And svelte2tsx's own tag matcher is narrower in one spelling: it doesn't
134
+ * take a closing tag with whitespace before the `>` (`</script >`), so there
135
+ * its virtual doesn't have the scripts as written while this returns them. A
136
+ * legacy component
137
+ * written that way documents no props, with a `svelte_prop_failed` warning
138
+ * for each `export let`; a runes one documents none, with no warning.
139
+ *
140
+ * @param svelteSource - the full Svelte source code
141
+ * @returns the top-level script tags and how they were decided
142
+ */
143
+ export declare const findScriptTags: (svelteSource: string, options?: FindScriptTagsOptions) => FoundScriptTags;
144
+ //# sourceMappingURL=svelte-scripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svelte-scripts.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/svelte-scripts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,oGAAoG;AACpG,MAAM,WAAW,eAAe;IAC/B,wEAAwE;IACxE,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,6FAA6F;IAC7F,KAAK,EAAE,MAAM,CAAC;CACd;AAED,yFAAyF;AACzF,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACxD,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;CACxB;AAwCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,cAAc,GAAI,cAAc,MAAM,KAAG,KAAK,CAAC,gBAAgB,CA8B3E,CAAC;AAiBF;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAI,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,KAAG,OACL,CAAC;AAuDpE,oEAAoE;AACpE,MAAM,WAAW,qBAAqB;IACrC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpC,2DAA2D;IAC3D,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,aAAa,EAAE,MAAM,KAAK,qBAAqB,CAAC;AAUnF;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhE,qCAAqC;AACrC,MAAM,WAAW,eAAe;IAC/B,oDAAoD;IACpD,IAAI,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;IAC7B,SAAS,EAAE,kBAAkB,CAAC;CAC9B;AAED,oCAAoC;AACpC,MAAM,WAAW,qBAAqB;IACrC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,cAAc,GAC1B,cAAc,MAAM,EACpB,UAAU,qBAAqB,KAC7B,eAwBF,CAAC"}
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Locating a Svelte component's script tags: its instance `<script>` and its
3
+ * `<script module>`.
4
+ *
5
+ * Svelte takes a `<script>` for one of those only at the top level of the
6
+ * file. Nested in an element, a block, or `<svelte:head>` it's an ordinary
7
+ * element (a JSON-LD block, an inline analytics snippet), and its content says
8
+ * nothing about the component. So finding the tags takes two steps: a regex
9
+ * scan for candidates (`scanScriptTags`), then a decision about which of
10
+ * them are top-level (`findScriptTags`).
11
+ *
12
+ * @internal
13
+ *
14
+ * @module
15
+ */
16
+ import { parse } from 'svelte/compiler';
17
+ /**
18
+ * Matches, left to right, an HTML comment or a script tag.
19
+ *
20
+ * Ports Svelte's preprocessor regex (`svelte/src/compiler/preprocess`):
21
+ * quote-aware attributes (`>` inside a value doesn't end the tag),
22
+ * commented-out scripts consumed by the comment alternative, a self-closing
23
+ * form with no content. Adaptations: the `d` flag for content offsets, no `i`
24
+ * flag (`<Script>` is a component), `\s*` before the closing `>` per the
25
+ * parser's `/<\/script\s*>/`.
26
+ */
27
+ const SCRIPT_TAG_MATCHER = /<!--[^]*?-->|<script((?:\s+[^=>'"/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/\s]+)*\s*)(?:\/>|>([^]*?)<\/script\s*>)/dg;
28
+ /** `SCRIPT_TAG_MATCHER` for style tags, whose content is blanked before parsing. */
29
+ const STYLE_TAG_MATCHER = /<!--[^]*?-->|<style(?:\s+[^=>'"/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/\s]+)*\s*>([^]*?)<\/style\s*>/dg;
30
+ /**
31
+ * The attribute spellings the scan's proof accepts: names of word characters,
32
+ * values double-quoted, single-quoted, or bare word characters, whitespace
33
+ * between attributes. Narrower than `SCRIPT_TAG_MATCHER`'s attribute branch
34
+ * on purpose. That branch can backtrack into a second reading of the same
35
+ * text (an unterminated quote read as a bare value), and Svelte's parser,
36
+ * which never backtracks, may take the other one. This grammar has a single
37
+ * reading, the one the parser's `read_static_attribute` makes.
38
+ */
39
+ const UNAMBIGUOUS_ATTRIBUTES_MATCHER = /^(?:[ \t\r\n]+[A-Za-z][\w-]*(?:=(?:"[^"]*"|'[^']*'|[\w.-]+))?)*[ \t\r\n]*$/;
40
+ const WHITESPACE_MATCHER = /\s*/y;
41
+ /** Whether `source` holds only whitespace from `start` up to `end`. */
42
+ const isWhitespaceBetween = (source, start, end) => {
43
+ WHITESPACE_MATCHER.lastIndex = start;
44
+ WHITESPACE_MATCHER.test(source);
45
+ return WHITESPACE_MATCHER.lastIndex >= end;
46
+ };
47
+ /**
48
+ * Scan Svelte source for script tags with content, in source order, and mark
49
+ * the ones the scan itself proves top-level.
50
+ *
51
+ * The scan is syntactic and knows nothing about nesting, so it returns nested
52
+ * tags too; `findScriptTags` is the function that answers which are the
53
+ * component's. Limits: whitespace around an attribute `=` makes a tag
54
+ * unmatchable (Svelte rejects one of those spellings, and svelte2tsx matches
55
+ * neither), and `</script>` in a string literal ends the content early.
56
+ *
57
+ * **`provenTopLevel`** holds for a tag when everything from the start of the
58
+ * file to it is whitespace, complete HTML comments, and earlier script tags
59
+ * that are themselves proven. Svelte's parser reads each of those at the root
60
+ * and comes back to the root: whitespace is text, a comment runs to the first
61
+ * `-->`, and a top-level script runs from its opening tag to the first
62
+ * `</script>`, the same extents the regex matched. So it meets this tag at the
63
+ * root, where a `<script>` is the instance or module script.
64
+ *
65
+ * Anything that would need more than that argument leaves the tag unproven,
66
+ * along with every tag after it:
67
+ *
68
+ * - any other text or markup before the tag: a `<style>`,
69
+ * `<svelte:options>`, an unterminated comment, what's left over when a
70
+ * `</script>` in a string ended an earlier match early, and tags the regex
71
+ * doesn't match (`<SCRIPT>`, a spelling with whitespace around `=`)
72
+ * - a self-closing `<script />`, which Svelte's parser rejects at the top
73
+ * level
74
+ * - attributes outside `UNAMBIGUOUS_ATTRIBUTES_MATCHER`
75
+ */
76
+ export const scanScriptTags = (svelteSource) => {
77
+ const scripts = [];
78
+ // whether everything up to `cursor` is whitespace, comments, and proven scripts
79
+ let atRoot = true;
80
+ let cursor = 0;
81
+ SCRIPT_TAG_MATCHER.lastIndex = 0;
82
+ let match;
83
+ while ((match = SCRIPT_TAG_MATCHER.exec(svelteSource)) !== null) {
84
+ atRoot &&= isWhitespaceBetween(svelteSource, cursor, match.index);
85
+ cursor = match.index + match[0].length;
86
+ const attrs = match[1];
87
+ // the comment alternative captures no attributes
88
+ if (attrs === undefined)
89
+ continue;
90
+ const content = match[2];
91
+ if (content === undefined) {
92
+ // self-closing, so no content to return
93
+ atRoot = false;
94
+ continue;
95
+ }
96
+ atRoot &&= UNAMBIGUOUS_ATTRIBUTES_MATCHER.test(attrs);
97
+ scripts.push({
98
+ attributes: parseAttributes(attrs),
99
+ content,
100
+ start: match.indices[2][0],
101
+ open: match.index,
102
+ end: cursor,
103
+ provenTopLevel: atRoot
104
+ });
105
+ }
106
+ return scripts;
107
+ };
108
+ /**
109
+ * Parse an opening-tag attribute string into a name → value map — bare
110
+ * attributes map to `true`. The token grammar mirrors `SCRIPT_TAG_MATCHER`'s
111
+ * attribute branch, so anything that regex matched parses cleanly here.
112
+ */
113
+ const parseAttributes = (attrs) => {
114
+ const attributes = new Map();
115
+ const attributeRegex = /([^=>'"/\s]+)(?:=(?:"([^"]*)"|'([^']*)'|([^>\s]+)))?/g;
116
+ let match;
117
+ while ((match = attributeRegex.exec(attrs)) !== null) {
118
+ attributes.set(match[1], match[2] ?? match[3] ?? match[4] ?? true);
119
+ }
120
+ return attributes;
121
+ };
122
+ /**
123
+ * A script tag is a module script when it carries a `module` attribute
124
+ * (Svelte 5) or `context="module"` (Svelte 4) — Svelte's `read_script` test,
125
+ * minus its error paths. `module` inside an attribute *value* doesn't count.
126
+ */
127
+ export const isModuleScript = (attributes) => attributes.has('module') || attributes.get('context') === 'module';
128
+ /**
129
+ * Copy `svelteSource` with the content of its script and style tags
130
+ * overwritten by spaces, newlines kept, so every offset and line still means
131
+ * what it meant. Script content needn't be JavaScript Svelte's parser accepts,
132
+ * and a nested tag's content would be read as template.
133
+ *
134
+ * A style tag that opens inside a script tag is text in that script, and the
135
+ * search for styles resumes after the script. A leading byte-order mark
136
+ * becomes a space too: Svelte's `parse` strips one, which would shift every
137
+ * offset it reports.
138
+ */
139
+ const blankVerbatimContent = (svelteSource, scripts) => {
140
+ const ranges = scripts.map((tag) => [
141
+ tag.start,
142
+ tag.start + tag.content.length
143
+ ]);
144
+ STYLE_TAG_MATCHER.lastIndex = 0;
145
+ let match;
146
+ while ((match = STYLE_TAG_MATCHER.exec(svelteSource)) !== null) {
147
+ const range = match.indices[1];
148
+ // the comment alternative captures no content
149
+ if (!range)
150
+ continue;
151
+ const open = match.index;
152
+ const enclosing = scripts.find((tag) => tag.open < open && open < tag.end);
153
+ if (enclosing) {
154
+ STYLE_TAG_MATCHER.lastIndex = enclosing.end;
155
+ continue;
156
+ }
157
+ ranges.push(range);
158
+ }
159
+ // a style's content can hold a matched script, so ranges can overlap: each
160
+ // is clipped to what's still ahead of the cursor
161
+ ranges.sort((a, b) => a[0] - b[0]);
162
+ let blanked = '';
163
+ let cursor = 0;
164
+ if (svelteSource.charCodeAt(0) === 0xfeff) {
165
+ blanked = ' ';
166
+ cursor = 1;
167
+ }
168
+ for (const [rangeStart, end] of ranges) {
169
+ const start = Math.max(rangeStart, cursor);
170
+ if (end <= start)
171
+ continue;
172
+ blanked +=
173
+ svelteSource.slice(cursor, start) + svelteSource.slice(start, end).replace(/[^\n]/g, ' ');
174
+ cursor = end;
175
+ }
176
+ return blanked + svelteSource.slice(cursor);
177
+ };
178
+ /**
179
+ * The default `ParseSvelteTemplate`: Svelte's own parser. `loose` keeps it
180
+ * from throwing on a template error, the way svelte2tsx parses under
181
+ * `emitOnTemplateError`; `modern` skips the conversion to the legacy AST.
182
+ */
183
+ const parseSvelteTemplate = (blankedSource) => parse(blankedSource, { modern: true, loose: true });
184
+ const toScriptTag = ({ attributes, content, start }) => ({
185
+ attributes,
186
+ content,
187
+ start
188
+ });
189
+ /**
190
+ * Find a component's script tags: the `<script>` tags at the top level of the
191
+ * source, in source order. A `<script>` nested in an element, a block, or
192
+ * `<svelte:head>` isn't one, matching Svelte, which reads only a top-level
193
+ * tag as the instance or module script.
194
+ *
195
+ * `scanScriptTags` finds the candidates. When it proves every one of them
196
+ * top-level, which covers the usual component with its scripts ahead of the
197
+ * template, that's the answer. Otherwise Svelte's parser decides: the source
198
+ * is parsed with script and style content blanked, and the tags at the
199
+ * offsets of the root's `instance` and `module` are kept. svelte2tsx parses
200
+ * the same blanked source, but demotes only the tags the parser reads as
201
+ * nested elements, so a tag spelled inside an expression string or an
202
+ * attribute value is still a script to it and isn't one here.
203
+ *
204
+ * Limits: a `</script>` or `</style>` inside a string or comment ends that
205
+ * tag's blanked content early, and what's left over is parsed as template.
206
+ * And svelte2tsx's own tag matcher is narrower in one spelling: it doesn't
207
+ * take a closing tag with whitespace before the `>` (`</script >`), so there
208
+ * its virtual doesn't have the scripts as written while this returns them. A
209
+ * legacy component
210
+ * written that way documents no props, with a `svelte_prop_failed` warning
211
+ * for each `export let`; a runes one documents none, with no warning.
212
+ *
213
+ * @param svelteSource - the full Svelte source code
214
+ * @returns the top-level script tags and how they were decided
215
+ */
216
+ export const findScriptTags = (svelteSource, options) => {
217
+ const scripts = scanScriptTags(svelteSource);
218
+ if (scripts.length === 0)
219
+ return { tags: [], decidedBy: 'scan' };
220
+ if (options?.scanProof !== false && scripts.every((tag) => tag.provenTopLevel)) {
221
+ return { tags: scripts.map(toScriptTag), decidedBy: 'scan' };
222
+ }
223
+ const parseTemplate = options?.parseTemplate ?? parseSvelteTemplate;
224
+ let parsed;
225
+ try {
226
+ parsed = parseTemplate(blankVerbatimContent(svelteSource, scripts));
227
+ }
228
+ catch (_) {
229
+ // Every matched tag, nested ones included: the answer the scan alone
230
+ // gives. Svelte's parser throws here on a template error when it predates
231
+ // `loose` parsing (Svelte 5.13), which the peer range (5.0 and up) still
232
+ // admits, and in any version on the few errors `loose` doesn't absorb.
233
+ // TODO: remove this fallback when the `svelte` peer floor reaches a
234
+ // version with `loose` parsing
235
+ return { tags: scripts.map(toScriptTag), decidedBy: 'unparsed' };
236
+ }
237
+ const topLevel = new Set([parsed.instance?.start, parsed.module?.start]);
238
+ return {
239
+ tags: scripts.filter((tag) => topLevel.has(tag.open)).map(toScriptTag),
240
+ decidedBy: 'parser'
241
+ };
242
+ };
package/dist/svelte.d.ts CHANGED
@@ -19,6 +19,8 @@
19
19
  * @see `typescript-extract-type-json.ts` for `resolveTypeInfo`, `referenceSymbolName`, `tupleElements`, `restElementForms`
20
20
  * @see `tsdoc.ts` for `parseComment`, `applyToDeclaration`
21
21
  * @see `source.ts` for `SourceFileInfo`, `getComponentName`
22
+ * @see `svelte-legacy.ts` for `scanLegacyExports`, `resolveLegacyPropsAnchor`
23
+ * @see `svelte-scripts.ts` for `findScriptTags`, `isModuleScript`
22
24
  *
23
25
  * @module
24
26
  */
@@ -31,6 +33,7 @@ import { type AliasRegistry } from './typescript-extract-type-json.js';
31
33
  import { type SourceFileInfo } from './source.js';
32
34
  import { type ModuleSourceOptions } from './source-config.js';
33
35
  import { type Diagnostic } from './diagnostics.js';
36
+ import { type SvelteScriptTag } from './svelte-scripts.js';
34
37
  /** Resolved source map type (avoids repeating the verbose `InstanceType<...>` inline). */
35
38
  type SourceMap = InstanceType<typeof TraceMap>;
36
39
  /**
@@ -55,6 +58,16 @@ export interface SvelteVirtualFile {
55
58
  * derived from it at output.
56
59
  */
57
60
  scriptKind: ts.ScriptKind;
61
+ /**
62
+ * The component's script tags as located in the original source: the
63
+ * top-level `<script>` tags, in source order (`findScriptTags`).
64
+ * `transformSvelteSource` locates them once, and `analyzeSvelteModule`
65
+ * reads the instance and module scripts from here on every analysis.
66
+ *
67
+ * Optional so a virtual built by hand needs none: `analyzeSvelteModule`
68
+ * then locates them in the source it's given.
69
+ */
70
+ scriptTags?: ReadonlyArray<SvelteScriptTag>;
58
71
  }
59
72
  /**
60
73
  * Result of `transformSvelteSource` — a virtual file (when transform succeeded)
@@ -92,18 +105,24 @@ export interface TransformResult {
92
105
  */
93
106
  export declare const transformSvelteSource: (sourceFile: SourceFileInfo) => TransformResult;
94
107
  /**
95
- * Extract the content of the main `<script>` tag from Svelte source —
96
- * commented-out scripts skipped, module scripts (`<script module>`,
97
- * `<script context="module">`) excluded.
108
+ * Extract the content of the component's instance `<script>` from Svelte
109
+ * source: the top-level one that isn't a module script (`<script module>`,
110
+ * `<script context="module">`). A commented-out script doesn't count, and
111
+ * neither does one nested in the template (`<svelte:head>`, an element, a
112
+ * block), which is an ordinary element.
113
+ *
114
+ * Locates the tags itself on every call (`findScriptTags`), parsing the
115
+ * template when the scan can't prove them top-level.
98
116
  *
99
- * @returns the script tag content, or undefined if no matching script tag is found
117
+ * @returns the script tag content, or undefined if the source has no instance script
100
118
  */
101
119
  export declare const extractScriptContent: (svelteSource: string) => string | undefined;
102
120
  /**
103
- * Extract the content of the module `<script>` tag from Svelte source.
121
+ * Extract the content of the component's module `<script>` from Svelte source.
104
122
  *
105
- * Counterpart of `extractScriptContent`: matches only module scripts, so the
106
- * two partition a source's script tags consistently.
123
+ * Counterpart of `extractScriptContent`: matches only the module script, under
124
+ * the same top-level rule and at the same per-call cost, so the two partition
125
+ * a source's script tags consistently.
107
126
  *
108
127
  * @returns the module script tag content, or undefined if no module script is found
109
128
  */
@@ -253,10 +272,13 @@ export declare const synthesizeSnippetTypeSignature: (parameters: Array<Paramete
253
272
  * 2. svelte2tsx internals are filtered (`isSvelte2tsxGeneratedExport`) and
254
273
  * exported snippets reclassified to `kind: 'snippet'` (`isSnippetReturnType`);
255
274
  * 2b remaps module-level `sourceLine`s to the original `.svelte` source
256
- * 3. the component declaration is synthesized: props via `extractPropsViaChecker`,
257
- * `acceptsChildren` from a `Snippet`-typed `children` prop or, failing that,
258
- * template use (`__sveltets_2_ensureSnippet`), plus generics, doc comment, and
259
- * source line from the landmarks `findComponentNodes` locates
275
+ * 3. the component declaration is synthesized: props via `extractPropsViaChecker`
276
+ * from the component's `PropsAnchor` (`resolveRunesPropsAnchor` for a
277
+ * `$props()` declaration, else `resolveExportLetPropsAnchor` for a legacy
278
+ * component's exports), `acceptsChildren` from a `Snippet`-typed `children`
279
+ * prop, template use (`__sveltets_2_ensureSnippet`) or, failing those, a
280
+ * legacy component's default slot (`hasDefaultSlot`), plus generics, doc
281
+ * comment, and source line from the landmarks `findComponentNodes` locates
260
282
  * 4. the module comment is read from the original source
261
283
  * 5. declarations combine, component first
262
284
  * 6. dependencies are extracted
@@ -1 +1 @@
1
- {"version":3,"file":"svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/svelte.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/svelte.ts"],"names":[],"mappings":"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"}