svelte-scripts.ts

Locating a Svelte component's script tags: its instance <script> and its <script module>.

Svelte takes a <script> for one of those only at the top level of the file. Nested in an element, a block, or <svelte:head> it's an ordinary element (a JSON-LD block, an inline analytics snippet), and its content says nothing about the component. So finding the tags takes two steps: a regex scan for candidates (scanScriptTags), then a decision about which of them are top-level (findScriptTags).

@internal

view source

Declarations
#

10 declarations

findScriptTags
#

svelte-scripts.ts view source

(svelteSource: string, options?: FindScriptTagsOptions | undefined): FoundScriptTags import {findScriptTags} from 'svelte-docinfo/svelte-scripts.js';

Find a component's script tags: the <script> tags at the top level of the source, in source order. A <script> nested in an element, a block, or <svelte:head> isn't one, matching Svelte, which reads only a top-level tag as the instance or module script.

scanScriptTags finds the candidates. When it proves every one of them top-level, which covers the usual component with its scripts ahead of the template, that's the answer. Otherwise Svelte's parser decides: the source is parsed with script and style content blanked, and the tags at the offsets of the root's instance and module are kept. svelte2tsx parses the same blanked source, but demotes only the tags the parser reads as nested elements, so a tag spelled inside an expression string or an attribute value is still a script to it and isn't one here.

Limits: a </script> or </style> inside a string or comment ends that tag's blanked content early, and what's left over is parsed as template. And svelte2tsx's own tag matcher is narrower in one spelling: it doesn't take a closing tag with whitespace before the > (</script >), so there its virtual doesn't have the scripts as written while this returns them. A legacy component written that way documents no props, with a svelte_prop_failed warning for each export let; a runes one documents none, with no warning.

svelteSource

the full Svelte source code

type string

options?

optional

returns

FoundScriptTags

the top-level script tags and how they were decided

FindScriptTagsOptions
#

svelte-scripts.ts view source

FindScriptTagsOptions import type {FindScriptTagsOptions} from 'svelte-docinfo/svelte-scripts.js';

Options for findScriptTags.

scanProof?

Take the scan's proof when it covers every tag, without parsing. false sends every source with a tag to the parser.

type boolean

default true

parseTemplate?

The parser asked about tags the scan can't prove. Defaults to Svelte's.

type (blankedSource: string): SvelteTemplateScripts

blankedSource

type string

FoundScriptTags
#

isModuleScript
#

svelte-scripts.ts view source

(attributes: Map<string, string | true>): boolean import {isModuleScript} from 'svelte-docinfo/svelte-scripts.js';

A script tag is a module script when it carries a module attribute (Svelte 5) or context="module" (Svelte 4) — Svelte's read_script test, minus its error paths. module inside an attribute *value* doesn't count.

attributes

type Map<string, string | true>

returns

boolean

ParseSvelteTemplate
#

svelte-scripts.ts view source

ParseSvelteTemplate import type {ParseSvelteTemplate} from 'svelte-docinfo/svelte-scripts.js';

Parses a Svelte source whose script and style content is blanked, and says where its top-level scripts are. Throws when the source doesn't parse.

(call)

type (blankedSource: string): SvelteTemplateScripts

blankedSource

type string

ScannedScriptTag
#

svelte-scripts.ts view source

ScannedScriptTag import type {ScannedScriptTag} from 'svelte-docinfo/svelte-scripts.js';

A script tag the scan matched, before anything has decided whether it's top-level.

inheritance

open

Offset of the tag's opening <, which is where Svelte's parser places the script.

type number

end

Offset just past the tag's closing >.

type number

provenTopLevel

Whether the scan alone proves the tag top-level, with no parser: see scanScriptTags for the proof and its conditions.

type boolean

scanScriptTags
#

svelte-scripts.ts view source

(svelteSource: string): ScannedScriptTag[] import {scanScriptTags} from 'svelte-docinfo/svelte-scripts.js';

Scan Svelte source for script tags with content, in source order, and mark the ones the scan itself proves top-level.

The scan is syntactic and knows nothing about nesting, so it returns nested tags too; findScriptTags is the function that answers which are the component's. Limits: whitespace around an attribute = makes a tag unmatchable (Svelte rejects one of those spellings, and svelte2tsx matches neither), and </script> in a string literal ends the content early.

provenTopLevel holds for a tag when everything from the start of the file to it is whitespace, complete HTML comments, and earlier script tags that are themselves proven. Svelte's parser reads each of those at the root and comes back to the root: whitespace is text, a comment runs to the first -->, and a top-level script runs from its opening tag to the first </script>, the same extents the regex matched. So it meets this tag at the root, where a <script> is the instance or module script.

Anything that would need more than that argument leaves the tag unproven, along with every tag after it:

  • any other text or markup before the tag: a <style>, <svelte:options>, an unterminated comment, what's left over when a </script> in a string ended an earlier match early, and tags the regex doesn't match (<SCRIPT>, a spelling with whitespace around =)
  • a self-closing <script />, which Svelte's parser rejects at the top level
  • attributes outside UNAMBIGUOUS_ATTRIBUTES_MATCHER

svelteSource

type string

returns

ScannedScriptTag[]

ScriptTagsDecision
#

svelte-scripts.ts view source

ScriptTagsDecision

type "scan" | "parser" | "unparsed"

import type {ScriptTagsDecision} from 'svelte-docinfo/svelte-scripts.js';

How findScriptTags decided which tags are top-level:

  • 'scan' — the scan proved every tag top-level (provenTopLevel), so nothing was parsed
  • 'parser' — Svelte's parser said which tags are the instance and module scripts
  • 'unparsed' — the parser threw, and every matched tag is returned

SvelteScriptTag
#

svelte-scripts.ts view source

SvelteScriptTag import type {SvelteScriptTag} from 'svelte-docinfo/svelte-scripts.js';

A located script tag: parsed attributes, content, and where the content starts in the source.

attributes

Opening-tag attributes; bare attributes (module) map to true.

type Map<string, string | true>

content

type string

start

Offset of content within the source, for mapping script positions to original lines.

type number

SvelteTemplateScripts
#

svelte-scripts.ts view source

SvelteTemplateScripts import type {SvelteTemplateScripts} from 'svelte-docinfo/svelte-scripts.js';

The part of Svelte's parsed root that findScriptTags reads.

instance?

The instance script, at the offset of its opening <.

type { start: number; } | null

module?

The module script, at the offset of its opening <.

type { start: number; } | null

Imported by
#