Complete residential site build with Docker Compose & Gitea Actions deployment

This commit is contained in:
CalebLewallen
2026-05-13 17:31:20 -04:00
parent f9c4e13a50
commit 3c22823f72
19354 changed files with 2097331 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
MIT License
Copyright (c) 2023 The Astro Technology Company
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
This license applies to code originating from the https://github.com/sveltejs/language-tools repository:
Copyright (c) 2020-Present [these people](https://github.com/sveltejs/language-tools/graphs/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
+25
View File
@@ -0,0 +1,25 @@
# @astrojs/language-server
The Astro language server, implement the [language server protocol](https://microsoft.github.io/language-server-protocol/)
## Folder structure
```plaintext
├── bin # .js file used to start the server
├── dist # Compiled files, generated by TypeScript
├── src # Source files
│ ├── core # Core code such as .astro file parsing, configuration manager, document definition etc
│ └── plugins # Modules for the different languages supported in .astro files
├── test # Tests
└── types # Types injected into Astro files by the language server under certain conditions
```
## Troubleshooting
### Formatting does not work
> Using VS Code? This section does not apply to you, the VS Code extension includes both Prettier and the Astro plugin by default.
The Astro language server uses Prettier to format Astro files, but does not include `prettier` or `prettier-plugin-astro` by itself as dependencies in order to keep the dependency count low and allow users to better control the version of Prettier they want to use.
As such, if you want to use formatting, you'll need to install `prettier` and `prettier-plugin-astro` as dependencies in your project.
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env node
if (process.argv.includes('--version')) {
const pkgJSON = require('../package.json');
console.info(`${pkgJSON['version']}`);
} else {
require('../dist/nodeServer.js');
}
+3
View File
@@ -0,0 +1,3 @@
import type { Mapping } from '@volar/language-core';
import type { Segment } from 'muggle-string';
export declare function buildMappings<T>(chunks: Segment<T>[]): Mapping<T>[];
+23
View File
@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildMappings = buildMappings;
function buildMappings(chunks) {
let length = 0;
const mappings = [];
for (const segment of chunks) {
if (typeof segment === 'string') {
length += segment.length;
}
else {
mappings.push({
sourceOffsets: [segment[2]],
generatedOffsets: [length],
lengths: [segment[0].length],
data: segment[3],
});
length += segment[0].length;
}
}
return mappings;
}
//# sourceMappingURL=buildMappings.js.map
+39
View File
@@ -0,0 +1,39 @@
import * as kit from '@volar/kit';
import { Diagnostic, DiagnosticSeverity } from '@volar/language-server';
export { Diagnostic, DiagnosticSeverity };
export interface CheckResult {
status: 'completed' | 'cancelled' | undefined;
fileChecked: number;
errors: number;
warnings: number;
hints: number;
fileResult: {
errors: kit.Diagnostic[];
fileUrl: URL;
fileContent: string;
text: string;
}[];
}
export declare class AstroCheck {
private ts;
linter: ReturnType<(typeof kit)['createTypeScriptChecker']>;
private readonly workspacePath;
private readonly typescriptPath;
private readonly tsconfigPath;
constructor(workspacePath: string, typescriptPath: string | undefined, tsconfigPath: string | undefined);
/**
* Lint a list of files or the entire project and optionally log the errors found
* @param fileNames List of files to lint, if undefined, all files included in the project will be linted
* @param logErrors Whether to log errors by itself. This is disabled by default.
* @return {CheckResult} The result of the lint, including a list of errors, the file's content and its file path.
*/
lint({ fileNames, cancel, logErrors, }: {
fileNames?: string[] | undefined;
cancel?: () => boolean;
logErrors?: {
level: 'error' | 'warning' | 'hint';
} | undefined;
}): Promise<CheckResult>;
private initialize;
private getTsconfig;
}
+168
View File
@@ -0,0 +1,168 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.AstroCheck = exports.DiagnosticSeverity = exports.Diagnostic = void 0;
const node_fs_1 = require("node:fs");
const node_os_1 = require("node:os");
const node_path_1 = require("node:path");
const node_url_1 = require("node:url");
const kit = __importStar(require("@volar/kit"));
const language_server_1 = require("@volar/language-server");
Object.defineProperty(exports, "Diagnostic", { enumerable: true, get: function () { return language_server_1.Diagnostic; } });
Object.defineProperty(exports, "DiagnosticSeverity", { enumerable: true, get: function () { return language_server_1.DiagnosticSeverity; } });
const tinyglobby_1 = require("tinyglobby");
const vscode_uri_1 = require("vscode-uri");
const index_js_1 = require("./core/index.js");
const svelte_js_1 = require("./core/svelte.js");
const vue_js_1 = require("./core/vue.js");
const astro_js_1 = require("./plugins/astro.js");
const index_js_2 = require("./plugins/typescript/index.js");
const utils_js_1 = require("./utils.js");
class AstroCheck {
constructor(workspacePath, typescriptPath, tsconfigPath) {
this.workspacePath = workspacePath;
this.typescriptPath = typescriptPath;
this.tsconfigPath = tsconfigPath;
this.initialize();
}
/**
* Lint a list of files or the entire project and optionally log the errors found
* @param fileNames List of files to lint, if undefined, all files included in the project will be linted
* @param logErrors Whether to log errors by itself. This is disabled by default.
* @return {CheckResult} The result of the lint, including a list of errors, the file's content and its file path.
*/
async lint({ fileNames = undefined, cancel = () => false, logErrors = undefined, }) {
let files = (fileNames !== undefined ? fileNames : this.linter.getRootFileNames()).filter((file) => {
// We don't have the same understanding of Svelte and Vue files as their own respective tools (vue-tsc, svelte-check)
// So we don't want to check them here
return !file.endsWith('.vue') && !file.endsWith('.svelte');
});
const result = {
status: undefined,
fileChecked: 0,
errors: 0,
warnings: 0,
hints: 0,
fileResult: [],
};
for (const file of files) {
if (cancel()) {
result.status = 'cancelled';
return result;
}
const fileDiagnostics = await this.linter.check(file);
// Filter diagnostics based on the logErrors level
const fileDiagnosticsToPrint = fileDiagnostics.filter((diag) => {
const severity = diag.severity ?? language_server_1.DiagnosticSeverity.Error;
switch (logErrors?.level ?? 'hint') {
case 'error':
return severity <= language_server_1.DiagnosticSeverity.Error;
case 'warning':
return severity <= language_server_1.DiagnosticSeverity.Warning;
case 'hint':
return severity <= language_server_1.DiagnosticSeverity.Hint;
}
});
if (fileDiagnostics.length > 0) {
const errorText = this.linter.printErrors(file, fileDiagnosticsToPrint);
if (logErrors !== undefined && errorText) {
console.info(errorText);
}
const fileSnapshot = this.linter.language.scripts.get(vscode_uri_1.URI.file(file))?.snapshot;
const fileContent = fileSnapshot?.getText(0, fileSnapshot.getLength());
result.fileResult.push({
errors: fileDiagnostics,
fileContent: fileContent ?? '',
fileUrl: (0, node_url_1.pathToFileURL)(file),
text: errorText,
});
result.errors += fileDiagnostics.filter((diag) => diag.severity === language_server_1.DiagnosticSeverity.Error).length;
result.warnings += fileDiagnostics.filter((diag) => diag.severity === language_server_1.DiagnosticSeverity.Warning).length;
result.hints += fileDiagnostics.filter((diag) => diag.severity === language_server_1.DiagnosticSeverity.Hint).length;
}
result.fileChecked += 1;
}
result.status = 'completed';
return result;
}
initialize() {
this.ts = this.typescriptPath ? require(this.typescriptPath) : require('typescript');
const tsconfigPath = this.getTsconfig();
const languagePlugins = [
(0, index_js_1.getAstroLanguagePlugin)(),
(0, svelte_js_1.getSvelteLanguagePlugin)(),
(0, vue_js_1.getVueLanguagePlugin)(),
];
const services = [...(0, index_js_2.create)(this.ts), (0, astro_js_1.create)()];
if (tsconfigPath) {
const includeProjectReference = false; // #920
this.linter = kit.createTypeScriptChecker(languagePlugins, services, tsconfigPath, includeProjectReference, ({ project }) => {
const { languageServiceHost } = project.typescript;
const astroInstall = (0, utils_js_1.getAstroInstall)([this.workspacePath]);
(0, index_js_1.addAstroTypes)(typeof astroInstall === 'string' ? undefined : astroInstall, this.ts, languageServiceHost);
});
}
else {
this.linter = kit.createTypeScriptInferredChecker(languagePlugins, services, () => {
return (0, tinyglobby_1.globSync)('**/*.astro', {
cwd: this.workspacePath,
ignore: ['node_modules'],
absolute: true,
// Required to avoid tinyglobby running eternally
expandDirectories: false,
});
}, undefined, ({ project }) => {
const { languageServiceHost } = project.typescript;
const astroInstall = (0, utils_js_1.getAstroInstall)([this.workspacePath]);
(0, index_js_1.addAstroTypes)(typeof astroInstall === 'string' ? undefined : astroInstall, this.ts, languageServiceHost);
});
}
}
getTsconfig() {
if (this.tsconfigPath) {
const tsconfig = (0, node_path_1.resolve)(this.workspacePath, this.tsconfigPath.replace(/^~/, (0, node_os_1.homedir)()));
if (!(0, node_fs_1.existsSync)(tsconfig)) {
throw new Error(`Specified tsconfig file \`${tsconfig}\` does not exist.`);
}
return tsconfig;
}
const searchPath = this.workspacePath;
const tsconfig = this.ts.findConfigFile(searchPath, this.ts.sys.fileExists) ||
this.ts.findConfigFile(searchPath, this.ts.sys.fileExists, 'jsconfig.json');
return tsconfig;
}
}
exports.AstroCheck = AstroCheck;
//# sourceMappingURL=check.js.map
+59
View File
@@ -0,0 +1,59 @@
import type { ConvertToTSXOptions, TSXExtractedScript, TSXExtractedStyle, TSXResult } from '@astrojs/compiler/types';
import type { VirtualCode } from '@volar/language-core';
import { Range } from '@volar/language-server';
export interface LSPTSXRanges {
frontmatter: Range;
body: Range;
scripts: TSXExtractedScript[];
styles: TSXExtractedStyle[];
}
export declare function safeConvertToTSX(content: string, options: ConvertToTSXOptions): TSXResult | {
code: string;
map: {
file: string;
sources: never[];
sourcesContent: never[];
names: never[];
mappings: string;
version: number;
};
diagnostics: {
code: 1000;
location: {
file: string;
line: number;
column: number;
length: number;
};
severity: 1;
text: string;
}[];
metaRanges: {
frontmatter: {
start: number;
end: number;
};
body: {
start: number;
end: number;
};
scripts: never[];
styles: never[];
};
};
export declare function getTSXRangesAsLSPRanges(tsx: TSXResult): LSPTSXRanges;
export declare function astro2tsx(input: string, fileName: string): {
virtualCode: VirtualCode;
diagnostics: import("@astrojs/compiler").DiagnosticMessage[] | {
code: 1000;
location: {
file: string;
line: number;
column: number;
length: number;
};
severity: 1;
text: string;
}[];
ranges: LSPTSXRanges;
};
+144
View File
@@ -0,0 +1,144 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.safeConvertToTSX = safeConvertToTSX;
exports.getTSXRangesAsLSPRanges = getTSXRangesAsLSPRanges;
exports.astro2tsx = astro2tsx;
const sync_1 = require("@astrojs/compiler/sync");
const sourcemap_codec_1 = require("@jridgewell/sourcemap-codec");
const language_server_1 = require("@volar/language-server");
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
const utils_js_1 = require("./utils.js");
function safeConvertToTSX(content, options) {
try {
const tsx = (0, sync_1.convertToTSX)(content, {
filename: options.filename,
includeScripts: false,
includeStyles: false,
});
return tsx;
}
catch (e) {
console.error(`There was an error transforming ${options.filename} to TSX. An empty file will be returned instead. Please create an issue: https://github.com/withastro/astro/issues\nError: ${e}.`);
return {
code: '',
map: {
file: options.filename ?? '',
sources: [],
sourcesContent: [],
names: [],
mappings: '',
version: 0,
},
diagnostics: [
{
code: 1000,
location: { file: options.filename, line: 1, column: 1, length: content.length },
severity: 1,
text: `The Astro compiler encountered an unknown error while transform this file to TSX. Please create an issue with your code and the error shown in the server's logs: https://github.com/withastro/astro/issues`,
},
],
metaRanges: {
frontmatter: {
start: 0,
end: 0,
},
body: {
start: 0,
end: 0,
},
scripts: [],
styles: [],
},
};
}
}
function getTSXRangesAsLSPRanges(tsx) {
const textDocument = vscode_html_languageservice_1.TextDocument.create('', 'typescriptreact', 0, tsx.code);
return {
frontmatter: language_server_1.Range.create(textDocument.positionAt(tsx.metaRanges.frontmatter.start), textDocument.positionAt(tsx.metaRanges.frontmatter.end)),
body: language_server_1.Range.create(textDocument.positionAt(tsx.metaRanges.body.start), textDocument.positionAt(tsx.metaRanges.body.end)),
scripts: tsx.metaRanges.scripts ?? [],
styles: tsx.metaRanges.styles ?? [],
};
}
function astro2tsx(input, fileName) {
const tsx = safeConvertToTSX(input, { filename: fileName });
return {
virtualCode: getVirtualCodeTSX(input, tsx, fileName),
diagnostics: tsx.diagnostics,
ranges: getTSXRangesAsLSPRanges(tsx),
};
}
function getVirtualCodeTSX(input, tsx, fileName) {
tsx.code = (0, utils_js_1.patchTSX)(tsx.code, fileName);
const v3Mappings = (0, sourcemap_codec_1.decode)(tsx.map.mappings);
const sourcedDoc = vscode_html_languageservice_1.TextDocument.create('', 'astro', 0, input);
const genDoc = vscode_html_languageservice_1.TextDocument.create('', 'typescriptreact', 0, tsx.code);
const mappings = [];
let current;
for (let genLine = 0; genLine < v3Mappings.length; genLine++) {
for (const segment of v3Mappings[genLine]) {
const genCharacter = segment[0];
const genOffset = genDoc.offsetAt({ line: genLine, character: genCharacter });
if (current) {
let length = genOffset - current.genOffset;
const sourceText = input.substring(current.sourceOffset, current.sourceOffset + length);
const genText = tsx.code.substring(current.genOffset, current.genOffset + length);
if (sourceText !== genText) {
length = 0;
for (let i = 0; i < genOffset - current.genOffset; i++) {
if (sourceText[i] === genText[i]) {
length = i + 1;
}
else {
break;
}
}
}
if (length > 0) {
const lastMapping = mappings.length ? mappings[mappings.length - 1] : undefined;
if (lastMapping &&
lastMapping.generatedOffsets[0] + lastMapping.lengths[0] === current.genOffset &&
lastMapping.sourceOffsets[0] + lastMapping.lengths[0] === current.sourceOffset) {
lastMapping.lengths[0] += length;
}
else {
mappings.push({
sourceOffsets: [current.sourceOffset],
generatedOffsets: [current.genOffset],
lengths: [length],
data: {
verification: true,
completion: true,
semantic: true,
navigation: true,
structure: true,
format: false,
},
});
}
}
current = undefined;
}
if (segment[2] !== undefined && segment[3] !== undefined) {
const sourceOffset = sourcedDoc.offsetAt({ line: segment[2], character: segment[3] });
current = {
genOffset,
sourceOffset,
};
}
}
}
return {
id: 'tsx',
languageId: 'typescriptreact',
snapshot: {
getText: (start, end) => tsx.code.substring(start, end),
getLength: () => tsx.code.length,
getChangeRange: () => undefined,
},
mappings: mappings,
embeddedCodes: [],
};
}
//# sourceMappingURL=astro2tsx.js.map
@@ -0,0 +1,38 @@
import { type CodeMapping, type LanguagePlugin, type VirtualCode } from '@volar/language-core';
import type ts from 'typescript';
import type { URI } from 'vscode-uri';
export declare const SUPPORTED_FRONTMATTER_EXTENSIONS: {
md: string;
mdx: string;
mdoc: string;
};
export declare const SUPPORTED_FRONTMATTER_EXTENSIONS_KEYS: string[];
export declare const frontmatterRE: RegExp;
export type CollectionConfig = {
reload: (folders: {
uri: string;
}[]) => void;
configs: {
folder: URI;
config: CollectionConfigInstance;
}[];
};
export type CollectionConfigInstance = {
collections: {
hasSchema: boolean;
name: string;
}[];
entries: Record<string, string>;
};
export declare function getFrontmatterLanguagePlugin(collectionConfig: CollectionConfig): LanguagePlugin<URI, FrontmatterHolder>;
export declare class FrontmatterHolder implements VirtualCode {
id: string;
mappings: CodeMapping[];
embeddedCodes: VirtualCode[];
hasFrontmatter: boolean;
fileName: string;
languageId: string;
snapshot: ts.IScriptSnapshot;
collection: string | undefined;
constructor(fileName: string, languageId: string, snapshot: ts.IScriptSnapshot, collection: string | undefined);
}
+119
View File
@@ -0,0 +1,119 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FrontmatterHolder = exports.frontmatterRE = exports.SUPPORTED_FRONTMATTER_EXTENSIONS_KEYS = exports.SUPPORTED_FRONTMATTER_EXTENSIONS = void 0;
exports.getFrontmatterLanguagePlugin = getFrontmatterLanguagePlugin;
const yaml2ts_1 = require("@astrojs/yaml2ts");
const language_core_1 = require("@volar/language-core");
exports.SUPPORTED_FRONTMATTER_EXTENSIONS = { md: 'markdown', mdx: 'mdx', mdoc: 'markdoc' };
exports.SUPPORTED_FRONTMATTER_EXTENSIONS_KEYS = Object.keys(exports.SUPPORTED_FRONTMATTER_EXTENSIONS);
const SUPPORTED_FRONTMATTER_EXTENSIONS_VALUES = Object.values(exports.SUPPORTED_FRONTMATTER_EXTENSIONS);
exports.frontmatterRE = /^---(.*?)^---/ms;
function getCollectionName(collectionConfig, fileURI) {
for (const collection of collectionConfig.configs) {
if (collection.config.entries[fileURI]) {
return collection.config.entries[fileURI];
}
}
}
function getFrontmatterLanguagePlugin(collectionConfig) {
return {
getLanguageId(scriptId) {
const fileType = exports.SUPPORTED_FRONTMATTER_EXTENSIONS_KEYS.find((ext) => scriptId.path.endsWith(`.${ext}`));
if (fileType) {
return exports.SUPPORTED_FRONTMATTER_EXTENSIONS[fileType];
}
},
createVirtualCode(scriptId, languageId, snapshot) {
if (SUPPORTED_FRONTMATTER_EXTENSIONS_VALUES.includes(languageId)) {
return new FrontmatterHolder(scriptId.fsPath.replace(/\\/g, '/'), languageId, snapshot, getCollectionName(collectionConfig,
// The scriptId here is encoded and somewhat normalized, as such we can't use it directly to compare with
// the file URLs in the collection config entries that Astro generates.
decodeURIComponent(scriptId.toString()).toLowerCase()));
}
},
typescript: {
extraFileExtensions: exports.SUPPORTED_FRONTMATTER_EXTENSIONS_KEYS.map((ext) => ({
extension: ext,
isMixedContent: true,
scriptKind: 7,
})),
getServiceScript(astroCode) {
for (const code of (0, language_core_1.forEachEmbeddedCode)(astroCode)) {
if (code.id === yaml2ts_1.VIRTUAL_CODE_ID) {
return {
code,
extension: '.ts',
scriptKind: 3,
};
}
}
return undefined;
},
},
};
}
class FrontmatterHolder {
constructor(fileName, languageId, snapshot, collection) {
this.id = 'frontmatter-holder';
this.hasFrontmatter = false;
this.fileName = fileName;
this.languageId = languageId;
this.snapshot = snapshot;
this.collection = collection;
this.mappings = [
{
sourceOffsets: [0],
generatedOffsets: [0],
lengths: [this.snapshot.getLength()],
data: {
verification: true,
completion: true,
semantic: true,
navigation: true,
structure: true,
format: true,
},
},
];
this.embeddedCodes = [];
this.snapshot = snapshot;
if (!this.collection) {
// If the file is not part of a collection, we don't need to do anything
return;
}
const frontmatterContent = exports.frontmatterRE
.exec(this.snapshot.getText(0, this.snapshot.getLength()))?.[0]
.replaceAll('---', ' ') ?? '';
this.hasFrontmatter = frontmatterContent.length > 0;
this.embeddedCodes.push({
id: `yaml_frontmatter_${this.collection}`,
languageId: 'yaml',
snapshot: {
getText: (start, end) => frontmatterContent.substring(start, end),
getLength: () => frontmatterContent.length,
getChangeRange: () => undefined,
},
mappings: [
{
sourceOffsets: [0],
generatedOffsets: [0],
lengths: [frontmatterContent.length],
data: {
verification: true,
completion: true,
semantic: true,
navigation: true,
structure: true,
format: false,
},
},
],
});
if (this.hasFrontmatter) {
const yaml2tsResult = (0, yaml2ts_1.yaml2ts)(frontmatterContent, this.collection);
this.embeddedCodes.push(yaml2tsResult.virtualCode);
}
}
}
exports.FrontmatterHolder = FrontmatterHolder;
//# sourceMappingURL=frontmatterHolders.js.map
+23
View File
@@ -0,0 +1,23 @@
import type { DiagnosticMessage } from '@astrojs/compiler/types';
import { type CodeMapping, type LanguagePlugin, type VirtualCode } from '@volar/language-core';
import type ts from 'typescript';
import type { HTMLDocument } from 'vscode-html-languageservice';
import type { URI } from 'vscode-uri';
import type { PackageInfo } from '../importPackage.js';
import type { AstroMetadata } from './parseAstro.js';
export declare function addAstroTypes(astroInstall: PackageInfo | undefined, ts: typeof import('typescript'), host: ts.LanguageServiceHost): void;
export declare function getAstroLanguagePlugin(): LanguagePlugin<URI, AstroVirtualCode>;
export declare class AstroVirtualCode implements VirtualCode {
id: string;
languageId: string;
mappings: CodeMapping[];
embeddedCodes: VirtualCode[];
astroMeta: AstroMetadata;
compilerDiagnostics: DiagnosticMessage[];
htmlDocument: HTMLDocument;
codegenStacks: never[];
fileName: string;
snapshot: ts.IScriptSnapshot;
constructor(fileName: string, snapshot: ts.IScriptSnapshot);
get hasCompilationErrors(): boolean;
}
+185
View File
@@ -0,0 +1,185 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.AstroVirtualCode = void 0;
exports.addAstroTypes = addAstroTypes;
exports.getAstroLanguagePlugin = getAstroLanguagePlugin;
const path = __importStar(require("node:path"));
const language_core_1 = require("@volar/language-core");
const utils_js_1 = require("../utils.js");
const astro2tsx_js_1 = require("./astro2tsx.js");
const parseAstro_js_1 = require("./parseAstro.js");
const parseCSS_js_1 = require("./parseCSS.js");
const parseHTML_js_1 = require("./parseHTML.js");
const parseJS_js_1 = require("./parseJS.js");
const decoratedHosts = new WeakSet();
function addAstroTypes(astroInstall, ts, host) {
if (decoratedHosts.has(host)) {
return;
}
decoratedHosts.add(host);
const getScriptFileNames = host.getScriptFileNames.bind(host);
const getCompilationSettings = host.getCompilationSettings.bind(host);
host.getScriptFileNames = () => {
const languageServerTypesDirectory = (0, utils_js_1.getLanguageServerTypesDir)(ts);
const fileNames = getScriptFileNames();
const addedFileNames = [];
if (astroInstall) {
addedFileNames.push(...['./env.d.ts', './astro-jsx.d.ts'].map((filePath) => ts.sys.resolvePath(path.resolve(astroInstall.directory, filePath))));
// If Astro version is < 4.0.8, add jsx-runtime-augment.d.ts to the files to fake `JSX` being available from "astro/jsx-runtime".
// TODO: Remove this once a majority of users are on Astro 4.0.8+, erika - 2023-12-28
if (astroInstall.version.major < 4 ||
(astroInstall.version.major === 4 &&
astroInstall.version.minor === 0 &&
astroInstall.version.patch < 8)) {
addedFileNames.push(...['./jsx-runtime-augment.d.ts'].map((filePath) => ts.sys.resolvePath(path.resolve(languageServerTypesDirectory, filePath))));
}
}
else {
// If we don't have an Astro installation, add the fallback types from the language server.
// See the README in packages/language-server/types for more information.
addedFileNames.push(...['./env.d.ts', './astro-jsx.d.ts', './jsx-runtime-fallback.d.ts'].map((f) => ts.sys.resolvePath(path.resolve(languageServerTypesDirectory, f))));
}
return [...fileNames, ...addedFileNames];
};
host.getCompilationSettings = () => {
const baseCompilationSettings = getCompilationSettings();
return {
...baseCompilationSettings,
module: ts.ModuleKind.ESNext ?? 99,
target: ts.ScriptTarget.ESNext ?? 99,
jsx: ts.JsxEmit.Preserve ?? 1,
resolveJsonModule: true,
allowJs: true, // Needed for inline scripts, which are virtual .js files
isolatedModules: true,
moduleResolution: baseCompilationSettings.moduleResolution === ts.ModuleResolutionKind.Classic ||
!baseCompilationSettings.moduleResolution
? ts.ModuleResolutionKind.Node10
: baseCompilationSettings.moduleResolution,
};
};
}
function getAstroLanguagePlugin() {
return {
getLanguageId(uri) {
if (uri.path.endsWith('.astro')) {
return 'astro';
}
},
createVirtualCode(uri, languageId, snapshot) {
if (languageId === 'astro') {
const fileName = uri.fsPath.replace(/\\/g, '/');
return new AstroVirtualCode(fileName, snapshot);
}
},
typescript: {
extraFileExtensions: [{ extension: 'astro', isMixedContent: true, scriptKind: 7 }],
getServiceScript(astroCode) {
for (const code of (0, language_core_1.forEachEmbeddedCode)(astroCode)) {
if (code.id === 'tsx') {
return {
code,
extension: '.tsx',
scriptKind: 4,
};
}
}
return undefined;
},
getExtraServiceScripts(fileName, astroCode) {
const result = [];
for (const code of (0, language_core_1.forEachEmbeddedCode)(astroCode)) {
if (code.id.endsWith('.mjs') || code.id.endsWith('.mts')) {
const fileExtension = code.id.endsWith('.mjs') ? '.mjs' : '.mts';
result.push({
fileName: fileName + '.' + code.id,
code,
extension: fileExtension,
scriptKind: fileExtension === '.mjs'
? 1
: 3,
});
}
}
return result;
},
},
};
}
class AstroVirtualCode {
constructor(fileName, snapshot) {
this.id = 'root';
this.languageId = 'astro';
this.codegenStacks = [];
this.fileName = fileName;
this.snapshot = snapshot;
this.mappings = [
{
sourceOffsets: [0],
generatedOffsets: [0],
lengths: [this.snapshot.getLength()],
data: {
verification: true,
completion: true,
semantic: true,
navigation: true,
structure: true,
format: true,
},
},
];
const tsx = (0, astro2tsx_js_1.astro2tsx)(this.snapshot.getText(0, this.snapshot.getLength()), this.fileName);
const astroMetadata = (0, parseAstro_js_1.getAstroMetadata)(this.fileName, this.snapshot.getText(0, this.snapshot.getLength()));
const { htmlDocument, virtualCode: htmlVirtualCode } = (0, parseHTML_js_1.parseHTML)(this.snapshot, astroMetadata.frontmatter.status === 'closed'
? astroMetadata.frontmatter.position.end.offset
: 0);
this.htmlDocument = htmlDocument;
htmlVirtualCode.embeddedCodes = [
...(0, parseCSS_js_1.extractStylesheets)(tsx.ranges.styles),
...(0, parseJS_js_1.extractScriptTags)(tsx.ranges.scripts),
];
this.astroMeta = { ...astroMetadata, tsxRanges: tsx.ranges };
this.compilerDiagnostics = [...tsx.diagnostics, ...astroMetadata.diagnostics];
this.embeddedCodes = [htmlVirtualCode, tsx.virtualCode];
}
get hasCompilationErrors() {
return (
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
this.compilerDiagnostics.filter((diag) => diag.severity === 1)
.length > 0);
}
}
exports.AstroVirtualCode = AstroVirtualCode;
//# sourceMappingURL=index.js.map
+27
View File
@@ -0,0 +1,27 @@
import type { ParseOptions, ParseResult, Point } from '@astrojs/compiler/types';
import type { LSPTSXRanges } from './astro2tsx.js';
export type AstroMetadata = ParseResult & {
frontmatter: FrontmatterStatus;
tsxRanges: LSPTSXRanges;
};
export declare function getAstroMetadata(fileName: string, input: string, options?: ParseOptions): Omit<AstroMetadata, 'tsxRanges'>;
interface FrontmatterOpen {
status: 'open';
position: {
start: Point;
end: undefined;
};
}
interface FrontmatterClosed {
status: 'closed';
position: {
start: Point;
end: Point;
};
}
interface FrontmatterNull {
status: 'doesnt-exist';
position: undefined;
}
export type FrontmatterStatus = FrontmatterOpen | FrontmatterClosed | FrontmatterNull;
export {};
+85
View File
@@ -0,0 +1,85 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAstroMetadata = getAstroMetadata;
const sync_1 = require("@astrojs/compiler/sync");
function getAstroMetadata(fileName, input, options = { position: true }) {
const parseResult = safeParseAst(fileName, input, options);
return {
...parseResult,
frontmatter: getFrontmatterStatus(parseResult.ast, input),
};
}
function safeParseAst(fileName, input, parseOptions) {
try {
const parseResult = (0, sync_1.parse)(input, parseOptions);
return parseResult;
}
catch (e) {
console.error(`There was an error parsing ${fileName}'s AST. An empty AST will be returned instead to avoid breaking the server. Please create an issue: https://github.com/withastro/astro/issues\nError: ${e}.`);
return {
ast: {
type: 'root',
children: [],
},
diagnostics: [
{
code: 1000,
location: {
file: fileName,
line: 1,
column: 1,
length: input.length,
},
severity: 1,
text: `The Astro compiler encountered an unknown error while parsing this file's AST. Please create an issue with your code and the error shown in the server's logs: https://github.com/withastro/astro/issues`,
},
],
};
}
}
function getFrontmatterStatus(ast, text) {
if (!ast.children || (ast.children && ast.children.length === 0)) {
return {
status: 'doesnt-exist',
position: undefined,
};
}
if (ast.children[0].type === 'frontmatter') {
const frontmatter = ast.children[0];
if (frontmatter.position) {
if (frontmatter.position.end) {
// HACK: The compiler as of 1.5.5 always return an ending position, even if there's only a frontmatter opening
// This hack checks if the frontmatter's ending is the end of the file, and if so, checks if there's a `---`.
// If there's not, it means the compiler returned the EOF with an opened frontmatter
if (frontmatter.position.end.offset === text.length && !text.endsWith('---')) {
return {
status: 'open',
position: {
start: frontmatter.position.start,
end: undefined,
},
};
}
return {
status: 'closed',
position: {
start: frontmatter.position.start,
end: frontmatter.position.end,
},
};
}
return {
status: 'open',
position: {
start: frontmatter.position.start,
end: undefined,
},
};
}
}
return {
status: 'doesnt-exist',
position: undefined,
};
}
//# sourceMappingURL=parseAstro.js.map
+3
View File
@@ -0,0 +1,3 @@
import type { TSXExtractedStyle } from '@astrojs/compiler/types';
import type { VirtualCode } from '@volar/language-core';
export declare function extractStylesheets(styles: TSXExtractedStyle[]): VirtualCode[];
+63
View File
@@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractStylesheets = extractStylesheets;
const muggle_string_1 = require("muggle-string");
const buildMappings_js_1 = require("../buildMappings.js");
const SUPPORTED_LANGUAGES = ['css', 'scss', 'less'];
function isSupportedLanguage(lang) {
return SUPPORTED_LANGUAGES.includes(lang);
}
function extractStylesheets(styles) {
return mergeCSSContextsByLanguage(styles);
}
function mergeCSSContextsByLanguage(inlineStyles) {
const codes = {
css: [],
scss: [],
less: [],
};
for (const cssContext of inlineStyles) {
const currentCode = isSupportedLanguage(cssContext.lang) ? codes[cssContext.lang] : codes.css;
const isStyleAttribute = cssContext.type === 'style-attribute';
if (isStyleAttribute)
currentCode.push('__ { ');
currentCode.push([
cssContext.content,
undefined,
cssContext.position.start,
{
verification: false,
completion: true,
semantic: true,
navigation: true,
structure: true,
format: false,
},
]);
if (isStyleAttribute)
currentCode.push(' }\n');
}
let virtualCodes = [];
for (const lang of SUPPORTED_LANGUAGES) {
if (codes[lang].length) {
virtualCodes.push(createVirtualCodeForLanguage(codes[lang], lang));
}
}
return virtualCodes;
}
function createVirtualCodeForLanguage(code, lang) {
const mappings = (0, buildMappings_js_1.buildMappings)(code);
const text = (0, muggle_string_1.toString)(code);
return {
id: `style.${lang}`,
languageId: lang,
snapshot: {
getText: (start, end) => text.substring(start, end),
getLength: () => text.length,
getChangeRange: () => undefined,
},
embeddedCodes: [],
mappings,
};
}
//# sourceMappingURL=parseCSS.js.map
+11
View File
@@ -0,0 +1,11 @@
import type { VirtualCode } from '@volar/language-core';
import type ts from 'typescript';
import * as html from 'vscode-html-languageservice';
export declare function parseHTML(snapshot: ts.IScriptSnapshot, frontmatterEnd: number): {
virtualCode: VirtualCode;
htmlDocument: html.HTMLDocument;
};
/**
* scan the text and remove any `>` or `<` that cause the tag to end short
*/
export declare function preprocessHTML(text: string, frontmatterEnd?: number): string;
+124
View File
@@ -0,0 +1,124 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseHTML = parseHTML;
exports.preprocessHTML = preprocessHTML;
const html = __importStar(require("vscode-html-languageservice"));
const utils_1 = require("../plugins/utils");
const htmlLs = html.getLanguageService();
function parseHTML(snapshot, frontmatterEnd) {
const htmlContent = preprocessHTML(snapshot.getText(0, snapshot.getLength()), frontmatterEnd);
return {
virtualCode: getHTMLVirtualCode(htmlContent),
htmlDocument: getHTMLDocument(htmlContent),
};
}
const createScanner = htmlLs.createScanner;
/**
* scan the text and remove any `>` or `<` that cause the tag to end short
*/
function preprocessHTML(text, frontmatterEnd) {
let content = text.split('').fill(' ', 0, frontmatterEnd).join('');
let scanner = createScanner(content);
let token = scanner.scan();
let currentStartTagStart = null;
while (token !== html.TokenType.EOS) {
const offset = scanner.getTokenOffset();
if (token === html.TokenType.StartTagOpen) {
currentStartTagStart = offset;
}
if (token === html.TokenType.StartTagClose) {
if (shouldBlankStartOrEndTagLike(offset)) {
blankStartOrEndTagLike(offset);
}
else {
currentStartTagStart = null;
}
}
if (token === html.TokenType.StartTagSelfClose) {
currentStartTagStart = null;
}
// <Foo checked={a < 1}>
// https://github.com/microsoft/vscode-html-languageservice/blob/71806ef57be07e1068ee40900ef8b0899c80e68a/src/parser/htmlScanner.ts#L327
if (token === html.TokenType.Unknown &&
scanner.getScannerState() === html.ScannerState.WithinTag &&
scanner.getTokenText() === '<' &&
shouldBlankStartOrEndTagLike(offset)) {
blankStartOrEndTagLike(offset);
}
// TODO: Handle TypeScript generics inside expressions / Use the compiler to parse HTML instead?
token = scanner.scan();
}
return content;
function shouldBlankStartOrEndTagLike(offset) {
// not null rather than falsy; otherwise, it won't work on first tag(0)
return (currentStartTagStart !== null && (0, utils_1.isInsideExpression)(content, currentStartTagStart, offset));
}
function blankStartOrEndTagLike(offset, state) {
content = content.substring(0, offset) + ' ' + content.substring(offset + 1);
scanner = createScanner(content, offset, state ?? html.ScannerState.WithinTag);
}
}
function getHTMLVirtualCode(preprocessedHTML) {
return {
id: `html`,
languageId: 'html',
snapshot: {
getText: (start, end) => preprocessedHTML.substring(start, end),
getLength: () => preprocessedHTML.length,
getChangeRange: () => undefined,
},
mappings: [
{
sourceOffsets: [0],
generatedOffsets: [0],
lengths: [preprocessedHTML.length],
data: {
verification: true,
completion: true,
semantic: true,
navigation: true,
structure: true,
format: false,
},
},
],
embeddedCodes: [],
};
}
function getHTMLDocument(preprocessedHTML) {
return htmlLs.parseHTMLDocument({ getText: () => preprocessedHTML });
}
//# sourceMappingURL=parseHTML.js.map
+3
View File
@@ -0,0 +1,3 @@
import type { TSXExtractedScript } from '@astrojs/compiler/types';
import type { VirtualCode } from '@volar/language-core';
export declare function extractScriptTags(scripts: TSXExtractedScript[]): VirtualCode[];
+130
View File
@@ -0,0 +1,130 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractScriptTags = extractScriptTags;
const muggle_string_1 = require("muggle-string");
const buildMappings_1 = require("../buildMappings");
function extractScriptTags(scripts) {
const embeddedJSCodes = [];
const moduleScripts = scripts
.filter((script) => script.type === 'module' || script.type === 'processed-module')
.map(moduleScriptToVirtualCode);
const inlineScripts = scripts
.filter((script) =>
// TODO: Change this at some point so that unknown scripts are not included
// We can't guarantee that they are JavaScript, so we shouldn't treat them as such, even if it might work in some cases
// Perhaps we should make it so that the user has to specify the language of the script if it's not a known type (ex: lang="js"), not sure.
script.type === 'event-attribute' || script.type === 'inline' || script.type === 'unknown')
.sort((a, b) => a.position.start - b.position.start);
embeddedJSCodes.push(...moduleScripts);
const mergedJSContext = mergeJSContexts(inlineScripts);
if (mergedJSContext) {
embeddedJSCodes.push(mergedJSContext);
}
const JSONScripts = scripts
.filter((script) => script.type === 'json')
.map(jsonScriptToVirtualCode);
embeddedJSCodes.push(...JSONScripts);
return embeddedJSCodes;
}
function moduleScriptToVirtualCode(script, index) {
let extension = 'mts';
let languageId = 'typescript';
if (script.type === 'module') {
extension = 'mjs';
languageId = 'javascript';
}
return {
id: `${index}.${extension}`,
languageId,
snapshot: {
getText: (start, end) => script.content.substring(start, end),
getLength: () => script.content.length,
getChangeRange: () => undefined,
},
mappings: [
{
sourceOffsets: [script.position.start],
generatedOffsets: [0],
lengths: [script.content.length],
data: {
verification: true,
completion: true,
semantic: true,
navigation: true,
structure: true,
format: false,
},
},
],
embeddedCodes: [],
};
}
function jsonScriptToVirtualCode(script, index) {
return {
id: `${index}.json`,
languageId: 'json',
snapshot: {
getText: (start, end) => script.content.substring(start, end),
getLength: () => script.content.length,
getChangeRange: () => undefined,
},
mappings: [
{
sourceOffsets: [script.position.start],
generatedOffsets: [0],
lengths: [script.content.length],
// TODO: Support JSON features
data: {
verification: false,
completion: false,
semantic: false,
navigation: false,
structure: false,
format: false,
},
},
],
embeddedCodes: [],
};
}
/**
* Merge all the inline and non-hoisted scripts into a single `.mjs` file
*/
function mergeJSContexts(inlineScripts) {
if (inlineScripts.length === 0) {
return undefined;
}
const codes = [];
for (const javascriptContext of inlineScripts) {
codes.push([
// Add a semicolon to the end of the event attribute to attempt to prevent errors from spreading to the rest of the document
// This is not perfect, but it's better than nothing
// See: https://github.com/microsoft/vscode/blob/e8e04769ec817a3374c3eaa26a08d3ae491820d5/extensions/html-language-features/server/src/modes/embeddedSupport.ts#L192
javascriptContext.content + ';',
undefined,
javascriptContext.position.start,
{
verification: true,
completion: true,
semantic: true,
navigation: true,
structure: true,
format: false,
},
]);
}
const mappings = (0, buildMappings_1.buildMappings)(codes);
const text = (0, muggle_string_1.toString)(codes);
return {
id: 'inline.mjs',
languageId: 'javascript',
snapshot: {
getText: (start, end) => text.substring(start, end),
getLength: () => text.length,
getChangeRange: () => undefined,
},
embeddedCodes: [],
mappings,
};
}
//# sourceMappingURL=parseJS.js.map
+15
View File
@@ -0,0 +1,15 @@
import { type CodeInformation, type LanguagePlugin, type Mapping, type VirtualCode } from '@volar/language-core';
import type ts from 'typescript';
import type { URI } from 'vscode-uri';
export declare function getSvelteLanguagePlugin(): LanguagePlugin<URI, SvelteVirtualCode>;
declare class SvelteVirtualCode implements VirtualCode {
id: string;
languageId: string;
mappings: Mapping<CodeInformation>[];
embeddedCodes: VirtualCode[];
codegenStacks: never[];
fileName: string;
snapshot: ts.IScriptSnapshot;
constructor(fileName: string, snapshot: ts.IScriptSnapshot);
}
export {};
+47
View File
@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSvelteLanguagePlugin = getSvelteLanguagePlugin;
const language_core_1 = require("@volar/language-core");
const utils_js_1 = require("./utils.js");
function getSvelteLanguagePlugin() {
return {
getLanguageId(uri) {
if (uri.path.endsWith('.svelte')) {
return 'svelte';
}
},
createVirtualCode(uri, languageId, snapshot) {
if (languageId === 'svelte') {
const fileName = uri.fsPath.replace(/\\/g, '/');
return new SvelteVirtualCode(fileName, snapshot);
}
},
typescript: {
extraFileExtensions: [{ extension: 'svelte', isMixedContent: true, scriptKind: 7 }],
getServiceScript(svelteCode) {
for (const code of (0, language_core_1.forEachEmbeddedCode)(svelteCode)) {
if (code.id === 'tsx') {
return {
code,
extension: '.tsx',
scriptKind: 4,
};
}
}
},
},
};
}
class SvelteVirtualCode {
constructor(fileName, snapshot) {
this.id = 'root';
this.languageId = 'svelte';
this.codegenStacks = [];
this.fileName = fileName;
this.snapshot = snapshot;
this.mappings = [];
this.embeddedCodes = [];
this.embeddedCodes.push((0, utils_js_1.framework2tsx)(this.fileName, this.snapshot.getText(0, this.snapshot.getLength()), 'svelte'));
}
}
//# sourceMappingURL=svelte.js.map
+4
View File
@@ -0,0 +1,4 @@
import type { VirtualCode } from '@volar/language-core';
export declare function framework2tsx(filePath: string, sourceCode: string, framework: 'vue' | 'svelte'): VirtualCode;
export declare function classNameFromFilename(filename: string): string;
export declare function patchTSX(code: string, filePath: string): string;
+75
View File
@@ -0,0 +1,75 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.framework2tsx = framework2tsx;
exports.classNameFromFilename = classNameFromFilename;
exports.patchTSX = patchTSX;
const vscode_uri_1 = require("vscode-uri");
const importPackage_1 = require("../importPackage");
function framework2tsx(filePath, sourceCode, framework) {
const integrationEditorEntrypoint = framework === 'vue' ? (0, importPackage_1.importVueIntegration)(filePath) : (0, importPackage_1.importSvelteIntegration)(filePath);
if (!integrationEditorEntrypoint) {
const EMPTY_FILE = '';
return getVirtualCode(EMPTY_FILE);
}
const className = classNameFromFilename(filePath);
const tsx = patchTSX(integrationEditorEntrypoint.toTSX(sourceCode, className), filePath);
return getVirtualCode(tsx);
function getVirtualCode(content) {
return {
id: 'tsx',
languageId: 'typescript',
snapshot: {
getText: (start, end) => content.substring(start, end),
getLength: () => content.length,
getChangeRange: () => undefined,
},
mappings: [],
embeddedCodes: [],
};
}
}
/**
* Transform a string into PascalCase
*/
function toPascalCase(string) {
return `${string}`
.replace(new RegExp(/[-_]+/, 'g'), ' ')
.replace(new RegExp(/[^\w\s]/, 'g'), '')
.replace(new RegExp(/\s+(.)(\w*)/, 'g'), (_, $2, $3) => `${$2.toUpperCase() + $3.toLowerCase()}`)
.replace(new RegExp(/\w/), (s) => s.toUpperCase());
}
function classNameFromFilename(filename) {
const url = vscode_uri_1.URI.parse(filename);
const withoutExtensions = vscode_uri_1.Utils.basename(url).slice(0, -vscode_uri_1.Utils.extname(url).length);
const withoutInvalidCharacters = withoutExtensions
.split('')
// Although "-" is invalid, we leave it in, pascal-case-handling will throw it out later
.filter((char) => /[\w$-]/.test(char))
.join('');
const firstValidCharIdx = withoutInvalidCharacters
.split('')
// Although _ and $ are valid first characters for classes, they are invalid first characters
// for tag names. For a better import autocompletion experience, we therefore throw them out.
.findIndex((char) => /[A-Za-z]/.test(char));
const withoutLeadingInvalidCharacters = withoutInvalidCharacters.substring(firstValidCharIdx);
const inPascalCase = toPascalCase(withoutLeadingInvalidCharacters);
const finalName = firstValidCharIdx === -1 ? `A${inPascalCase}` : inPascalCase;
return finalName;
}
// TODO: Patch the upstream packages with these changes
function patchTSX(code, filePath) {
const url = vscode_uri_1.URI.parse(filePath);
const basename = vscode_uri_1.Utils.basename(url).slice(0, -vscode_uri_1.Utils.extname(url).length);
const isDynamic = basename.startsWith('[') && basename.endsWith(']');
return code.replace(/\b(\S*)__AstroComponent_/g, (fullMatch, m1) => {
// If we don't have a match here, it usually means the file has a weird name that couldn't be expressed with valid identifier characters
if (!m1) {
if (basename === '404')
return 'FourOhFourAstroComponent';
return fullMatch;
}
const componentName = isDynamic ? `_${m1}_` : m1[0].toUpperCase() + m1.slice(1);
return `${componentName}AstroComponent`;
});
}
//# sourceMappingURL=utils.js.map
+15
View File
@@ -0,0 +1,15 @@
import { type CodeInformation, type LanguagePlugin, type Mapping, type VirtualCode } from '@volar/language-core';
import type ts from 'typescript';
import type { URI } from 'vscode-uri';
export declare function getVueLanguagePlugin(): LanguagePlugin<URI, VueVirtualCode>;
declare class VueVirtualCode implements VirtualCode {
id: string;
languageId: string;
mappings: Mapping<CodeInformation>[];
embeddedCodes: VirtualCode[];
codegenStacks: never[];
fileName: string;
snapshot: ts.IScriptSnapshot;
constructor(fileName: string, snapshot: ts.IScriptSnapshot);
}
export {};
+47
View File
@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getVueLanguagePlugin = getVueLanguagePlugin;
const language_core_1 = require("@volar/language-core");
const utils_js_1 = require("./utils.js");
function getVueLanguagePlugin() {
return {
getLanguageId(uri) {
if (uri.path.endsWith('.vue')) {
return 'vue';
}
},
createVirtualCode(uri, languageId, snapshot) {
if (languageId === 'vue') {
const fileName = uri.fsPath.replace(/\\/g, '/');
return new VueVirtualCode(fileName, snapshot);
}
},
typescript: {
extraFileExtensions: [{ extension: 'vue', isMixedContent: true, scriptKind: 7 }],
getServiceScript(vueCode) {
for (const code of (0, language_core_1.forEachEmbeddedCode)(vueCode)) {
if (code.id === 'tsx') {
return {
code,
extension: '.tsx',
scriptKind: 4,
};
}
}
},
},
};
}
class VueVirtualCode {
constructor(fileName, snapshot) {
this.id = 'root';
this.languageId = 'vue';
this.codegenStacks = [];
this.fileName = fileName;
this.snapshot = snapshot;
this.mappings = [];
this.embeddedCodes = [];
this.embeddedCodes.push((0, utils_js_1.framework2tsx)(this.fileName, this.snapshot.getText(0, this.snapshot.getLength()), 'vue'));
}
}
//# sourceMappingURL=vue.js.map
+30
View File
@@ -0,0 +1,30 @@
import type * as prettier from 'prettier';
type PackageVersion = {
full: string;
major: number;
minor: number;
patch: number;
};
export declare function setIsTrusted(_isTrusted: boolean): void;
export type PackageInfo = {
entrypoint: string;
directory: string;
version: PackageVersion;
};
/**
* Get the path of a package's directory from the paths in `fromPath`, if `root` is set to false, it will return the path of the package's entry point
*/
export declare function getPackageInfo(packageName: string, fromPath: string[]): PackageInfo | undefined;
type SvelteIntegration = {
toTSX(code: string, className: string): string;
};
type VueIntegration = {
toTSX(code: string, className: string): string;
};
export declare function importSvelteIntegration(fromPath: string): SvelteIntegration | undefined;
export declare function importVueIntegration(fromPath: string): VueIntegration | undefined;
export declare function importPrettier(fromPath: string): typeof prettier | undefined;
export declare function getPrettierPluginPath(fromPath: string): string | undefined;
export declare function getWorkspacePnpPath(workspacePath: string): string | null;
export declare function parsePackageVersion(version: string): PackageVersion;
export {};
+106
View File
@@ -0,0 +1,106 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setIsTrusted = setIsTrusted;
exports.getPackageInfo = getPackageInfo;
exports.importSvelteIntegration = importSvelteIntegration;
exports.importVueIntegration = importVueIntegration;
exports.importPrettier = importPrettier;
exports.getPrettierPluginPath = getPrettierPluginPath;
exports.getWorkspacePnpPath = getWorkspacePnpPath;
exports.parsePackageVersion = parsePackageVersion;
const node_path_1 = require("node:path");
let isTrusted = true;
function setIsTrusted(_isTrusted) {
isTrusted = _isTrusted;
}
/**
* Get the path of a package's directory from the paths in `fromPath`, if `root` is set to false, it will return the path of the package's entry point
*/
function getPackageInfo(packageName, fromPath) {
const paths = [];
if (isTrusted) {
paths.unshift(...fromPath);
}
try {
const packageJSON = require.resolve(packageName + '/package.json', { paths });
return {
directory: (0, node_path_1.dirname)(packageJSON),
entrypoint: require.resolve(packageName, { paths }),
version: parsePackageVersion(require(packageJSON).version),
};
}
catch {
return undefined;
}
}
function importEditorIntegration(packageName, fromPath) {
const pkgPath = getPackageInfo(packageName, [fromPath])?.directory;
if (pkgPath) {
try {
const main = (0, node_path_1.resolve)(pkgPath, 'dist', 'editor.cjs');
return require(main);
}
catch (e) {
console.error(`Couldn't load editor module from ${pkgPath}. Make sure you're using at least version v0.2.1 of the corresponding integration. Reason: ${e}`);
return undefined;
}
}
else {
console.info(`Couldn't find package ${packageName} (searching from ${fromPath}). Make sure it's installed. If you believe this to be an error, please open an issue.`);
}
return undefined;
}
function importSvelteIntegration(fromPath) {
return importEditorIntegration('@astrojs/svelte', fromPath);
}
function importVueIntegration(fromPath) {
return importEditorIntegration('@astrojs/vue', fromPath);
}
function importPrettier(fromPath) {
let prettierPkg = getPackageInfo('prettier', [fromPath, __dirname]);
if (!prettierPkg) {
return undefined;
}
if (prettierPkg.version.major < 3) {
console.error(`Prettier version ${prettierPkg.version.full} from ${prettierPkg.directory} is not supported, please update to at least version 3.0.0. Falling back to bundled version to ensure formatting works correctly.`);
prettierPkg = getPackageInfo('prettier', [__dirname]);
if (!prettierPkg) {
return undefined;
}
}
return require(prettierPkg.entrypoint);
}
function getPrettierPluginPath(fromPath) {
const prettierPluginPath = getPackageInfo('prettier-plugin-astro', [
fromPath,
__dirname,
])?.entrypoint;
if (!prettierPluginPath) {
return undefined;
}
return prettierPluginPath;
}
function getWorkspacePnpPath(workspacePath) {
try {
const possiblePath = (0, node_path_1.resolve)(workspacePath, '.pnp.cjs');
require.resolve(possiblePath);
return possiblePath;
}
catch {
return null;
}
}
function parsePackageVersion(version) {
let [major, minor, patch] = version.split('.');
if (patch.includes('-')) {
const patchParts = patch.split('-');
patch = patchParts[0];
}
return {
full: version,
major: Number(major),
minor: Number(minor),
patch: Number(patch),
};
}
//# sourceMappingURL=importPackage.js.map
+1
View File
@@ -0,0 +1 @@
export { AstroCheck, CheckResult, Diagnostic, DiagnosticSeverity } from './check.js';
+8
View File
@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DiagnosticSeverity = exports.Diagnostic = exports.AstroCheck = void 0;
var check_js_1 = require("./check.js");
Object.defineProperty(exports, "AstroCheck", { enumerable: true, get: function () { return check_js_1.AstroCheck; } });
Object.defineProperty(exports, "Diagnostic", { enumerable: true, get: function () { return check_js_1.Diagnostic; } });
Object.defineProperty(exports, "DiagnosticSeverity", { enumerable: true, get: function () { return check_js_1.DiagnosticSeverity; } });
//# sourceMappingURL=index.js.map
+5
View File
@@ -0,0 +1,5 @@
import { type Connection, type InitializeParams, type LanguagePlugin } from '@volar/language-server/node';
import { URI } from 'vscode-uri';
import { type CollectionConfig } from './core/frontmatterHolders.js';
export declare function getLanguagePlugins(collectionConfig: CollectionConfig): LanguagePlugin<URI, import("@volar/language-server/node").VirtualCode>[];
export declare function getLanguageServicePlugins(connection: Connection, ts: typeof import('typescript'), collectionConfig: CollectionConfig, initializeParams?: InitializeParams): import("@volar/language-server/node").LanguageServicePlugin<any>[];
+118
View File
@@ -0,0 +1,118 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLanguagePlugins = getLanguagePlugins;
exports.getLanguageServicePlugins = getLanguageServicePlugins;
const node_1 = require("@volar/language-server/node");
// Services
const volar_service_css_1 = require("volar-service-css");
const volar_service_emmet_1 = require("volar-service-emmet");
const volar_service_prettier_1 = require("volar-service-prettier");
const volar_service_typescript_twoslash_queries_1 = require("volar-service-typescript-twoslash-queries");
const vscode_uri_1 = require("vscode-uri");
const core_1 = require("./core");
const frontmatterHolders_js_1 = require("./core/frontmatterHolders.js");
const svelte_js_1 = require("./core/svelte.js");
const vue_js_1 = require("./core/vue.js");
const importPackage_js_1 = require("./importPackage.js");
const astro_js_1 = require("./plugins/astro.js");
const html_js_1 = require("./plugins/html.js");
const index_js_1 = require("./plugins/typescript/index.js");
const index_js_2 = require("./plugins/typescript-addons/index.js");
const yaml_js_1 = require("./plugins/yaml.js");
function getLanguagePlugins(collectionConfig) {
const languagePlugins = [
(0, core_1.getAstroLanguagePlugin)(),
(0, vue_js_1.getVueLanguagePlugin)(),
(0, svelte_js_1.getSvelteLanguagePlugin)(),
(0, frontmatterHolders_js_1.getFrontmatterLanguagePlugin)(collectionConfig),
];
return languagePlugins;
}
function getLanguageServicePlugins(connection, ts, collectionConfig, initializeParams) {
const LanguageServicePlugins = [
(0, html_js_1.create)(),
(0, volar_service_css_1.create)(),
(0, volar_service_emmet_1.create)(),
...(0, index_js_1.create)(ts, {
disableAutoImportCache: initializeParams?.initializationOptions?.disableAutoImportCache,
}),
(0, volar_service_typescript_twoslash_queries_1.create)(ts),
(0, index_js_2.create)(),
(0, astro_js_1.create)(),
getPrettierService(),
(0, yaml_js_1.create)(collectionConfig),
];
return LanguageServicePlugins;
function getPrettierService() {
let prettier;
let prettierPluginPath;
let hasShownNotification = false;
return (0, volar_service_prettier_1.create)((context) => {
for (const workspaceFolder of context.env.workspaceFolders) {
if (workspaceFolder.scheme === 'file') {
prettier = (0, importPackage_js_1.importPrettier)(workspaceFolder.fsPath);
prettierPluginPath = (0, importPackage_js_1.getPrettierPluginPath)(workspaceFolder.fsPath);
if ((!prettier || !prettierPluginPath) && !hasShownNotification) {
connection.sendNotification(node_1.ShowMessageNotification.type, {
message: "Couldn't load `prettier` or `prettier-plugin-astro`. Formatting will not work. Please make sure those two packages are installed into your project and restart the language server.",
type: node_1.MessageType.Warning,
});
hasShownNotification = true;
}
return prettier;
}
}
}, {
documentSelector: ['astro'],
getFormattingOptions: async (prettierInstance, document, formatOptions, context) => {
const uri = vscode_uri_1.URI.parse(document.uri);
const documentUri = context.decodeEmbeddedDocumentUri(uri)?.[0] ?? uri;
const filePath = documentUri.fsPath;
if (!filePath) {
return {};
}
let configOptions = null;
try {
configOptions = await prettierInstance.resolveConfig(filePath, {
// This seems to be broken since Prettier 3, and it'll always use its cumbersome cache. Hopefully it works one day.
useCache: false,
editorconfig: true,
});
}
catch (e) {
connection.sendNotification(node_1.ShowMessageNotification.type, {
message: `Failed to load Prettier config.\n\nError:\n${e}`,
type: node_1.MessageType.Warning,
});
console.error('Failed to load Prettier config.', e);
}
const editorOptions = await context.env.getConfiguration?.('prettier', document.uri);
// Return a config with the following cascade:
// - Prettier config file should always win if it exists, if it doesn't:
// - Prettier config from the VS Code extension is used, if it doesn't exist:
// - Use the editor's basic configuration settings
const resolvedConfig = {
filepath: filePath,
tabWidth: formatOptions.tabSize,
useTabs: !formatOptions.insertSpaces,
...editorOptions,
...configOptions,
};
return {
...resolvedConfig,
plugins: [...(await getAstroPrettierPlugin()), ...(resolvedConfig.plugins ?? [])],
parser: 'astro',
};
async function getAstroPrettierPlugin() {
if (!prettier || !prettierPluginPath) {
return [];
}
const hasPluginLoadedAlready = (await prettier.getSupportInfo()).languages.some((l) => l.name === 'astro') ||
resolvedConfig.plugins?.includes('prettier-plugin-astro'); // getSupportInfo doesn't seems to work very well in Prettier 3 for plugins
return hasPluginLoadedAlready ? [] : [prettierPluginPath];
}
},
});
}
}
//# sourceMappingURL=languageServerPlugin.js.map
+1
View File
@@ -0,0 +1 @@
export {};
+103
View File
@@ -0,0 +1,103 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const node_1 = require("@volar/language-server/node");
const vscode_uri_1 = require("vscode-uri");
const frontmatterHolders_js_1 = require("./core/frontmatterHolders.js");
const index_js_1 = require("./core/index.js");
const languageServerPlugin_js_1 = require("./languageServerPlugin.js");
const utils_js_1 = require("./utils.js");
const connection = (0, node_1.createConnection)();
const server = (0, node_1.createServer)(connection);
let contentIntellisenseEnabled = false;
connection.listen();
connection.onInitialize((params) => {
const tsdk = params.initializationOptions?.typescript?.tsdk;
if (!tsdk) {
throw new Error('The `typescript.tsdk` init option is required. It should point to a directory containing a `typescript.js` or `tsserverlibrary.js` file, such as `node_modules/typescript/lib`.');
}
const { typescript, diagnosticMessages } = (0, node_1.loadTsdkByPath)(tsdk, params.locale);
contentIntellisenseEnabled = params.initializationOptions?.contentIntellisense ?? false;
const collectionConfig = {
reload(folders) {
this.configs = loadCollectionConfig(folders);
},
configs: contentIntellisenseEnabled
? loadCollectionConfig(
// The vast majority of clients support workspaceFolders, but sometimes some unusual environments like tests don't
// @ts-expect-error - Just deprecated types, it's fine
params.workspaceFolders ?? (params.rootUri ? [{ uri: params.rootUri }] : []) ?? [])
: [],
};
function loadCollectionConfig(folders) {
return folders.flatMap((folder) => {
try {
const folderUri = vscode_uri_1.URI.parse(folder.uri);
let config = server.fileSystem.readFile(vscode_uri_1.Utils.joinPath(folderUri, '.astro/collections/collections.json'));
if (!config) {
return [];
}
// `server.fs.readFile` can theoretically be async, but in practice it's always sync
const collections = JSON.parse(config);
return { folder: folderUri, config: collections };
}
catch (err) {
// If the file doesn't exist, we don't really care, but if it's something else, we want to know
if (err && err.code !== 'ENOENT')
console.error(err);
return [];
}
});
}
return server.initialize(params, (0, node_1.createTypeScriptProject)(typescript, diagnosticMessages, ({ env }) => {
return {
languagePlugins: (0, languageServerPlugin_js_1.getLanguagePlugins)(collectionConfig),
setup({ project }) {
const { languageServiceHost, configFileName } = project.typescript;
const rootPath = configFileName
? configFileName.split('/').slice(0, -1).join('/')
: env.workspaceFolders[0].fsPath;
const nearestPackageJson = typescript.findConfigFile(rootPath, typescript.sys.fileExists, 'package.json');
const astroInstall = (0, utils_js_1.getAstroInstall)([rootPath], {
nearestPackageJson: nearestPackageJson,
readDirectory: typescript.sys.readDirectory,
});
if (astroInstall === 'not-found') {
connection.sendNotification(node_1.ShowMessageNotification.type, {
message: `Couldn't find Astro in workspace "${rootPath}". Experience might be degraded. For the best experience, please make sure Astro is installed into your project and restart the language server.`,
type: node_1.MessageType.Warning,
});
}
(0, index_js_1.addAstroTypes)(typeof astroInstall === 'string' ? undefined : astroInstall, typescript, languageServiceHost);
},
};
}), (0, languageServerPlugin_js_1.getLanguageServicePlugins)(connection, typescript, collectionConfig, params));
});
connection.onInitialized(() => {
server.initialized();
const extensions = [
'js',
'cjs',
'mjs',
'ts',
'cts',
'mts',
'jsx',
'tsx',
'json',
'astro',
'vue',
'svelte',
];
if (contentIntellisenseEnabled) {
extensions.push(...frontmatterHolders_js_1.SUPPORTED_FRONTMATTER_EXTENSIONS_KEYS);
server.fileWatcher.watchFiles(['**/*.schema.json', '**/collections.json']);
server.fileWatcher.onDidChangeWatchedFiles(({ changes }) => {
const shouldReload = changes.some((change) => change.uri.endsWith('.schema.json') || change.uri.endsWith('collections.json'));
if (shouldReload) {
server.project.reload();
}
});
}
server.fileWatcher.watchFiles([`**/*.{${extensions.join(',')}}`]);
});
//# sourceMappingURL=nodeServer.js.map
+2
View File
@@ -0,0 +1,2 @@
import type { LanguageServicePlugin } from '@volar/language-server';
export declare const create: () => LanguageServicePlugin;
+105
View File
@@ -0,0 +1,105 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = void 0;
const language_server_1 = require("@volar/language-server");
const vscode_uri_1 = require("vscode-uri");
const index_js_1 = require("../core/index.js");
const create = () => {
return {
capabilities: {
completionProvider: {
triggerCharacters: ['-'],
},
diagnosticProvider: {
interFileDependencies: false,
workspaceDiagnostics: false,
},
},
create(context) {
return {
provideCompletionItems(document, position, completionContext, token) {
if (token.isCancellationRequested)
return null;
let items = [];
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(document.uri));
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
if (!(virtualCode instanceof index_js_1.AstroVirtualCode))
return;
if (completionContext.triggerCharacter === '-') {
const frontmatterCompletion = getFrontmatterCompletion(virtualCode, document, position);
if (frontmatterCompletion)
items.push(frontmatterCompletion);
}
return {
isIncomplete: false,
items: items,
};
},
provideDiagnostics(document, token) {
if (token.isCancellationRequested)
return [];
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(document.uri));
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
if (!(virtualCode instanceof index_js_1.AstroVirtualCode))
return;
return virtualCode.compilerDiagnostics.map(compilerMessageToDiagnostic);
function compilerMessageToDiagnostic(message) {
const start = language_server_1.Position.create(message.location.line - 1, message.location.column - 1);
const end = document.positionAt(document.offsetAt(start) + message.location.length);
return {
message: message.text + (message.hint ? '\n\n' + message.hint : ''),
range: language_server_1.Range.create(start, end),
code: message.code,
severity: message.severity,
source: 'astro',
};
}
},
};
},
};
};
exports.create = create;
function getFrontmatterCompletion(file, document, position) {
const base = {
kind: language_server_1.CompletionItemKind.Snippet,
label: '---',
sortText: '\0',
preselect: true,
detail: 'Create component script block',
insertTextFormat: language_server_1.InsertTextFormat.Snippet,
commitCharacters: [],
};
const documentLines = document.getText().split(/\r?\n/);
const { line, character } = document.positionAt(document.offsetAt(position));
const prefix = documentLines[line].slice(0, character);
if (file.astroMeta.frontmatter.status === 'doesnt-exist') {
return {
...base,
insertText: '---\n$0\n---',
textEdit: /^\s*-+/.test(prefix)
? language_server_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, '---\n$0\n---')
: undefined,
};
}
if (file.astroMeta.frontmatter.status === 'open') {
let insertText = '---';
// If the current line is a full component script starter/ender, the user expects a full frontmatter
// completion and not just a completion for "---" on the same line (which result in, well, nothing)
if (prefix === '---') {
insertText = '---\n$0\n---';
}
return {
...base,
insertText,
detail: insertText === '---' ? 'Close component script block' : 'Create component script block',
textEdit: /^\s*-+/.test(prefix)
? language_server_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, insertText)
: undefined,
};
}
return null;
}
//# sourceMappingURL=astro.js.map
+4
View File
@@ -0,0 +1,4 @@
export declare const classListAttribute: import("vscode-html-languageservice").IHTMLDataProvider;
export declare const astroElements: import("vscode-html-languageservice").IHTMLDataProvider;
export declare const astroAttributes: import("vscode-html-languageservice").IHTMLDataProvider;
export declare const astroDirectives: import("vscode-html-languageservice").IHTMLDataProvider;
+277
View File
@@ -0,0 +1,277 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.astroDirectives = exports.astroAttributes = exports.astroElements = exports.classListAttribute = void 0;
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
const defaultProvider = (0, vscode_html_languageservice_1.getDefaultHTMLDataProvider)();
const slotAttr = defaultProvider.provideAttributes('div').find((attr) => attr.name === 'slot');
exports.classListAttribute = (0, vscode_html_languageservice_1.newHTMLDataProvider)('class-list', {
version: 1,
globalAttributes: [
{
name: 'class:list',
description: 'Utility to provide a list of classes of the element. Takes an array of class values and converts them into a class string.',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#classlist',
},
],
},
],
});
exports.astroElements = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-elements', {
version: 1,
tags: [
{
name: 'slot',
description: 'The slot element is a placeholder for external HTML content, allowing you to inject (or “slot”) child elements from other files into your component template.',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/basics/astro-components/#slots',
},
],
attributes: [
{
name: 'name',
description: 'The name attribute allows you to pass only HTML elements with the corresponding slot name into a slots location.',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/basics/astro-components/#named-slots',
},
],
},
],
},
{
name: 'script',
attributes: [
{
// The VS Code tag definitions does not provide a description for the deprecated `charset` attribute on script tags
// Which mean that since we get no hover info for this, we instead get JSX hover info. So we'll just specify a description ourselves for this specific case
name: 'charset',
description: "**Deprecated**\n\nIt's unnecessary to specify the charset attribute, because documents must use UTF-8, and the script element inherits its character encoding from the document.",
},
{
name: 'define:vars',
description: 'Passes serializable server-side variables into a client-side script element.',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#definevars',
},
],
},
{
name: 'hoist',
description: '**Deprecated in Astro >= 0.26.0**\n\nBuilds, optimizes, and bundles your script with the other JavaScript on the page.',
valueSet: 'v',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/core-concepts/astro-components/#using-hoisted-scripts',
},
],
},
{
name: 'is:inline',
description: 'Leave a script tag inline in the page template. No processing will be done on its content.',
valueSet: 'v',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#isinline',
},
],
},
{
name: 'data-astro-rerun',
description: 'Force a script to be reexecuted when using <ViewTransitions/>. This will make your script is:inline as well.',
valueSet: 'v',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/guides/view-transitions/#data-astro-rerun',
},
],
},
],
},
{
name: 'style',
attributes: [
{
name: 'define:vars',
description: 'Passes serializable server-side variables into a client-side style element.',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#definevars',
},
],
},
{
name: 'global',
description: '**Deprecated in favor of `is:global` in >= Astro 0.26.0**\n\nOpts-out of automatic CSS scoping, all contents will be available globally.',
valueSet: 'v',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#isglobal',
},
],
},
{
name: 'is:global',
description: 'Opts-out of automatic CSS scoping, all contents will be available globally.',
valueSet: 'v',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#isglobal',
},
],
},
{
name: 'is:inline',
description: 'Leave a style tag inline in the page template. No processing will be done on its content.',
valueSet: 'v',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#isinline',
},
],
},
],
},
],
});
exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-attributes', {
version: 1,
globalAttributes: [
{
name: 'set:html',
description: 'Inject unescaped HTML into this tag.',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#sethtml',
},
],
},
{
name: 'set:text',
description: 'Inject escaped text into this tag.',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#settext',
},
],
},
{
name: 'is:raw',
description: 'Instructs the Astro compiler to treat any children of this element as text.',
valueSet: 'v',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#israw',
},
],
},
{
name: 'transition:animate',
description: 'Specifies an animation to use with this element on page transition.',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/guides/view-transitions/#transition-directives',
},
],
},
{
name: 'transition:name',
description: 'Specifies a `view-transition-name` for this element. The name must be unique on the page.',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/guides/view-transitions/#transition-directives',
},
],
},
{
name: 'transition:persist',
description: 'Marks this element to be moved to the next page during view transitions.',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/guides/view-transitions/#transition-directives',
},
],
},
slotAttr,
],
});
exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-directives', {
version: 1,
globalAttributes: [
{
name: 'client:load',
description: 'Start importing the component JS at page load. Hydrate the component when import completes.',
valueSet: 'v',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#clientload',
},
],
},
{
name: 'client:idle',
description: 'Start importing the component JS as soon as main thread is free (uses requestIdleCallback()). Hydrate the component when import completes.',
valueSet: 'v',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#clientidle',
},
],
},
{
name: 'client:visible',
description: 'Start importing the component JS as soon as the element enters the viewport (uses IntersectionObserver). Hydrate the component when import completes. Useful for content lower down on the page.',
valueSet: 'v',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#clientvisible',
},
],
},
{
name: 'client:media',
description: 'Start importing the component JS as soon as the browser matches the given media query (uses matchMedia). Hydrate the component when import completes. Useful for sidebar toggles, or other elements that should only display on mobile or desktop devices.',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#clientmedia',
},
],
},
{
name: 'client:only',
description: 'Start importing the component JS at page load and hydrate when the import completes, similar to client:load. The component will be skipped at build time, useful for components that are entirely dependent on client-side APIs. This is best avoided unless absolutely needed, in most cases it is best to render placeholder content on the server and delay any browser API calls until the component hydrates in the browser.',
valueSet: 'v',
references: [
{
name: 'Astro reference',
url: 'https://docs.astro.build/en/reference/directives-reference/#clientonly',
},
],
},
],
});
//# sourceMappingURL=html-data.js.map
+2
View File
@@ -0,0 +1,2 @@
import type { LanguageServicePlugin } from '@volar/language-server';
export declare const create: () => LanguageServicePlugin;
+110
View File
@@ -0,0 +1,110 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = void 0;
const language_server_1 = require("@volar/language-server");
const volar_service_html_1 = require("volar-service-html");
const html = __importStar(require("vscode-html-languageservice"));
const vscode_uri_1 = require("vscode-uri");
const index_js_1 = require("../core/index.js");
const html_data_js_1 = require("./html-data.js");
const utils_js_1 = require("./utils.js");
const create = () => {
const htmlPlugin = (0, volar_service_html_1.create)({
getCustomData: async (context) => {
const customData = (await context.env.getConfiguration?.('html.customData')) ?? [];
const newData = [];
for (const customDataPath of customData) {
for (const workspaceFolder of context.env.workspaceFolders) {
const uri = vscode_uri_1.Utils.resolvePath(workspaceFolder, customDataPath);
const json = await context.env.fs?.readFile?.(uri);
if (json) {
try {
const data = JSON.parse(json);
newData.push(html.newHTMLDataProvider(customDataPath, data));
}
catch (error) {
console.error(error);
}
break;
}
}
}
return [...newData, html_data_js_1.astroAttributes, html_data_js_1.astroElements, html_data_js_1.classListAttribute];
},
});
return {
...htmlPlugin,
create(context) {
const htmlPluginInstance = htmlPlugin.create(context);
return {
...htmlPluginInstance,
async provideCompletionItems(document, position, completionContext, token) {
if (document.languageId !== 'html')
return;
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(document.uri));
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
const root = sourceScript?.generated?.root;
if (!(root instanceof index_js_1.AstroVirtualCode))
return;
const offset = document.offsetAt(position);
// Don't return completions if the current node is a component
if ((0, utils_js_1.isInComponentStartTag)(root.htmlDocument, offset)) {
return null;
}
const currentNode = root.htmlDocument.findNodeAt(offset);
const sourceText = root.snapshot.getText(0, root.snapshot.getLength());
// Let the TypeScript service handle `{...}` expressions in HTML attributes.
if ((0, utils_js_1.isInsideExpression)(sourceText, currentNode.start, offset)) {
return null;
}
const completions = await htmlPluginInstance.provideCompletionItems(document, position, completionContext, token);
if (!completions) {
return null;
}
// We don't want completions for file references, as they're mostly invalid for Astro
completions.items = completions.items.filter((completion) => completion.kind !== language_server_1.CompletionItemKind.File);
return completions;
},
// Document links provided by `vscode-html-languageservice` are invalid for Astro
provideDocumentLinks() {
return [];
},
};
},
};
};
exports.create = create;
//# sourceMappingURL=html.js.map
@@ -0,0 +1,2 @@
import type { LanguageServicePlugin } from '@volar/language-server';
export declare const create: () => LanguageServicePlugin;
@@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = void 0;
const vscode_uri_1 = require("vscode-uri");
const index_js_1 = require("../../core/index.js");
const utils_js_1 = require("../utils.js");
const snippets_js_1 = require("./snippets.js");
const create = () => {
return {
capabilities: {
completionProvider: {
resolveProvider: true,
},
},
create(context) {
return {
isAdditionalCompletion: true,
// Q: Why the empty transform and resolve functions?
// A: Volar will skip mapping the completion items if those functions are defined, as such we can return the snippets
// completions as-is, this is notably useful for snippets that insert to the frontmatter, since we don't need to map anything.
transformCompletionItem(item) {
return item;
},
provideCompletionItems(document, position, completionContext, token) {
if (!context ||
!utils_js_1.isJSDocument ||
token.isCancellationRequested ||
completionContext.triggerKind === 2)
return null;
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(document.uri));
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
const root = sourceScript?.generated?.root;
if (!(root instanceof index_js_1.AstroVirtualCode))
return undefined;
if (!(0, utils_js_1.isInsideFrontmatter)(document.offsetAt(position), root.astroMeta.frontmatter))
return null;
const completionList = {
items: [],
isIncomplete: false,
};
completionList.items.push(...(0, snippets_js_1.getSnippetCompletions)(root.astroMeta.frontmatter));
return completionList;
},
resolveCompletionItem(item) {
return item;
},
};
},
};
};
exports.create = create;
//# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
import { type CompletionItem } from '@volar/language-server';
import type { FrontmatterStatus } from '../../core/parseAstro.js';
export declare function getSnippetCompletions(frontmatter: FrontmatterStatus): CompletionItem[];
@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSnippetCompletions = getSnippetCompletions;
const language_server_1 = require("@volar/language-server");
function getSnippetCompletions(frontmatter) {
if (frontmatter.status === 'doesnt-exist')
return [];
const frontmatterStartPosition = {
line: frontmatter.position.start.line,
character: frontmatter.position.start.column - 1,
};
return [
{
label: 'interface Props',
kind: language_server_1.CompletionItemKind.Snippet,
labelDetails: { description: 'Create a new interface to type your props' },
documentation: {
kind: 'markdown',
value: [
'Create a new interface to type your props.',
'\n',
'[Astro reference](https://docs.astro.build/en/guides/typescript/#component-props)',
].join('\n'),
},
insertTextFormat: 2,
filterText: 'interface props',
insertText: 'interface Props {\n\t$1\n}',
},
{
label: 'getStaticPaths',
kind: language_server_1.CompletionItemKind.Snippet,
labelDetails: { description: 'Create a new getStaticPaths function' },
documentation: {
kind: 'markdown',
value: [
'Create a new getStaticPaths function.',
'\n',
'[Astro reference](https://docs.astro.build/en/reference/routing-reference/#getstaticpaths)',
].join('\n'),
},
insertText: 'export const getStaticPaths = (() => {\n\t$1\n\treturn [];\n}) satisfies GetStaticPaths;',
additionalTextEdits: [
language_server_1.TextEdit.insert(frontmatterStartPosition, 'import type { GetStaticPaths } from "astro";\n'),
],
filterText: 'getstaticpaths',
insertTextFormat: 2,
},
{
label: 'prerender',
kind: language_server_1.CompletionItemKind.Snippet,
labelDetails: { description: 'Add prerender export' },
documentation: {
kind: 'markdown',
value: [
'Add prerender export. When [using server-side rendering](https://docs.astro.build/en/guides/on-demand-rendering/#enabling-on-demand-rendering), this value will be used to determine whether or not to prerender the page.',
'\n',
'[Astro reference](https://docs.astro.build/en/reference/routing-reference/#prerender)',
].join('\n'),
},
insertText: 'export const prerender = ${1|true,false|}',
insertTextFormat: 2,
},
];
}
//# sourceMappingURL=snippets.js.map
@@ -0,0 +1,3 @@
import type { CodeAction, LanguageServiceContext } from '@volar/language-service';
export declare function enhancedProvideCodeActions(codeActions: CodeAction[], context: LanguageServiceContext): CodeAction[];
export declare function enhancedResolveCodeAction(codeAction: CodeAction, context: LanguageServiceContext): CodeAction;
@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.enhancedProvideCodeActions = enhancedProvideCodeActions;
exports.enhancedResolveCodeAction = enhancedResolveCodeAction;
const language_server_1 = require("@volar/language-server");
const vscode_uri_1 = require("vscode-uri");
const index_js_1 = require("../../core/index.js");
const utils_js_1 = require("./utils.js");
function enhancedProvideCodeActions(codeActions, context) {
return codeActions.map((codeAction) => mapCodeAction(codeAction, context));
}
function enhancedResolveCodeAction(codeAction, context) {
/**
* TypeScript code actions don't come through here, as they're considered to be already fully resolved
* A lot of the code actions we'll encounter here are more tricky ones, such as fixAll or refactor
* For now, it seems like we don't need to do anything special here, but we'll keep this function around
*/
return mapCodeAction(codeAction, context);
}
function mapCodeAction(codeAction, context) {
if (!codeAction.edit || !codeAction.edit.documentChanges)
return codeAction;
codeAction.edit.documentChanges = codeAction.edit.documentChanges.map((change) => {
if (language_server_1.TextDocumentEdit.is(change)) {
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(change.textDocument.uri));
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
const root = sourceScript?.generated?.root;
if (!virtualCode || !(root instanceof index_js_1.AstroVirtualCode))
return change;
change.edits = change.edits.map((edit) => (0, utils_js_1.mapEdit)(edit, root, virtualCode.languageId));
}
return change;
});
return codeAction;
}
//# sourceMappingURL=codeActions.js.map
@@ -0,0 +1,3 @@
import type { CompletionItem, CompletionList, LanguageServiceContext } from '@volar/language-server';
export declare function enhancedProvideCompletionItems(ts: typeof import('typescript'), completions: CompletionList, documentText: string): CompletionList;
export declare function enhancedResolveCompletionItem(resolvedCompletion: CompletionItem, context: LanguageServiceContext): CompletionItem;
@@ -0,0 +1,109 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.enhancedProvideCompletionItems = enhancedProvideCompletionItems;
exports.enhancedResolveCompletionItem = enhancedResolveCompletionItem;
const language_server_1 = require("@volar/language-server");
const vscode_uri_1 = require("vscode-uri");
const index_js_1 = require("../../core/index.js");
const utils_js_1 = require("./utils.js");
function enhancedProvideCompletionItems(ts, completions, documentText) {
const importedAstroSources = (0, utils_js_1.getAlreadyImportedAstroComponentSources)(ts, documentText);
completions.items = completions.items
.filter((completion) => {
if (!isValidCompletion(completion)) {
return false;
}
const source = completion?.data?.originalItem?.source;
return !(source && importedAstroSources.has(source));
})
.map((completion) => {
const source = completion?.data?.originalItem?.source;
if (source) {
// Sort completions starting with `astro:` higher than other imports
if (source.startsWith('astro:')) {
completion.sortText = '\u0000' + (completion.sortText ?? completion.label);
}
// For components import, use the file kind and sort them first, as they're often what the user want over something else
if (['.astro', '.svelte', '.vue'].some((ext) => source.endsWith(ext))) {
completion.kind = language_server_1.CompletionItemKind.File;
completion.detail = completion.detail + '\n\n' + source;
completion.sortText = '\u0001' + (completion.sortText ?? completion.label);
completion.data.isComponent = true;
if ((0, utils_js_1.isAstroComponentImportSource)(source)) {
rewriteAstroComponentCompletion(completion);
}
}
}
return completion;
});
return completions;
}
function enhancedResolveCompletionItem(resolvedCompletion, context) {
// Make sure we keep our icons even when the completion is resolved
if (resolvedCompletion.data.isComponent) {
resolvedCompletion.detail = getDetailForFileCompletion(resolvedCompletion.detail ?? '', resolvedCompletion.data.originalItem.source);
}
if ((0, utils_js_1.isAstroComponentImportSource)(resolvedCompletion.data.originalItem.source)) {
rewriteAstroComponentCompletion(resolvedCompletion);
}
if (resolvedCompletion.additionalTextEdits) {
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(resolvedCompletion.data.uri));
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
const root = sourceScript?.generated?.root;
if (!virtualCode || !(root instanceof index_js_1.AstroVirtualCode))
return resolvedCompletion;
resolvedCompletion.additionalTextEdits = resolvedCompletion.additionalTextEdits.map((edit) => (0, utils_js_1.mapEdit)(edit, root, virtualCode.languageId));
}
return resolvedCompletion;
}
function rewriteAstroComponentCompletion(completion) {
completion.label = (0, utils_js_1.stripAstroComponentSuffix)(String(completion.label));
completion.filterText = completion.filterText
? (0, utils_js_1.stripAstroComponentSuffix)(completion.filterText)
: completion.filterText;
completion.insertText = completion.insertText
? (0, utils_js_1.stripAstroComponentSuffix)(completion.insertText)
: completion.insertText;
if (completion.textEdit && 'newText' in completion.textEdit) {
completion.textEdit.newText = (0, utils_js_1.stripAstroComponentSuffix)(completion.textEdit.newText);
}
if (completion.additionalTextEdits) {
completion.additionalTextEdits = completion.additionalTextEdits.map((edit) => ({
...edit,
newText: (0, utils_js_1.rewriteAstroImportText)(edit.newText),
}));
}
}
function getDetailForFileCompletion(detail, source) {
return `${detail}\n\n${source}`;
}
// When Svelte components are imported, we have to reference the svelte2tsx's types to properly type the component
// An unfortunate downside of this is that it pollutes completions, so let's filter those internal types manually
const svelte2tsxTypes = new Set([
'Svelte2TsxComponent',
'Svelte2TsxComponentConstructorParameters',
'SvelteComponentConstructor',
'SvelteActionReturnType',
'SvelteTransitionConfig',
'SvelteTransitionReturnType',
'SvelteAnimationReturnType',
'SvelteWithOptionalProps',
'SvelteAllProps',
'SveltePropsAnyFallback',
'SvelteSlotsAnyFallback',
'SvelteRestProps',
'SvelteSlots',
'SvelteStore',
]);
function isValidCompletion(completion) {
const isSvelte2tsxCompletion = completion.label.startsWith('__sveltets_') || svelte2tsxTypes.has(completion.label);
// Filter out completions for the children prop, as it doesn't work in Astro
const isChildrenCompletion = completion.label === 'children?' &&
completion.kind === language_server_1.CompletionItemKind.Field &&
completion.filterText === 'children={$1}';
if (isSvelte2tsxCompletion || isChildrenCompletion)
return false;
return true;
}
//# sourceMappingURL=completions.js.map
@@ -0,0 +1,12 @@
import type { Diagnostic } from '@volar/language-server';
export declare enum DiagnosticCodes {
IS_NOT_A_MODULE = 2306,// '{0}' is not a module.
CANNOT_FIND_MODULE = 2307,// Cannot find module '{0}' or its corresponding type declarations.
DUPLICATED_JSX_ATTRIBUTES = 17001,// JSX elements cannot have multiple attributes with the same name.
CANT_RETURN_OUTSIDE_FUNC = 1108,// A 'return' statement can only be used within a function body.
ISOLATED_MODULE_COMPILE_ERR = 1208,// '{0}' cannot be compiled under '--isolatedModules' because it is considered a global script file.
TYPE_NOT_ASSIGNABLE = 2322,// Type '{0}' is not assignable to type '{1}'.
JSX_NO_CLOSING_TAG = 17008,// JSX element '{0}' has no corresponding closing tag.
JSX_ELEMENT_NO_CALL = 2604
}
export declare function enhancedProvideSemanticDiagnostics(originalDiagnostics: Diagnostic[], tsxLineCount?: number): Diagnostic[];
@@ -0,0 +1,104 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DiagnosticCodes = void 0;
exports.enhancedProvideSemanticDiagnostics = enhancedProvideSemanticDiagnostics;
// List of codes:
// https://github.com/Microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
var DiagnosticCodes;
(function (DiagnosticCodes) {
DiagnosticCodes[DiagnosticCodes["IS_NOT_A_MODULE"] = 2306] = "IS_NOT_A_MODULE";
DiagnosticCodes[DiagnosticCodes["CANNOT_FIND_MODULE"] = 2307] = "CANNOT_FIND_MODULE";
DiagnosticCodes[DiagnosticCodes["DUPLICATED_JSX_ATTRIBUTES"] = 17001] = "DUPLICATED_JSX_ATTRIBUTES";
DiagnosticCodes[DiagnosticCodes["CANT_RETURN_OUTSIDE_FUNC"] = 1108] = "CANT_RETURN_OUTSIDE_FUNC";
DiagnosticCodes[DiagnosticCodes["ISOLATED_MODULE_COMPILE_ERR"] = 1208] = "ISOLATED_MODULE_COMPILE_ERR";
DiagnosticCodes[DiagnosticCodes["TYPE_NOT_ASSIGNABLE"] = 2322] = "TYPE_NOT_ASSIGNABLE";
DiagnosticCodes[DiagnosticCodes["JSX_NO_CLOSING_TAG"] = 17008] = "JSX_NO_CLOSING_TAG";
DiagnosticCodes[DiagnosticCodes["JSX_ELEMENT_NO_CALL"] = 2604] = "JSX_ELEMENT_NO_CALL";
})(DiagnosticCodes || (exports.DiagnosticCodes = DiagnosticCodes = {}));
function enhancedProvideSemanticDiagnostics(originalDiagnostics, tsxLineCount) {
const diagnostics = originalDiagnostics
.filter((diagnostic) => (tsxLineCount ? diagnostic.range.start.line <= tsxLineCount : true) &&
isNoCantReturnOutsideFunction(diagnostic) &&
isNoIsolatedModuleError(diagnostic) &&
isNoJsxCannotHaveMultipleAttrsError(diagnostic))
.map((diag) => tsxLineCount ? generalEnhancements(astroEnhancements(diag)) : generalEnhancements(diag));
return diagnostics;
}
// General enhancements that apply to all files
function generalEnhancements(diagnostic) {
if (diagnostic.code === DiagnosticCodes.CANNOT_FIND_MODULE &&
diagnostic.message.includes('astro:content')) {
diagnostic.message +=
"\n\nIf you're using content collections, make sure to run `astro dev`, `astro build` or `astro sync` to first generate the types so you can import from them. If you already ran one of those commands, restarting the language server might be necessary in order for the change to take effect.";
return diagnostic;
}
return diagnostic;
}
/**
* Astro-specific enhancements. For instance, when the user tries to import a component from a framework that is not installed
* or a difference with JSX needing a different error message
*/
function astroEnhancements(diagnostic) {
// When the language integrations are not installed, the content of the imported snapshot is empty
// As such, it triggers the "is not a module error", which we can enhance with a more helpful message for the related framework
if (diagnostic.code === DiagnosticCodes.IS_NOT_A_MODULE) {
if (diagnostic.message.includes('.svelte')) {
diagnostic.message +=
'\n\nIs the `@astrojs/svelte` package installed? You can add it to your project by running the following command: `astro add svelte`. If already installed, restarting the language server might be necessary in order for the change to take effect.';
}
if (diagnostic.message.includes('.vue')) {
diagnostic.message +=
'\n\nIs the `@astrojs/vue` package installed? You can add it to your project by running the following command: `astro add vue`. If already installed, restarting the language server might be necessary in order for the change to take effect.';
}
return diagnostic;
}
// JSX element has no closing tag. JSX -> HTML
if (diagnostic.code === DiagnosticCodes.JSX_NO_CLOSING_TAG) {
return {
...diagnostic,
message: diagnostic.message.replace('JSX', 'HTML'),
};
}
// JSX Element can't be constructed or called. This happens on syntax errors / invalid components
if (diagnostic.code === DiagnosticCodes.JSX_ELEMENT_NO_CALL) {
return {
...diagnostic,
message: diagnostic.message
.replace('JSX element type', 'Component')
.replace('does not have any construct or call signatures.', 'is not a valid component.\n\nIf this is a Svelte or Vue component, it might have a syntax error that makes it impossible to parse.'),
};
}
// For the rare case where an user might try to put a client directive on something that is not a component
if (diagnostic.code === DiagnosticCodes.TYPE_NOT_ASSIGNABLE) {
if (diagnostic.message.includes("Property 'client:") &&
diagnostic.message.includes("to type 'HTMLAttributes")) {
return {
...diagnostic,
message: diagnostic.message + '\n\nClient directives are only available on framework components.',
};
}
}
return diagnostic;
}
/**
* Astro allows multiple attributes to have the same name
*/
function isNoJsxCannotHaveMultipleAttrsError(diagnostic) {
return diagnostic.code !== DiagnosticCodes.DUPLICATED_JSX_ATTRIBUTES;
}
/**
* Ignore "Can't return outside of function body"
* Since the frontmatter is at the top level, users trying to return a Response for SSR mode run into this
* TODO: Update the TSX shape so this is not an issue anymore
*/
function isNoCantReturnOutsideFunction(diagnostic) {
return diagnostic.code !== DiagnosticCodes.CANT_RETURN_OUTSIDE_FUNC;
}
/**
* When the content of the file is invalid and can't be parsed properly for TSX generation, TS will show an error about
* how the current module can't be compiled under --isolatedModule, this is confusing to users so let's ignore this
*/
function isNoIsolatedModuleError(diagnostic) {
return diagnostic.code !== DiagnosticCodes.ISOLATED_MODULE_COMPILE_ERR;
}
//# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1,4 @@
import type { LanguageServicePlugin } from '@volar/language-server';
export declare const create: (ts: typeof import("typescript"), options?: {
disableAutoImportCache: boolean | undefined;
}) => LanguageServicePlugin[];
+79
View File
@@ -0,0 +1,79 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = void 0;
const volar_service_typescript_1 = require("volar-service-typescript");
const vscode_uri_1 = require("vscode-uri");
const index_js_1 = require("../../core/index.js");
const codeActions_js_1 = require("./codeActions.js");
const completions_js_1 = require("./completions.js");
const diagnostics_js_1 = require("./diagnostics.js");
const create = (ts, options) => {
const tsServicePlugins = (0, volar_service_typescript_1.create)(ts, {
disableAutoImportCache: options?.disableAutoImportCache,
});
return tsServicePlugins.map((plugin) => {
if (plugin.name === 'typescript-semantic') {
return {
...plugin,
create(context) {
const typeScriptPlugin = plugin.create(context);
return {
...typeScriptPlugin,
async provideFileRenameEdits(oldUri, newUri, token) {
const astroConfig = await context.env.getConfiguration?.('astro');
// Check for `false` explicitly, as the default value is `true`, but it might not be set explicitly depending on the editor
if (astroConfig?.updateImportsOnFileMove.enabled === false) {
return null;
}
return typeScriptPlugin.provideFileRenameEdits(oldUri, newUri, token);
},
async provideCompletionItems(document, position, completionContext, token) {
const originalCompletions = await typeScriptPlugin.provideCompletionItems(document, position, completionContext, token);
if (!originalCompletions)
return null;
return (0, completions_js_1.enhancedProvideCompletionItems)(ts, originalCompletions, document.getText());
},
async resolveCompletionItem(item, token) {
const resolvedCompletionItem = await typeScriptPlugin.resolveCompletionItem(item, token);
if (!resolvedCompletionItem)
return item;
return (0, completions_js_1.enhancedResolveCompletionItem)(resolvedCompletionItem, context);
},
async provideCodeActions(document, range, codeActionContext, token) {
const originalCodeActions = await typeScriptPlugin.provideCodeActions(document, range, codeActionContext, token);
if (!originalCodeActions)
return null;
return (0, codeActions_js_1.enhancedProvideCodeActions)(originalCodeActions, context);
},
async resolveCodeAction(codeAction, token) {
const resolvedCodeAction = await typeScriptPlugin.resolveCodeAction(codeAction, token);
if (!resolvedCodeAction)
return codeAction;
return (0, codeActions_js_1.enhancedResolveCodeAction)(resolvedCodeAction, context);
},
async provideDiagnostics(document, token) {
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(document.uri));
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
const root = sourceScript?.generated?.root;
let tsxLineCount = undefined;
if (root instanceof index_js_1.AstroVirtualCode && decoded?.[1] === 'tsx') {
// If we have compiler errors, our TSX isn't valid so don't bother showing TS errors
if (root.hasCompilationErrors)
return null;
// We'll use this to filter out diagnostics that are outside the mapped range of the TSX
tsxLineCount = root.astroMeta.tsxRanges.body.end.line;
}
const diagnostics = await typeScriptPlugin.provideDiagnostics(document, token);
if (!diagnostics)
return null;
return (0, diagnostics_js_1.enhancedProvideSemanticDiagnostics)(diagnostics, tsxLineCount);
},
};
},
};
}
return plugin;
});
};
exports.create = create;
//# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
import type { TextEdit } from 'vscode-html-languageservice';
import type { AstroVirtualCode } from '../../core/index.js';
export declare function isAstroComponentImportSource(source: string | undefined): source is string;
export declare function stripAstroComponentSuffix(name: string): string;
export declare function rewriteAstroImportText(text: string): string;
export declare function getAlreadyImportedAstroComponentSources(ts: typeof import('typescript'), documentText: string): Set<string>;
export declare function mapEdit(edit: TextEdit, code: AstroVirtualCode, languageId: string): TextEdit;
+90
View File
@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isAstroComponentImportSource = isAstroComponentImportSource;
exports.stripAstroComponentSuffix = stripAstroComponentSuffix;
exports.rewriteAstroImportText = rewriteAstroImportText;
exports.getAlreadyImportedAstroComponentSources = getAlreadyImportedAstroComponentSources;
exports.mapEdit = mapEdit;
const utils_js_1 = require("../utils.js");
const ASTRO_COMPONENT_SUFFIX = 'AstroComponent';
const ASTRO_IMPORT_FROM_PATTERN = /\bfrom\s+['"][^'"]+\.astro['"]/;
const ASTRO_DEFAULT_IMPORT_PATTERN = /^(\s*import(?:\s+type)?\s+)([A-Za-z_$][\w$]*)AstroComponent(?=\s*,|\s+from\b)/;
const ASTRO_DEFAULT_ALIAS_PATTERN = /(default\s+as\s+)([A-Za-z_$][\w$]*)AstroComponent(?=\s*\})/;
function isAstroComponentImportSource(source) {
return !!source && source.endsWith('.astro');
}
function stripAstroComponentSuffix(name) {
if (!name.endsWith(ASTRO_COMPONENT_SUFFIX)) {
return name;
}
return name.slice(0, -ASTRO_COMPONENT_SUFFIX.length);
}
function rewriteAstroImportText(text) {
return text
.split('\n')
.map((line) => {
if (!ASTRO_IMPORT_FROM_PATTERN.test(line)) {
return line;
}
return line
.replace(ASTRO_DEFAULT_IMPORT_PATTERN, '$1$2')
.replace(ASTRO_DEFAULT_ALIAS_PATTERN, '$1$2');
})
.join('\n');
}
function getAlreadyImportedAstroComponentSources(ts, documentText) {
const sources = new Set();
const sourceFile = ts.createSourceFile('component-imports.tsx', getImportParseText(documentText), ts.ScriptTarget.Latest, false, ts.ScriptKind.TSX);
for (const statement of sourceFile.statements) {
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) {
continue;
}
const source = statement.moduleSpecifier.text;
const importClause = statement.importClause;
if (!importClause || importClause.isTypeOnly || !isAstroComponentImportSource(source)) {
continue;
}
if (importClause.name) {
sources.add(source);
continue;
}
const namedBindings = importClause.namedBindings;
if (!namedBindings || !ts.isNamedImports(namedBindings)) {
continue;
}
if (namedBindings.elements.some((element) => element.propertyName?.text === 'default')) {
sources.add(source);
}
}
return sources;
}
function getImportParseText(documentText) {
if (!documentText.startsWith('---')) {
return documentText;
}
const lines = documentText.split('\n');
if (lines[0]?.trim() !== '---') {
return documentText;
}
const closingFrontmatterLine = lines.findIndex((line, index) => index > 0 && line.trim() === '---');
return lines
.slice(1, closingFrontmatterLine === -1 ? undefined : closingFrontmatterLine)
.join('\n');
}
function mapEdit(edit, code, languageId) {
// Don't attempt to move the edit to the frontmatter if the file isn't the root TSX file, it means it's a script tag
if (languageId === 'typescriptreact') {
if ((0, utils_js_1.editShouldBeInFrontmatter)(edit.range, code.astroMeta).itShould) {
edit = (0, utils_js_1.ensureProperEditForFrontmatter)(edit, code.astroMeta, '\n');
}
}
else {
// If the edit is at the start of the file, add a newline before it; otherwise, we'll get `<script>text`
if (edit.range.start.line === 0 && edit.range.start.character === 0) {
edit.newText = '\n' + edit.newText;
}
}
edit.newText = rewriteAstroImportText(edit.newText);
return edit;
}
//# sourceMappingURL=utils.js.map
+38
View File
@@ -0,0 +1,38 @@
import type { HTMLDocument, Node, TextEdit } from 'vscode-html-languageservice';
import { Range } from 'vscode-html-languageservice';
import type { AstroMetadata, FrontmatterStatus } from '../core/parseAstro.js';
export declare function isJSDocument(languageId: string): languageId is "typescript" | "typescriptreact" | "javascript" | "javascriptreact";
/**
* Return true if a specific node could be a component.
* This is not a 100% sure test as it'll return false for any component that does not match the standard format for a component
*/
export declare function isPossibleComponent(node: Node): boolean;
/**
* Return if a given offset is inside the start tag of a component
*/
export declare function isInComponentStartTag(html: HTMLDocument, offset: number): boolean;
/**
* Return if a given position is inside a JSX expression
*/
export declare function isInsideExpression(html: string, tagStart: number, position: number): boolean;
/**
* Return if a given offset is inside the frontmatter
*/
export declare function isInsideFrontmatter(offset: number, frontmatter: FrontmatterStatus): boolean;
type FrontmatterEditPosition = 'top' | 'bottom';
export declare function ensureProperEditForFrontmatter(edit: TextEdit, metadata: AstroMetadata, newLine: string, position?: FrontmatterEditPosition): TextEdit;
/**
* Force a range to be at the start of the frontmatter if it is outside
*/
export declare function ensureRangeIsInFrontmatter(range: Range, metadata: AstroMetadata, position?: FrontmatterEditPosition): Range;
export declare function getNewFrontmatterEdit(edit: TextEdit, astroMetadata: AstroMetadata, newLine: string): TextEdit;
export declare function getOpenFrontmatterEdit(edit: TextEdit, astroMetadata: AstroMetadata, newLine: string): TextEdit;
type FrontmatterEditValidity = {
itShould: false;
position: undefined;
} | {
itShould: true;
position: FrontmatterEditPosition;
};
export declare function editShouldBeInFrontmatter(range: Range, astroMetadata: AstroMetadata): FrontmatterEditValidity;
export {};
+114
View File
@@ -0,0 +1,114 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isJSDocument = isJSDocument;
exports.isPossibleComponent = isPossibleComponent;
exports.isInComponentStartTag = isInComponentStartTag;
exports.isInsideExpression = isInsideExpression;
exports.isInsideFrontmatter = isInsideFrontmatter;
exports.ensureProperEditForFrontmatter = ensureProperEditForFrontmatter;
exports.ensureRangeIsInFrontmatter = ensureRangeIsInFrontmatter;
exports.getNewFrontmatterEdit = getNewFrontmatterEdit;
exports.getOpenFrontmatterEdit = getOpenFrontmatterEdit;
exports.editShouldBeInFrontmatter = editShouldBeInFrontmatter;
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
function isJSDocument(languageId) {
return (languageId === 'javascript' ||
languageId === 'typescript' ||
languageId === 'javascriptreact' ||
languageId === 'typescriptreact');
}
/**
* Return true if a specific node could be a component.
* This is not a 100% sure test as it'll return false for any component that does not match the standard format for a component
*/
function isPossibleComponent(node) {
if (!node.tag)
return false;
return !!/[A-Z]/.test(node.tag?.[0]) || !!/.+\.[A-Z]?/.test(node.tag);
}
/**
* Return if a given offset is inside the start tag of a component
*/
function isInComponentStartTag(html, offset) {
const node = html.findNodeAt(offset);
return isPossibleComponent(node) && (!node.startTagEnd || offset < node.startTagEnd);
}
/**
* Return if a given position is inside a JSX expression
*/
function isInsideExpression(html, tagStart, position) {
const charactersInNode = html.substring(tagStart, position);
return charactersInNode.lastIndexOf('{') > charactersInNode.lastIndexOf('}');
}
/**
* Return if a given offset is inside the frontmatter
*/
function isInsideFrontmatter(offset, frontmatter) {
switch (frontmatter.status) {
case 'closed':
return offset > frontmatter.position.start.offset && offset < frontmatter.position.end.offset;
case 'open':
return offset > frontmatter.position.start.offset;
case 'doesnt-exist':
return false;
}
}
function ensureProperEditForFrontmatter(edit, metadata, newLine, position = 'top') {
switch (metadata.frontmatter.status) {
case 'open':
return getOpenFrontmatterEdit(edit, metadata, newLine);
case 'closed':
const newRange = ensureRangeIsInFrontmatter(edit.range, metadata, position);
return {
newText: newRange.start.line === metadata.frontmatter.position.start.line &&
edit.newText.startsWith(newLine)
? edit.newText.trimStart()
: edit.newText,
range: newRange,
};
case 'doesnt-exist':
return getNewFrontmatterEdit(edit, metadata, newLine);
}
}
/**
* Force a range to be at the start of the frontmatter if it is outside
*/
function ensureRangeIsInFrontmatter(range, metadata, position = 'top') {
if (metadata.frontmatter.status === 'open' || metadata.frontmatter.status === 'closed') {
const frontmatterEndPosition = metadata.frontmatter.position.end
? metadata.tsxRanges.frontmatter.end
: undefined;
// If the range start is outside the frontmatter, return a range at the start of the frontmatter
if (range.start.line < metadata.tsxRanges.frontmatter.start.line ||
(frontmatterEndPosition && range.start.line > frontmatterEndPosition.line)) {
if (frontmatterEndPosition && position === 'bottom') {
return vscode_html_languageservice_1.Range.create(frontmatterEndPosition, frontmatterEndPosition);
}
return vscode_html_languageservice_1.Range.create(metadata.tsxRanges.frontmatter.start, metadata.tsxRanges.frontmatter.start);
}
return range;
}
return range;
}
function getNewFrontmatterEdit(edit, astroMetadata, newLine) {
edit.newText = `---${edit.newText.startsWith(newLine) ? '' : newLine}${edit.newText}---${newLine}${newLine}`;
edit.range = vscode_html_languageservice_1.Range.create(astroMetadata.tsxRanges.frontmatter.start, astroMetadata.tsxRanges.frontmatter.start);
return edit;
}
function getOpenFrontmatterEdit(edit, astroMetadata, newLine) {
edit.newText = edit.newText.startsWith(newLine)
? `${edit.newText}---`
: `${newLine}${edit.newText}---`;
edit.range = vscode_html_languageservice_1.Range.create(astroMetadata.tsxRanges.frontmatter.start, astroMetadata.tsxRanges.frontmatter.start);
return edit;
}
// Most edits that are at the beginning of the TSX, or outside the document are intended for the frontmatter
function editShouldBeInFrontmatter(range, astroMetadata) {
const isAtTSXStart = range.start.line < astroMetadata.tsxRanges.frontmatter.start.line;
const isPastFile = range.start.line > astroMetadata.tsxRanges.body.end.line;
const shouldIt = isAtTSXStart || isPastFile;
return shouldIt
? { itShould: true, position: isPastFile ? 'bottom' : 'top' }
: { itShould: false, position: undefined };
}
//# sourceMappingURL=utils.js.map
+7
View File
@@ -0,0 +1,7 @@
import type { LanguageServicePlugin } from '@volar/language-service';
import type { Provide } from 'volar-service-yaml';
import type { CollectionConfig } from '../core/frontmatterHolders.js';
type LanguageSettings = Parameters<ReturnType<Provide['yaml/languageService']>['configure']>['0'];
export declare function getSettings(collectionConfig: CollectionConfig): LanguageSettings;
export declare const create: (collectionConfig: CollectionConfig) => LanguageServicePlugin;
export {};
+113
View File
@@ -0,0 +1,113 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = void 0;
exports.getSettings = getSettings;
const language_server_1 = require("@volar/language-server");
const volar_service_yaml_1 = require("volar-service-yaml");
const vscode_uri_1 = require("vscode-uri");
const frontmatterHolders_js_1 = require("../core/frontmatterHolders.js");
function getSettings(collectionConfig) {
const schemas = collectionConfig.configs.flatMap((workspaceCollectionConfig) => {
return workspaceCollectionConfig.config.collections.flatMap((collection) => {
return {
fileMatch: frontmatterHolders_js_1.SUPPORTED_FRONTMATTER_EXTENSIONS_KEYS.map((ext) => `volar-embedded-content://yaml_frontmatter_${collection.name}/**/*${ext}`),
uri: vscode_uri_1.Utils.joinPath(workspaceCollectionConfig.folder, '.astro/collections', `${collection.name}.schema.json`).toString(),
};
});
});
return {
completion: true,
format: false,
hover: true,
validate: true,
customTags: [],
yamlVersion: '1.2',
isKubernetes: false,
parentSkeletonSelectedFirst: false,
disableDefaultProperties: false,
schemas: schemas,
};
}
const create = (collectionConfig) => {
const yamlPlugin = (0, volar_service_yaml_1.create)({
getLanguageSettings: () => getSettings(collectionConfig),
});
return {
...yamlPlugin,
capabilities: {
...yamlPlugin.capabilities,
codeLensProvider: undefined,
},
create(context) {
const yamlPluginInstance = yamlPlugin.create(context);
const languageService = yamlPluginInstance.provide?.['yaml/languageService']();
if (languageService && context.env.onDidChangeWatchedFiles) {
context.env.onDidChangeWatchedFiles(async (events) => {
const changedSchemas = events.changes.filter((change) => change.uri.endsWith('.schema.json'));
const changedConfig = events.changes.some((change) => change.uri.endsWith('collections.json'));
if (changedConfig) {
collectionConfig.reload(
// For some reason, context.env.workspaceFolders is neither an array of WorkspaceFolders nor the older format, strange
context.env.workspaceFolders.map((folder) => ({ uri: folder.toString() })));
languageService.configure(getSettings(collectionConfig));
}
for (const change of changedSchemas) {
languageService.resetSchema(change.uri);
}
});
}
return {
...yamlPluginInstance,
// Disable codelenses, we'll provide our own
provideCodeLenses: undefined,
resolveCodeLens: undefined,
async provideDiagnostics(document, token) {
const originalDiagnostics = await yamlPluginInstance.provideDiagnostics(document, token);
if (!originalDiagnostics) {
return null;
}
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(document.uri));
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
const root = sourceScript?.generated?.root;
if (!(root instanceof frontmatterHolders_js_1.FrontmatterHolder))
return undefined;
// If we don't have a frontmatter, but there are errors, it probably means a frontmatter was required
if (!root.hasFrontmatter && originalDiagnostics.length > 0) {
return [
language_server_1.Diagnostic.create(language_server_1.Range.create(0, 0, 0, 0), 'Frontmatter is required for this file.', language_server_1.DiagnosticSeverity.Error),
];
}
return originalDiagnostics.map((diagnostic) => {
// The YAML schema source is not useful to users, since it's generated. Also, it's quite long.
if (diagnostic.source?.startsWith('yaml-schema:')) {
diagnostic.source = 'astro';
// In Astro, schema errors are always fatal
diagnostic.severity = language_server_1.DiagnosticSeverity.Error;
// Map missing properties to the entire frontmatter
if (diagnostic.message.startsWith('Missing property')) {
diagnostic.range = language_server_1.Range.create({ line: 0, character: 0 }, document.positionAt(document.getText().length));
}
}
return diagnostic;
});
},
async provideHover(document, position, token) {
const originalHover = await yamlPluginInstance.provideHover(document, position, token);
if (!originalHover) {
return null;
}
if (language_server_1.MarkupContent.is(originalHover.contents)) {
// Remove last line that contains the source schema, it's not useful to users since they're generated
originalHover.contents.value = originalHover.contents.value
.replace(/\nSource:.*$/, '')
.replace(/\n\nsource$/, '')
.trim();
}
return originalHover;
},
};
},
};
};
exports.create = create;
//# sourceMappingURL=yaml.js.map
+6
View File
@@ -0,0 +1,6 @@
import type { PackageInfo } from './importPackage.js';
export declare function getLanguageServerTypesDir(ts: typeof import('typescript')): string;
export declare function getAstroInstall(basePaths: string[], checkForAstro?: {
nearestPackageJson: string | undefined;
readDirectory: typeof import('typescript').sys.readDirectory;
}): PackageInfo | 'not-an-astro-project' | 'not-found';
+75
View File
@@ -0,0 +1,75 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLanguageServerTypesDir = getLanguageServerTypesDir;
exports.getAstroInstall = getAstroInstall;
const path = __importStar(require("node:path"));
const importPackage_js_1 = require("./importPackage.js");
function getLanguageServerTypesDir(ts) {
return ts.sys.resolvePath(path.resolve(__dirname, '../types'));
}
function getAstroInstall(basePaths, checkForAstro) {
if (checkForAstro && checkForAstro.nearestPackageJson) {
basePaths.push(path.dirname(checkForAstro.nearestPackageJson));
let deps = new Set();
try {
const packageJSON = require(checkForAstro.nearestPackageJson);
[
...Object.keys(packageJSON.dependencies ?? {}),
...Object.keys(packageJSON.devDependencies ?? {}),
...Object.keys(packageJSON.peerDependencies ?? {}),
].forEach((dep) => deps.add(dep));
}
catch { }
if (!deps.has('astro')) {
const directoryContent = checkForAstro.readDirectory(path.dirname(checkForAstro.nearestPackageJson), ['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'], undefined, undefined, 1);
if (!directoryContent.some((file) => path.basename(file).startsWith('astro.config'))) {
return 'not-an-astro-project';
}
}
}
let astroPackage = (0, importPackage_js_1.getPackageInfo)('astro', basePaths);
if (!astroPackage) {
// If we couldn't find it inside the workspace's node_modules, it might means we're in the Astro development monorepo
astroPackage = (0, importPackage_js_1.getPackageInfo)('./packages/astro', basePaths);
if (!astroPackage) {
console.error(`${basePaths[0]} seems to be an Astro project, but we couldn't find Astro or Astro is not installed`);
// If we still couldn't find it, it probably just doesn't exist
return 'not-found';
}
}
return astroPackage;
}
//# sourceMappingURL=utils.js.map
@@ -0,0 +1,53 @@
MIT License
Copyright (c) 2021 [Astro contributors](https://github.com/withastro/compiler/graphs/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
This license applies to parts of the `internal/` subdirectory originating from
the https://cs.opensource.google/go/x/net/+/master:html/ repository:
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,72 @@
# Astro Compiler
Astros [Go](https://golang.org/) + WASM compiler.
## Install
```
npm install @astrojs/compiler
```
## Usage
#### Transform `.astro` to valid TypeScript
The Astro compiler can convert `.astro` syntax to a TypeScript Module whose default export generates HTML.
**Some notes**...
- TypeScript is valid `.astro` syntax! The output code may need an additional post-processing step to generate valid JavaScript.
- `.astro` files rely on a server implementation exposed as `astro/runtime/server/index.js` in the Node ecosystem. Other runtimes currently need to bring their own rendering implementation and reference it via `internalURL`. This is a pain point we're looking into fixing.
```js
import { transform, type TransformResult } from "@astrojs/compiler";
const result = await transform(source, {
filename: "/Users/astro/Code/project/src/pages/index.astro",
sourcemap: "both",
internalURL: "astro/runtime/server/index.js",
});
```
#### Parse `.astro` and return an AST
The Astro compiler can emit an AST using the `parse` method.
**Some notes**...
- Position data is currently incomplete and in some cases incorrect. We're working on it!
- A `TextNode` can represent both HTML `text` and JavaScript/TypeScript source code.
- The `@astrojs/compiler/utils` entrypoint exposes `walk` and `walkAsync` functions that can be used to traverse the AST. It also exposes the `is` helper which can be used as guards to derive the proper types for each `node`.
```js
import { parse } from "@astrojs/compiler";
import { walk, walkAsync, is } from "@astrojs/compiler/utils";
const result = await parse(source, {
position: false, // defaults to `true`
});
walk(result.ast, (node) => {
// `tag` nodes are `element` | `custom-element` | `component`
if (is.tag(node)) {
console.log(node.name);
}
});
await walkAsync(result.ast, async (node) => {
if (is.tag(node)) {
node.value = await expensiveCalculation(node)
}
});
```
## Develop
### VSCode / CodeSpaces
A `devcontainer` configuration is available for use with VSCode's [Remote Development extension pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) and GitHub CodeSpaces.
## Contributing
[CONTRIBUTING.md](/CONTRIBUTING.md)
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
import { transform as transform$1, parse as parse$1, convertToTSX as convertToTSX$1, teardown as teardown$1, initialize as initialize$1 } from '../shared/types.js';
import '../shared/ast.js';
import '../shared/diagnostics.js';
declare const transform: typeof transform$1;
declare const parse: typeof parse$1;
declare const convertToTSX: typeof convertToTSX$1;
declare const teardown: typeof teardown$1;
declare const initialize: typeof initialize$1;
export { convertToTSX, initialize, parse, teardown, transform };
@@ -0,0 +1 @@
import{a as f}from"../chunk-QR6QDSEV.js";var u=(t,e)=>p().transform(t,e),S=(t,e)=>p().parse(t,e),v=(t,e)=>p().convertToTSX(t,e),a,i,h=()=>{a=void 0,i=void 0,globalThis["@astrojs/compiler"]=void 0},T=async t=>{let e=t.wasmURL;if(!e)throw new Error('Must provide the "wasmURL" option');e+="",a||(a=m(e).catch(n=>{throw a=void 0,n})),i=i||await a},p=()=>{if(!a)throw new Error('You need to call "initialize" before calling this');if(!i)throw new Error('You need to wait for the promise returned from "initialize" to be resolved before calling this');return i},y=async(t,e)=>{let n;return WebAssembly.instantiateStreaming?n=await WebAssembly.instantiateStreaming(fetch(t),e):n=await(async()=>{let s=await fetch(t).then(o=>o.arrayBuffer());return WebAssembly.instantiate(s,e)})(),n},m=async t=>{let e=new f,n=await y(t,e.importObject);e.run(n.instance);let c=globalThis["@astrojs/compiler"];return{transform:(s,o)=>new Promise(r=>r(c.transform(s,o||{}))),convertToTSX:(s,o)=>new Promise(r=>r(c.convertToTSX(s,o||{}))).then(r=>({...r,map:JSON.parse(r.map)})),parse:(s,o)=>new Promise(r=>r(c.parse(s,o||{}))).then(r=>({...r,ast:JSON.parse(r.ast)}))}};export{v as convertToTSX,T as initialize,S as parse,h as teardown,u as transform};
@@ -0,0 +1,3 @@
"use strict";var c=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var u=(o,e)=>{for(var t in e)c(o,t,{get:e[t],enumerable:!0})},f=(o,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of p(e))!N.call(o,r)&&r!==t&&c(o,r,{get:()=>e[r],enumerable:!(a=d(e,r))||a.enumerable});return o};var y=o=>f(c({},"__esModule",{value:!0}),o);var v={};u(v,{is:()=>s,serialize:()=>k,walk:()=>h,walkAsync:()=>x});module.exports=y(v);function n(o){return e=>e.type===o}var s={parent(o){return Array.isArray(o.children)},literal(o){return typeof o.value=="string"},tag(o){return o.type==="element"||o.type==="custom-element"||o.type==="component"||o.type==="fragment"},whitespace(o){return o.type==="text"&&o.value.trim().length===0},root:n("root"),element:n("element"),customElement:n("custom-element"),component:n("component"),fragment:n("fragment"),expression:n("expression"),text:n("text"),doctype:n("doctype"),comment:n("comment"),frontmatter:n("frontmatter")},l=class{constructor(e){this.callback=e}async visit(e,t,a){if(await this.callback(e,t,a),s.parent(e)){let r=[];for(let i=0;i<e.children.length;i++){let m=e.children[i];r.push(this.callback(m,e,i))}await Promise.all(r)}}};function h(o,e){new l(e).visit(o)}function x(o,e){return new l(e).visit(o)}function g(o){let e="";for(let t of o.attributes)switch(e+=" ",t.kind){case"empty":{e+=`${t.name}`;break}case"expression":{e+=`${t.name}={${t.value}}`;break}case"quoted":{e+=`${t.name}=${t.raw}`;break}case"template-literal":{e+=`${t.name}=\`${t.value}\``;break}case"shorthand":{e+=`{${t.name}}`;break}case"spread":{e+=`{...${t.value}}`;break}}return e}function k(o,e={selfClose:!0}){let t="";function a(r){if(s.root(r))for(let i of r.children)a(i);else if(s.frontmatter(r))t+=`---${r.value}---
`;else if(s.comment(r))t+=`<!--${r.value}-->`;else if(s.expression(r)){t+="{";for(let i of r.children)a(i);t+="}"}else if(s.literal(r))t+=r.value;else if(s.tag(r))if(t+=`<${r.name}`,t+=g(r),r.children.length===0&&e.selfClose)t+=" />";else{t+=">";for(let i of r.children)a(i);t+=`</${r.name}>`}}return a(o),t}0&&(module.exports={is,serialize,walk,walkAsync});
@@ -0,0 +1,29 @@
import { Node, ParentNode, LiteralNode, TagLikeNode, TextNode, RootNode, ElementNode, CustomElementNode, ComponentNode, FragmentNode, ExpressionNode, DoctypeNode, CommentNode, FrontmatterNode } from '../shared/ast.js';
type Visitor = (node: Node, parent?: ParentNode, index?: number) => void | Promise<void>;
declare const is: {
parent(node: Node): node is ParentNode;
literal(node: Node): node is LiteralNode;
tag(node: Node): node is TagLikeNode;
whitespace(node: Node): node is TextNode;
root: (node: Node) => node is RootNode;
element: (node: Node) => node is ElementNode;
customElement: (node: Node) => node is CustomElementNode;
component: (node: Node) => node is ComponentNode;
fragment: (node: Node) => node is FragmentNode;
expression: (node: Node) => node is ExpressionNode;
text: (node: Node) => node is TextNode;
doctype: (node: Node) => node is DoctypeNode;
comment: (node: Node) => node is CommentNode;
frontmatter: (node: Node) => node is FrontmatterNode;
};
declare function walk(node: ParentNode, callback: Visitor): void;
declare function walkAsync(node: ParentNode, callback: Visitor): Promise<void>;
interface SerializeOptions {
selfClose: boolean;
}
/** @deprecated Please use `SerializeOptions` */
type SerializeOtions = SerializeOptions;
declare function serialize(root: Node, opts?: SerializeOptions): string;
export { SerializeOptions, SerializeOtions, Visitor, is, serialize, walk, walkAsync };
@@ -0,0 +1,3 @@
function n(o){return t=>t.type===o}var a={parent(o){return Array.isArray(o.children)},literal(o){return typeof o.value=="string"},tag(o){return o.type==="element"||o.type==="custom-element"||o.type==="component"||o.type==="fragment"},whitespace(o){return o.type==="text"&&o.value.trim().length===0},root:n("root"),element:n("element"),customElement:n("custom-element"),component:n("component"),fragment:n("fragment"),expression:n("expression"),text:n("text"),doctype:n("doctype"),comment:n("comment"),frontmatter:n("frontmatter")},l=class{constructor(t){this.callback=t}async visit(t,e,s){if(await this.callback(t,e,s),a.parent(t)){let r=[];for(let i=0;i<t.children.length;i++){let c=t.children[i];r.push(this.callback(c,t,i))}await Promise.all(r)}}};function N(o,t){new l(t).visit(o)}function u(o,t){return new l(t).visit(o)}function m(o){let t="";for(let e of o.attributes)switch(t+=" ",e.kind){case"empty":{t+=`${e.name}`;break}case"expression":{t+=`${e.name}={${e.value}}`;break}case"quoted":{t+=`${e.name}=${e.raw}`;break}case"template-literal":{t+=`${e.name}=\`${e.value}\``;break}case"shorthand":{t+=`{${e.name}}`;break}case"spread":{t+=`{...${e.value}}`;break}}return t}function f(o,t={selfClose:!0}){let e="";function s(r){if(a.root(r))for(let i of r.children)s(i);else if(a.frontmatter(r))e+=`---${r.value}---
`;else if(a.comment(r))e+=`<!--${r.value}-->`;else if(a.expression(r)){e+="{";for(let i of r.children)s(i);e+="}"}else if(a.literal(r))e+=r.value;else if(a.tag(r))if(e+=`<${r.name}`,e+=m(r),r.children.length===0&&t.selfClose)e+=" />";else{e+=">";for(let i of r.children)s(i);e+=`</${r.name}>`}}return s(o),e}export{a as is,f as serialize,N as walk,u as walkAsync};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,37 @@
declare class Go {
importObject: {
gojs: {
'runtime.wasmExit': (sp: any) => void;
'runtime.wasmWrite': (sp: any) => void;
'runtime.resetMemoryDataView': (sp: any) => void;
'runtime.nanotime1': (sp: any) => void;
'runtime.walltime': (sp: any) => void;
'runtime.scheduleTimeoutEvent': (sp: any) => void;
'runtime.clearTimeoutEvent': (sp: any) => void;
'runtime.getRandomData': (sp: any) => void;
'syscall/js.finalizeRef': (sp: any) => void;
'syscall/js.stringVal': (sp: any) => void;
'syscall/js.valueGet': (sp: any) => void;
'syscall/js.valueSet': (sp: any) => void;
'syscall/js.valueDelete': (sp: any) => void;
'syscall/js.valueIndex': (sp: any) => void;
'syscall/js.valueSetIndex': (sp: any) => void;
'syscall/js.valueCall': (sp: any) => void;
'syscall/js.valueInvoke': (sp: any) => void;
'syscall/js.valueNew': (sp: any) => void;
'syscall/js.valueLength': (sp: any) => void;
'syscall/js.valuePrepareString': (sp: any) => void;
'syscall/js.valueLoadString': (sp: any) => void;
'syscall/js.valueInstanceOf': (sp: any) => void;
'syscall/js.copyBytesToGo': (sp: any) => void;
'syscall/js.copyBytesToJS': (sp: any) => void;
debug: (value: any) => void;
};
};
constructor();
run(instance: any): Promise<void>;
private _resume;
private _makeFuncWrapper;
}
export { Go as default };
@@ -0,0 +1 @@
import{a}from"../chunk-QR6QDSEV.js";export{a as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
import { transform as transform$1, parse as parse$1, convertToTSX as convertToTSX$1, teardown as teardown$1 } from '../shared/types.js';
export { HoistedScript, ParseOptions, ParseResult, PreprocessorResult, TransformOptions, TransformResult } from '../shared/types.js';
import '../shared/ast.js';
import '../shared/diagnostics.js';
declare const transform: typeof transform$1;
declare const parse: typeof parse$1;
declare const convertToTSX: typeof convertToTSX$1;
declare const compile: (template: string) => Promise<string>;
declare const teardown: typeof teardown$1;
export { compile, convertToTSX, parse, teardown, transform };
@@ -0,0 +1 @@
import{a as c}from"../chunk-W5DTLHV4.js";import{promises as m}from"fs";import{fileURLToPath as f}from"url";var w=async(t,s)=>i().then(r=>r.transform(t,s)),l=async(t,s)=>i().then(r=>r.parse(t,s)),b=async(t,s)=>i().then(r=>r.convertToTSX(t,s)),P=async t=>{let{default:s}=await import(`data:text/javascript;charset=utf-8;base64,${Buffer.from(t).toString("base64")}`);return s},n,g=()=>{n=void 0,globalThis["@astrojs/compiler"]=void 0},i=()=>(n||(n=d().catch(t=>{throw n=void 0,t})),n),y=async(t,s)=>{let r;return r=await(async()=>{let o=await m.readFile(t).then(e=>e.buffer);return WebAssembly.instantiate(new Uint8Array(o),s)})(),r},d=async()=>{let t=new c,s=await y(f(new URL("../astro.wasm",import.meta.url)),t.importObject);t.run(s.instance);let r=globalThis["@astrojs/compiler"];return{transform:(a,o)=>new Promise(e=>{try{e(r.transform(a,o||{}))}catch(p){throw n=void 0,p}}),parse:(a,o)=>new Promise(e=>e(r.parse(a,o||{}))).catch(e=>{throw n=void 0,e}).then(e=>({...e,ast:JSON.parse(e.ast)})),convertToTSX:(a,o)=>new Promise(e=>e(r.convertToTSX(a,o||{}))).catch(e=>{throw n=void 0,e}).then(e=>({...e,map:JSON.parse(e.map)}))}};export{P as compile,b as convertToTSX,l as parse,g as teardown,w as transform};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
import { TransformOptions, TransformResult, ParseOptions, ParseResult, ConvertToTSXOptions, TSXResult, transform as transform$1, parse as parse$1, convertToTSX as convertToTSX$1 } from '../shared/types.js';
import '../shared/ast.js';
import '../shared/diagnostics.js';
type UnwrappedPromise<T> = T extends (...params: any) => Promise<infer Return> ? (...params: Parameters<T>) => Return : T;
interface Service {
transform: UnwrappedPromise<typeof transform$1>;
parse: UnwrappedPromise<typeof parse$1>;
convertToTSX: UnwrappedPromise<typeof convertToTSX$1>;
}
declare const transform: (input: string, options: TransformOptions | undefined) => TransformResult;
declare const parse: (input: string, options: ParseOptions | undefined) => ParseResult;
declare const convertToTSX: (input: string, options: ConvertToTSXOptions | undefined) => TSXResult;
declare function startRunningService(): Service;
export { convertToTSX, parse, startRunningService, transform };
@@ -0,0 +1 @@
import{a as c}from"../chunk-W5DTLHV4.js";import{readFileSync as p}from"fs";import{fileURLToPath as m}from"url";function i(){return s||(s=f()),s}var s,l=(e,t)=>i().transform(e,t),w=(e,t)=>i().parse(e,t),h=(e,t)=>i().convertToTSX(e,t);function f(){let e=new c,t=v(m(new URL("../astro.wasm",import.meta.url)),e.importObject);e.run(t);let o=globalThis["@astrojs/compiler"];return{transform:(n,a)=>{try{return o.transform(n,a||{})}catch(r){throw s=void 0,r}},parse:(n,a)=>{try{let r=o.parse(n,a||{});return{...r,ast:JSON.parse(r.ast)}}catch(r){throw s=void 0,r}},convertToTSX:(n,a)=>{try{let r=o.convertToTSX(n,a||{});return{...r,map:JSON.parse(r.map)}}catch(r){throw s=void 0,r}}}}function v(e,t){let o=p(e);return new WebAssembly.Instance(new WebAssembly.Module(o),t)}export{h as convertToTSX,w as parse,f as startRunningService,l as transform};
@@ -0,0 +1,3 @@
"use strict";var m=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var u=(o,e)=>{for(var t in e)m(o,t,{get:e[t],enumerable:!0})},f=(o,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of p(e))!N.call(o,r)&&r!==t&&m(o,r,{get:()=>e[r],enumerable:!(a=d(e,r))||a.enumerable});return o};var y=o=>f(m({},"__esModule",{value:!0}),o);var v={};u(v,{is:()=>s,serialize:()=>k,walk:()=>h,walkAsync:()=>x});module.exports=y(v);function n(o){return e=>e.type===o}var s={parent(o){return Array.isArray(o.children)},literal(o){return typeof o.value=="string"},tag(o){return o.type==="element"||o.type==="custom-element"||o.type==="component"||o.type==="fragment"},whitespace(o){return o.type==="text"&&o.value.trim().length===0},root:n("root"),element:n("element"),customElement:n("custom-element"),component:n("component"),fragment:n("fragment"),expression:n("expression"),text:n("text"),doctype:n("doctype"),comment:n("comment"),frontmatter:n("frontmatter")},l=class{constructor(e){this.callback=e}async visit(e,t,a){if(await this.callback(e,t,a),s.parent(e)){let r=[];for(let i=0;i<e.children.length;i++){let c=e.children[i];r.push(this.callback(c,e,i))}await Promise.all(r)}}};function h(o,e){new l(e).visit(o)}function x(o,e){return new l(e).visit(o)}function g(o){let e="";for(let t of o.attributes)switch(e+=" ",t.kind){case"empty":{e+=`${t.name}`;break}case"expression":{e+=`${t.name}={${t.value}}`;break}case"quoted":{e+=`${t.name}=${t.raw}`;break}case"template-literal":{e+=`${t.name}=\`${t.value}\``;break}case"shorthand":{e+=`{${t.name}}`;break}case"spread":{e+=`{...${t.name}}`;break}}return e}function k(o,e={selfClose:!0}){let t="";function a(r){if(s.root(r))for(let i of r.children)a(i);else if(s.frontmatter(r))t+=`---${r.value}---
`;else if(s.comment(r))t+=`<!--${r.value}-->`;else if(s.expression(r)){t+="{";for(let i of r.children)a(i);t+="}"}else if(s.literal(r))t+=r.value;else if(s.tag(r))if(t+=`<${r.name}`,t+=g(r),r.children.length===0&&e.selfClose)t+=" />";else{t+=">";for(let i of r.children)a(i);t+=`</${r.name}>`}}return a(o),t}0&&(module.exports={is,serialize,walk,walkAsync});
@@ -0,0 +1,29 @@
import { Node, ParentNode, LiteralNode, TagLikeNode, TextNode, RootNode, ElementNode, CustomElementNode, ComponentNode, FragmentNode, ExpressionNode, DoctypeNode, CommentNode, FrontmatterNode } from '../shared/ast.js';
type Visitor = (node: Node, parent?: ParentNode, index?: number) => void | Promise<void>;
declare const is: {
parent(node: Node): node is ParentNode;
literal(node: Node): node is LiteralNode;
tag(node: Node): node is TagLikeNode;
whitespace(node: Node): node is TextNode;
root: (node: Node) => node is RootNode;
element: (node: Node) => node is ElementNode;
customElement: (node: Node) => node is CustomElementNode;
component: (node: Node) => node is ComponentNode;
fragment: (node: Node) => node is FragmentNode;
expression: (node: Node) => node is ExpressionNode;
text: (node: Node) => node is TextNode;
doctype: (node: Node) => node is DoctypeNode;
comment: (node: Node) => node is CommentNode;
frontmatter: (node: Node) => node is FrontmatterNode;
};
declare function walk(node: ParentNode, callback: Visitor): void;
declare function walkAsync(node: ParentNode, callback: Visitor): Promise<void>;
interface SerializeOptions {
selfClose: boolean;
}
/** @deprecated Please use `SerializeOptions` */
type SerializeOtions = SerializeOptions;
declare function serialize(root: Node, opts?: SerializeOptions): string;
export { SerializeOptions, SerializeOtions, Visitor, is, serialize, walk, walkAsync };
@@ -0,0 +1,3 @@
function n(o){return t=>t.type===o}var a={parent(o){return Array.isArray(o.children)},literal(o){return typeof o.value=="string"},tag(o){return o.type==="element"||o.type==="custom-element"||o.type==="component"||o.type==="fragment"},whitespace(o){return o.type==="text"&&o.value.trim().length===0},root:n("root"),element:n("element"),customElement:n("custom-element"),component:n("component"),fragment:n("fragment"),expression:n("expression"),text:n("text"),doctype:n("doctype"),comment:n("comment"),frontmatter:n("frontmatter")},l=class{constructor(t){this.callback=t}async visit(t,e,s){if(await this.callback(t,e,s),a.parent(t)){let r=[];for(let i=0;i<t.children.length;i++){let m=t.children[i];r.push(this.callback(m,t,i))}await Promise.all(r)}}};function N(o,t){new l(t).visit(o)}function u(o,t){return new l(t).visit(o)}function c(o){let t="";for(let e of o.attributes)switch(t+=" ",e.kind){case"empty":{t+=`${e.name}`;break}case"expression":{t+=`${e.name}={${e.value}}`;break}case"quoted":{t+=`${e.name}=${e.raw}`;break}case"template-literal":{t+=`${e.name}=\`${e.value}\``;break}case"shorthand":{t+=`{${e.name}}`;break}case"spread":{t+=`{...${e.name}}`;break}}return t}function f(o,t={selfClose:!0}){let e="";function s(r){if(a.root(r))for(let i of r.children)s(i);else if(a.frontmatter(r))e+=`---${r.value}---
`;else if(a.comment(r))e+=`<!--${r.value}-->`;else if(a.expression(r)){e+="{";for(let i of r.children)s(i);e+="}"}else if(a.literal(r))e+=r.value;else if(a.tag(r))if(e+=`<${r.name}`,e+=c(r),r.children.length===0&&t.selfClose)e+=" />";else{e+=">";for(let i of r.children)s(i);e+=`</${r.name}>`}}return s(o),e}export{a as is,f as serialize,N as walk,u as walkAsync};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,37 @@
declare class Go {
importObject: {
gojs: {
'runtime.wasmExit': (sp: any) => void;
'runtime.wasmWrite': (sp: any) => void;
'runtime.resetMemoryDataView': (sp: any) => void;
'runtime.nanotime1': (sp: any) => void;
'runtime.walltime': (sp: any) => void;
'runtime.scheduleTimeoutEvent': (sp: any) => void;
'runtime.clearTimeoutEvent': (sp: any) => void;
'runtime.getRandomData': (sp: any) => void;
'syscall/js.finalizeRef': (sp: any) => void;
'syscall/js.stringVal': (sp: any) => void;
'syscall/js.valueGet': (sp: any) => void;
'syscall/js.valueSet': (sp: any) => void;
'syscall/js.valueDelete': (sp: any) => void;
'syscall/js.valueIndex': (sp: any) => void;
'syscall/js.valueSetIndex': (sp: any) => void;
'syscall/js.valueCall': (sp: any) => void;
'syscall/js.valueInvoke': (sp: any) => void;
'syscall/js.valueNew': (sp: any) => void;
'syscall/js.valueLength': (sp: any) => void;
'syscall/js.valuePrepareString': (sp: any) => void;
'syscall/js.valueLoadString': (sp: any) => void;
'syscall/js.valueInstanceOf': (sp: any) => void;
'syscall/js.copyBytesToGo': (sp: any) => void;
'syscall/js.copyBytesToJS': (sp: any) => void;
debug: (value: any) => void;
};
};
constructor();
run(instance: any): Promise<void>;
private _resume;
private _makeFuncWrapper;
}
export { Go as default };
@@ -0,0 +1 @@
import{a}from"../chunk-W5DTLHV4.js";export{a as default};
@@ -0,0 +1 @@
"use strict";var r=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var p=(t,e,d,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of i(e))!N.call(t,o)&&o!==d&&r(t,o,{get:()=>e[o],enumerable:!(n=a(e,o))||n.enumerable});return t};var s=t=>p(r({},"__esModule",{value:!0}),t);var m={};module.exports=s(m);
@@ -0,0 +1,74 @@
type ParentNode = RootNode | ElementNode | ComponentNode | CustomElementNode | FragmentNode | ExpressionNode;
type LiteralNode = TextNode | DoctypeNode | CommentNode | FrontmatterNode;
type Node = RootNode | ElementNode | ComponentNode | CustomElementNode | FragmentNode | ExpressionNode | TextNode | FrontmatterNode | DoctypeNode | CommentNode;
interface Position {
start: Point;
end?: Point;
}
interface Point {
/** 1-based line number */
line: number;
/** 1-based column number, per-line */
column: number;
/** 0-based byte offset */
offset: number;
}
interface BaseNode {
type: string;
position?: Position;
}
interface ParentLikeNode extends BaseNode {
type: 'element' | 'component' | 'custom-element' | 'fragment' | 'expression' | 'root';
children: Node[];
}
interface ValueNode extends BaseNode {
value: string;
}
interface RootNode extends ParentLikeNode {
type: 'root';
}
interface AttributeNode extends BaseNode {
type: 'attribute';
kind: 'quoted' | 'empty' | 'expression' | 'spread' | 'shorthand' | 'template-literal';
name: string;
value: string;
raw?: string;
}
interface TextNode extends ValueNode {
type: 'text';
}
interface ElementNode extends ParentLikeNode {
type: 'element';
name: string;
attributes: AttributeNode[];
}
interface FragmentNode extends ParentLikeNode {
type: 'fragment';
name: string;
attributes: AttributeNode[];
}
interface ComponentNode extends ParentLikeNode {
type: 'component';
name: string;
attributes: AttributeNode[];
}
interface CustomElementNode extends ParentLikeNode {
type: 'custom-element';
name: string;
attributes: AttributeNode[];
}
type TagLikeNode = ElementNode | FragmentNode | ComponentNode | CustomElementNode;
interface DoctypeNode extends ValueNode {
type: 'doctype';
}
interface CommentNode extends ValueNode {
type: 'comment';
}
interface FrontmatterNode extends ValueNode {
type: 'frontmatter';
}
interface ExpressionNode extends ParentLikeNode {
type: 'expression';
}
export { AttributeNode, BaseNode, CommentNode, ComponentNode, CustomElementNode, DoctypeNode, ElementNode, ExpressionNode, FragmentNode, FrontmatterNode, LiteralNode, Node, ParentLikeNode, ParentNode, Point, Position, RootNode, TagLikeNode, TextNode, ValueNode };
@@ -0,0 +1 @@
"use strict";var I=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var S=Object.prototype.hasOwnProperty;var U=(E,N)=>{for(var _ in N)I(E,_,{get:N[_],enumerable:!0})},H=(E,N,_,A)=>{if(N&&typeof N=="object"||typeof N=="function")for(let T of G(N))!S.call(E,T)&&T!==_&&I(E,T,{get:()=>N[T],enumerable:!(A=M(N,T))||A.enumerable});return E};var W=E=>H(I({},"__esModule",{value:!0}),E);var P={};U(P,{DiagnosticCode:()=>O});module.exports=W(P);var O=(R=>(R[R.ERROR=1e3]="ERROR",R[R.ERROR_UNTERMINATED_JS_COMMENT=1001]="ERROR_UNTERMINATED_JS_COMMENT",R[R.ERROR_FRAGMENT_SHORTHAND_ATTRS=1002]="ERROR_FRAGMENT_SHORTHAND_ATTRS",R[R.ERROR_UNMATCHED_IMPORT=1003]="ERROR_UNMATCHED_IMPORT",R[R.ERROR_UNSUPPORTED_SLOT_ATTRIBUTE=1004]="ERROR_UNSUPPORTED_SLOT_ATTRIBUTE",R[R.WARNING=2e3]="WARNING",R[R.WARNING_UNTERMINATED_HTML_COMMENT=2001]="WARNING_UNTERMINATED_HTML_COMMENT",R[R.WARNING_UNCLOSED_HTML_TAG=2002]="WARNING_UNCLOSED_HTML_TAG",R[R.WARNING_DEPRECATED_DIRECTIVE=2003]="WARNING_DEPRECATED_DIRECTIVE",R[R.WARNING_IGNORED_DIRECTIVE=2004]="WARNING_IGNORED_DIRECTIVE",R[R.WARNING_UNSUPPORTED_EXPRESSION=2005]="WARNING_UNSUPPORTED_EXPRESSION",R[R.WARNING_SET_WITH_CHILDREN=2006]="WARNING_SET_WITH_CHILDREN",R[R.INFO=3e3]="INFO",R[R.HINT=4e3]="HINT",R))(O||{});0&&(module.exports={DiagnosticCode});
@@ -0,0 +1,18 @@
declare enum DiagnosticCode {
ERROR = 1000,
ERROR_UNTERMINATED_JS_COMMENT = 1001,
ERROR_FRAGMENT_SHORTHAND_ATTRS = 1002,
ERROR_UNMATCHED_IMPORT = 1003,
ERROR_UNSUPPORTED_SLOT_ATTRIBUTE = 1004,
WARNING = 2000,
WARNING_UNTERMINATED_HTML_COMMENT = 2001,
WARNING_UNCLOSED_HTML_TAG = 2002,
WARNING_DEPRECATED_DIRECTIVE = 2003,
WARNING_IGNORED_DIRECTIVE = 2004,
WARNING_UNSUPPORTED_EXPRESSION = 2005,
WARNING_SET_WITH_CHILDREN = 2006,
INFO = 3000,
HINT = 4000
}
export { DiagnosticCode };
@@ -0,0 +1 @@
var N=(R=>(R[R.ERROR=1e3]="ERROR",R[R.ERROR_UNTERMINATED_JS_COMMENT=1001]="ERROR_UNTERMINATED_JS_COMMENT",R[R.ERROR_FRAGMENT_SHORTHAND_ATTRS=1002]="ERROR_FRAGMENT_SHORTHAND_ATTRS",R[R.ERROR_UNMATCHED_IMPORT=1003]="ERROR_UNMATCHED_IMPORT",R[R.ERROR_UNSUPPORTED_SLOT_ATTRIBUTE=1004]="ERROR_UNSUPPORTED_SLOT_ATTRIBUTE",R[R.WARNING=2e3]="WARNING",R[R.WARNING_UNTERMINATED_HTML_COMMENT=2001]="WARNING_UNTERMINATED_HTML_COMMENT",R[R.WARNING_UNCLOSED_HTML_TAG=2002]="WARNING_UNCLOSED_HTML_TAG",R[R.WARNING_DEPRECATED_DIRECTIVE=2003]="WARNING_DEPRECATED_DIRECTIVE",R[R.WARNING_IGNORED_DIRECTIVE=2004]="WARNING_IGNORED_DIRECTIVE",R[R.WARNING_UNSUPPORTED_EXPRESSION=2005]="WARNING_UNSUPPORTED_EXPRESSION",R[R.WARNING_SET_WITH_CHILDREN=2006]="WARNING_SET_WITH_CHILDREN",R[R.INFO=3e3]="INFO",R[R.HINT=4e3]="HINT",R))(N||{});export{N as DiagnosticCode};
@@ -0,0 +1 @@
"use strict";var o=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var l=(r,t)=>{for(var n in t)o(r,n,{get:t[n],enumerable:!0})},g=(r,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of p(t))!c.call(r,e)&&e!==n&&o(r,e,{get:()=>t[e],enumerable:!(s=a(t,e))||s.enumerable});return r};var d=r=>g(o({},"__esModule",{value:!0}),r);var m={};l(m,{DiagnosticSeverity:()=>i});module.exports=d(m);var i=(e=>(e[e.Error=1]="Error",e[e.Warning=2]="Warning",e[e.Information=3]="Information",e[e.Hint=4]="Hint",e))(i||{});0&&(module.exports={DiagnosticSeverity});
@@ -0,0 +1,160 @@
import { RootNode } from './ast.js';
export { AttributeNode, BaseNode, CommentNode, ComponentNode, CustomElementNode, DoctypeNode, ElementNode, ExpressionNode, FragmentNode, FrontmatterNode, LiteralNode, Node, ParentLikeNode, ParentNode, Point, Position, TagLikeNode, TextNode, ValueNode } from './ast.js';
import { DiagnosticCode } from './diagnostics.js';
interface PreprocessorResult {
code: string;
map?: string;
}
interface PreprocessorError {
error: string;
}
interface ParseOptions {
position?: boolean;
}
declare enum DiagnosticSeverity {
Error = 1,
Warning = 2,
Information = 3,
Hint = 4
}
interface DiagnosticMessage {
severity: DiagnosticSeverity;
code: DiagnosticCode;
location: DiagnosticLocation;
hint?: string;
text: string;
}
interface DiagnosticLocation {
file: string;
line: number;
column: number;
length: number;
}
interface TransformOptions {
internalURL?: string;
filename?: string;
normalizedFilename?: string;
sourcemap?: boolean | 'inline' | 'external' | 'both';
astroGlobalArgs?: string;
compact?: boolean;
resultScopedSlot?: boolean;
scopedStyleStrategy?: 'where' | 'class' | 'attribute';
/**
* @deprecated "as" has been removed and no longer has any effect!
*/
as?: 'document' | 'fragment';
transitionsAnimationURL?: string;
resolvePath?: (specifier: string) => Promise<string> | string;
preprocessStyle?: (content: string, attrs: Record<string, string>) => null | Promise<PreprocessorResult | PreprocessorError>;
annotateSourceFile?: boolean;
/**
* Render script tags to be processed (e.g. script tags that have no attributes or only a `src` attribute)
* using a `renderScript` function from `internalURL`, instead of stripping the script entirely.
* @experimental
*/
renderScript?: boolean;
experimentalScriptOrder?: boolean;
}
type ConvertToTSXOptions = Pick<TransformOptions, 'filename' | 'normalizedFilename' | 'sourcemap'> & {
/** If set to true, script tags content will be included in the generated TSX
* Scripts will be wrapped in an arrow function to be compatible with JSX's spec
*/
includeScripts?: boolean;
/** If set to true, style tags content will be included in the generated TSX
* Styles will be wrapped in a template literal to be compatible with JSX's spec
*/
includeStyles?: boolean;
};
type HoistedScript = {
type: string;
} & ({
type: 'external';
src: string;
} | {
type: 'inline';
code: string;
map: string;
});
interface HydratedComponent {
exportName: string;
localName: string;
specifier: string;
resolvedPath: string;
}
interface TransformResult {
code: string;
map: string;
scope: string;
styleError: string[];
diagnostics: DiagnosticMessage[];
css: string[];
scripts: HoistedScript[];
hydratedComponents: HydratedComponent[];
clientOnlyComponents: HydratedComponent[];
serverComponents: HydratedComponent[];
containsHead: boolean;
propagation: boolean;
}
interface SourceMap {
file: string;
mappings: string;
names: string[];
sources: string[];
sourcesContent: string[];
version: number;
}
/**
* Represents a location in a TSX file.
* Both the `start` and `end` properties are 0-based, and are based off utf-16 code units. (i.e. JavaScript's `String.prototype.length`)
*/
interface TSXLocation {
start: number;
end: number;
}
interface TSXExtractedTag {
position: TSXLocation;
content: string;
}
interface TSXExtractedScript extends TSXExtractedTag {
type: 'processed-module' | 'module' | 'inline' | 'event-attribute' | 'json' | 'raw' | 'unknown';
}
interface TSXExtractedStyle extends TSXExtractedTag {
type: 'tag' | 'style-attribute';
lang: 'css' | 'scss' | 'sass' | 'less' | 'stylus' | 'styl' | 'postcss' | 'pcss' | 'unknown' | (string & {});
}
interface TSXResult {
code: string;
map: SourceMap;
diagnostics: DiagnosticMessage[];
metaRanges: {
frontmatter: TSXLocation;
body: TSXLocation;
scripts?: TSXExtractedScript[];
styles?: TSXExtractedStyle[];
};
}
interface ParseResult {
ast: RootNode;
diagnostics: DiagnosticMessage[];
}
declare function transform(input: string, options?: TransformOptions): Promise<TransformResult>;
declare function parse(input: string, options?: ParseOptions): Promise<ParseResult>;
declare function convertToTSX(input: string, options?: ConvertToTSXOptions): Promise<TSXResult>;
declare function initialize(options: InitializeOptions): Promise<void>;
/**
* When calling the core compiler APIs, e.g. `transform`, `parse`, etc, they
* would automatically instantiate a WASM instance to process the input. When
* done, you can call this to manually teardown the WASM instance.
*
* If the APIs are called again, they will automatically instantiate a new WASM
* instance. In browsers, you have to call `initialize()` again before using the APIs.
*
* Note: Calling teardown is optional and exists mostly as an optimization only.
*/
declare function teardown(): void;
interface InitializeOptions {
wasmURL?: string;
}
export { ConvertToTSXOptions, DiagnosticLocation, DiagnosticMessage, DiagnosticSeverity, HoistedScript, HydratedComponent, InitializeOptions, ParseOptions, ParseResult, PreprocessorError, PreprocessorResult, RootNode, SourceMap, TSXExtractedScript, TSXExtractedStyle, TSXExtractedTag, TSXLocation, TSXResult, TransformOptions, TransformResult, convertToTSX, initialize, parse, teardown, transform };
@@ -0,0 +1 @@
var t=(e=>(e[e.Error=1]="Error",e[e.Warning=2]="Warning",e[e.Information=3]="Information",e[e.Hint=4]="Hint",e))(t||{});export{t as DiagnosticSeverity};
@@ -0,0 +1,58 @@
{
"name": "@astrojs/compiler",
"author": "withastro",
"license": "MIT",
"type": "module",
"bugs": "https://github.com/withastro/compiler/issues",
"homepage": "https://astro.build",
"version": "2.13.1",
"main": "./dist/node/index.js",
"types": "./dist/shared/types.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/withastro/compiler.git"
},
"files": [
"dist",
"types.d.ts",
"utils.d.ts",
"sync.d.ts"
],
"exports": {
".": {
"types": "./dist/node/index.d.ts",
"browser": "./dist/browser/index.js",
"import": "./dist/node/index.js",
"require": "./dist/node/index.cjs",
"default": "./dist/browser/index.js"
},
"./sync": {
"types": "./dist/node/sync.d.ts",
"import": "./dist/node/sync.js",
"require": "./dist/node/sync.cjs",
"default": "./dist/node/sync.js"
},
"./utils": {
"types": "./dist/node/utils.d.ts",
"browser": "./dist/browser/utils.js",
"import": "./dist/node/utils.js",
"require": "./dist/node/utils.cjs",
"default": "./dist/browser/utils.js"
},
"./astro.wasm": "./dist/astro.wasm",
"./types": "./dist/shared/types.d.ts",
"./package.json": "./package.json"
},
"devDependencies": {
"@jridgewell/trace-mapping": "^0.3.16",
"@types/node": "^18.15.11",
"@types/sass": "^1.43.1",
"acorn": "^8.8.1",
"esbuild": "^0.17.17",
"tsup": "^6.7.0",
"typescript": "~5.0.2"
},
"scripts": {
"build": "tsup"
}
}
@@ -0,0 +1 @@
export * from './dist/node/sync.js';
@@ -0,0 +1 @@
export type * from './dist/shared/types.js';
@@ -0,0 +1 @@
export * from './dist/node/utils.js';

Some files were not shown because too many files have changed in this diff Show More