@staticbolt/lsp 1.0.0-beta.13 → 1.0.0-beta.14

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.
package/lib/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import * as vs from "vscode-languageserver/node.js";
1
+ import * as vs from "vscode-languageserver/node";
2
2
  import * as vscode$1 from "vscode-languageserver";
3
3
  import vscode, { RequestType } from "vscode-languageserver";
4
4
  import { TextDocument } from "vscode-languageserver-textdocument";
@@ -122,9 +122,11 @@ var ConfigManager = class {
122
122
  }
123
123
  async collectData(config) {
124
124
  this.lspHtmlData = [];
125
- for (const pluginOrArray of config.plugins ?? []) {
125
+ const plugins = config.plugins ?? [];
126
+ for (const pluginOrArray of plugins) {
126
127
  const plugins = Array.isArray(pluginOrArray) ? pluginOrArray : [pluginOrArray];
127
- for (const plugin of plugins) if (plugin.lspHtmlData) {
128
+ for (const plugin of plugins) {
129
+ if (!plugin.lspHtmlData) continue;
128
130
  const htmlData = await plugin.lspHtmlData();
129
131
  if (htmlData) {
130
132
  htmlDataInjectPluginName(htmlData, plugin.name);
@@ -135,11 +137,14 @@ var ConfigManager = class {
135
137
  }
136
138
  };
137
139
  function htmlDataInjectPluginName(htmlData, pluginName) {
138
- for (const tag of htmlData.tags ?? []) {
140
+ const tags = htmlData.tags ?? [];
141
+ for (const tag of tags) {
139
142
  tag.description = replaceDescription(tag.description, pluginName);
140
- for (const attribute of tag.attributes ?? []) attribute.description = replaceDescription(attribute.description, pluginName);
143
+ const attributes = tag.attributes ?? [];
144
+ for (const attribute of attributes) attribute.description = replaceDescription(attribute.description, pluginName);
141
145
  }
142
- for (const attribute of htmlData.globalAttributes ?? []) attribute.description = replaceDescription(attribute.description, pluginName);
146
+ const globalAttributes = htmlData.globalAttributes ?? [];
147
+ for (const attribute of globalAttributes) attribute.description = replaceDescription(attribute.description, pluginName);
143
148
  }
144
149
  function replaceDescription(description, pluginName) {
145
150
  const info = `_Provided by **staticbolt** \`${pluginName}\` plugin._`;
@@ -180,7 +185,7 @@ function findStaticboltProjects(searchRoots) {
180
185
  function getLanguageModelCache(maxEntries, cleanupIntervalTimeInSec, parse) {
181
186
  let languageModels = {};
182
187
  let nModels = 0;
183
- let cleanupInterval = void 0;
188
+ let cleanupInterval;
184
189
  if (cleanupIntervalTimeInSec > 0) cleanupInterval = setInterval(() => {
185
190
  const cutoffTime = Date.now() - cleanupIntervalTimeInSec * 1e3;
186
191
  const uris = Object.keys(languageModels);
@@ -225,18 +230,17 @@ function getLanguageModelCache(maxEntries, cleanupIntervalTimeInSec, parse) {
225
230
  },
226
231
  onDocumentRemoved(document) {
227
232
  const uri = document.uri;
228
- if (languageModels[uri]) {
233
+ if (Object.hasOwn(languageModels, uri)) {
229
234
  delete languageModels[uri];
230
235
  nModels--;
231
236
  }
232
237
  },
233
238
  dispose() {
234
- if (cleanupInterval !== void 0) {
235
- clearInterval(cleanupInterval);
236
- cleanupInterval = void 0;
237
- languageModels = {};
238
- nModels = 0;
239
- }
239
+ if (cleanupInterval === void 0) return;
240
+ clearInterval(cleanupInterval);
241
+ cleanupInterval = void 0;
242
+ languageModels = {};
243
+ nModels = 0;
240
244
  }
241
245
  };
242
246
  }
@@ -250,7 +254,7 @@ function getDocumentRegions(languageService, document) {
250
254
  const scanner = languageService.createScanner(document.getText());
251
255
  let lastTagName = "";
252
256
  let lastAttributeName = null;
253
- let languageIdFromType = void 0;
257
+ let languageIdFromType;
254
258
  const importedScripts = [];
255
259
  let token = scanner.scan();
256
260
  while (token !== TokenType.EOS) {
@@ -312,7 +316,7 @@ function getDocumentRegions(languageService, document) {
312
316
  }
313
317
  return {
314
318
  getLanguageRanges: (range) => getLanguageRanges(document, regions, range),
315
- getEmbeddedDocument: (languageId, ignoreAttributeValues) => getEmbeddedDocument(document, regions, languageId, ignoreAttributeValues),
319
+ getEmbeddedDocument: (languageId, shouldIgnoreAttributeValues) => getEmbeddedDocument(document, regions, languageId, shouldIgnoreAttributeValues),
316
320
  getLanguageAtPosition: (position) => getLanguageAtPosition(document, regions, position),
317
321
  getLanguagesInDocument: () => getLanguagesInDocument(document, regions),
318
322
  getImportedScripts: () => importedScripts
@@ -323,7 +327,8 @@ function getLanguageRanges(document, regions, range) {
323
327
  let currentPos = range ? range.start : Position.create(0, 0);
324
328
  let currentOffset = range ? document.offsetAt(range.start) : 0;
325
329
  const endOffset = range ? document.offsetAt(range.end) : document.getText().length;
326
- for (const region of regions) if (region.end > currentOffset && region.start < endOffset) {
330
+ for (const region of regions) {
331
+ if (!(region.end > currentOffset && region.start < endOffset)) continue;
327
332
  const start = Math.max(region.start, currentOffset);
328
333
  const startPos = document.positionAt(start);
329
334
  if (currentOffset < region.start) result.push({
@@ -354,7 +359,8 @@ function getLanguageRanges(document, regions, range) {
354
359
  }
355
360
  function getLanguagesInDocument(_document, regions) {
356
361
  const result = [];
357
- for (const region of regions) if (region.languageId && !result.includes(region.languageId)) {
362
+ for (const region of regions) {
363
+ if (!(region.languageId && !result.includes(region.languageId))) continue;
358
364
  result.push(region.languageId);
359
365
  if (result.length === 3) return result;
360
366
  }
@@ -368,12 +374,13 @@ function getLanguageAtPosition(document, regions, position) {
368
374
  } else break;
369
375
  return "html";
370
376
  }
371
- function getEmbeddedDocument(document, contents, languageId, ignoreAttributeValues) {
377
+ function getEmbeddedDocument(document, contents, languageId, shouldIgnoreAttributeValues) {
372
378
  let currentPos = 0;
373
379
  const oldContent = document.getText();
374
380
  let result = "";
375
381
  let lastSuffix = "";
376
- for (const c of contents) if (c.languageId === languageId && (!ignoreAttributeValues || !c.attributeValue)) {
382
+ for (const c of contents) {
383
+ if (!(c.languageId === languageId && (!shouldIgnoreAttributeValues || !c.attributeValue))) continue;
377
384
  result = substituteWithWhitespace(result, currentPos, c.start, oldContent, lastSuffix, getPrefix(c));
378
385
  result += updateContent(c, oldContent.slice(c.start, c.end));
379
386
  currentPos = c.end;
@@ -606,11 +613,11 @@ function getFileSystemProvider(handledSchemas, connection, runtime) {
606
613
  return {
607
614
  async stat(uri) {
608
615
  if (fileFs && uri.startsWith("file:")) return fileFs.stat(uri);
609
- return await connection.sendRequest(FsStatRequest.type, uri.toString());
616
+ return await connection.sendRequest(FsStatRequest.type, uri);
610
617
  },
611
618
  readDirectory(uri) {
612
619
  if (fileFs && uri.startsWith("file:")) return fileFs.readDirectory(uri);
613
- return connection.sendRequest(FsReadDirectoryRequest.type, uri.toString());
620
+ return connection.sendRequest(FsReadDirectoryRequest.type, uri);
614
621
  }
615
622
  };
616
623
  }
@@ -623,12 +630,12 @@ function pushAll(to, from) {
623
630
 
624
631
  //#endregion
625
632
  //#region src/utils/strings.ts
626
- function startsWith(haystack, needle) {
633
+ function isStartingWith(haystack, needle) {
627
634
  if (haystack.length < needle.length) return false;
628
635
  for (let index = 0; index < needle.length; index++) if (haystack[index] !== needle[index]) return false;
629
636
  return true;
630
637
  }
631
- function endsWith(haystack, needle) {
638
+ function isEndingWith(haystack, needle) {
632
639
  const diff = haystack.length - needle.length;
633
640
  if (diff > 0) return haystack.indexOf(needle, diff) === diff;
634
641
  if (diff === 0) return haystack === needle;
@@ -643,8 +650,8 @@ function getDocumentContext(documentUri, workspaceFolders) {
643
650
  function getRootFolder() {
644
651
  for (const folder of workspaceFolders) {
645
652
  let folderURI = folder.uri;
646
- if (!endsWith(folderURI, "/")) folderURI = folderURI + "/";
647
- if (startsWith(documentUri, folderURI)) return folderURI;
653
+ if (!isEndingWith(folderURI, "/")) folderURI += "/";
654
+ if (isStartingWith(documentUri, folderURI)) return folderURI;
648
655
  }
649
656
  }
650
657
  return { resolveReference: (reference, base = documentUri) => {
@@ -676,7 +683,7 @@ function findProjectRoot(fileUri) {
676
683
  function formatError(message, error) {
677
684
  if (error instanceof Error) return `${message}: ${error.message}\n${error.stack}`;
678
685
  if (typeof error === "string") return `${message}: ${error}`;
679
- if (error) return `${message}: ${error.toString()}`;
686
+ if (error) return `${message}: ${error}`;
680
687
  return message;
681
688
  }
682
689
  function runSafe(runtime, function_, errorValue, errorMessage, token) {
@@ -864,9 +871,8 @@ function getNodeFileFS() {
864
871
  if (error) return error_(error);
865
872
  c(children.map((stat) => {
866
873
  if (stat.isSymbolicLink()) return [stat.name, FileType.SymbolicLink];
867
- else if (stat.isDirectory()) return [stat.name, FileType.Directory];
868
- else if (stat.isFile()) return [stat.name, FileType.File];
869
- else return [stat.name, FileType.Unknown];
874
+ if (stat.isDirectory()) return [stat.name, FileType.Directory];
875
+ return stat.isFile() ? [stat.name, FileType.File] : [stat.name, FileType.Unknown];
870
876
  }));
871
877
  });
872
878
  });
package/lib/index.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["path","FileType","path","vscode"],"sources":["../src/helpers/config-loader.ts","../src/helpers/find-projects.ts","../src/language-model-cache.ts","../src/modes/embedded-support.ts","../src/modes/html-mode.ts","../src/modes/language-modes.ts","../src/requests.ts","../src/utils/arrays.ts","../src/utils/strings.ts","../src/utils/document-context.ts","../src/utils/find-project-root.ts","../src/utils/runner.ts","../src/html-server.ts","../src/utils/node-fs.ts","../src/index.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\";\nimport { watch, type FSWatcher } from \"node:fs\";\nimport { access, constants } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport type { AppConfig } from \"@staticbolt/core\";\nimport type { HTMLDataV1 } from \"vscode-html-languageservice\";\nimport type { MarkupContent, RemoteConsole } from \"vscode-languageserver\";\n\nexport type StaticBoltConfig = AppConfig;\n\nexport interface ConfigLoaderEvents {\n change: [config: StaticBoltConfig];\n error: [err: Error];\n}\n\nconst CONFIG_CANDIDATES = [\".staticbolt.ts\", \".staticbolt.js\"] as const;\n\nasync function findConfigFile(workspaceRoot: string): Promise<string | null> {\n for (const name of CONFIG_CANDIDATES) {\n const full = join(workspaceRoot, name);\n\n try {\n await access(full, constants.R_OK);\n return full;\n } catch {\n // not found or not readable — try next\n }\n }\n\n return null;\n}\n\nasync function importFresh(absolutePath: string): Promise<StaticBoltConfig> {\n const url = `${pathToFileURL(absolutePath).href}?t=${Date.now()}`;\n const module_ = (await import(url)) as { default: StaticBoltConfig };\n\n if (!(\"default\" in module_)) {\n throw new Error(`Config file \"${absolutePath}\" has no default export. ` + `Use \\`export default { … }\\`.`);\n }\n\n return module_.default;\n}\n\n// eslint-disable-next-line unicorn/prefer-event-target\nexport class ConfigLoader extends EventEmitter<ConfigLoaderEvents> {\n private readonly workspaceRoot: string;\n private configPath: string | null = null;\n private watcher: FSWatcher | null = null;\n private current: StaticBoltConfig | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly DEBOUNCE_MS = 150;\n\n constructor(workspaceRoot: string) {\n super();\n this.workspaceRoot = workspaceRoot;\n }\n\n /** Start watching. Resolves with the initial config (or null if absent). */\n async start(): Promise<StaticBoltConfig | null> {\n this.configPath = await findConfigFile(this.workspaceRoot);\n\n if (!this.configPath) {\n return null;\n }\n\n await this.load();\n this.watch(this.configPath);\n return this.current;\n }\n\n /** Stop watching and release all resources. */\n dispose(): void {\n if (this.debounceTimer !== null) {\n clearTimeout(this.debounceTimer);\n }\n this.watcher?.close();\n this.watcher = null;\n }\n\n /** The last successfully loaded config, or null if none loaded yet. */\n get config(): StaticBoltConfig | null {\n return this.current;\n }\n\n private async load(): Promise<void> {\n if (!this.configPath) return;\n\n try {\n this.current = await importFresh(this.configPath);\n this.emit(\"change\", this.current);\n } catch (error) {\n this.emit(\"error\", error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private watch(configPath: string): void {\n this.watcher = watch(configPath, { persistent: false }, event => {\n if (event === \"rename\" || event === \"change\") {\n this.scheduleReload();\n }\n });\n\n this.watcher.on(\"error\", error => this.emit(\"error\", error));\n }\n\n private scheduleReload(): void {\n if (this.debounceTimer !== null) {\n clearTimeout(this.debounceTimer);\n }\n\n this.debounceTimer = setTimeout(async () => {\n this.debounceTimer = null;\n\n // The file might have been atomically replaced (Vim, VS Code safe-write).\n // Re-check existence; if it disappeared we just bail.\n if (!this.configPath) return;\n\n try {\n await access(this.configPath, constants.R_OK);\n } catch {\n this.emit(\"error\", new Error(`Config file was removed: ${this.configPath}`));\n return;\n }\n\n await this.load();\n }, this.DEBOUNCE_MS);\n }\n}\n\nexport class ConfigManager {\n private readonly console: RemoteConsole;\n readonly configs = new Map<string, ConfigLoader>();\n lspHtmlData: HTMLDataV1[] = [];\n\n constructor(console: RemoteConsole) {\n this.console = console;\n }\n\n async get(workspaceRoot: string): Promise<AppConfig | null> {\n const configLoader = this.configs.get(workspaceRoot);\n if (configLoader) {\n if (!configLoader.config) {\n this.configs.delete(workspaceRoot);\n return null;\n }\n\n return configLoader.config;\n }\n\n const newConfigLoader = new ConfigLoader(workspaceRoot);\n this.configs.set(workspaceRoot, newConfigLoader);\n\n newConfigLoader.on(\"error\", error => {\n this.console.error(`Failed to load config file: ${error.message}`);\n });\n\n newConfigLoader.on(\"change\", async config => {\n await this.collectData(config);\n });\n\n await newConfigLoader.start();\n\n if (!newConfigLoader.config) {\n return null;\n }\n\n return newConfigLoader.config;\n }\n\n dispose(): void {\n for (const configLoader of this.configs.values()) {\n configLoader.dispose();\n }\n }\n\n private async collectData(config: StaticBoltConfig) {\n this.lspHtmlData = [];\n\n for (const pluginOrArray of config.plugins ?? []) {\n const plugins = Array.isArray(pluginOrArray) ? pluginOrArray : [pluginOrArray];\n\n for (const plugin of plugins) {\n if (plugin.lspHtmlData) {\n const htmlData = await plugin.lspHtmlData();\n if (htmlData) {\n htmlDataInjectPluginName(htmlData, plugin.name);\n this.lspHtmlData.push(htmlData);\n }\n }\n }\n }\n }\n}\n\nfunction htmlDataInjectPluginName(htmlData: HTMLDataV1, pluginName: string) {\n for (const tag of htmlData.tags ?? []) {\n tag.description = replaceDescription(tag.description, pluginName);\n\n for (const attribute of tag.attributes ?? []) {\n attribute.description = replaceDescription(attribute.description, pluginName);\n }\n }\n\n for (const attribute of htmlData.globalAttributes ?? []) {\n attribute.description = replaceDescription(attribute.description, pluginName);\n }\n}\n\nfunction replaceDescription(description: string | MarkupContent | undefined, pluginName: string) {\n const info = `_Provided by **staticbolt** \\`${pluginName}\\` plugin._`;\n\n if (!description) {\n return info;\n }\n\n if (typeof description === \"string\") {\n if (description.includes(info)) {\n return description;\n }\n\n return `${description}\\n\\n${info}`;\n }\n\n if (description.value.includes(info)) {\n return description;\n }\n\n description.value = `${description.value}\\n\\n${info}`;\n return description;\n}\n","import { globSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as vscodeUri from \"vscode-uri\";\n\nimport type { WorkspaceFolder } from \"vscode-languageserver\";\n\nexport function findStaticboltProjects(searchRoots: WorkspaceFolder[]): WorkspaceFolder[] {\n const results: WorkspaceFolder[] = [];\n\n for (const root of searchRoots) {\n const rootPath = vscodeUri.URI.parse(root.uri).fsPath;\n\n const configs = globSync(\"**/.staticbolt.{ts,js}\", { cwd: rootPath, exclude: [\"**/node_modules/**\", \"**/.git/**\"] });\n\n for (const configPath of configs) {\n const absDirectory = path.join(rootPath, path.dirname(configPath));\n const projectUri = vscodeUri.URI.file(absDirectory).toString();\n results.push({ name: path.basename(absDirectory), uri: projectUri });\n }\n }\n\n return results;\n}\n","import type { TextDocument } from \"vscode-html-languageservice\";\n\nexport interface LanguageModelCache<T> {\n get(document: TextDocument): T;\n onDocumentRemoved(document: TextDocument): void;\n dispose(): void;\n}\n\nexport function getLanguageModelCache<T>(\n maxEntries: number,\n cleanupIntervalTimeInSec: number,\n parse: (document: TextDocument) => T\n): LanguageModelCache<T> {\n let languageModels: { [uri: string]: { version: number; languageId: string; cTime: number; languageModel: T } } = {};\n let nModels = 0;\n\n let cleanupInterval: NodeJS.Timeout | undefined = undefined;\n\n if (cleanupIntervalTimeInSec > 0) {\n cleanupInterval = setInterval(() => {\n const cutoffTime = Date.now() - cleanupIntervalTimeInSec * 1000;\n const uris = Object.keys(languageModels);\n\n for (const uri of uris) {\n const languageModelInfo = languageModels[uri];\n if (languageModelInfo.cTime < cutoffTime) {\n delete languageModels[uri];\n nModels--;\n }\n }\n }, cleanupIntervalTimeInSec * 1000);\n }\n\n return {\n get(document: TextDocument): T {\n const version = document.version;\n const languageId = document.languageId;\n const languageModelInfo = languageModels[document.uri];\n\n if (languageModelInfo && languageModelInfo.version === version && languageModelInfo.languageId === languageId) {\n languageModelInfo.cTime = Date.now();\n return languageModelInfo.languageModel;\n }\n\n const languageModel = parse(document);\n languageModels[document.uri] = { languageModel, version, languageId, cTime: Date.now() };\n if (!languageModelInfo) {\n nModels++;\n }\n\n if (nModels === maxEntries) {\n let oldestTime = Number.MAX_VALUE;\n let oldestUri = null;\n\n for (const uri in languageModels) {\n const languageModelInfo = languageModels[uri];\n if (languageModelInfo.cTime < oldestTime) {\n oldestUri = uri;\n oldestTime = languageModelInfo.cTime;\n }\n }\n\n if (oldestUri) {\n delete languageModels[oldestUri];\n nModels--;\n }\n }\n\n return languageModel;\n },\n\n onDocumentRemoved(document: TextDocument) {\n const uri = document.uri;\n if (languageModels[uri]) {\n delete languageModels[uri];\n nModels--;\n }\n },\n\n dispose() {\n if (cleanupInterval !== undefined) {\n clearInterval(cleanupInterval);\n cleanupInterval = undefined;\n languageModels = {};\n nModels = 0;\n }\n },\n };\n}\n","import vscodeHtml from \"vscode-html-languageservice\";\nimport { TextDocument } from \"vscode-languageserver-textdocument\";\n\nimport type { LanguageService, Range } from \"vscode-html-languageservice\";\n\nexport interface LanguageRange extends Range {\n languageId: string | undefined;\n attributeValue?: boolean;\n}\n\nexport interface HTMLDocumentRegions {\n getEmbeddedDocument(languageId: string, ignoreAttributeValues?: boolean): TextDocument;\n getLanguageRanges(range: Range): LanguageRange[];\n getLanguageAtPosition(position: Position): string | undefined;\n getLanguagesInDocument(): string[];\n getImportedScripts(): string[];\n}\n\nconst CSS_STYLE_RULE = \"__\";\nconst TokenType = vscodeHtml.TokenType;\nconst Position = vscodeHtml.Position;\ntype Position = vscodeHtml.Position;\n\ninterface EmbeddedRegion {\n languageId: string | undefined;\n start: number;\n end: number;\n attributeValue?: boolean;\n}\n\nexport function getDocumentRegions(languageService: LanguageService, document: TextDocument): HTMLDocumentRegions {\n const regions: EmbeddedRegion[] = [];\n const scanner = languageService.createScanner(document.getText());\n let lastTagName: string = \"\";\n let lastAttributeName: string | null = null;\n let languageIdFromType: string | undefined = undefined;\n const importedScripts: string[] = [];\n\n let token = scanner.scan();\n\n while (token !== TokenType.EOS) {\n switch (token) {\n case TokenType.StartTag:\n lastTagName = scanner.getTokenText();\n lastAttributeName = null;\n languageIdFromType = \"javascript\";\n break;\n case TokenType.Styles:\n regions.push({ languageId: \"css\", start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });\n break;\n case TokenType.Script:\n regions.push({ languageId: languageIdFromType, start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });\n break;\n case TokenType.AttributeName:\n lastAttributeName = scanner.getTokenText();\n break;\n case TokenType.AttributeValue:\n if (lastAttributeName === \"src\" && lastTagName.toLowerCase() === \"script\") {\n let value = scanner.getTokenText();\n if (value[0] === \"'\" || value[0] === '\"') {\n value = value.slice(1, -1);\n }\n importedScripts.push(value);\n } else if (lastAttributeName === \"type\" && lastTagName.toLowerCase() === \"script\") {\n const token = scanner.getTokenText();\n if (/[\"'](module|(text|application)\\/(java|ecma)script|text\\/babel)[\"']/.test(token) || token === \"module\") {\n languageIdFromType = \"javascript\";\n } else if (/[\"']text\\/typescript[\"']/.test(token)) {\n languageIdFromType = \"typescript\";\n } else {\n languageIdFromType = undefined;\n }\n } else {\n const attributeLanguageId = getAttributeLanguage(lastAttributeName!);\n if (attributeLanguageId) {\n let start = scanner.getTokenOffset();\n let end = scanner.getTokenEnd();\n const firstChar = document.getText()[start];\n if (firstChar === \"'\" || firstChar === '\"') {\n start++;\n end--;\n }\n regions.push({ languageId: attributeLanguageId, start, end, attributeValue: true });\n }\n }\n lastAttributeName = null;\n break;\n }\n token = scanner.scan();\n }\n return {\n getLanguageRanges: (range: Range) => getLanguageRanges(document, regions, range),\n getEmbeddedDocument: (languageId: string, ignoreAttributeValues: boolean) =>\n getEmbeddedDocument(document, regions, languageId, ignoreAttributeValues),\n getLanguageAtPosition: (position: Position) => getLanguageAtPosition(document, regions, position),\n getLanguagesInDocument: () => getLanguagesInDocument(document, regions),\n getImportedScripts: () => importedScripts,\n };\n}\n\nfunction getLanguageRanges(document: TextDocument, regions: EmbeddedRegion[], range: Range): LanguageRange[] {\n const result: LanguageRange[] = [];\n let currentPos = range ? range.start : Position.create(0, 0);\n let currentOffset = range ? document.offsetAt(range.start) : 0;\n const endOffset = range ? document.offsetAt(range.end) : document.getText().length;\n for (const region of regions) {\n if (region.end > currentOffset && region.start < endOffset) {\n const start = Math.max(region.start, currentOffset);\n const startPos = document.positionAt(start);\n if (currentOffset < region.start) {\n result.push({\n start: currentPos,\n end: startPos,\n languageId: \"html\",\n });\n }\n const end = Math.min(region.end, endOffset);\n const endPos = document.positionAt(end);\n if (end > region.start) {\n result.push({\n start: startPos,\n end: endPos,\n languageId: region.languageId,\n attributeValue: region.attributeValue,\n });\n }\n currentOffset = end;\n currentPos = endPos;\n }\n }\n if (currentOffset < endOffset) {\n const endPos = range ? range.end : document.positionAt(endOffset);\n result.push({\n start: currentPos,\n end: endPos,\n languageId: \"html\",\n });\n }\n return result;\n}\n\nfunction getLanguagesInDocument(_document: TextDocument, regions: EmbeddedRegion[]): string[] {\n const result: string[] = [];\n\n for (const region of regions) {\n if (region.languageId && !result.includes(region.languageId)) {\n result.push(region.languageId);\n if (result.length === 3) {\n return result;\n }\n }\n }\n\n result.push(\"html\");\n\n return result;\n}\n\nfunction getLanguageAtPosition(document: TextDocument, regions: EmbeddedRegion[], position: Position): string | undefined {\n const offset = document.offsetAt(position);\n for (const region of regions) {\n if (region.start <= offset) {\n if (offset <= region.end) {\n return region.languageId;\n }\n } else {\n break;\n }\n }\n return \"html\";\n}\n\nfunction getEmbeddedDocument(\n document: TextDocument,\n contents: EmbeddedRegion[],\n languageId: string,\n ignoreAttributeValues: boolean\n): TextDocument {\n let currentPos = 0;\n const oldContent = document.getText();\n let result = \"\";\n let lastSuffix = \"\";\n for (const c of contents) {\n if (c.languageId === languageId && (!ignoreAttributeValues || !c.attributeValue)) {\n result = substituteWithWhitespace(result, currentPos, c.start, oldContent, lastSuffix, getPrefix(c));\n result += updateContent(c, oldContent.slice(c.start, c.end));\n currentPos = c.end;\n lastSuffix = getSuffix(c);\n }\n }\n result = substituteWithWhitespace(result, currentPos, oldContent.length, oldContent, lastSuffix, \"\");\n return TextDocument.create(document.uri, languageId, document.version, result);\n}\n\nfunction getPrefix(c: EmbeddedRegion) {\n if (c.attributeValue) {\n switch (c.languageId) {\n case \"css\":\n return CSS_STYLE_RULE + \"{\";\n }\n }\n return \"\";\n}\nfunction getSuffix(c: EmbeddedRegion) {\n if (c.attributeValue) {\n switch (c.languageId) {\n case \"css\":\n return \"}\";\n case \"javascript\":\n return \";\";\n }\n }\n return \"\";\n}\nfunction updateContent(c: EmbeddedRegion, content: string): string {\n if (!c.attributeValue && c.languageId === \"javascript\") {\n return content.replace(`<!--`, `/* `).replace(`-->`, ` */`);\n }\n if (c.languageId === \"css\") {\n const quoteEscape = /(&quot;|&#34;)/g;\n return content.replace(quoteEscape, (match, _, offset: number) => {\n const spaces = \" \".repeat(match.length - 1);\n const afterChar = content[offset + match.length];\n if (!afterChar || afterChar.includes(\" \")) {\n return `${spaces}\"`;\n }\n return `\"${spaces}`;\n });\n }\n return content;\n}\n\nfunction substituteWithWhitespace(result: string, start: number, end: number, oldContent: string, before: string, after: string) {\n result += before;\n let accumulatedWS = -before.length; // start with a negative value to account for the before string\n for (let index = start; index < end; index++) {\n const ch = oldContent[index];\n if (ch === \"\\n\" || ch === \"\\r\") {\n // only write new lines, skip the whitespace\n accumulatedWS = 0;\n result += ch;\n } else {\n accumulatedWS++;\n }\n }\n result = append(result, \" \", accumulatedWS - after.length);\n result += after;\n return result;\n}\n\nfunction append(result: string, string_: string, n: number): string {\n while (n > 0) {\n if (n & 1) {\n result += string_;\n }\n n >>= 1;\n string_ += string_;\n }\n return result;\n}\n\nfunction getAttributeLanguage(attributeName: string): string | null {\n const match = attributeName.match(/^(style)$|^(on\\w+)$/i);\n if (!match) {\n return null;\n }\n return match[1] ? \"css\" : \"javascript\";\n}\n","/* eslint-disable @typescript-eslint/require-await */\nimport path from \"node:path\";\nimport { Resolver } from \"@staticbolt/core\";\nimport * as vscodeUri from \"vscode-uri\";\n\nimport { getLanguageModelCache } from \"../language-model-cache.ts\";\nimport { FILE_PROTOCOL } from \"./language-modes.ts\";\n\nimport type { LanguageMode } from \"./language-modes.ts\";\nimport type { HTMLDataV1, HTMLDocument, LanguageService, TextDocument } from \"vscode-html-languageservice\";\n\nexport function getHTMLMode(htmlLanguageService: LanguageService): LanguageMode {\n const htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => htmlLanguageService.parseHTMLDocument(document));\n\n return {\n getId() {\n return \"html\";\n },\n\n async doComplete(document, position, documentContext, htmlData) {\n setHtmlDataProviders(htmlLanguageService, htmlData);\n\n const htmlDocument = htmlDocuments.get(document);\n const completionList = await htmlLanguageService.doComplete2(document, position, htmlDocument, documentContext);\n\n for (const item of completionList.items) {\n item.sortText = \"0_\" + item.label;\n }\n\n return completionList;\n },\n\n async doHover(document, position, htmlData) {\n setHtmlDataProviders(htmlLanguageService, htmlData);\n\n return htmlLanguageService.doHover(document, position, htmlDocuments.get(document));\n },\n\n async onDocumentRemoved(document: TextDocument) {\n htmlDocuments.onDocumentRemoved(document);\n },\n\n async findDocumentLinks(document, documentContext, projectRoot) {\n const resolver = new Resolver(projectRoot);\n const documentFs = vscodeUri.URI.parse(document.uri).fsPath;\n const projectRootRelative = path.relative(projectRoot, documentFs);\n\n const links = htmlLanguageService.findDocumentLinks(document, documentContext);\n\n for (const link of links) {\n if (!link.target) continue;\n\n const linkFs = vscodeUri.URI.parse(link.target ?? \"\").fsPath;\n const source = path.relative(path.dirname(documentFs), linkFs);\n\n const resolved = resolver.resolve(source, projectRootRelative);\n if (resolved) {\n link.target = vscodeUri.URI.file(resolved.path).toString();\n }\n }\n\n return links;\n },\n\n dispose() {\n htmlDocuments.dispose();\n },\n };\n}\n\nfunction setHtmlDataProviders(htmlLanguageService: LanguageService, htmlData: HTMLDataV1[]) {\n htmlLanguageService.setDataProviders(false, [\n {\n getId() {\n return FILE_PROTOCOL;\n },\n isApplicable(languageId) {\n return languageId === \"html\";\n },\n provideValues(tag, attribute) {\n const tags = htmlData.flatMap(data => data.tags?.filter(t => t.name === tag) ?? []);\n const attributes = tags.flatMap(t => t.attributes?.filter(a => a.name === attribute) ?? []);\n const globalAttributes = htmlData.flatMap(data => data.globalAttributes?.filter(a => a.name === attribute) ?? []);\n const values = [...globalAttributes, ...attributes].flatMap(a => a.values ?? []);\n return values;\n },\n provideTags() {\n const tags = htmlData.flatMap(data => data.tags ?? []);\n return tags;\n },\n provideAttributes(tag: string) {\n const tags = htmlData.flatMap(data => data.tags?.filter(t => t.name === tag) ?? []);\n const globalAttributes = htmlData.flatMap(data => data.globalAttributes ?? []);\n const attributes = tags.flatMap(t => t.attributes ?? []);\n return [...globalAttributes, ...attributes];\n },\n },\n ]);\n}\n","import vscodeHtml from \"vscode-html-languageservice\";\n\nimport { getLanguageModelCache } from \"../language-model-cache.ts\";\nimport { getDocumentRegions } from \"./embedded-support.ts\";\nimport { getHTMLMode } from \"./html-mode.ts\";\n\nimport type { LanguageModelCache } from \"../language-model-cache.ts\";\nimport type { FileSystemProvider } from \"../requests.ts\";\nimport type { HTMLDocumentRegions } from \"./embedded-support.ts\";\nimport type {\n ClientCapabilities,\n CompletionConfiguration,\n DocumentContext,\n HoverSettings,\n HTMLDataV1,\n IHTMLDataProvider,\n} from \"vscode-html-languageservice\";\nimport type {\n CompletionItem,\n CompletionList,\n DocumentLink,\n Hover,\n Position,\n Range,\n WorkspaceFolder,\n} from \"vscode-languageserver\";\nimport type { TextDocument } from \"vscode-languageserver-textdocument\";\n\nexport interface Settings {\n hover?: HoverSettings;\n autoClosingTags?: boolean;\n completion?: CompletionConfiguration;\n suggest?: CompletionConfiguration;\n}\n\nexport interface Workspace {\n readonly settings: Settings;\n readonly folders: WorkspaceFolder[];\n}\n\nexport interface SemanticTokenData {\n start: Position;\n length: number;\n typeIdx: number;\n modifierSet: number;\n}\n\nexport type CompletionItemData = {\n languageId: string;\n uri: string;\n offset: number;\n};\n\nexport function isCompletionItemData(value: Record<string, unknown>): value is CompletionItemData {\n return value && typeof value.languageId === \"string\" && typeof value.uri === \"string\" && typeof value.offset === \"number\";\n}\n\nexport interface LanguageMode {\n getId(): string;\n doComplete?: (\n document: TextDocument,\n position: Position,\n documentContext: DocumentContext,\n htmlData: HTMLDataV1[]\n ) => Promise<CompletionList>;\n doResolve?: (document: TextDocument, item: CompletionItem) => Promise<CompletionItem>;\n doHover?: (document: TextDocument, position: Position, htmlData: HTMLDataV1[]) => Promise<Hover | null>;\n findDocumentLinks?: (document: TextDocument, documentContext: DocumentContext, projectRoot: string) => Promise<DocumentLink[]>;\n onDocumentRemoved(document: TextDocument): void;\n dispose(): void;\n}\n\nexport interface LanguageModes {\n updateDataProviders(dataProviders: IHTMLDataProvider[]): void;\n getModeAtPosition(document: TextDocument, position: Position): LanguageMode | undefined;\n getModesInRange(document: TextDocument, range: Range): LanguageModeRange[];\n getAllModes(): LanguageMode[];\n getAllModesInDocument(document: TextDocument): LanguageMode[];\n getMode(languageId: string): LanguageMode | undefined;\n onDocumentRemoved(document: TextDocument): void;\n dispose(): void;\n}\n\nexport interface LanguageModeRange extends Range {\n mode: LanguageMode | undefined;\n attributeValue?: boolean;\n}\n\nexport const FILE_PROTOCOL = \"staticbolt-server\";\n\nexport function getLanguageModes(clientCapabilities: ClientCapabilities, requestService: FileSystemProvider): LanguageModes {\n const htmlLanguageService = vscodeHtml.getLanguageService({\n clientCapabilities,\n fileSystemProvider: requestService,\n customDataProviders: [\n {\n getId() {\n return FILE_PROTOCOL;\n },\n isApplicable(languageId) {\n return languageId === \"html\";\n },\n provideValues(tag, attribute) {\n return [{ name: `tag:${tag} attribute:${attribute}` }];\n },\n provideTags() {\n return [{ name: \"staticbolt\", description: \"# staticbolt-description\", attributes: [] }];\n },\n\n provideAttributes(tag: string) {\n if (tag === \"staticbolt\") {\n return [\n {\n name: \"staticbolt-attribute\",\n description: \"# staticbolt-attribute-description\",\n values: [{ name: \"staticbolt-attribute-value\" }],\n },\n ];\n }\n\n return [{ name: \"global-attribute\" }];\n },\n },\n ],\n useDefaultDataProvider: false,\n });\n\n const documentRegions = getLanguageModelCache<HTMLDocumentRegions>(10, 60, document =>\n getDocumentRegions(htmlLanguageService, document)\n );\n\n let modelCaches: LanguageModelCache<unknown>[] = [documentRegions];\n\n let modes = Object.create(null) as { [languageId: string]: LanguageMode };\n modes[\"html\"] = getHTMLMode(htmlLanguageService);\n\n return {\n // eslint-disable-next-line @typescript-eslint/require-await\n async updateDataProviders(dataProviders: IHTMLDataProvider[]): Promise<void> {\n htmlLanguageService.setDataProviders(true, dataProviders);\n },\n\n getModeAtPosition(document: TextDocument, position: Position): LanguageMode | undefined {\n const languageId = documentRegions.get(document).getLanguageAtPosition(position);\n if (languageId) {\n return modes[languageId];\n }\n\n return undefined;\n },\n\n getModesInRange(document: TextDocument, range: Range): LanguageModeRange[] {\n return documentRegions\n .get(document)\n .getLanguageRanges(range)\n .map((r): LanguageModeRange => {\n return {\n start: r.start,\n end: r.end,\n mode: r.languageId ? modes[r.languageId] : undefined,\n attributeValue: r.attributeValue,\n };\n });\n },\n\n getAllModesInDocument(document: TextDocument): LanguageMode[] {\n const result: LanguageMode[] = [];\n for (const languageId of documentRegions.get(document).getLanguagesInDocument()) {\n const mode = modes[languageId];\n if (mode) {\n result.push(mode);\n }\n }\n\n return result;\n },\n\n getAllModes(): LanguageMode[] {\n const result = [];\n for (const languageId in modes) {\n const mode = modes[languageId];\n if (mode) {\n result.push(mode);\n }\n }\n\n return result;\n },\n\n getMode(languageId: string): LanguageMode {\n return modes[languageId];\n },\n\n onDocumentRemoved(document: TextDocument) {\n for (const mc of modelCaches) {\n mc.onDocumentRemoved(document);\n }\n\n for (const mode in modes) {\n modes[mode].onDocumentRemoved(document);\n }\n },\n\n dispose(): void {\n for (const mc of modelCaches) {\n mc.dispose();\n }\n\n modelCaches = [];\n for (const mode in modes) {\n modes[mode].dispose();\n }\n\n modes = {};\n },\n };\n}\n","import { RequestType } from \"vscode-languageserver\";\n\nimport type { RuntimeEnvironment } from \"./html-server.ts\";\nimport type { Connection } from \"vscode-languageserver\";\n\n// Interface\nexport const FsStatRequest = { type: new RequestType<string, FileStat, unknown>(\"fs/stat\") } as const;\n\n// Interface\nexport const FsReadDirectoryRequest = { type: new RequestType<string, [string, FileType][], unknown>(\"fs/readDir\") } as const;\n\nexport const FileType = Object.freeze({\n /** The file type is unknown. */\n Unknown: 0,\n\n /** A regular file. */\n File: 1,\n\n /** A directory. */\n Directory: 2,\n\n /** A symbolic link to a file. */\n SymbolicLink: 64,\n});\n\nexport type FileType = (typeof FileType)[keyof typeof FileType];\n\nexport interface FileStat {\n /** The type of the file, e.g. is a regular file, a directory, or symbolic link to a file. */\n type: FileType;\n\n /** The creation timestamp in milliseconds elapsed since January 1, 1970 00:00:00 UTC. */\n ctime: number;\n\n /** The modification timestamp in milliseconds elapsed since January 1, 1970 00:00:00 UTC. */\n mtime: number;\n\n /** The size in bytes. */\n size: number;\n}\n\nexport interface FileSystemProvider {\n stat(uri: string): Promise<FileStat>;\n readDirectory(uri: string): Promise<[string, FileType][]>;\n}\n\nexport function getFileSystemProvider(\n handledSchemas: string[],\n connection: Connection,\n runtime: RuntimeEnvironment\n): FileSystemProvider {\n const fileFs = runtime.fileFs && handledSchemas.includes(\"file\") ? runtime.fileFs : undefined;\n\n return {\n async stat(uri: string): Promise<FileStat> {\n if (fileFs && uri.startsWith(\"file:\")) {\n return fileFs.stat(uri);\n }\n\n const result = await connection.sendRequest(FsStatRequest.type, uri.toString());\n return result;\n },\n\n readDirectory(uri: string): Promise<[string, FileType][]> {\n if (fileFs && uri.startsWith(\"file:\")) {\n return fileFs.readDirectory(uri);\n }\n\n return connection.sendRequest(FsReadDirectoryRequest.type, uri.toString());\n },\n };\n}\n","export function pushAll<T>(to: T[], from: T[]) {\n if (from) {\n for (const item of from) {\n to.push(item);\n }\n }\n}\n\nexport function contains<T>(array: T[], value: T) {\n return array.includes(value);\n}\n\n/**\n * Like `Array#sort` but always stable. Usually runs a little slower `than Array#sort` so only use this when actually needing\n * stable sort.\n */\nexport function mergeSort<T>(data: T[], compare: (a: T, b: T) => number): T[] {\n _divideAndMerge(data, compare);\n return data;\n}\n\nfunction _divideAndMerge<T>(data: T[], compare: (a: T, b: T) => number): void {\n if (data.length <= 1) {\n // sorted\n return;\n }\n const p = Math.trunc(data.length / 2);\n const left = data.slice(0, p);\n const right = data.slice(p);\n\n _divideAndMerge(left, compare);\n _divideAndMerge(right, compare);\n\n let leftIndex = 0;\n let rightIndex = 0;\n let index = 0;\n while (leftIndex < left.length && rightIndex < right.length) {\n const returnValue = compare(left[leftIndex], right[rightIndex]);\n if (returnValue <= 0) {\n // smaller_equal -> take left to preserve order\n data[index++] = left[leftIndex++];\n } else {\n // greater -> take right\n data[index++] = right[rightIndex++];\n }\n }\n while (leftIndex < left.length) {\n data[index++] = left[leftIndex++];\n }\n while (rightIndex < right.length) {\n data[index++] = right[rightIndex++];\n }\n}\n\nexport function binarySearch<T>(array: T[], key: T, comparator: (op1: T, op2: T) => number): number {\n let low = 0,\n high = array.length - 1;\n\n while (low <= high) {\n const mid = Math.trunc((low + high) / 2);\n const comp = comparator(array[mid], key);\n if (comp < 0) {\n low = mid + 1;\n } else if (comp > 0) {\n high = mid - 1;\n } else {\n return mid;\n }\n }\n\n return -(low + 1);\n}\n","export function getWordAtText(text: string, offset: number, wordDefinition: RegExp): { start: number; length: number } {\n let lineStart = offset;\n while (lineStart > 0 && !isNewlineCharacter(text.codePointAt(lineStart - 1)!)) {\n lineStart--;\n }\n const offsetInLine = offset - lineStart;\n const lineText = text.slice(lineStart);\n\n // make a copy of the regex as to not keep the state\n const flags = wordDefinition.ignoreCase ? \"gi\" : \"g\";\n wordDefinition = new RegExp(wordDefinition.source, flags);\n\n let match = wordDefinition.exec(lineText);\n while (match && match.index + match[0].length < offsetInLine) {\n match = wordDefinition.exec(lineText);\n }\n if (match && match.index <= offsetInLine) {\n return { start: match.index + lineStart, length: match[0].length };\n }\n\n return { start: offset, length: 0 };\n}\n\nexport function startsWith(haystack: string, needle: string): boolean {\n if (haystack.length < needle.length) {\n return false;\n }\n\n // eslint-disable-next-line unicorn/no-for-loop\n for (let index = 0; index < needle.length; index++) {\n if (haystack[index] !== needle[index]) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function endsWith(haystack: string, needle: string): boolean {\n const diff = haystack.length - needle.length;\n if (diff > 0) {\n return haystack.indexOf(needle, diff) === diff;\n }\n\n if (diff === 0) {\n return haystack === needle;\n }\n\n return false;\n}\n\nexport function repeat(value: string, count: number) {\n let s = \"\";\n while (count > 0) {\n if ((count & 1) === 1) {\n s += value;\n }\n value += value;\n count = count >>> 1;\n }\n return s;\n}\n\nexport function isWhitespaceOnly(string_: string) {\n return /^\\s*$/.test(string_);\n}\n\nexport function isEOL(content: string, offset: number) {\n return isNewlineCharacter(content.codePointAt(offset)!);\n}\n\nconst CR = \"\\r\".codePointAt(0);\nconst NL = \"\\n\".codePointAt(0);\nexport function isNewlineCharacter(charCode: number) {\n return charCode === CR || charCode === NL;\n}\n","import * as vscodeUri from \"vscode-uri\";\n\nimport { endsWith, startsWith } from \"../utils/strings.ts\";\n\nimport type { DocumentContext } from \"vscode-css-languageservice\";\nimport type { WorkspaceFolder } from \"vscode-languageserver\";\n\nexport function getDocumentContext(documentUri: string, workspaceFolders: WorkspaceFolder[]): DocumentContext {\n function getRootFolder(): string | undefined {\n for (const folder of workspaceFolders) {\n let folderURI = folder.uri;\n if (!endsWith(folderURI, \"/\")) {\n folderURI = folderURI + \"/\";\n }\n\n if (startsWith(documentUri, folderURI)) {\n return folderURI;\n }\n }\n\n return undefined;\n }\n\n return {\n resolveReference: (reference: string, base = documentUri) => {\n if (/^\\w[\\w\\d+.-]*:/.test(reference)) {\n // starts with a schema\n return reference;\n }\n\n if (reference[0] === \"/\") {\n // resolve absolute path against the current workspace folder\n const folderUri = getRootFolder();\n if (folderUri) {\n return folderUri + reference.slice(1);\n }\n }\n\n const baseUri = vscodeUri.URI.parse(base);\n const baseUriDirectory = baseUri.path.endsWith(\"/\") ? baseUri : vscodeUri.Utils.dirname(baseUri);\n return vscodeUri.Utils.resolvePath(baseUriDirectory, reference).toString(true);\n },\n };\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as vscodeUri from \"vscode-uri\";\n\nexport function findProjectRoot(fileUri: string): string | null {\n let directory = path.dirname(vscodeUri.URI.parse(fileUri).fsPath);\n\n while (true) {\n for (const config of [\".staticbolt.ts\", \".staticbolt.js\"]) {\n if (fs.existsSync(path.join(directory, config))) {\n return directory;\n }\n }\n\n const parent = path.dirname(directory);\n\n // reached fs root, no config found\n if (parent === directory) {\n return null;\n }\n\n directory = parent;\n }\n}\n","import vscode from \"vscode-languageserver\";\n\nimport type { RuntimeEnvironment } from \"../html-server.ts\";\nimport type { CancellationToken, ResponseError } from \"vscode-languageserver\";\n\nexport function formatError(message: string, error: unknown): string {\n if (error instanceof Error) {\n return `${message}: ${error.message}\\n${error.stack}`;\n }\n\n if (typeof error === \"string\") {\n return `${message}: ${error}`;\n }\n\n if (error) {\n return `${message}: ${(error as string).toString()}`;\n }\n\n return message;\n}\n\nexport function runSafe<T>(\n runtime: RuntimeEnvironment,\n function_: () => Thenable<T>,\n errorValue: T,\n errorMessage: string,\n token: CancellationToken\n): Thenable<T | ResponseError<never>> {\n return new Promise<T | ResponseError<never>>(resolve => {\n runtime.timer.setImmediate(() => {\n if (token.isCancellationRequested) {\n resolve(cancelValue());\n return;\n }\n return function_().then(\n result => {\n if (token.isCancellationRequested) {\n resolve(cancelValue());\n return;\n }\n\n resolve(result);\n },\n\n error => {\n console.error(formatError(errorMessage, error));\n resolve(errorValue);\n }\n );\n });\n });\n}\n\nfunction cancelValue<E>() {\n return new vscode.ResponseError<E>(vscode.LSPErrorCodes.RequestCancelled, \"Request cancelled\");\n}\n","import * as vscode from \"vscode-languageserver\";\nimport { TextDocument } from \"vscode-languageserver-textdocument\";\nimport * as vscodeUri from \"vscode-uri\";\n\nimport { ConfigManager } from \"./helpers/config-loader.ts\";\nimport { findStaticboltProjects } from \"./helpers/find-projects.ts\";\nimport { getLanguageModes } from \"./modes/language-modes.ts\";\nimport { getFileSystemProvider } from \"./requests.ts\";\nimport { pushAll } from \"./utils/arrays.ts\";\nimport { getDocumentContext } from \"./utils/document-context.ts\";\nimport { findProjectRoot } from \"./utils/find-project-root.ts\";\nimport { runSafe } from \"./utils/runner.ts\";\n\nimport type { CompletionItemData, LanguageModes, Settings } from \"./modes/language-modes.ts\";\nimport type { FileSystemProvider } from \"./requests.ts\";\nimport type { Connection, Disposable, InitializeParams, WorkspaceFolder } from \"vscode-languageserver\";\n\nexport interface RuntimeEnvironment {\n fileFs?: FileSystemProvider;\n\n configureHttpRequests?(proxy: string | undefined, strictSSL: boolean): void;\n\n readonly timer: {\n setImmediate(callback: (...arguments_: unknown[]) => void, ...arguments_: unknown[]): Disposable;\n setTimeout(callback: (...arguments_: unknown[]) => void, ms: number, ...arguments_: unknown[]): Disposable;\n };\n}\n\nexport interface CustomDataRequestService {\n getContent(uri: string): Promise<string>;\n}\n\nexport function startServer(connection: Connection, runtime: RuntimeEnvironment) {\n // Create a text document manager.\n const documents = new vscode.TextDocuments(TextDocument);\n // Make the text document manager listen on the connection\n // for open, change and close text document events\n documents.listen(connection);\n\n let lspSearchRoots: WorkspaceFolder[] = [];\n let workspaceFolders: WorkspaceFolder[] = [];\n let configManager: ConfigManager;\n\n let languageModes: LanguageModes;\n\n const documentSettings: { [key: string]: Thenable<Settings> } = {};\n\n // remove document settings on close\n documents.onDidClose(document => {\n delete documentSettings[document.document.uri];\n });\n\n connection.onInitialize((parameters: InitializeParams) => {\n if (Array.isArray(parameters.workspaceFolders)) {\n lspSearchRoots = parameters.workspaceFolders;\n } else {\n lspSearchRoots = [];\n if (parameters.rootPath) {\n lspSearchRoots.push({ name: \"\", uri: vscodeUri.URI.file(parameters.rootPath).toString() });\n }\n }\n\n workspaceFolders = findStaticboltProjects(lspSearchRoots);\n connection.console.log(\n `[staticbolt] discovered projects:\\n` + workspaceFolders.map(f => ` - [${f.name}]: ${f.uri}`).join(\"\\n\")\n );\n\n const fileSystemProvider = getFileSystemProvider([\"file\"], connection, runtime);\n languageModes = getLanguageModes(parameters.capabilities, fileSystemProvider);\n\n configManager = new ConfigManager(connection.console);\n\n documents.onDidClose(document => {\n languageModes.onDocumentRemoved(document.document);\n });\n\n connection.onShutdown(() => {\n languageModes.dispose();\n configManager.dispose();\n });\n\n return {\n capabilities: {\n textDocumentSync: vscode.TextDocumentSyncKind.Incremental,\n completionProvider: {\n resolveProvider: true,\n triggerCharacters: [\".\", \":\", \"<\", '\"', \"=\", \"/\"],\n },\n hoverProvider: true,\n documentLinkProvider: { resolveProvider: false },\n },\n };\n });\n\n connection.onInitialized(() => {});\n\n connection.onCompletion(async (textDocumentPosition, token) => {\n return runSafe(\n runtime,\n async () => {\n const projectRoot = findProjectRoot(textDocumentPosition.textDocument.uri);\n if (!projectRoot) return null;\n\n const document = documents.get(textDocumentPosition.textDocument.uri);\n if (!document) return null;\n\n const mode = languageModes.getModeAtPosition(document, textDocumentPosition.position);\n if (!mode?.doComplete) return { isIncomplete: true, items: [] };\n\n const config = await configManager.get(projectRoot);\n if (!config) return { isIncomplete: true, items: [] };\n\n const documentContext = getDocumentContext(document.uri, workspaceFolders);\n return mode.doComplete(document, textDocumentPosition.position, documentContext, configManager.lspHtmlData);\n },\n null,\n `Error while computing completions for ${textDocumentPosition.textDocument.uri}`,\n token\n );\n });\n\n connection.onCompletionResolve((item, token) => {\n return runSafe(\n runtime,\n async () => {\n const data = item.data as Record<string, unknown>;\n if (!isCompletionItemData(data)) return item;\n\n const document = documents.get(data.uri);\n if (!document) return item;\n\n const mode = languageModes.getMode(data.languageId);\n if (!mode?.doResolve) return item;\n\n return mode.doResolve(document, item);\n },\n item,\n `Error while resolving completion proposal`,\n token\n );\n });\n\n connection.onHover((textDocumentPosition, token) => {\n return runSafe(\n runtime,\n async () => {\n const projectRoot = findProjectRoot(textDocumentPosition.textDocument.uri);\n if (!projectRoot) return null;\n\n const document = documents.get(textDocumentPosition.textDocument.uri);\n if (!document) return null;\n\n const mode = languageModes.getModeAtPosition(document, textDocumentPosition.position);\n if (!mode?.doHover) return null;\n\n const config = await configManager.get(projectRoot);\n if (!config) return null;\n\n return mode.doHover(document, textDocumentPosition.position, configManager.lspHtmlData);\n },\n null,\n `Error while computing hover for ${textDocumentPosition.textDocument.uri}`,\n token\n );\n });\n\n connection.onDocumentLinks((documentLinkParameter, token) => {\n return runSafe(\n runtime,\n async () => {\n const projectRoot = findProjectRoot(documentLinkParameter.textDocument.uri);\n if (!projectRoot) return null;\n\n const document = documents.get(documentLinkParameter.textDocument.uri);\n if (!document) return [];\n\n const links: vscode.DocumentLink[] = [];\n\n const documentContext = getDocumentContext(document.uri, workspaceFolders);\n for (const mode of languageModes.getAllModesInDocument(document)) {\n if (mode.findDocumentLinks) {\n pushAll(links, await mode.findDocumentLinks(document, documentContext, projectRoot));\n }\n }\n\n return links;\n },\n [],\n `Error while document links for ${documentLinkParameter.textDocument.uri}`,\n token\n );\n });\n\n // Listen on the connection\n connection.listen();\n}\n\nexport function isCompletionItemData(value: Record<string, unknown>): value is CompletionItemData {\n return value && typeof value.languageId === \"string\" && typeof value.uri === \"string\" && typeof value.offset === \"number\";\n}\n","import * as fs from \"node:fs\";\nimport * as vscodeUri from \"vscode-uri\";\n\nimport type { FileSystemProvider } from \"../requests.ts\";\n\nconst FileType = Object.freeze({\n /** The file type is unknown. */\n Unknown: 0,\n /** A regular file. */\n File: 1,\n /** A directory. */\n Directory: 2,\n /** A symbolic link to a file. */\n SymbolicLink: 64,\n});\n\ntype FileType = (typeof FileType)[keyof typeof FileType];\n\nexport function getNodeFileFS(): FileSystemProvider {\n function ensureFileUri(location: string) {\n if (!location.startsWith(\"file:\")) {\n throw new Error(\"fileSystemProvider can only handle file URLs\");\n }\n }\n return {\n stat(location: string) {\n ensureFileUri(location);\n return new Promise((c, error_) => {\n const uri = vscodeUri.URI.parse(location);\n fs.stat(uri.fsPath, (error, stats) => {\n if (error) {\n return error.code === \"ENOENT\" ? c({ type: FileType.Unknown, ctime: -1, mtime: -1, size: -1 }) : error_(error);\n }\n\n let type: FileType = FileType.Unknown;\n if (stats.isFile()) {\n type = FileType.File;\n } else if (stats.isDirectory()) {\n type = FileType.Directory;\n } else if (stats.isSymbolicLink()) {\n type = FileType.SymbolicLink;\n }\n\n c({\n type,\n ctime: stats.ctime.getTime(),\n mtime: stats.mtime.getTime(),\n size: stats.size,\n });\n });\n });\n },\n readDirectory(location: string) {\n ensureFileUri(location);\n return new Promise((c, error_) => {\n const path = vscodeUri.URI.parse(location).fsPath;\n\n fs.readdir(path, { withFileTypes: true }, (error, children) => {\n if (error) {\n return error_(error);\n }\n c(\n children.map(stat => {\n if (stat.isSymbolicLink()) {\n return [stat.name, FileType.SymbolicLink];\n } else if (stat.isDirectory()) {\n return [stat.name, FileType.Directory];\n } else if (stat.isFile()) {\n return [stat.name, FileType.File];\n } else {\n return [stat.name, FileType.Unknown];\n }\n })\n );\n });\n });\n },\n };\n}\n","import * as vs from \"vscode-languageserver/node\";\n\nimport { startServer } from \"./html-server.ts\";\nimport { getNodeFileFS } from \"./utils/node-fs.ts\";\nimport { formatError } from \"./utils/runner.ts\";\n\nimport type { RuntimeEnvironment } from \"./html-server.ts\";\nimport type { Connection, Disposable } from \"vscode-languageserver/node\";\n\n// Create a connection for the server.\nconst connection: Connection = vs.createConnection();\n\nconsole.log = connection.console.log.bind(connection.console);\nconsole.error = connection.console.error.bind(connection.console);\n\nprocess.on(\"unhandledRejection\", (error: unknown) => {\n connection.console.error(formatError(`Unhandled exception`, error));\n});\n\nconst runtime: RuntimeEnvironment = {\n timer: {\n setImmediate(callback: (...arguments_: unknown[]) => void, ...arguments_: unknown[]): Disposable {\n const handle = setImmediate(callback, ...arguments_);\n return { dispose: () => clearImmediate(handle) };\n },\n\n setTimeout(callback: (...arguments_: unknown[]) => void, ms: number, ...arguments_: unknown[]): Disposable {\n const handle = setTimeout(callback, ms, ...arguments_);\n return { dispose: () => clearTimeout(handle) };\n },\n },\n\n fileFs: getNodeFileFS(),\n};\n\nconnection.console.log(\"[staticbolt] starting server\");\nstartServer(connection, runtime);\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["path","FileType","path","vscode"],"sources":["../src/helpers/config-loader.ts","../src/helpers/find-projects.ts","../src/language-model-cache.ts","../src/modes/embedded-support.ts","../src/modes/html-mode.ts","../src/modes/language-modes.ts","../src/requests.ts","../src/utils/arrays.ts","../src/utils/strings.ts","../src/utils/document-context.ts","../src/utils/find-project-root.ts","../src/utils/runner.ts","../src/html-server.ts","../src/utils/node-fs.ts","../src/index.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\";\nimport { watch, type FSWatcher } from \"node:fs\";\nimport { access, constants } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport type { AppConfig } from \"@staticbolt/core\";\nimport type { HTMLDataV1 } from \"vscode-html-languageservice\";\nimport type { MarkupContent, RemoteConsole } from \"vscode-languageserver\";\n\nexport type StaticBoltConfig = AppConfig;\n\nexport interface ConfigLoaderEvents {\n change: [config: StaticBoltConfig];\n error: [err: Error];\n}\n\nconst CONFIG_CANDIDATES = [\".staticbolt.ts\", \".staticbolt.js\"] as const;\n\nasync function findConfigFile(workspaceRoot: string): Promise<string | null> {\n for (const name of CONFIG_CANDIDATES) {\n const full = join(workspaceRoot, name);\n\n try {\n await access(full, constants.R_OK);\n return full;\n } catch {\n // not found or not readable — try next\n }\n }\n\n return null;\n}\n\nasync function importFresh(absolutePath: string): Promise<StaticBoltConfig> {\n const url = `${pathToFileURL(absolutePath).href}?t=${Date.now()}`;\n const module_ = (await import(url)) as { default: StaticBoltConfig };\n\n if (!(\"default\" in module_)) {\n throw new Error(`Config file \"${absolutePath}\" has no default export. Use \\`export default { … }\\`.`);\n }\n\n return module_.default;\n}\n\n// eslint-disable-next-line unicorn/prefer-event-target\nexport class ConfigLoader extends EventEmitter<ConfigLoaderEvents> {\n private readonly workspaceRoot: string;\n private configPath: string | null = null;\n private watcher: FSWatcher | null = null;\n private current: StaticBoltConfig | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly DEBOUNCE_MS = 150;\n\n constructor(workspaceRoot: string) {\n super();\n this.workspaceRoot = workspaceRoot;\n }\n\n /** Start watching. Resolves with the initial config (or null if absent). */\n async start(): Promise<StaticBoltConfig | null> {\n this.configPath = await findConfigFile(this.workspaceRoot);\n\n if (!this.configPath) {\n return null;\n }\n\n await this.load();\n this.watch(this.configPath);\n return this.current;\n }\n\n /** Stop watching and release all resources. */\n dispose(): void {\n if (this.debounceTimer !== null) {\n clearTimeout(this.debounceTimer);\n }\n this.watcher?.close();\n this.watcher = null;\n }\n\n /** The last successfully loaded config, or null if none loaded yet. */\n get config(): StaticBoltConfig | null {\n return this.current;\n }\n\n private async load(): Promise<void> {\n if (!this.configPath) return;\n\n try {\n this.current = await importFresh(this.configPath);\n this.emit(\"change\", this.current);\n } catch (error) {\n this.emit(\"error\", error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private watch(configPath: string): void {\n this.watcher = watch(configPath, { persistent: false }, event => {\n if (event === \"rename\" || event === \"change\") {\n this.scheduleReload();\n }\n });\n\n this.watcher.on(\"error\", error => this.emit(\"error\", error));\n }\n\n private scheduleReload(): void {\n if (this.debounceTimer !== null) {\n clearTimeout(this.debounceTimer);\n }\n\n this.debounceTimer = setTimeout(async () => {\n this.debounceTimer = null;\n\n // The file might have been atomically replaced (Vim, VS Code safe-write).\n // Re-check existence; if it disappeared we just bail.\n if (!this.configPath) return;\n\n try {\n await access(this.configPath, constants.R_OK);\n } catch {\n this.emit(\"error\", new Error(`Config file was removed: ${this.configPath}`));\n return;\n }\n\n await this.load();\n }, this.DEBOUNCE_MS);\n }\n}\n\nexport class ConfigManager {\n private readonly console: RemoteConsole;\n readonly configs = new Map<string, ConfigLoader>();\n lspHtmlData: HTMLDataV1[] = [];\n\n constructor(console: RemoteConsole) {\n this.console = console;\n }\n\n async get(workspaceRoot: string): Promise<AppConfig | null> {\n const configLoader = this.configs.get(workspaceRoot);\n if (configLoader) {\n if (!configLoader.config) {\n this.configs.delete(workspaceRoot);\n return null;\n }\n\n return configLoader.config;\n }\n\n const newConfigLoader = new ConfigLoader(workspaceRoot);\n this.configs.set(workspaceRoot, newConfigLoader);\n\n newConfigLoader.on(\"error\", error => {\n this.console.error(`Failed to load config file: ${error.message}`);\n });\n\n newConfigLoader.on(\"change\", async config => {\n await this.collectData(config);\n });\n\n await newConfigLoader.start();\n\n if (!newConfigLoader.config) {\n return null;\n }\n\n return newConfigLoader.config;\n }\n\n dispose(): void {\n for (const configLoader of this.configs.values()) {\n configLoader.dispose();\n }\n }\n\n private async collectData(config: StaticBoltConfig) {\n this.lspHtmlData = [];\n\n const plugins = config.plugins ?? [];\n\n for (const pluginOrArray of plugins) {\n const plugins = Array.isArray(pluginOrArray) ? pluginOrArray : [pluginOrArray];\n\n for (const plugin of plugins) {\n if (!plugin.lspHtmlData) {\n continue;\n }\n\n const htmlData = await plugin.lspHtmlData();\n if (htmlData) {\n htmlDataInjectPluginName(htmlData, plugin.name);\n this.lspHtmlData.push(htmlData);\n }\n }\n }\n }\n}\n\nfunction htmlDataInjectPluginName(htmlData: HTMLDataV1, pluginName: string) {\n const tags = htmlData.tags ?? [];\n for (const tag of tags) {\n tag.description = replaceDescription(tag.description, pluginName);\n\n const attributes = tag.attributes ?? [];\n for (const attribute of attributes) {\n attribute.description = replaceDescription(attribute.description, pluginName);\n }\n }\n\n const globalAttributes = htmlData.globalAttributes ?? [];\n for (const attribute of globalAttributes) {\n attribute.description = replaceDescription(attribute.description, pluginName);\n }\n}\n\nfunction replaceDescription(description: string | MarkupContent | undefined, pluginName: string) {\n const info = `_Provided by **staticbolt** \\`${pluginName}\\` plugin._`;\n\n if (!description) {\n return info;\n }\n\n if (typeof description === \"string\") {\n if (description.includes(info)) {\n return description;\n }\n\n return `${description}\\n\\n${info}`;\n }\n\n if (description.value.includes(info)) {\n return description;\n }\n\n description.value = `${description.value}\\n\\n${info}`;\n return description;\n}\n","import { globSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as vscodeUri from \"vscode-uri\";\n\nimport type { WorkspaceFolder } from \"vscode-languageserver\";\n\nexport function findStaticboltProjects(searchRoots: WorkspaceFolder[]): WorkspaceFolder[] {\n const results: WorkspaceFolder[] = [];\n\n for (const root of searchRoots) {\n const rootPath = vscodeUri.URI.parse(root.uri).fsPath;\n\n const configs = globSync(\"**/.staticbolt.{ts,js}\", { cwd: rootPath, exclude: [\"**/node_modules/**\", \"**/.git/**\"] });\n\n for (const configPath of configs) {\n const absDirectory = path.join(rootPath, path.dirname(configPath));\n const projectUri = vscodeUri.URI.file(absDirectory).toString();\n results.push({ name: path.basename(absDirectory), uri: projectUri });\n }\n }\n\n return results;\n}\n","import type { TextDocument } from \"vscode-html-languageservice\";\n\nexport interface LanguageModelCache<T> {\n get(document: TextDocument): T;\n onDocumentRemoved(document: TextDocument): void;\n dispose(): void;\n}\n\nexport function getLanguageModelCache<T>(\n maxEntries: number,\n cleanupIntervalTimeInSec: number,\n parse: (document: TextDocument) => T\n): LanguageModelCache<T> {\n let languageModels: { [uri: string]: { version: number; languageId: string; cTime: number; languageModel: T } } = {};\n let nModels = 0;\n\n let cleanupInterval: NodeJS.Timeout | undefined;\n\n if (cleanupIntervalTimeInSec > 0) {\n cleanupInterval = setInterval(() => {\n const cutoffTime = Date.now() - cleanupIntervalTimeInSec * 1000;\n const uris = Object.keys(languageModels);\n\n for (const uri of uris) {\n const languageModelInfo = languageModels[uri];\n if (languageModelInfo.cTime < cutoffTime) {\n delete languageModels[uri];\n nModels--;\n }\n }\n }, cleanupIntervalTimeInSec * 1000);\n }\n\n return {\n get(document: TextDocument): T {\n const version = document.version;\n const languageId = document.languageId;\n const languageModelInfo = languageModels[document.uri];\n\n if (languageModelInfo && languageModelInfo.version === version && languageModelInfo.languageId === languageId) {\n languageModelInfo.cTime = Date.now();\n return languageModelInfo.languageModel;\n }\n\n const languageModel = parse(document);\n languageModels[document.uri] = { languageModel, version, languageId, cTime: Date.now() };\n if (!languageModelInfo) {\n nModels++;\n }\n\n if (nModels === maxEntries) {\n let oldestTime = Number.MAX_VALUE;\n let oldestUri = null;\n\n for (const uri in languageModels) {\n const languageModelInfo = languageModels[uri];\n if (languageModelInfo.cTime < oldestTime) {\n oldestUri = uri;\n oldestTime = languageModelInfo.cTime;\n }\n }\n\n if (oldestUri) {\n delete languageModels[oldestUri];\n nModels--;\n }\n }\n\n return languageModel;\n },\n\n onDocumentRemoved(document: TextDocument) {\n const uri = document.uri;\n if (Object.hasOwn(languageModels, uri)) {\n delete languageModels[uri];\n nModels--;\n }\n },\n\n dispose() {\n if (cleanupInterval === undefined) {\n return;\n }\n\n clearInterval(cleanupInterval);\n cleanupInterval = undefined;\n languageModels = {};\n nModels = 0;\n },\n };\n}\n","import vscodeHtml from \"vscode-html-languageservice\";\nimport { TextDocument } from \"vscode-languageserver-textdocument\";\n\nimport type { LanguageService, Range } from \"vscode-html-languageservice\";\n\nexport interface LanguageRange extends Range {\n languageId: string | undefined;\n attributeValue?: boolean;\n}\n\nexport interface HTMLDocumentRegions {\n getEmbeddedDocument(languageId: string, shouldIgnoreAttributeValues?: boolean): TextDocument;\n getLanguageRanges(range: Range): LanguageRange[];\n getLanguageAtPosition(position: Position): string | undefined;\n getLanguagesInDocument(): string[];\n getImportedScripts(): string[];\n}\n\nconst CSS_STYLE_RULE = \"__\";\nconst TokenType = vscodeHtml.TokenType;\nconst Position = vscodeHtml.Position;\ntype Position = vscodeHtml.Position;\n\ninterface EmbeddedRegion {\n languageId: string | undefined;\n start: number;\n end: number;\n attributeValue?: boolean;\n}\n\nexport function getDocumentRegions(languageService: LanguageService, document: TextDocument): HTMLDocumentRegions {\n const regions: EmbeddedRegion[] = [];\n const scanner = languageService.createScanner(document.getText());\n let lastTagName: string = \"\";\n let lastAttributeName: string | null = null;\n let languageIdFromType: string | undefined;\n const importedScripts: string[] = [];\n\n let token = scanner.scan();\n\n while (token !== TokenType.EOS) {\n switch (token) {\n case TokenType.StartTag: {\n lastTagName = scanner.getTokenText();\n lastAttributeName = null;\n languageIdFromType = \"javascript\";\n break;\n }\n case TokenType.Styles: {\n regions.push({ languageId: \"css\", start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });\n break;\n }\n case TokenType.Script: {\n regions.push({ languageId: languageIdFromType, start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });\n break;\n }\n case TokenType.AttributeName: {\n lastAttributeName = scanner.getTokenText();\n break;\n }\n case TokenType.AttributeValue: {\n if (lastAttributeName === \"src\" && lastTagName.toLowerCase() === \"script\") {\n let value = scanner.getTokenText();\n if (value[0] === \"'\" || value[0] === '\"') {\n value = value.slice(1, -1);\n }\n importedScripts.push(value);\n } else if (lastAttributeName === \"type\" && lastTagName.toLowerCase() === \"script\") {\n const token = scanner.getTokenText();\n if (/[\"'](module|(text|application)\\/(java|ecma)script|text\\/babel)[\"']/.test(token) || token === \"module\") {\n languageIdFromType = \"javascript\";\n } else if (/[\"']text\\/typescript[\"']/.test(token)) {\n languageIdFromType = \"typescript\";\n } else {\n languageIdFromType = undefined;\n }\n } else {\n const attributeLanguageId = getAttributeLanguage(lastAttributeName!);\n if (attributeLanguageId) {\n let start = scanner.getTokenOffset();\n let end = scanner.getTokenEnd();\n const firstChar = document.getText()[start];\n if (firstChar === \"'\" || firstChar === '\"') {\n start++;\n end--;\n }\n regions.push({ languageId: attributeLanguageId, start, end, attributeValue: true });\n }\n }\n lastAttributeName = null;\n break;\n }\n }\n token = scanner.scan();\n }\n return {\n getLanguageRanges: (range: Range) => getLanguageRanges(document, regions, range),\n getEmbeddedDocument: (languageId: string, shouldIgnoreAttributeValues: boolean) =>\n getEmbeddedDocument(document, regions, languageId, shouldIgnoreAttributeValues),\n getLanguageAtPosition: (position: Position) => getLanguageAtPosition(document, regions, position),\n getLanguagesInDocument: () => getLanguagesInDocument(document, regions),\n getImportedScripts: () => importedScripts,\n };\n}\n\nfunction getLanguageRanges(document: TextDocument, regions: EmbeddedRegion[], range: Range): LanguageRange[] {\n const result: LanguageRange[] = [];\n let currentPos = range ? range.start : Position.create(0, 0);\n let currentOffset = range ? document.offsetAt(range.start) : 0;\n const endOffset = range ? document.offsetAt(range.end) : document.getText().length;\n for (const region of regions) {\n if (!(region.end > currentOffset && region.start < endOffset)) {\n continue;\n }\n\n const start = Math.max(region.start, currentOffset);\n const startPos = document.positionAt(start);\n if (currentOffset < region.start) {\n result.push({\n start: currentPos,\n end: startPos,\n languageId: \"html\",\n });\n }\n const end = Math.min(region.end, endOffset);\n const endPos = document.positionAt(end);\n if (end > region.start) {\n result.push({\n start: startPos,\n end: endPos,\n languageId: region.languageId,\n attributeValue: region.attributeValue,\n });\n }\n currentOffset = end;\n currentPos = endPos;\n }\n if (currentOffset < endOffset) {\n const endPos = range ? range.end : document.positionAt(endOffset);\n result.push({\n start: currentPos,\n end: endPos,\n languageId: \"html\",\n });\n }\n return result;\n}\n\nfunction getLanguagesInDocument(_document: TextDocument, regions: EmbeddedRegion[]): string[] {\n const result: string[] = [];\n\n for (const region of regions) {\n if (!(region.languageId && !result.includes(region.languageId))) {\n continue;\n }\n\n result.push(region.languageId);\n if (result.length === 3) {\n return result;\n }\n }\n\n result.push(\"html\");\n\n return result;\n}\n\nfunction getLanguageAtPosition(document: TextDocument, regions: EmbeddedRegion[], position: Position): string | undefined {\n const offset = document.offsetAt(position);\n for (const region of regions) {\n if (region.start <= offset) {\n if (offset <= region.end) {\n return region.languageId;\n }\n } else {\n break;\n }\n }\n return \"html\";\n}\n\nfunction getEmbeddedDocument(\n document: TextDocument,\n contents: EmbeddedRegion[],\n languageId: string,\n shouldIgnoreAttributeValues: boolean\n): TextDocument {\n let currentPos = 0;\n const oldContent = document.getText();\n let result = \"\";\n let lastSuffix = \"\";\n for (const c of contents) {\n if (!(c.languageId === languageId && (!shouldIgnoreAttributeValues || !c.attributeValue))) {\n continue;\n }\n\n result = substituteWithWhitespace(result, currentPos, c.start, oldContent, lastSuffix, getPrefix(c));\n result += updateContent(c, oldContent.slice(c.start, c.end));\n currentPos = c.end;\n lastSuffix = getSuffix(c);\n }\n result = substituteWithWhitespace(result, currentPos, oldContent.length, oldContent, lastSuffix, \"\");\n return TextDocument.create(document.uri, languageId, document.version, result);\n}\n\nfunction getPrefix(c: EmbeddedRegion) {\n if (c.attributeValue) {\n switch (c.languageId) {\n case \"css\": {\n return CSS_STYLE_RULE + \"{\";\n }\n }\n }\n return \"\";\n}\nfunction getSuffix(c: EmbeddedRegion) {\n if (c.attributeValue) {\n switch (c.languageId) {\n case \"css\": {\n return \"}\";\n }\n case \"javascript\": {\n return \";\";\n }\n }\n }\n return \"\";\n}\nfunction updateContent(c: EmbeddedRegion, content: string): string {\n if (!c.attributeValue && c.languageId === \"javascript\") {\n return content.replace(`<!--`, `/* `).replace(`-->`, ` */`);\n }\n if (c.languageId === \"css\") {\n const quoteEscape = /(&quot;|&#34;)/g;\n return content.replace(quoteEscape, (match, _, offset: number) => {\n const spaces = \" \".repeat(match.length - 1);\n const afterChar = content[offset + match.length];\n if (!afterChar || afterChar.includes(\" \")) {\n return `${spaces}\"`;\n }\n return `\"${spaces}`;\n });\n }\n return content;\n}\n\nfunction substituteWithWhitespace(result: string, start: number, end: number, oldContent: string, before: string, after: string) {\n result += before;\n let accumulatedWS = -before.length; // start with a negative value to account for the before string\n for (let index = start; index < end; index++) {\n const ch = oldContent[index];\n if (ch === \"\\n\" || ch === \"\\r\") {\n // only write new lines, skip the whitespace\n accumulatedWS = 0;\n result += ch;\n } else {\n accumulatedWS++;\n }\n }\n result = append(result, \" \", accumulatedWS - after.length);\n result += after;\n return result;\n}\n\nfunction append(result: string, string_: string, n: number): string {\n while (n > 0) {\n if (n & 1) {\n result += string_;\n }\n n >>= 1;\n string_ += string_;\n }\n return result;\n}\n\nfunction getAttributeLanguage(attributeName: string): string | null {\n const match = attributeName.match(/^(style)$|^(on\\w+)$/i);\n if (!match) {\n return null;\n }\n return match[1] ? \"css\" : \"javascript\";\n}\n","/* eslint-disable @typescript-eslint/require-await */\nimport path from \"node:path\";\nimport { Resolver } from \"@staticbolt/core\";\nimport * as vscodeUri from \"vscode-uri\";\n\nimport { getLanguageModelCache } from \"../language-model-cache.ts\";\nimport { FILE_PROTOCOL } from \"./language-modes.ts\";\n\nimport type { LanguageMode } from \"./language-modes.ts\";\nimport type { HTMLDataV1, HTMLDocument, LanguageService, TextDocument } from \"vscode-html-languageservice\";\n\nexport function getHTMLMode(htmlLanguageService: LanguageService): LanguageMode {\n const htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => htmlLanguageService.parseHTMLDocument(document));\n\n return {\n getId() {\n return \"html\";\n },\n\n async doComplete(document, position, documentContext, htmlData) {\n setHtmlDataProviders(htmlLanguageService, htmlData);\n\n const htmlDocument = htmlDocuments.get(document);\n const completionList = await htmlLanguageService.doComplete2(document, position, htmlDocument, documentContext);\n\n for (const item of completionList.items) {\n item.sortText = \"0_\" + item.label;\n }\n\n return completionList;\n },\n\n async doHover(document, position, htmlData) {\n setHtmlDataProviders(htmlLanguageService, htmlData);\n\n return htmlLanguageService.doHover(document, position, htmlDocuments.get(document));\n },\n\n async onDocumentRemoved(document: TextDocument) {\n htmlDocuments.onDocumentRemoved(document);\n },\n\n async findDocumentLinks(document, documentContext, projectRoot) {\n const resolver = new Resolver(projectRoot);\n const documentFs = vscodeUri.URI.parse(document.uri).fsPath;\n const projectRootRelative = path.relative(projectRoot, documentFs);\n\n const links = htmlLanguageService.findDocumentLinks(document, documentContext);\n\n for (const link of links) {\n if (!link.target) continue;\n\n const linkFs = vscodeUri.URI.parse(link.target ?? \"\").fsPath;\n const source = path.relative(path.dirname(documentFs), linkFs);\n\n const resolved = resolver.resolve(source, projectRootRelative);\n if (resolved) {\n link.target = vscodeUri.URI.file(resolved.path).toString();\n }\n }\n\n return links;\n },\n\n dispose() {\n htmlDocuments.dispose();\n },\n };\n}\n\nfunction setHtmlDataProviders(htmlLanguageService: LanguageService, htmlData: HTMLDataV1[]) {\n htmlLanguageService.setDataProviders(false, [\n {\n getId() {\n return FILE_PROTOCOL;\n },\n isApplicable(languageId) {\n return languageId === \"html\";\n },\n provideValues(tag, attribute) {\n const tags = htmlData.flatMap(data => data.tags?.filter(t => t.name === tag) ?? []);\n const attributes = tags.flatMap(t => t.attributes?.filter(a => a.name === attribute) ?? []);\n const globalAttributes = htmlData.flatMap(data => data.globalAttributes?.filter(a => a.name === attribute) ?? []);\n const values = [...globalAttributes, ...attributes].flatMap(a => a.values ?? []);\n return values;\n },\n provideTags() {\n const tags = htmlData.flatMap(data => data.tags ?? []);\n return tags;\n },\n provideAttributes(tag: string) {\n const tags = htmlData.flatMap(data => data.tags?.filter(t => t.name === tag) ?? []);\n const globalAttributes = htmlData.flatMap(data => data.globalAttributes ?? []);\n const attributes = tags.flatMap(t => t.attributes ?? []);\n return [...globalAttributes, ...attributes];\n },\n },\n ]);\n}\n","import vscodeHtml from \"vscode-html-languageservice\";\n\nimport { getLanguageModelCache } from \"../language-model-cache.ts\";\nimport { getDocumentRegions } from \"./embedded-support.ts\";\nimport { getHTMLMode } from \"./html-mode.ts\";\n\nimport type { LanguageModelCache } from \"../language-model-cache.ts\";\nimport type { FileSystemProvider } from \"../requests.ts\";\nimport type { HTMLDocumentRegions } from \"./embedded-support.ts\";\nimport type {\n ClientCapabilities,\n CompletionConfiguration,\n DocumentContext,\n HoverSettings,\n HTMLDataV1,\n IHTMLDataProvider,\n} from \"vscode-html-languageservice\";\nimport type {\n CompletionItem,\n CompletionList,\n DocumentLink,\n Hover,\n Position,\n Range,\n WorkspaceFolder,\n} from \"vscode-languageserver\";\nimport type { TextDocument } from \"vscode-languageserver-textdocument\";\n\nexport interface Settings {\n hover?: HoverSettings;\n autoClosingTags?: boolean;\n completion?: CompletionConfiguration;\n suggest?: CompletionConfiguration;\n}\n\nexport interface Workspace {\n readonly settings: Settings;\n readonly folders: WorkspaceFolder[];\n}\n\nexport interface SemanticTokenData {\n start: Position;\n length: number;\n typeIdx: number;\n modifierSet: number;\n}\n\nexport type CompletionItemData = {\n languageId: string;\n uri: string;\n offset: number;\n};\n\nexport function isCompletionItemData(value: Record<string, unknown>): value is CompletionItemData {\n return value && typeof value.languageId === \"string\" && typeof value.uri === \"string\" && typeof value.offset === \"number\";\n}\n\nexport interface LanguageMode {\n getId(): string;\n doComplete?: (\n document: TextDocument,\n position: Position,\n documentContext: DocumentContext,\n htmlData: HTMLDataV1[]\n ) => Promise<CompletionList>;\n doResolve?: (document: TextDocument, item: CompletionItem) => Promise<CompletionItem>;\n doHover?: (document: TextDocument, position: Position, htmlData: HTMLDataV1[]) => Promise<Hover | null>;\n findDocumentLinks?: (document: TextDocument, documentContext: DocumentContext, projectRoot: string) => Promise<DocumentLink[]>;\n onDocumentRemoved(document: TextDocument): void;\n dispose(): void;\n}\n\nexport interface LanguageModes {\n updateDataProviders(dataProviders: IHTMLDataProvider[]): void;\n getModeAtPosition(document: TextDocument, position: Position): LanguageMode | undefined;\n getModesInRange(document: TextDocument, range: Range): LanguageModeRange[];\n getAllModes(): LanguageMode[];\n getAllModesInDocument(document: TextDocument): LanguageMode[];\n getMode(languageId: string): LanguageMode | undefined;\n onDocumentRemoved(document: TextDocument): void;\n dispose(): void;\n}\n\nexport interface LanguageModeRange extends Range {\n mode: LanguageMode | undefined;\n attributeValue?: boolean;\n}\n\nexport const FILE_PROTOCOL = \"staticbolt-server\";\n\nexport function getLanguageModes(clientCapabilities: ClientCapabilities, requestService: FileSystemProvider): LanguageModes {\n const htmlLanguageService = vscodeHtml.getLanguageService({\n clientCapabilities,\n fileSystemProvider: requestService,\n customDataProviders: [\n {\n getId() {\n return FILE_PROTOCOL;\n },\n isApplicable(languageId) {\n return languageId === \"html\";\n },\n provideValues(tag, attribute) {\n return [{ name: `tag:${tag} attribute:${attribute}` }];\n },\n provideTags() {\n return [{ name: \"staticbolt\", description: \"# staticbolt-description\", attributes: [] }];\n },\n\n provideAttributes(tag: string) {\n if (tag === \"staticbolt\") {\n return [\n {\n name: \"staticbolt-attribute\",\n description: \"# staticbolt-attribute-description\",\n values: [{ name: \"staticbolt-attribute-value\" }],\n },\n ];\n }\n\n return [{ name: \"global-attribute\" }];\n },\n },\n ],\n useDefaultDataProvider: false,\n });\n\n const documentRegions = getLanguageModelCache<HTMLDocumentRegions>(10, 60, document =>\n getDocumentRegions(htmlLanguageService, document)\n );\n\n let modelCaches: LanguageModelCache<unknown>[] = [documentRegions];\n\n let modes = Object.create(null) as { [languageId: string]: LanguageMode };\n modes[\"html\"] = getHTMLMode(htmlLanguageService);\n\n return {\n // eslint-disable-next-line @typescript-eslint/require-await\n async updateDataProviders(dataProviders: IHTMLDataProvider[]): Promise<void> {\n htmlLanguageService.setDataProviders(true, dataProviders);\n },\n\n getModeAtPosition(document: TextDocument, position: Position): LanguageMode | undefined {\n const languageId = documentRegions.get(document).getLanguageAtPosition(position);\n if (languageId) {\n return modes[languageId];\n }\n\n return undefined;\n },\n\n getModesInRange(document: TextDocument, range: Range): LanguageModeRange[] {\n return documentRegions\n .get(document)\n .getLanguageRanges(range)\n .map((r): LanguageModeRange => {\n return {\n start: r.start,\n end: r.end,\n mode: r.languageId ? modes[r.languageId] : undefined,\n attributeValue: r.attributeValue,\n };\n });\n },\n\n getAllModesInDocument(document: TextDocument): LanguageMode[] {\n const result: LanguageMode[] = [];\n for (const languageId of documentRegions.get(document).getLanguagesInDocument()) {\n const mode = modes[languageId];\n if (mode) {\n result.push(mode);\n }\n }\n\n return result;\n },\n\n getAllModes(): LanguageMode[] {\n const result = [];\n for (const languageId in modes) {\n const mode = modes[languageId];\n if (mode) {\n result.push(mode);\n }\n }\n\n return result;\n },\n\n getMode(languageId: string): LanguageMode {\n return modes[languageId];\n },\n\n onDocumentRemoved(document: TextDocument) {\n for (const mc of modelCaches) {\n mc.onDocumentRemoved(document);\n }\n\n for (const mode in modes) {\n modes[mode].onDocumentRemoved(document);\n }\n },\n\n dispose(): void {\n for (const mc of modelCaches) {\n mc.dispose();\n }\n\n modelCaches = [];\n for (const mode in modes) {\n modes[mode].dispose();\n }\n\n modes = {};\n },\n };\n}\n","import { RequestType } from \"vscode-languageserver\";\n\nimport type { RuntimeEnvironment } from \"./html-server.ts\";\nimport type { Connection } from \"vscode-languageserver\";\n\n// Interface\nexport const FsStatRequest = { type: new RequestType<string, FileStat, unknown>(\"fs/stat\") } as const;\n\n// Interface\nexport const FsReadDirectoryRequest = { type: new RequestType<string, [string, FileType][], unknown>(\"fs/readDir\") } as const;\n\nexport const FileType = Object.freeze({\n /** The file type is unknown. */\n Unknown: 0,\n\n /** A regular file. */\n File: 1,\n\n /** A directory. */\n Directory: 2,\n\n /** A symbolic link to a file. */\n SymbolicLink: 64,\n});\n\nexport type FileType = (typeof FileType)[keyof typeof FileType];\n\nexport interface FileStat {\n /** The type of the file, e.g. is a regular file, a directory, or symbolic link to a file. */\n type: FileType;\n\n /** The creation timestamp in milliseconds elapsed since January 1, 1970 00:00:00 UTC. */\n ctime: number;\n\n /** The modification timestamp in milliseconds elapsed since January 1, 1970 00:00:00 UTC. */\n mtime: number;\n\n /** The size in bytes. */\n size: number;\n}\n\nexport interface FileSystemProvider {\n stat(uri: string): Promise<FileStat>;\n readDirectory(uri: string): Promise<[string, FileType][]>;\n}\n\nexport function getFileSystemProvider(\n handledSchemas: string[],\n connection: Connection,\n runtime: RuntimeEnvironment\n): FileSystemProvider {\n const fileFs = runtime.fileFs && handledSchemas.includes(\"file\") ? runtime.fileFs : undefined;\n\n return {\n async stat(uri: string): Promise<FileStat> {\n if (fileFs && uri.startsWith(\"file:\")) {\n return fileFs.stat(uri);\n }\n\n const result = await connection.sendRequest(FsStatRequest.type, uri);\n return result;\n },\n\n readDirectory(uri: string): Promise<[string, FileType][]> {\n if (fileFs && uri.startsWith(\"file:\")) {\n return fileFs.readDirectory(uri);\n }\n\n return connection.sendRequest(FsReadDirectoryRequest.type, uri);\n },\n };\n}\n","export function pushAll<T>(to: T[], from: T[]) {\n if (from) {\n for (const item of from) {\n to.push(item);\n }\n }\n}\n\n// eslint-disable-next-line unicorn/consistent-boolean-name\nexport function contains<T>(array: T[], value: T) {\n return array.includes(value);\n}\n\n/**\n * Like `Array#sort` but always stable. Usually runs a little slower `than Array#sort` so only use this when actually needing\n * stable sort.\n */\nexport function mergeSort<T>(data: T[], compare: (a: T, b: T) => number): T[] {\n _divideAndMerge(data, compare);\n return data;\n}\n\nfunction _divideAndMerge<T>(data: T[], compare: (a: T, b: T) => number): void {\n if (data.length <= 1) {\n // sorted\n return;\n }\n const p = Math.trunc(data.length / 2);\n const left = data.slice(0, p);\n const right = data.slice(p);\n\n _divideAndMerge(left, compare);\n _divideAndMerge(right, compare);\n\n let leftIndex = 0;\n let rightIndex = 0;\n let index = 0;\n while (leftIndex < left.length && rightIndex < right.length) {\n const returnValue = compare(left[leftIndex], right[rightIndex]);\n if (returnValue <= 0) {\n // smaller_equal -> take left to preserve order\n data[index++] = left[leftIndex++];\n } else {\n // greater -> take right\n data[index++] = right[rightIndex++];\n }\n }\n while (leftIndex < left.length) {\n data[index++] = left[leftIndex++];\n }\n while (rightIndex < right.length) {\n data[index++] = right[rightIndex++];\n }\n}\n\nexport function binarySearch<T>(array: T[], key: T, comparator: (op1: T, op2: T) => number): number {\n let low = 0,\n high = array.length - 1;\n\n while (low <= high) {\n const mid = Math.trunc((low + high) / 2);\n const comp = comparator(array[mid], key);\n if (comp < 0) {\n low = mid + 1;\n } else if (comp > 0) {\n high = mid - 1;\n } else {\n return mid;\n }\n }\n\n return -(low + 1);\n}\n","export function getWordAtText(text: string, offset: number, wordDefinition: RegExp): { start: number; length: number } {\n let lineStart = offset;\n while (lineStart > 0 && !isNewlineCharacter(text.codePointAt(lineStart - 1)!)) {\n lineStart--;\n }\n const offsetInLine = offset - lineStart;\n const lineText = text.slice(lineStart);\n\n // make a copy of the regex as to not keep the state\n const flags = wordDefinition.ignoreCase ? \"gi\" : \"g\";\n wordDefinition = new RegExp(wordDefinition.source, flags);\n\n let match = wordDefinition.exec(lineText);\n while (match && match.index + match[0].length < offsetInLine) {\n match = wordDefinition.exec(lineText);\n }\n if (match && match.index <= offsetInLine) {\n return { start: match.index + lineStart, length: match[0].length };\n }\n\n return { start: offset, length: 0 };\n}\n\nexport function isStartingWith(haystack: string, needle: string): boolean {\n if (haystack.length < needle.length) {\n return false;\n }\n\n // eslint-disable-next-line unicorn/no-for-loop\n for (let index = 0; index < needle.length; index++) {\n if (haystack[index] !== needle[index]) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function isEndingWith(haystack: string, needle: string): boolean {\n const diff = haystack.length - needle.length;\n if (diff > 0) {\n return haystack.indexOf(needle, diff) === diff;\n }\n\n if (diff === 0) {\n return haystack === needle;\n }\n\n return false;\n}\n\nexport function repeat(value: string, count: number) {\n let s = \"\";\n while (count > 0) {\n if ((count & 1) === 1) {\n s += value;\n }\n value += value;\n count >>>= 1;\n }\n return s;\n}\n\nexport function isWhitespaceOnly(string_: string) {\n return /^\\s*$/.test(string_);\n}\n\nexport function isEOL(content: string, offset: number) {\n return isNewlineCharacter(content.codePointAt(offset)!);\n}\n\nconst CR = \"\\r\".codePointAt(0);\nconst NL = \"\\n\".codePointAt(0);\nexport function isNewlineCharacter(charCode: number) {\n return charCode === CR || charCode === NL;\n}\n","import * as vscodeUri from \"vscode-uri\";\n\nimport { isEndingWith, isStartingWith } from \"../utils/strings.ts\";\n\nimport type { DocumentContext } from \"vscode-css-languageservice\";\nimport type { WorkspaceFolder } from \"vscode-languageserver\";\n\nexport function getDocumentContext(documentUri: string, workspaceFolders: WorkspaceFolder[]): DocumentContext {\n function getRootFolder(): string | undefined {\n for (const folder of workspaceFolders) {\n let folderURI = folder.uri;\n if (!isEndingWith(folderURI, \"/\")) {\n folderURI += \"/\";\n }\n\n if (isStartingWith(documentUri, folderURI)) {\n return folderURI;\n }\n }\n\n return undefined;\n }\n\n return {\n resolveReference: (reference: string, base = documentUri) => {\n if (/^\\w[\\w\\d+.-]*:/.test(reference)) {\n // starts with a schema\n return reference;\n }\n\n if (reference[0] === \"/\") {\n // resolve absolute path against the current workspace folder\n const folderUri = getRootFolder();\n if (folderUri) {\n return folderUri + reference.slice(1);\n }\n }\n\n const baseUri = vscodeUri.URI.parse(base);\n const baseUriDirectory = baseUri.path.endsWith(\"/\") ? baseUri : vscodeUri.Utils.dirname(baseUri);\n return vscodeUri.Utils.resolvePath(baseUriDirectory, reference).toString(true);\n },\n };\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as vscodeUri from \"vscode-uri\";\n\nexport function findProjectRoot(fileUri: string): string | null {\n let directory = path.dirname(vscodeUri.URI.parse(fileUri).fsPath);\n\n while (true) {\n for (const config of [\".staticbolt.ts\", \".staticbolt.js\"]) {\n if (fs.existsSync(path.join(directory, config))) {\n return directory;\n }\n }\n\n const parent = path.dirname(directory);\n\n // reached fs root, no config found\n if (parent === directory) {\n return null;\n }\n\n directory = parent;\n }\n}\n","import vscode from \"vscode-languageserver\";\n\nimport type { RuntimeEnvironment } from \"../html-server.ts\";\nimport type { CancellationToken, ResponseError } from \"vscode-languageserver\";\n\nexport function formatError(message: string, error: unknown): string {\n if (error instanceof Error) {\n return `${message}: ${error.message}\\n${error.stack}`;\n }\n\n if (typeof error === \"string\") {\n return `${message}: ${error}`;\n }\n\n if (error) {\n return `${message}: ${error as string}`;\n }\n\n return message;\n}\n\nexport function runSafe<T>(\n runtime: RuntimeEnvironment,\n function_: () => Thenable<T>,\n errorValue: T,\n errorMessage: string,\n token: CancellationToken\n): Thenable<T | ResponseError<never>> {\n return new Promise<T | ResponseError<never>>(resolve => {\n runtime.timer.setImmediate(() => {\n if (token.isCancellationRequested) {\n resolve(cancelValue());\n return;\n }\n return function_().then(\n result => {\n if (token.isCancellationRequested) {\n resolve(cancelValue());\n return;\n }\n\n resolve(result);\n },\n\n error => {\n console.error(formatError(errorMessage, error));\n resolve(errorValue);\n }\n );\n });\n });\n}\n\nfunction cancelValue<E>() {\n return new vscode.ResponseError<E>(vscode.LSPErrorCodes.RequestCancelled, \"Request cancelled\");\n}\n","import * as vscode from \"vscode-languageserver\";\nimport { TextDocument } from \"vscode-languageserver-textdocument\";\nimport * as vscodeUri from \"vscode-uri\";\n\nimport { ConfigManager } from \"./helpers/config-loader.ts\";\nimport { findStaticboltProjects } from \"./helpers/find-projects.ts\";\nimport { getLanguageModes } from \"./modes/language-modes.ts\";\nimport { getFileSystemProvider } from \"./requests.ts\";\nimport { pushAll } from \"./utils/arrays.ts\";\nimport { getDocumentContext } from \"./utils/document-context.ts\";\nimport { findProjectRoot } from \"./utils/find-project-root.ts\";\nimport { runSafe } from \"./utils/runner.ts\";\n\nimport type { CompletionItemData, LanguageModes, Settings } from \"./modes/language-modes.ts\";\nimport type { FileSystemProvider } from \"./requests.ts\";\nimport type { Connection, Disposable, InitializeParams, WorkspaceFolder } from \"vscode-languageserver\";\n\nexport interface RuntimeEnvironment {\n fileFs?: FileSystemProvider;\n\n configureHttpRequests?(proxy: string | undefined, isStrictSSL: boolean): void;\n\n readonly timer: {\n setImmediate(callback: (...arguments_: unknown[]) => void, ...arguments_: unknown[]): Disposable;\n setTimeout(callback: (...arguments_: unknown[]) => void, ms: number, ...arguments_: unknown[]): Disposable;\n };\n}\n\nexport interface CustomDataRequestService {\n getContent(uri: string): Promise<string>;\n}\n\nexport function startServer(connection: Connection, runtime: RuntimeEnvironment) {\n // Create a text document manager.\n const documents = new vscode.TextDocuments(TextDocument);\n // Make the text document manager listen on the connection\n // for open, change and close text document events\n documents.listen(connection);\n\n let lspSearchRoots: WorkspaceFolder[] = [];\n let workspaceFolders: WorkspaceFolder[] = [];\n let configManager: ConfigManager;\n\n let languageModes: LanguageModes;\n\n const documentSettings: { [key: string]: Thenable<Settings> } = {};\n\n // remove document settings on close\n documents.onDidClose(document => {\n delete documentSettings[document.document.uri];\n });\n\n connection.onInitialize((parameters: InitializeParams) => {\n if (Array.isArray(parameters.workspaceFolders)) {\n lspSearchRoots = parameters.workspaceFolders;\n } else {\n lspSearchRoots = [];\n if (parameters.rootPath) {\n lspSearchRoots.push({ name: \"\", uri: vscodeUri.URI.file(parameters.rootPath).toString() });\n }\n }\n\n workspaceFolders = findStaticboltProjects(lspSearchRoots);\n connection.console.log(\n `[staticbolt] discovered projects:\\n` + workspaceFolders.map(f => ` - [${f.name}]: ${f.uri}`).join(\"\\n\")\n );\n\n const fileSystemProvider = getFileSystemProvider([\"file\"], connection, runtime);\n languageModes = getLanguageModes(parameters.capabilities, fileSystemProvider);\n\n configManager = new ConfigManager(connection.console);\n\n documents.onDidClose(document => {\n languageModes.onDocumentRemoved(document.document);\n });\n\n connection.onShutdown(() => {\n languageModes.dispose();\n configManager.dispose();\n });\n\n return {\n capabilities: {\n textDocumentSync: vscode.TextDocumentSyncKind.Incremental,\n completionProvider: {\n resolveProvider: true,\n triggerCharacters: [\".\", \":\", \"<\", '\"', \"=\", \"/\"],\n },\n hoverProvider: true,\n documentLinkProvider: { resolveProvider: false },\n },\n };\n });\n\n connection.onInitialized(() => {});\n\n connection.onCompletion(async (textDocumentPosition, token) => {\n return runSafe(\n runtime,\n async () => {\n const projectRoot = findProjectRoot(textDocumentPosition.textDocument.uri);\n if (!projectRoot) return null;\n\n const document = documents.get(textDocumentPosition.textDocument.uri);\n if (!document) return null;\n\n const mode = languageModes.getModeAtPosition(document, textDocumentPosition.position);\n if (!mode?.doComplete) return { isIncomplete: true, items: [] };\n\n const config = await configManager.get(projectRoot);\n if (!config) return { isIncomplete: true, items: [] };\n\n const documentContext = getDocumentContext(document.uri, workspaceFolders);\n return mode.doComplete(document, textDocumentPosition.position, documentContext, configManager.lspHtmlData);\n },\n null,\n `Error while computing completions for ${textDocumentPosition.textDocument.uri}`,\n token\n );\n });\n\n connection.onCompletionResolve((item, token) => {\n return runSafe(\n runtime,\n async () => {\n const data = item.data as Record<string, unknown>;\n if (!isCompletionItemData(data)) return item;\n\n const document = documents.get(data.uri);\n if (!document) return item;\n\n const mode = languageModes.getMode(data.languageId);\n if (!mode?.doResolve) return item;\n\n return mode.doResolve(document, item);\n },\n item,\n `Error while resolving completion proposal`,\n token\n );\n });\n\n connection.onHover((textDocumentPosition, token) => {\n return runSafe(\n runtime,\n async () => {\n const projectRoot = findProjectRoot(textDocumentPosition.textDocument.uri);\n if (!projectRoot) return null;\n\n const document = documents.get(textDocumentPosition.textDocument.uri);\n if (!document) return null;\n\n const mode = languageModes.getModeAtPosition(document, textDocumentPosition.position);\n if (!mode?.doHover) return null;\n\n const config = await configManager.get(projectRoot);\n if (!config) return null;\n\n return mode.doHover(document, textDocumentPosition.position, configManager.lspHtmlData);\n },\n null,\n `Error while computing hover for ${textDocumentPosition.textDocument.uri}`,\n token\n );\n });\n\n connection.onDocumentLinks((documentLinkParameter, token) => {\n return runSafe(\n runtime,\n async () => {\n const projectRoot = findProjectRoot(documentLinkParameter.textDocument.uri);\n if (!projectRoot) return null;\n\n const document = documents.get(documentLinkParameter.textDocument.uri);\n if (!document) return [];\n\n const links: vscode.DocumentLink[] = [];\n\n const documentContext = getDocumentContext(document.uri, workspaceFolders);\n for (const mode of languageModes.getAllModesInDocument(document)) {\n if (mode.findDocumentLinks) {\n pushAll(links, await mode.findDocumentLinks(document, documentContext, projectRoot));\n }\n }\n\n return links;\n },\n [],\n `Error while document links for ${documentLinkParameter.textDocument.uri}`,\n token\n );\n });\n\n // Listen on the connection\n connection.listen();\n}\n\nexport function isCompletionItemData(value: Record<string, unknown>): value is CompletionItemData {\n return value && typeof value.languageId === \"string\" && typeof value.uri === \"string\" && typeof value.offset === \"number\";\n}\n","import * as fs from \"node:fs\";\nimport * as vscodeUri from \"vscode-uri\";\n\nimport type { FileSystemProvider } from \"../requests.ts\";\n\nconst FileType = Object.freeze({\n /** The file type is unknown. */\n Unknown: 0,\n /** A regular file. */\n File: 1,\n /** A directory. */\n Directory: 2,\n /** A symbolic link to a file. */\n SymbolicLink: 64,\n});\n\ntype FileType = (typeof FileType)[keyof typeof FileType];\n\nexport function getNodeFileFS(): FileSystemProvider {\n function ensureFileUri(location: string) {\n if (!location.startsWith(\"file:\")) {\n throw new Error(\"fileSystemProvider can only handle file URLs\");\n }\n }\n return {\n stat(location: string) {\n ensureFileUri(location);\n return new Promise((c, error_) => {\n const uri = vscodeUri.URI.parse(location);\n fs.stat(uri.fsPath, (error, stats) => {\n if (error) {\n return error.code === \"ENOENT\" ? c({ type: FileType.Unknown, ctime: -1, mtime: -1, size: -1 }) : error_(error);\n }\n\n let type: FileType = FileType.Unknown;\n if (stats.isFile()) {\n type = FileType.File;\n } else if (stats.isDirectory()) {\n type = FileType.Directory;\n } else if (stats.isSymbolicLink()) {\n type = FileType.SymbolicLink;\n }\n\n c({\n type,\n ctime: stats.ctime.getTime(),\n mtime: stats.mtime.getTime(),\n size: stats.size,\n });\n });\n });\n },\n readDirectory(location: string) {\n ensureFileUri(location);\n return new Promise((c, error_) => {\n const path = vscodeUri.URI.parse(location).fsPath;\n\n fs.readdir(path, { withFileTypes: true }, (error, children) => {\n if (error) {\n return error_(error);\n }\n c(\n children.map(stat => {\n if (stat.isSymbolicLink()) {\n return [stat.name, FileType.SymbolicLink];\n }\n if (stat.isDirectory()) {\n return [stat.name, FileType.Directory];\n }\n return stat.isFile() ? [stat.name, FileType.File] : [stat.name, FileType.Unknown];\n })\n );\n });\n });\n },\n };\n}\n","import * as vs from \"vscode-languageserver/node\";\n\nimport { startServer } from \"./html-server.ts\";\nimport { getNodeFileFS } from \"./utils/node-fs.ts\";\nimport { formatError } from \"./utils/runner.ts\";\n\nimport type { RuntimeEnvironment } from \"./html-server.ts\";\nimport type { Connection, Disposable } from \"vscode-languageserver/node\";\n\n// Create a connection for the server.\nconst connection: Connection = vs.createConnection();\n\nconsole.log = connection.console.log.bind(connection.console);\nconsole.error = connection.console.error.bind(connection.console);\n\nprocess.on(\"unhandledRejection\", (error: unknown) => {\n connection.console.error(formatError(`Unhandled exception`, error));\n});\n\nconst runtime: RuntimeEnvironment = {\n timer: {\n setImmediate(callback: (...arguments_: unknown[]) => void, ...arguments_: unknown[]): Disposable {\n const handle = setImmediate(callback, ...arguments_);\n return { dispose: () => clearImmediate(handle) };\n },\n\n setTimeout(callback: (...arguments_: unknown[]) => void, ms: number, ...arguments_: unknown[]): Disposable {\n const handle = setTimeout(callback, ms, ...arguments_);\n return { dispose: () => clearTimeout(handle) };\n },\n },\n\n fileFs: getNodeFileFS(),\n};\n\nconnection.console.log(\"[staticbolt] starting server\");\nstartServer(connection, runtime);\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@staticbolt/lsp",
3
3
  "description": "Language Server Protocol for staticbolt",
4
- "version": "1.0.0-beta.13",
4
+ "version": "1.0.0-beta.14",
5
5
  "author": "Ahmed ALABSI",
6
6
  "dependencies": {
7
- "@staticbolt/core": "1.0.0-beta.13",
7
+ "@staticbolt/core": "1.0.0-beta.14",
8
8
  "vscode-html-languageservice": "^5.6.2",
9
- "vscode-languageserver": "^9.0.1",
10
- "vscode-languageserver-textdocument": "^1.0.12",
9
+ "vscode-languageserver": "^10.0.1",
10
+ "vscode-languageserver-textdocument": "^1.0.13",
11
11
  "vscode-uri": "^3.1.0"
12
12
  },
13
13
  "exports": {
@@ -23,7 +23,7 @@
23
23
  ],
24
24
  "license": "MIT",
25
25
  "peerDependencies": {
26
- "@staticbolt/core": "1.0.0-beta.13"
26
+ "@staticbolt/core": "1.0.0-beta.14"
27
27
  },
28
28
  "private": false,
29
29
  "scripts": {
@@ -37,7 +37,7 @@ async function importFresh(absolutePath: string): Promise<StaticBoltConfig> {
37
37
  const module_ = (await import(url)) as { default: StaticBoltConfig };
38
38
 
39
39
  if (!("default" in module_)) {
40
- throw new Error(`Config file "${absolutePath}" has no default export. ` + `Use \`export default { … }\`.`);
40
+ throw new Error(`Config file "${absolutePath}" has no default export. Use \`export default { … }\`.`);
41
41
  }
42
42
 
43
43
  return module_.default;
@@ -178,16 +178,20 @@ export class ConfigManager {
178
178
  private async collectData(config: StaticBoltConfig) {
179
179
  this.lspHtmlData = [];
180
180
 
181
- for (const pluginOrArray of config.plugins ?? []) {
181
+ const plugins = config.plugins ?? [];
182
+
183
+ for (const pluginOrArray of plugins) {
182
184
  const plugins = Array.isArray(pluginOrArray) ? pluginOrArray : [pluginOrArray];
183
185
 
184
186
  for (const plugin of plugins) {
185
- if (plugin.lspHtmlData) {
186
- const htmlData = await plugin.lspHtmlData();
187
- if (htmlData) {
188
- htmlDataInjectPluginName(htmlData, plugin.name);
189
- this.lspHtmlData.push(htmlData);
190
- }
187
+ if (!plugin.lspHtmlData) {
188
+ continue;
189
+ }
190
+
191
+ const htmlData = await plugin.lspHtmlData();
192
+ if (htmlData) {
193
+ htmlDataInjectPluginName(htmlData, plugin.name);
194
+ this.lspHtmlData.push(htmlData);
191
195
  }
192
196
  }
193
197
  }
@@ -195,15 +199,18 @@ export class ConfigManager {
195
199
  }
196
200
 
197
201
  function htmlDataInjectPluginName(htmlData: HTMLDataV1, pluginName: string) {
198
- for (const tag of htmlData.tags ?? []) {
202
+ const tags = htmlData.tags ?? [];
203
+ for (const tag of tags) {
199
204
  tag.description = replaceDescription(tag.description, pluginName);
200
205
 
201
- for (const attribute of tag.attributes ?? []) {
206
+ const attributes = tag.attributes ?? [];
207
+ for (const attribute of attributes) {
202
208
  attribute.description = replaceDescription(attribute.description, pluginName);
203
209
  }
204
210
  }
205
211
 
206
- for (const attribute of htmlData.globalAttributes ?? []) {
212
+ const globalAttributes = htmlData.globalAttributes ?? [];
213
+ for (const attribute of globalAttributes) {
207
214
  attribute.description = replaceDescription(attribute.description, pluginName);
208
215
  }
209
216
  }
@@ -18,7 +18,7 @@ import type { Connection, Disposable, InitializeParams, WorkspaceFolder } from "
18
18
  export interface RuntimeEnvironment {
19
19
  fileFs?: FileSystemProvider;
20
20
 
21
- configureHttpRequests?(proxy: string | undefined, strictSSL: boolean): void;
21
+ configureHttpRequests?(proxy: string | undefined, isStrictSSL: boolean): void;
22
22
 
23
23
  readonly timer: {
24
24
  setImmediate(callback: (...arguments_: unknown[]) => void, ...arguments_: unknown[]): Disposable;
@@ -14,7 +14,7 @@ export function getLanguageModelCache<T>(
14
14
  let languageModels: { [uri: string]: { version: number; languageId: string; cTime: number; languageModel: T } } = {};
15
15
  let nModels = 0;
16
16
 
17
- let cleanupInterval: NodeJS.Timeout | undefined = undefined;
17
+ let cleanupInterval: NodeJS.Timeout | undefined;
18
18
 
19
19
  if (cleanupIntervalTimeInSec > 0) {
20
20
  cleanupInterval = setInterval(() => {
@@ -71,19 +71,21 @@ export function getLanguageModelCache<T>(
71
71
 
72
72
  onDocumentRemoved(document: TextDocument) {
73
73
  const uri = document.uri;
74
- if (languageModels[uri]) {
74
+ if (Object.hasOwn(languageModels, uri)) {
75
75
  delete languageModels[uri];
76
76
  nModels--;
77
77
  }
78
78
  },
79
79
 
80
80
  dispose() {
81
- if (cleanupInterval !== undefined) {
82
- clearInterval(cleanupInterval);
83
- cleanupInterval = undefined;
84
- languageModels = {};
85
- nModels = 0;
81
+ if (cleanupInterval === undefined) {
82
+ return;
86
83
  }
84
+
85
+ clearInterval(cleanupInterval);
86
+ cleanupInterval = undefined;
87
+ languageModels = {};
88
+ nModels = 0;
87
89
  },
88
90
  };
89
91
  }
@@ -9,7 +9,7 @@ export interface LanguageRange extends Range {
9
9
  }
10
10
 
11
11
  export interface HTMLDocumentRegions {
12
- getEmbeddedDocument(languageId: string, ignoreAttributeValues?: boolean): TextDocument;
12
+ getEmbeddedDocument(languageId: string, shouldIgnoreAttributeValues?: boolean): TextDocument;
13
13
  getLanguageRanges(range: Range): LanguageRange[];
14
14
  getLanguageAtPosition(position: Position): string | undefined;
15
15
  getLanguagesInDocument(): string[];
@@ -33,28 +33,32 @@ export function getDocumentRegions(languageService: LanguageService, document: T
33
33
  const scanner = languageService.createScanner(document.getText());
34
34
  let lastTagName: string = "";
35
35
  let lastAttributeName: string | null = null;
36
- let languageIdFromType: string | undefined = undefined;
36
+ let languageIdFromType: string | undefined;
37
37
  const importedScripts: string[] = [];
38
38
 
39
39
  let token = scanner.scan();
40
40
 
41
41
  while (token !== TokenType.EOS) {
42
42
  switch (token) {
43
- case TokenType.StartTag:
43
+ case TokenType.StartTag: {
44
44
  lastTagName = scanner.getTokenText();
45
45
  lastAttributeName = null;
46
46
  languageIdFromType = "javascript";
47
47
  break;
48
- case TokenType.Styles:
48
+ }
49
+ case TokenType.Styles: {
49
50
  regions.push({ languageId: "css", start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });
50
51
  break;
51
- case TokenType.Script:
52
+ }
53
+ case TokenType.Script: {
52
54
  regions.push({ languageId: languageIdFromType, start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });
53
55
  break;
54
- case TokenType.AttributeName:
56
+ }
57
+ case TokenType.AttributeName: {
55
58
  lastAttributeName = scanner.getTokenText();
56
59
  break;
57
- case TokenType.AttributeValue:
60
+ }
61
+ case TokenType.AttributeValue: {
58
62
  if (lastAttributeName === "src" && lastTagName.toLowerCase() === "script") {
59
63
  let value = scanner.getTokenText();
60
64
  if (value[0] === "'" || value[0] === '"') {
@@ -85,13 +89,14 @@ export function getDocumentRegions(languageService: LanguageService, document: T
85
89
  }
86
90
  lastAttributeName = null;
87
91
  break;
92
+ }
88
93
  }
89
94
  token = scanner.scan();
90
95
  }
91
96
  return {
92
97
  getLanguageRanges: (range: Range) => getLanguageRanges(document, regions, range),
93
- getEmbeddedDocument: (languageId: string, ignoreAttributeValues: boolean) =>
94
- getEmbeddedDocument(document, regions, languageId, ignoreAttributeValues),
98
+ getEmbeddedDocument: (languageId: string, shouldIgnoreAttributeValues: boolean) =>
99
+ getEmbeddedDocument(document, regions, languageId, shouldIgnoreAttributeValues),
95
100
  getLanguageAtPosition: (position: Position) => getLanguageAtPosition(document, regions, position),
96
101
  getLanguagesInDocument: () => getLanguagesInDocument(document, regions),
97
102
  getImportedScripts: () => importedScripts,
@@ -104,29 +109,31 @@ function getLanguageRanges(document: TextDocument, regions: EmbeddedRegion[], ra
104
109
  let currentOffset = range ? document.offsetAt(range.start) : 0;
105
110
  const endOffset = range ? document.offsetAt(range.end) : document.getText().length;
106
111
  for (const region of regions) {
107
- if (region.end > currentOffset && region.start < endOffset) {
108
- const start = Math.max(region.start, currentOffset);
109
- const startPos = document.positionAt(start);
110
- if (currentOffset < region.start) {
111
- result.push({
112
- start: currentPos,
113
- end: startPos,
114
- languageId: "html",
115
- });
116
- }
117
- const end = Math.min(region.end, endOffset);
118
- const endPos = document.positionAt(end);
119
- if (end > region.start) {
120
- result.push({
121
- start: startPos,
122
- end: endPos,
123
- languageId: region.languageId,
124
- attributeValue: region.attributeValue,
125
- });
126
- }
127
- currentOffset = end;
128
- currentPos = endPos;
112
+ if (!(region.end > currentOffset && region.start < endOffset)) {
113
+ continue;
114
+ }
115
+
116
+ const start = Math.max(region.start, currentOffset);
117
+ const startPos = document.positionAt(start);
118
+ if (currentOffset < region.start) {
119
+ result.push({
120
+ start: currentPos,
121
+ end: startPos,
122
+ languageId: "html",
123
+ });
129
124
  }
125
+ const end = Math.min(region.end, endOffset);
126
+ const endPos = document.positionAt(end);
127
+ if (end > region.start) {
128
+ result.push({
129
+ start: startPos,
130
+ end: endPos,
131
+ languageId: region.languageId,
132
+ attributeValue: region.attributeValue,
133
+ });
134
+ }
135
+ currentOffset = end;
136
+ currentPos = endPos;
130
137
  }
131
138
  if (currentOffset < endOffset) {
132
139
  const endPos = range ? range.end : document.positionAt(endOffset);
@@ -143,11 +150,13 @@ function getLanguagesInDocument(_document: TextDocument, regions: EmbeddedRegion
143
150
  const result: string[] = [];
144
151
 
145
152
  for (const region of regions) {
146
- if (region.languageId && !result.includes(region.languageId)) {
147
- result.push(region.languageId);
148
- if (result.length === 3) {
149
- return result;
150
- }
153
+ if (!(region.languageId && !result.includes(region.languageId))) {
154
+ continue;
155
+ }
156
+
157
+ result.push(region.languageId);
158
+ if (result.length === 3) {
159
+ return result;
151
160
  }
152
161
  }
153
162
 
@@ -174,19 +183,21 @@ function getEmbeddedDocument(
174
183
  document: TextDocument,
175
184
  contents: EmbeddedRegion[],
176
185
  languageId: string,
177
- ignoreAttributeValues: boolean
186
+ shouldIgnoreAttributeValues: boolean
178
187
  ): TextDocument {
179
188
  let currentPos = 0;
180
189
  const oldContent = document.getText();
181
190
  let result = "";
182
191
  let lastSuffix = "";
183
192
  for (const c of contents) {
184
- if (c.languageId === languageId && (!ignoreAttributeValues || !c.attributeValue)) {
185
- result = substituteWithWhitespace(result, currentPos, c.start, oldContent, lastSuffix, getPrefix(c));
186
- result += updateContent(c, oldContent.slice(c.start, c.end));
187
- currentPos = c.end;
188
- lastSuffix = getSuffix(c);
193
+ if (!(c.languageId === languageId && (!shouldIgnoreAttributeValues || !c.attributeValue))) {
194
+ continue;
189
195
  }
196
+
197
+ result = substituteWithWhitespace(result, currentPos, c.start, oldContent, lastSuffix, getPrefix(c));
198
+ result += updateContent(c, oldContent.slice(c.start, c.end));
199
+ currentPos = c.end;
200
+ lastSuffix = getSuffix(c);
190
201
  }
191
202
  result = substituteWithWhitespace(result, currentPos, oldContent.length, oldContent, lastSuffix, "");
192
203
  return TextDocument.create(document.uri, languageId, document.version, result);
@@ -195,8 +206,9 @@ function getEmbeddedDocument(
195
206
  function getPrefix(c: EmbeddedRegion) {
196
207
  if (c.attributeValue) {
197
208
  switch (c.languageId) {
198
- case "css":
209
+ case "css": {
199
210
  return CSS_STYLE_RULE + "{";
211
+ }
200
212
  }
201
213
  }
202
214
  return "";
@@ -204,10 +216,12 @@ function getPrefix(c: EmbeddedRegion) {
204
216
  function getSuffix(c: EmbeddedRegion) {
205
217
  if (c.attributeValue) {
206
218
  switch (c.languageId) {
207
- case "css":
219
+ case "css": {
208
220
  return "}";
209
- case "javascript":
221
+ }
222
+ case "javascript": {
210
223
  return ";";
224
+ }
211
225
  }
212
226
  }
213
227
  return "";
package/src/requests.ts CHANGED
@@ -57,7 +57,7 @@ export function getFileSystemProvider(
57
57
  return fileFs.stat(uri);
58
58
  }
59
59
 
60
- const result = await connection.sendRequest(FsStatRequest.type, uri.toString());
60
+ const result = await connection.sendRequest(FsStatRequest.type, uri);
61
61
  return result;
62
62
  },
63
63
 
@@ -66,7 +66,7 @@ export function getFileSystemProvider(
66
66
  return fileFs.readDirectory(uri);
67
67
  }
68
68
 
69
- return connection.sendRequest(FsReadDirectoryRequest.type, uri.toString());
69
+ return connection.sendRequest(FsReadDirectoryRequest.type, uri);
70
70
  },
71
71
  };
72
72
  }
@@ -6,6 +6,7 @@ export function pushAll<T>(to: T[], from: T[]) {
6
6
  }
7
7
  }
8
8
 
9
+ // eslint-disable-next-line unicorn/consistent-boolean-name
9
10
  export function contains<T>(array: T[], value: T) {
10
11
  return array.includes(value);
11
12
  }
@@ -1,6 +1,6 @@
1
1
  import * as vscodeUri from "vscode-uri";
2
2
 
3
- import { endsWith, startsWith } from "../utils/strings.ts";
3
+ import { isEndingWith, isStartingWith } from "../utils/strings.ts";
4
4
 
5
5
  import type { DocumentContext } from "vscode-css-languageservice";
6
6
  import type { WorkspaceFolder } from "vscode-languageserver";
@@ -9,11 +9,11 @@ export function getDocumentContext(documentUri: string, workspaceFolders: Worksp
9
9
  function getRootFolder(): string | undefined {
10
10
  for (const folder of workspaceFolders) {
11
11
  let folderURI = folder.uri;
12
- if (!endsWith(folderURI, "/")) {
13
- folderURI = folderURI + "/";
12
+ if (!isEndingWith(folderURI, "/")) {
13
+ folderURI += "/";
14
14
  }
15
15
 
16
- if (startsWith(documentUri, folderURI)) {
16
+ if (isStartingWith(documentUri, folderURI)) {
17
17
  return folderURI;
18
18
  }
19
19
  }
@@ -63,13 +63,11 @@ export function getNodeFileFS(): FileSystemProvider {
63
63
  children.map(stat => {
64
64
  if (stat.isSymbolicLink()) {
65
65
  return [stat.name, FileType.SymbolicLink];
66
- } else if (stat.isDirectory()) {
66
+ }
67
+ if (stat.isDirectory()) {
67
68
  return [stat.name, FileType.Directory];
68
- } else if (stat.isFile()) {
69
- return [stat.name, FileType.File];
70
- } else {
71
- return [stat.name, FileType.Unknown];
72
69
  }
70
+ return stat.isFile() ? [stat.name, FileType.File] : [stat.name, FileType.Unknown];
73
71
  })
74
72
  );
75
73
  });
@@ -13,7 +13,7 @@ export function formatError(message: string, error: unknown): string {
13
13
  }
14
14
 
15
15
  if (error) {
16
- return `${message}: ${(error as string).toString()}`;
16
+ return `${message}: ${error as string}`;
17
17
  }
18
18
 
19
19
  return message;
@@ -21,7 +21,7 @@ export function getWordAtText(text: string, offset: number, wordDefinition: RegE
21
21
  return { start: offset, length: 0 };
22
22
  }
23
23
 
24
- export function startsWith(haystack: string, needle: string): boolean {
24
+ export function isStartingWith(haystack: string, needle: string): boolean {
25
25
  if (haystack.length < needle.length) {
26
26
  return false;
27
27
  }
@@ -36,7 +36,7 @@ export function startsWith(haystack: string, needle: string): boolean {
36
36
  return true;
37
37
  }
38
38
 
39
- export function endsWith(haystack: string, needle: string): boolean {
39
+ export function isEndingWith(haystack: string, needle: string): boolean {
40
40
  const diff = haystack.length - needle.length;
41
41
  if (diff > 0) {
42
42
  return haystack.indexOf(needle, diff) === diff;
@@ -56,7 +56,7 @@ export function repeat(value: string, count: number) {
56
56
  s += value;
57
57
  }
58
58
  value += value;
59
- count = count >>> 1;
59
+ count >>>= 1;
60
60
  }
61
61
  return s;
62
62
  }