🎉 initiate project *astro_rewrite*

This commit is contained in:
sindrekjelsrud 2023-07-19 21:31:30 +02:00
parent ffd4d5e86c
commit 2ba37bfbe3
8658 changed files with 2268794 additions and 2538 deletions

53
node_modules/@astrojs/compiler/LICENSE generated vendored Normal file
View file

@ -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.

66
node_modules/@astrojs/compiler/README.md generated vendored Normal file
View file

@ -0,0 +1,66 @@
# 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 } 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 a `walk` function 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, 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);
}
});
```
## 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)

BIN
node_modules/@astrojs/compiler/dist/astro.wasm generated vendored Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

11
node_modules/@astrojs/compiler/dist/browser/index.d.ts generated vendored Normal file
View file

@ -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 };

1
node_modules/@astrojs/compiler/dist/browser/index.js generated vendored Normal file
View file

@ -0,0 +1 @@
import{a as f}from"../chunk-XZNZIE5X.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};

View file

@ -0,0 +1,3 @@
"use strict";var l=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var u=(o,e)=>{for(var t in e)l(o,t,{get:e[t],enumerable:!0})},f=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of p(e))!N.call(o,r)&&r!==t&&l(o,r,{get:()=>e[r],enumerable:!(n=d(e,r))||n.enumerable});return o};var h=o=>f(l({},"__esModule",{value:!0}),o);var v={};u(v,{is:()=>s,serialize:()=>g,walk:()=>y});module.exports=h(v);function i(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:i("root"),element:i("element"),customElement:i("custom-element"),component:i("component"),fragment:i("fragment"),expression:i("expression"),text:i("text"),doctype:i("doctype"),comment:i("comment"),frontmatter:i("frontmatter")},m=class{constructor(e){this.callback=e}async visit(e,t,n){if(await this.callback(e,t,n),s.parent(e)){let r=[];for(let a=0;a<e.children.length;a++){let c=e.children[a];r.push(this.callback(c,e,a))}await Promise.all(r)}}};function y(o,e){new m(e).visit(o)}function x(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 g(o,e={selfClose:!0}){let t="";function n(r){s.root(r)?r.children.forEach(a=>n(a)):s.frontmatter(r)?t+=`---${r.value}---
`:s.comment(r)?t+=`<!--${r.value}-->`:s.expression(r)?(t+="{",r.children.forEach(a=>n(a)),t+="}"):s.literal(r)?t+=r.value:s.tag(r)&&(t+=`<${r.name}`,t+=x(r),r.children.length==0&&e.selfClose?t+=" />":(t+=">",r.children.forEach(a=>n(a)),t+=`</${r.name}>`))}return n(o),t}0&&(module.exports={is,serialize,walk});

30
node_modules/@astrojs/compiler/dist/browser/utils.d.ts generated vendored Normal file
View file

@ -0,0 +1,30 @@
import { Node, ParentNode, LiteralNode, TagLikeNode, TextNode, RootNode, ElementNode, CustomElementNode, ComponentNode, FragmentNode, ExpressionNode, DoctypeNode, CommentNode, FrontmatterNode } from '../shared/ast.js';
interface 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;
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 };

3
node_modules/@astrojs/compiler/dist/browser/utils.js generated vendored Normal file
View file

@ -0,0 +1,3 @@
function i(o){return t=>t.type===o}var n={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:i("root"),element:i("element"),customElement:i("custom-element"),component:i("component"),fragment:i("fragment"),expression:i("expression"),text:i("text"),doctype:i("doctype"),comment:i("comment"),frontmatter:i("frontmatter")},l=class{constructor(t){this.callback=t}async visit(t,e,s){if(await this.callback(t,e,s),n.parent(t)){let r=[];for(let a=0;a<t.children.length;a++){let m=t.children[a];r.push(this.callback(m,t,a))}await Promise.all(r)}}};function N(o,t){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.value}}`;break}}return t}function u(o,t={selfClose:!0}){let e="";function s(r){n.root(r)?r.children.forEach(a=>s(a)):n.frontmatter(r)?e+=`---${r.value}---
`:n.comment(r)?e+=`<!--${r.value}-->`:n.expression(r)?(e+="{",r.children.forEach(a=>s(a)),e+="}"):n.literal(r)?e+=r.value:n.tag(r)&&(e+=`<${r.name}`,e+=c(r),r.children.length==0&&t.selfClose?e+=" />":(e+=">",r.children.forEach(a=>s(a)),e+=`</${r.name}>`))}return s(o),e}export{n as is,u as serialize,N as walk};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,37 @@
declare class Go {
importObject: {
go: {
'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 };

View file

@ -0,0 +1 @@
import{a}from"../chunk-XZNZIE5X.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

1
node_modules/@astrojs/compiler/dist/node/index.cjs generated vendored Normal file

File diff suppressed because one or more lines are too long

12
node_modules/@astrojs/compiler/dist/node/index.d.ts generated vendored Normal file
View file

@ -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 };

1
node_modules/@astrojs/compiler/dist/node/index.js generated vendored Normal file
View file

@ -0,0 +1 @@
import{a as c}from"../chunk-GFDH6LQW.js";import{promises as m}from"fs";import{fileURLToPath as f}from"url";var l=async(t,s)=>i().then(r=>r.transform(t,s)),w=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,w as parse,g as teardown,l as transform};

1
node_modules/@astrojs/compiler/dist/node/sync.cjs generated vendored Normal file

File diff suppressed because one or more lines are too long

16
node_modules/@astrojs/compiler/dist/node/sync.d.ts generated vendored Normal file
View file

@ -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 };

1
node_modules/@astrojs/compiler/dist/node/sync.js generated vendored Normal file
View file

@ -0,0 +1 @@
import{a as c}from"../chunk-GFDH6LQW.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};

3
node_modules/@astrojs/compiler/dist/node/utils.cjs generated vendored Normal file
View file

@ -0,0 +1,3 @@
"use strict";var l=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var u=(o,e)=>{for(var t in e)l(o,t,{get:e[t],enumerable:!0})},f=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of p(e))!N.call(o,r)&&r!==t&&l(o,r,{get:()=>e[r],enumerable:!(n=d(e,r))||n.enumerable});return o};var h=o=>f(l({},"__esModule",{value:!0}),o);var k={};u(k,{is:()=>s,serialize:()=>g,walk:()=>y});module.exports=h(k);function i(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:i("root"),element:i("element"),customElement:i("custom-element"),component:i("component"),fragment:i("fragment"),expression:i("expression"),text:i("text"),doctype:i("doctype"),comment:i("comment"),frontmatter:i("frontmatter")},m=class{constructor(e){this.callback=e}async visit(e,t,n){if(await this.callback(e,t,n),s.parent(e)){let r=[];for(let a=0;a<e.children.length;a++){let c=e.children[a];r.push(this.callback(c,e,a))}await Promise.all(r)}}};function y(o,e){new m(e).visit(o)}function x(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 g(o,e={selfClose:!0}){let t="";function n(r){s.root(r)?r.children.forEach(a=>n(a)):s.frontmatter(r)?t+=`---${r.value}---
`:s.comment(r)?t+=`<!--${r.value}-->`:s.expression(r)?(t+="{",r.children.forEach(a=>n(a)),t+="}"):s.literal(r)?t+=r.value:s.tag(r)&&(t+=`<${r.name}`,t+=x(r),r.children.length==0&&e.selfClose?t+=" />":(t+=">",r.children.forEach(a=>n(a)),t+=`</${r.name}>`))}return n(o),t}0&&(module.exports={is,serialize,walk});

30
node_modules/@astrojs/compiler/dist/node/utils.d.ts generated vendored Normal file
View file

@ -0,0 +1,30 @@
import { Node, ParentNode, LiteralNode, TagLikeNode, TextNode, RootNode, ElementNode, CustomElementNode, ComponentNode, FragmentNode, ExpressionNode, DoctypeNode, CommentNode, FrontmatterNode } from '../shared/ast.js';
interface 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;
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 };

3
node_modules/@astrojs/compiler/dist/node/utils.js generated vendored Normal file
View file

@ -0,0 +1,3 @@
function i(o){return t=>t.type===o}var n={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:i("root"),element:i("element"),customElement:i("custom-element"),component:i("component"),fragment:i("fragment"),expression:i("expression"),text:i("text"),doctype:i("doctype"),comment:i("comment"),frontmatter:i("frontmatter")},l=class{constructor(t){this.callback=t}async visit(t,e,s){if(await this.callback(t,e,s),n.parent(t)){let r=[];for(let a=0;a<t.children.length;a++){let m=t.children[a];r.push(this.callback(m,t,a))}await Promise.all(r)}}};function N(o,t){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 u(o,t={selfClose:!0}){let e="";function s(r){n.root(r)?r.children.forEach(a=>s(a)):n.frontmatter(r)?e+=`---${r.value}---
`:n.comment(r)?e+=`<!--${r.value}-->`:n.expression(r)?(e+="{",r.children.forEach(a=>s(a)),e+="}"):n.literal(r)?e+=r.value:n.tag(r)&&(e+=`<${r.name}`,e+=c(r),r.children.length==0&&t.selfClose?e+=" />":(e+=">",r.children.forEach(a=>s(a)),e+=`</${r.name}>`))}return s(o),e}export{n as is,u as serialize,N as walk};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,37 @@
declare class Go {
importObject: {
go: {
'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 };

View file

@ -0,0 +1 @@
import{a}from"../chunk-GFDH6LQW.js";export{a as default};

1
node_modules/@astrojs/compiler/dist/shared/ast.cjs generated vendored Normal file
View file

@ -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);

74
node_modules/@astrojs/compiler/dist/shared/ast.d.ts generated vendored Normal file
View file

@ -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
node_modules/@astrojs/compiler/dist/shared/ast.js generated vendored Normal file
View file

View file

@ -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});

View file

@ -0,0 +1,18 @@
declare const 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 };

View file

@ -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};

1
node_modules/@astrojs/compiler/dist/shared/types.cjs generated vendored Normal file
View file

@ -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 m=r=>g(o({},"__esModule",{value:!0}),r);var d={};l(d,{DiagnosticSeverity:()=>i});module.exports=m(d);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});

116
node_modules/@astrojs/compiler/dist/shared/types.d.ts generated vendored Normal file
View file

@ -0,0 +1,116 @@
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';
/**
* @deprecated "as" has been removed and no longer has any effect!
*/
as?: 'document' | 'fragment';
experimentalTransitions?: boolean;
transitionsAnimationURL?: string;
resolvePath?: (specifier: string) => Promise<string>;
preprocessStyle?: (content: string, attrs: Record<string, string>) => null | Promise<PreprocessorResult | PreprocessorError>;
}
type ConvertToTSXOptions = Pick<TransformOptions, 'filename' | 'normalizedFilename'>;
type HoistedScript = {
type: string;
} & ({
type: 'external';
src: string;
} | {
type: 'inline';
code: string;
map: string;
});
interface HydratedComponent {
exportName: 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[];
containsHead: boolean;
}
interface SourceMap {
file: string;
mappings: string;
names: string[];
sources: string[];
sourcesContent: string[];
version: number;
}
interface TSXResult {
code: string;
map: SourceMap;
diagnostics: DiagnosticMessage[];
}
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, TSXResult, TransformOptions, TransformResult, convertToTSX, initialize, parse, teardown, transform };

1
node_modules/@astrojs/compiler/dist/shared/types.js generated vendored Normal file
View file

@ -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};

58
node_modules/@astrojs/compiler/package.json generated vendored Normal file
View file

@ -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": "1.6.0",
"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"
}
}

1
node_modules/@astrojs/compiler/sync.d.ts generated vendored Normal file
View file

@ -0,0 +1 @@
export * from './dist/node/sync.js';

1
node_modules/@astrojs/compiler/types.d.ts generated vendored Normal file
View file

@ -0,0 +1 @@
export type * from './dist/shared/types.js';

1
node_modules/@astrojs/compiler/utils.d.ts generated vendored Normal file
View file

@ -0,0 +1 @@
export * from './dist/node/utils.js';

61
node_modules/@astrojs/internal-helpers/LICENSE generated vendored Normal file
View file

@ -0,0 +1,61 @@
MIT License
Copyright (c) 2021 Fred K. Schott
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 `packages/create-astro` and `packages/astro` subdirectories originating from the https://github.com/sveltejs/kit repository:
Copyright (c) 2020 [these people](https://github.com/sveltejs/kit/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 `packages/create-astro` and `packages/astro` subdirectories originating from the https://github.com/vitejs/vite repository:
MIT License
Copyright (c) 2019-present, Yuxi (Evan) You and Vite 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.
"""

20
node_modules/@astrojs/internal-helpers/dist/path.d.ts generated vendored Normal file
View file

@ -0,0 +1,20 @@
/**
* A set of common path utilities commonly used through the Astro core and integration
* projects. These do things like ensure a forward slash prepends paths.
*/
export declare function appendExtension(path: string, extension: string): string;
export declare function appendForwardSlash(path: string): string;
export declare function prependForwardSlash(path: string): string;
export declare function removeTrailingForwardSlash(path: string): string;
export declare function removeLeadingForwardSlash(path: string): string;
export declare function removeLeadingForwardSlashWindows(path: string): string;
export declare function trimSlashes(path: string): string;
export declare function startsWithForwardSlash(path: string): boolean;
export declare function startsWithDotDotSlash(path: string): boolean;
export declare function startsWithDotSlash(path: string): boolean;
export declare function isRelativePath(path: string): boolean;
export declare function joinPaths(...paths: (string | undefined)[]): string;
export declare function removeFileExtension(path: string): string;
export declare function removeQueryString(path: string): string;
export declare function isRemotePath(src: string): boolean;
export declare function slash(path: string): string;

84
node_modules/@astrojs/internal-helpers/dist/path.js generated vendored Normal file
View file

@ -0,0 +1,84 @@
function appendExtension(path, extension) {
return path + "." + extension;
}
function appendForwardSlash(path) {
return path.endsWith("/") ? path : path + "/";
}
function prependForwardSlash(path) {
return path[0] === "/" ? path : "/" + path;
}
function removeTrailingForwardSlash(path) {
return path.endsWith("/") ? path.slice(0, path.length - 1) : path;
}
function removeLeadingForwardSlash(path) {
return path.startsWith("/") ? path.substring(1) : path;
}
function removeLeadingForwardSlashWindows(path) {
return path.startsWith("/") && path[2] === ":" ? path.substring(1) : path;
}
function trimSlashes(path) {
return path.replace(/^\/|\/$/g, "");
}
function startsWithForwardSlash(path) {
return path[0] === "/";
}
function startsWithDotDotSlash(path) {
const c1 = path[0];
const c2 = path[1];
const c3 = path[2];
return c1 === "." && c2 === "." && c3 === "/";
}
function startsWithDotSlash(path) {
const c1 = path[0];
const c2 = path[1];
return c1 === "." && c2 === "/";
}
function isRelativePath(path) {
return startsWithDotDotSlash(path) || startsWithDotSlash(path);
}
function isString(path) {
return typeof path === "string" || path instanceof String;
}
function joinPaths(...paths) {
return paths.filter(isString).map((path, i) => {
if (i === 0) {
return removeTrailingForwardSlash(path);
} else if (i === paths.length - 1) {
return removeLeadingForwardSlash(path);
} else {
return trimSlashes(path);
}
}).join("/");
}
function removeFileExtension(path) {
let idx = path.lastIndexOf(".");
return idx === -1 ? path : path.slice(0, idx);
}
function removeQueryString(path) {
const index = path.lastIndexOf("?");
return index > 0 ? path.substring(0, index) : path;
}
function isRemotePath(src) {
return /^(http|ftp|https|ws):?\/\//.test(src) || src.startsWith("data:");
}
function slash(path) {
return path.replace(/\\/g, "/");
}
export {
appendExtension,
appendForwardSlash,
isRelativePath,
isRemotePath,
joinPaths,
prependForwardSlash,
removeFileExtension,
removeLeadingForwardSlash,
removeLeadingForwardSlashWindows,
removeQueryString,
removeTrailingForwardSlash,
slash,
startsWithDotDotSlash,
startsWithDotSlash,
startsWithForwardSlash,
trimSlashes
};

41
node_modules/@astrojs/internal-helpers/package.json generated vendored Normal file
View file

@ -0,0 +1,41 @@
{
"name": "@astrojs/internal-helpers",
"description": "Internal helpers used by core Astro packages.",
"version": "0.1.1",
"type": "module",
"author": "withastro",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/withastro/astro.git",
"directory": "packages/internal-helpers"
},
"bugs": "https://github.com/withastro/astro/issues",
"exports": {
"./path": "./dist/path.js"
},
"typesVersions": {
"*": {
"path": [
"./dist/path.d.ts"
]
}
},
"files": [
"dist"
],
"devDependencies": {
"astro-scripts": "0.0.14"
},
"keywords": [
"astro",
"astro-component"
],
"scripts": {
"prepublish": "pnpm build",
"build": "astro-scripts build \"src/**/*.ts\" && tsc -p tsconfig.json",
"build:ci": "astro-scripts build \"src/**/*.ts\"",
"postbuild": "astro-scripts copy \"src/**/*.js\"",
"dev": "astro-scripts dev \"src/**/*.ts\""
}
}

3
node_modules/@astrojs/internal-helpers/readme.md generated vendored Normal file
View file

@ -0,0 +1,3 @@
# @astrojs/internal-helpers
These are internal helpers used by core Astro packages. This package does not follow semver and should not be used externally.

37
node_modules/@astrojs/language-server/LICENSE generated vendored Normal file
View file

@ -0,0 +1,37 @@
MIT License
Copyright (c) 2021 Nate Moore
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,
which has provided an extremely solid foundation for us to build upon:
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.
"""

15
node_modules/@astrojs/language-server/README.md generated vendored Normal file
View file

@ -0,0 +1,15 @@
# @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
```

View file

@ -0,0 +1,3 @@
#! /usr/bin/env node
require('../dist/browser.js');

3
node_modules/@astrojs/language-server/bin/nodeServer.js generated vendored Executable file
View file

@ -0,0 +1,3 @@
#! /usr/bin/env node
require('../dist/node.js');

View file

@ -0,0 +1 @@
export {};

15
node_modules/@astrojs/language-server/dist/browser.js generated vendored Normal file
View file

@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const browser_1 = require("vscode-languageserver/browser");
const server_1 = require("./server");
const messageReader = new browser_1.BrowserMessageReader(self);
const messageWriter = new browser_1.BrowserMessageWriter(self);
const connection = (0, browser_1.createConnection)(messageReader, messageWriter);
(0, server_1.startLanguageServer)(connection, {
loadTypescript(options) {
return undefined; // TODO: Full browser support
},
loadTypescriptLocalized(options) {
return undefined;
},
});

23
node_modules/@astrojs/language-server/dist/check.d.ts generated vendored Normal file
View file

@ -0,0 +1,23 @@
import type { Diagnostic } from 'vscode-languageserver-types';
import { LSConfig } from './core/config';
export { DiagnosticSeverity } from 'vscode-languageserver-types';
export { Diagnostic };
export interface GetDiagnosticsResult {
fileUri: string;
text: string;
diagnostics: Diagnostic[];
}
export declare class AstroCheck {
private docManager;
private configManager;
private pluginHost;
constructor(workspacePath: string, typescriptPath: string, options?: LSConfig);
upsertDocument(doc: {
text: string;
uri: string;
}): void;
removeDocument(uri: string): void;
getDiagnostics(): Promise<GetDiagnosticsResult[]>;
private initialize;
private getDiagnosticsForFile;
}

60
node_modules/@astrojs/language-server/dist/check.js generated vendored Normal file
View file

@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AstroCheck = exports.DiagnosticSeverity = void 0;
const config_1 = require("./core/config");
const documents_1 = require("./core/documents");
const plugins_1 = require("./plugins");
const LanguageServiceManager_1 = require("./plugins/typescript/LanguageServiceManager");
const utils_1 = require("./utils");
var vscode_languageserver_types_1 = require("vscode-languageserver-types");
Object.defineProperty(exports, "DiagnosticSeverity", { enumerable: true, get: function () { return vscode_languageserver_types_1.DiagnosticSeverity; } });
class AstroCheck {
constructor(workspacePath, typescriptPath, options) {
this.docManager = documents_1.DocumentManager.newInstance();
this.configManager = new config_1.ConfigManager();
this.pluginHost = new plugins_1.PluginHost(this.docManager);
try {
const ts = require(typescriptPath);
this.initialize(workspacePath, ts);
}
catch (e) {
throw new Error(`Couldn't load TypeScript from path ${typescriptPath}`);
}
if (options) {
this.configManager.updateGlobalConfig(options);
}
}
upsertDocument(doc) {
this.docManager.openDocument({
text: doc.text,
uri: doc.uri,
});
this.docManager.markAsOpenedInClient(doc.uri);
}
removeDocument(uri) {
if (!this.docManager.get(uri)) {
return;
}
this.docManager.closeDocument(uri);
this.docManager.releaseDocument(uri);
}
async getDiagnostics() {
return await Promise.all(this.docManager.getAllOpenedByClient().map(async (doc) => {
const uri = doc[1].uri;
return await this.getDiagnosticsForFile(uri);
}));
}
initialize(workspacePath, ts) {
const languageServiceManager = new LanguageServiceManager_1.LanguageServiceManager(this.docManager, [(0, utils_1.normalizeUri)(workspacePath)], this.configManager, ts);
this.pluginHost.registerPlugin(new plugins_1.TypeScriptPlugin(this.configManager, languageServiceManager));
}
async getDiagnosticsForFile(uri) {
const diagnostics = await this.pluginHost.getDiagnostics({ uri });
return {
fileUri: uri || '',
text: this.docManager.get(uri)?.getText() || '',
diagnostics,
};
}
}
exports.AstroCheck = AstroCheck;

View file

@ -0,0 +1,13 @@
import type { Connection, Diagnostic, TextDocumentIdentifier } from 'vscode-languageserver';
import type { AstroDocument, DocumentManager } from './documents';
export type SendDiagnostics = Connection['sendDiagnostics'];
export type GetDiagnostics = (doc: TextDocumentIdentifier) => Thenable<Diagnostic[]>;
export declare class DiagnosticsManager {
private sendDiagnostics;
private docManager;
private getDiagnostics;
constructor(sendDiagnostics: SendDiagnostics, docManager: DocumentManager, getDiagnostics: GetDiagnostics);
updateAll(): void;
update(document: AstroDocument): Promise<void>;
removeDiagnostics(document: AstroDocument): void;
}

View file

@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DiagnosticsManager = void 0;
class DiagnosticsManager {
constructor(sendDiagnostics, docManager, getDiagnostics) {
this.sendDiagnostics = sendDiagnostics;
this.docManager = docManager;
this.getDiagnostics = getDiagnostics;
}
updateAll() {
this.docManager.getAllOpenedByClient().forEach((doc) => {
this.update(doc[1]);
});
}
async update(document) {
const diagnostics = await this.getDiagnostics({ uri: document.getURL() });
this.sendDiagnostics({
uri: document.getURL(),
diagnostics,
});
}
removeDiagnostics(document) {
this.sendDiagnostics({
uri: document.getURL(),
diagnostics: [],
});
}
}
exports.DiagnosticsManager = DiagnosticsManager;

View file

@ -0,0 +1,43 @@
import type { VSCodeEmmetConfig } from '@vscode/emmet-helper';
import type { FormatCodeSettings, UserPreferences } from 'typescript';
import type { Connection, FormattingOptions } from 'vscode-languageserver';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import type { LSConfig, LSCSSConfig, LSHTMLConfig, LSTypescriptConfig } from './interfaces';
export declare const defaultLSConfig: LSConfig;
type DeepPartial<T> = T extends Record<string, unknown> ? {
[P in keyof T]?: DeepPartial<T[P]>;
} : T;
/**
* Manager class to facilitate accessing and updating the user's config
* Not to be confused with other kind of configurations (such as the Astro project configuration and the TypeScript/Javascript one)
* For more info on this, see the [internal docs](../../../../../docs/internal/language-server/config.md)
*/
export declare class ConfigManager {
private connection?;
private hasConfigurationCapability?;
private globalConfig;
private documentSettings;
shouldRefreshTSServices: boolean;
private isTrusted;
constructor(connection?: Connection | undefined, hasConfigurationCapability?: boolean | undefined);
updateConfig(): void;
removeDocument(scopeUri: string): void;
getConfig<T>(section: string, scopeUri: string): Promise<T | Record<string, any>>;
getEmmetConfig(document: TextDocument): Promise<VSCodeEmmetConfig>;
getPrettierVSConfig(document: TextDocument): Promise<Record<string, any>>;
getTSFormatConfig(document: TextDocument, vscodeOptions?: FormattingOptions): Promise<FormatCodeSettings>;
getTSPreferences(document: TextDocument): Promise<UserPreferences>;
/**
* Return true if a plugin and an optional feature is enabled
*/
isEnabled(document: TextDocument, plugin: keyof LSConfig, feature?: keyof LSTypescriptConfig | keyof LSCSSConfig | keyof LSHTMLConfig): Promise<boolean>;
/**
* Updating the global config should only be done in cases where the client doesn't support `workspace/configuration`
* or inside of tests.
*
* The `outsideAstro` parameter can be set to true to change configurations in the global scope.
* For example, to change TypeScript settings
*/
updateGlobalConfig(config: DeepPartial<LSConfig> | any, outsideAstro?: boolean): void;
}
export {};

View file

@ -0,0 +1,226 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigManager = exports.defaultLSConfig = void 0;
const utils_1 = require("../../utils");
// The default language server configuration is used only in two cases:
// 1. When the client does not support `workspace/configuration` requests and as such, needs a global config
// 2. Inside tests, where we don't have a client connection because.. well.. we don't have a client
// Additionally, the default config is used to set default settings for some settings (ex: formatting settings)
exports.defaultLSConfig = {
typescript: {
enabled: true,
allowArbitraryAttributes: false,
diagnostics: { enabled: true },
hover: { enabled: true },
completions: { enabled: true },
definitions: { enabled: true },
documentSymbols: { enabled: true },
codeActions: { enabled: true },
rename: { enabled: true },
signatureHelp: { enabled: true },
semanticTokens: { enabled: true },
},
css: {
enabled: true,
hover: { enabled: true },
completions: { enabled: true, emmet: true },
documentColors: { enabled: true },
documentSymbols: { enabled: true },
},
html: {
enabled: true,
hover: { enabled: true },
completions: { enabled: true, emmet: true },
tagComplete: { enabled: true },
documentSymbols: { enabled: true },
},
format: {
indentFrontmatter: false,
newLineAfterFrontmatter: true,
},
};
/**
* Manager class to facilitate accessing and updating the user's config
* Not to be confused with other kind of configurations (such as the Astro project configuration and the TypeScript/Javascript one)
* For more info on this, see the [internal docs](../../../../../docs/internal/language-server/config.md)
*/
class ConfigManager {
constructor(connection, hasConfigurationCapability) {
this.connection = connection;
this.hasConfigurationCapability = hasConfigurationCapability;
this.globalConfig = { astro: exports.defaultLSConfig };
this.documentSettings = {};
// If set to true, the next time we need a TypeScript language service, we'll rebuild it so it gets the new config
this.shouldRefreshTSServices = false;
this.isTrusted = true;
}
updateConfig() {
// Reset all cached document settings
this.documentSettings = {};
this.shouldRefreshTSServices = true;
}
removeDocument(scopeUri) {
delete this.documentSettings[scopeUri];
}
async getConfig(section, scopeUri) {
if (!this.connection || !this.hasConfigurationCapability) {
return (0, utils_1.get)(this.globalConfig, section) ?? {};
}
if (!this.documentSettings[scopeUri]) {
this.documentSettings[scopeUri] = {};
}
if (!this.documentSettings[scopeUri][section]) {
this.documentSettings[scopeUri][section] = await this.connection.workspace.getConfiguration({
scopeUri,
section,
});
}
return this.documentSettings[scopeUri][section];
}
async getEmmetConfig(document) {
const emmetConfig = (await this.getConfig('emmet', document.uri)) ?? {};
return {
...emmetConfig,
preferences: emmetConfig.preferences ?? {},
showExpandedAbbreviation: emmetConfig.showExpandedAbbreviation ?? 'always',
showAbbreviationSuggestions: emmetConfig.showAbbreviationSuggestions ?? true,
syntaxProfiles: emmetConfig.syntaxProfiles ?? {},
variables: emmetConfig.variables ?? {},
excludeLanguages: emmetConfig.excludeLanguages ?? [],
showSuggestionsAsSnippets: emmetConfig.showSuggestionsAsSnippets ?? false,
};
}
async getPrettierVSConfig(document) {
const prettierVSConfig = (await this.getConfig('prettier', document.uri)) ?? {};
return prettierVSConfig;
}
async getTSFormatConfig(document, vscodeOptions) {
const formatConfig = (await this.getConfig('typescript.format', document.uri)) ?? {};
return {
tabSize: vscodeOptions?.tabSize,
indentSize: vscodeOptions?.tabSize,
convertTabsToSpaces: vscodeOptions?.insertSpaces,
// We can use \n here since the editor normalizes later on to its line endings.
newLineCharacter: '\n',
insertSpaceAfterCommaDelimiter: formatConfig.insertSpaceAfterCommaDelimiter ?? true,
insertSpaceAfterConstructor: formatConfig.insertSpaceAfterConstructor ?? false,
insertSpaceAfterSemicolonInForStatements: formatConfig.insertSpaceAfterSemicolonInForStatements ?? true,
insertSpaceBeforeAndAfterBinaryOperators: formatConfig.insertSpaceBeforeAndAfterBinaryOperators ?? true,
insertSpaceAfterKeywordsInControlFlowStatements: formatConfig.insertSpaceAfterKeywordsInControlFlowStatements ?? true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: formatConfig.insertSpaceAfterFunctionKeywordForAnonymousFunctions ?? true,
insertSpaceBeforeFunctionParenthesis: formatConfig.insertSpaceBeforeFunctionParenthesis ?? false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: formatConfig.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis ?? false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: formatConfig.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets ?? false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: formatConfig.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces ?? true,
insertSpaceAfterOpeningAndBeforeClosingEmptyBraces: formatConfig.insertSpaceAfterOpeningAndBeforeClosingEmptyBraces ?? true,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: formatConfig.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces ?? false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: formatConfig.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces ?? false,
insertSpaceAfterTypeAssertion: formatConfig.insertSpaceAfterTypeAssertion ?? false,
placeOpenBraceOnNewLineForFunctions: formatConfig.placeOpenBraceOnNewLineForFunctions ?? false,
placeOpenBraceOnNewLineForControlBlocks: formatConfig.placeOpenBraceOnNewLineForControlBlocks ?? false,
semicolons: formatConfig.semicolons ?? 'ignore',
};
}
async getTSPreferences(document) {
const config = (await this.getConfig('typescript', document.uri)) ?? {};
const preferences = (await this.getConfig('typescript.preferences', document.uri)) ?? {};
return {
quotePreference: getQuoteStylePreference(preferences),
importModuleSpecifierPreference: getImportModuleSpecifierPreference(preferences),
importModuleSpecifierEnding: getImportModuleSpecifierEndingPreference(preferences),
allowTextChangesInNewFiles: document.uri.startsWith('file://'),
providePrefixAndSuffixTextForRename: (preferences.renameShorthandProperties ?? true) === false ? false : preferences.useAliasesForRenames ?? true,
includeAutomaticOptionalChainCompletions: config.suggest?.includeAutomaticOptionalChainCompletions ?? true,
includeCompletionsForImportStatements: config.suggest?.includeCompletionsForImportStatements ?? true,
includeCompletionsWithSnippetText: config.suggest?.includeCompletionsWithSnippetText ?? true,
includeCompletionsForModuleExports: config.suggest?.autoImports ?? true,
allowIncompleteCompletions: true,
includeCompletionsWithInsertText: true,
// Inlay Hints
includeInlayParameterNameHints: getInlayParameterNameHintsPreference(config),
includeInlayParameterNameHintsWhenArgumentMatchesName: !(config.inlayHints?.parameterNames?.suppressWhenArgumentMatchesName ?? true),
includeInlayFunctionParameterTypeHints: config.inlayHints?.parameterTypes?.enabled ?? false,
includeInlayVariableTypeHints: config.inlayHints?.variableTypes?.enabled ?? false,
includeInlayPropertyDeclarationTypeHints: config.inlayHints?.propertyDeclarationTypes?.enabled ?? false,
includeInlayFunctionLikeReturnTypeHints: config.inlayHints?.functionLikeReturnTypes?.enabled ?? false,
includeInlayEnumMemberValueHints: config.inlayHints?.enumMemberValues?.enabled ?? false,
};
}
/**
* Return true if a plugin and an optional feature is enabled
*/
async isEnabled(document, plugin, feature) {
const config = (await this.getConfig('astro', document.uri)) ?? {};
if (config[plugin]) {
let res = config[plugin].enabled ?? true;
if (feature && config[plugin][feature]) {
res = (res && config[plugin][feature].enabled) ?? true;
}
return res;
}
return true;
}
/**
* Updating the global config should only be done in cases where the client doesn't support `workspace/configuration`
* or inside of tests.
*
* The `outsideAstro` parameter can be set to true to change configurations in the global scope.
* For example, to change TypeScript settings
*/
updateGlobalConfig(config, outsideAstro) {
if (outsideAstro) {
this.globalConfig = (0, utils_1.mergeDeep)({}, this.globalConfig, config);
}
else {
this.globalConfig.astro = (0, utils_1.mergeDeep)({}, exports.defaultLSConfig, this.globalConfig.astro, config);
}
this.shouldRefreshTSServices = true;
}
}
exports.ConfigManager = ConfigManager;
function getQuoteStylePreference(config) {
switch (config.quoteStyle) {
case 'single':
return 'single';
case 'double':
return 'double';
default:
return 'auto';
}
}
function getImportModuleSpecifierPreference(config) {
switch (config.importModuleSpecifier) {
case 'project-relative':
return 'project-relative';
case 'relative':
return 'relative';
case 'non-relative':
return 'non-relative';
default:
return undefined;
}
}
function getImportModuleSpecifierEndingPreference(config) {
switch (config.importModuleSpecifierEnding) {
case 'minimal':
return 'minimal';
case 'index':
return 'index';
case 'js':
return 'js';
default:
return 'auto';
}
}
function getInlayParameterNameHintsPreference(config) {
switch (config.inlayHints?.parameterNames?.enabled) {
case 'none':
return 'none';
case 'literals':
return 'literals';
case 'all':
return 'all';
default:
return undefined;
}
}

View file

@ -0,0 +1,2 @@
export * from './ConfigManager';
export * from './interfaces';

View file

@ -0,0 +1,18 @@
"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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./ConfigManager"), exports);
__exportStar(require("./interfaces"), exports);

View file

@ -0,0 +1,77 @@
/**
* Representation of the language server config.
* Make sure that this is kept in sync with the `package.json` of the VS Code extension
*/
export interface LSConfig {
typescript?: LSTypescriptConfig;
html?: LSHTMLConfig;
css?: LSCSSConfig;
format?: LSFormatConfig;
}
export interface LSFormatConfig {
indentFrontmatter?: boolean;
newLineAfterFrontmatter?: boolean;
}
export interface LSTypescriptConfig {
enabled?: boolean;
allowArbitraryAttributes?: boolean;
diagnostics?: {
enabled?: boolean;
};
hover?: {
enabled?: boolean;
};
documentSymbols?: {
enabled?: boolean;
};
completions?: {
enabled?: boolean;
};
definitions?: {
enabled?: boolean;
};
codeActions?: {
enabled?: boolean;
};
rename?: {
enabled?: boolean;
};
signatureHelp?: {
enabled?: boolean;
};
semanticTokens?: {
enabled?: boolean;
};
}
export interface LSHTMLConfig {
enabled?: boolean;
hover?: {
enabled?: boolean;
};
completions?: {
enabled?: boolean;
emmet?: boolean;
};
tagComplete?: {
enabled?: boolean;
};
documentSymbols?: {
enabled?: boolean;
};
}
export interface LSCSSConfig {
enabled?: boolean;
hover?: {
enabled?: boolean;
};
completions?: {
enabled?: boolean;
emmet?: boolean;
};
documentColors?: {
enabled?: boolean;
};
documentSymbols?: {
enabled?: boolean;
};
}

View file

@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View file

@ -0,0 +1,19 @@
import type { HTMLDocument, Range } from 'vscode-html-languageservice';
import { WritableDocument } from './DocumentBase';
import { AstroMetadata } from './parseAstro';
import { TagInformation } from './utils';
export declare class AstroDocument extends WritableDocument {
url: string;
content: string;
languageId: string;
astroMeta: AstroMetadata;
html: HTMLDocument;
styleTags: TagInformation[];
scriptTags: TagInformation[];
constructor(url: string, content: string);
private updateDocInfo;
setText(text: string): void;
getText(range?: Range | undefined): string;
getURL(): string;
getFilePath(): string | null;
}

View file

@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AstroDocument = void 0;
const utils_1 = require("../../utils");
const DocumentBase_1 = require("./DocumentBase");
const parseAstro_1 = require("./parseAstro");
const parseHtml_1 = require("./parseHtml");
const utils_2 = require("./utils");
class AstroDocument extends DocumentBase_1.WritableDocument {
constructor(url, content) {
super();
this.url = url;
this.content = content;
this.languageId = 'astro';
this.updateDocInfo();
}
updateDocInfo() {
this.astroMeta = (0, parseAstro_1.parseAstro)(this.content);
this.html = (0, parseHtml_1.parseHtml)(this.content, this.astroMeta);
this.styleTags = (0, utils_2.extractStyleTags)(this.content, this.html);
this.scriptTags = (0, utils_2.extractScriptTags)(this.content, this.html);
}
setText(text) {
this.content = text;
this.version++;
this.updateDocInfo();
}
getText(range) {
if (range) {
const start = this.offsetAt(range.start);
const end = this.offsetAt(range.end);
return this.content.substring(start, end);
}
return this.content;
}
getURL() {
return this.url;
}
getFilePath() {
return (0, utils_1.urlToPath)(this.url);
}
}
exports.AstroDocument = AstroDocument;

View file

@ -0,0 +1,68 @@
import type { Position } from 'vscode-languageserver';
import type { TextDocument } from 'vscode-languageserver-textdocument';
/**
* Represents a textual document.
*/
export declare abstract class ReadableDocument implements TextDocument {
/**
* Get the text content of the document
*/
abstract getText(): string;
/**
* Returns the url of the document
*/
abstract getURL(): string;
/**
* Returns the file path if the url scheme is file
*/
abstract getFilePath(): string | null;
/**
* Current version of the document.
*/
version: number;
/**
* Should be cleared when there's an update to the text
*/
protected lineOffsets?: number[];
/**
* Get the length of the document's content
*/
getTextLength(): number;
/**
* Get the line and character based on the offset
* @param offset The index of the position
*/
positionAt(offset: number): Position;
/**
* Get the index of the line and character position
* @param position Line and character position
*/
offsetAt(position: Position): number;
getLineUntilOffset(offset: number): string;
private getLineOffsets;
/**
* Implements TextDocument
*/
get uri(): string;
get lines(): string[];
get lineCount(): number;
abstract languageId: string;
}
/**
* Represents a textual document that can be manipulated.
*/
export declare abstract class WritableDocument extends ReadableDocument {
/**
* Set the text content of the document.
* Implementers should set `lineOffsets` to `undefined` here.
* @param text The new text content
*/
abstract setText(text: string): void;
/**
* Update the text between two positions.
* @param text The new text slice
* @param start Start offset of the new text
* @param end End offset of the new text
*/
update(text: string, start: number, end: number): void;
}

View file

@ -0,0 +1,75 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WritableDocument = exports.ReadableDocument = void 0;
const utils_1 = require("./utils");
/**
* Represents a textual document.
*/
class ReadableDocument {
constructor() {
/**
* Current version of the document.
*/
this.version = 0;
}
/**
* Get the length of the document's content
*/
getTextLength() {
return this.getText().length;
}
/**
* Get the line and character based on the offset
* @param offset The index of the position
*/
positionAt(offset) {
return (0, utils_1.positionAt)(offset, this.getText(), this.getLineOffsets());
}
/**
* Get the index of the line and character position
* @param position Line and character position
*/
offsetAt(position) {
return (0, utils_1.offsetAt)(position, this.getText(), this.getLineOffsets());
}
getLineUntilOffset(offset) {
const { line, character } = this.positionAt(offset);
return this.lines[line].slice(0, character);
}
getLineOffsets() {
if (!this.lineOffsets) {
this.lineOffsets = (0, utils_1.getLineOffsets)(this.getText());
}
return this.lineOffsets;
}
/**
* Implements TextDocument
*/
get uri() {
return this.getURL();
}
get lines() {
return this.getText().split(/\r?\n/);
}
get lineCount() {
return this.lines.length;
}
}
exports.ReadableDocument = ReadableDocument;
/**
* Represents a textual document that can be manipulated.
*/
class WritableDocument extends ReadableDocument {
/**
* Update the text between two positions.
* @param text The new text slice
* @param start Start offset of the new text
* @param end End offset of the new text
*/
update(text, start, end) {
this.lineOffsets = undefined;
const content = this.getText();
this.setText(content.slice(0, start) + text + content.slice(end));
}
}
exports.WritableDocument = WritableDocument;

View file

@ -0,0 +1,23 @@
import type { TextDocumentContentChangeEvent, TextDocumentItem, VersionedTextDocumentIdentifier } from 'vscode-languageserver';
import { AstroDocument } from './AstroDocument';
export type DocumentEvent = 'documentOpen' | 'documentChange' | 'documentClose';
export declare class DocumentManager {
private createDocument?;
private emitter;
private openedInClient;
private documents;
private locked;
private deleteCandidates;
constructor(createDocument?: ((textDocument: Pick<TextDocumentItem, 'text' | 'uri'>) => AstroDocument) | undefined);
openDocument(textDocument: Pick<TextDocumentItem, 'text' | 'uri'>): AstroDocument;
lockDocument(uri: string): void;
markAsOpenedInClient(uri: string): void;
getAllOpenedByClient(): [string, AstroDocument][];
releaseDocument(uri: string): void;
closeDocument(uri: string): void;
updateDocument(textDocument: VersionedTextDocumentIdentifier, changes: TextDocumentContentChangeEvent[]): void;
on(name: DocumentEvent, listener: (document: AstroDocument) => void): void;
get(uri: string): AstroDocument | undefined;
private notify;
static newInstance(): DocumentManager;
}

View file

@ -0,0 +1,100 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DocumentManager = void 0;
const events_1 = require("events");
const utils_1 = require("../../utils");
const AstroDocument_1 = require("./AstroDocument");
class DocumentManager {
constructor(createDocument) {
this.createDocument = createDocument;
this.emitter = new events_1.EventEmitter();
this.openedInClient = new Set();
this.documents = new Map();
this.locked = new Set();
this.deleteCandidates = new Set();
if (!createDocument) {
this.createDocument = (textDocument) => new AstroDocument_1.AstroDocument(textDocument.uri, textDocument.text);
}
}
openDocument(textDocument) {
textDocument = { ...textDocument, uri: (0, utils_1.normalizeUri)(textDocument.uri) };
let document;
if (this.documents.has(textDocument.uri)) {
document = this.documents.get(textDocument.uri);
document.setText(textDocument.text);
}
else {
document = this.createDocument(textDocument);
this.documents.set(textDocument.uri, document);
this.notify('documentOpen', document);
}
this.notify('documentChange', document);
return document;
}
lockDocument(uri) {
this.locked.add((0, utils_1.normalizeUri)(uri));
}
markAsOpenedInClient(uri) {
this.openedInClient.add((0, utils_1.normalizeUri)(uri));
}
getAllOpenedByClient() {
return Array.from(this.documents.entries()).filter((doc) => this.openedInClient.has(doc[0]));
}
releaseDocument(uri) {
uri = (0, utils_1.normalizeUri)(uri);
this.locked.delete(uri);
this.openedInClient.delete(uri);
if (this.deleteCandidates.has(uri)) {
this.deleteCandidates.delete(uri);
this.closeDocument(uri);
}
}
closeDocument(uri) {
uri = (0, utils_1.normalizeUri)(uri);
const document = this.documents.get(uri);
if (!document) {
throw new Error('Cannot call methods on an unopened document');
}
this.notify('documentClose', document);
// Some plugin may prevent a document from actually being closed.
if (!this.locked.has(uri)) {
this.documents.delete(uri);
}
else {
this.deleteCandidates.add(uri);
}
this.openedInClient.delete(uri);
}
updateDocument(textDocument, changes) {
const document = this.documents.get((0, utils_1.normalizeUri)(textDocument.uri));
if (!document) {
throw new Error('Cannot call methods on an unopened document');
}
for (const change of changes) {
let start = 0;
let end = 0;
if ('range' in change) {
start = document.offsetAt(change.range.start);
end = document.offsetAt(change.range.end);
}
else {
end = document.getTextLength();
}
document.update(change.text, start, end);
}
this.notify('documentChange', document);
}
on(name, listener) {
this.emitter.on(name, listener);
}
get(uri) {
return this.documents.get((0, utils_1.normalizeUri)(uri));
}
notify(name, document) {
this.emitter.emit(name, document);
}
static newInstance() {
return new DocumentManager(({ uri, text }) => new AstroDocument_1.AstroDocument(uri, text));
}
}
exports.DocumentManager = DocumentManager;

View file

@ -0,0 +1,94 @@
import { TraceMap } from '@jridgewell/trace-mapping';
import type ts from 'typescript';
import { CodeAction, ColorPresentation, CompletionItem, Diagnostic, FoldingRange, Hover, InsertReplaceEdit, LocationLink, Position, Range, SelectionRange, SymbolInformation, TextDocumentEdit, TextEdit } from 'vscode-languageserver';
import { DocumentSnapshot, ScriptTagDocumentSnapshot } from '../../plugins/typescript/snapshots/DocumentSnapshot';
import { TagInformation } from './utils';
export interface DocumentMapper {
/**
* Map the generated position to the original position
* @param generatedPosition Position in fragment
*/
getOriginalPosition(generatedPosition: Position): Position;
/**
* Map the original position to the generated position
* @param originalPosition Position in parent
*/
getGeneratedPosition(originalPosition: Position): Position;
/**
* Returns true if the given original position is inside of the generated map
* @param pos Position in original
*/
isInGenerated(pos: Position): boolean;
/**
* Get document URL
*/
getURL(): string;
/**
* Implement this if you need teardown logic before this mapper gets cleaned up.
*/
destroy?(): void;
}
/**
* Does not map, returns positions as is.
*/
export declare class IdentityMapper implements DocumentMapper {
private url;
private parent?;
constructor(url: string, parent?: DocumentMapper | undefined);
getOriginalPosition(generatedPosition: Position): Position;
getGeneratedPosition(originalPosition: Position): Position;
isInGenerated(position: Position): boolean;
getURL(): string;
destroy(): void;
}
/**
* Maps positions in a fragment relative to a parent.
*/
export declare class FragmentMapper implements DocumentMapper {
private originalText;
private tagInfo;
private url;
private lineOffsetsOriginal;
private lineOffsetsGenerated;
constructor(originalText: string, tagInfo: TagInformation, url: string);
getOriginalPosition(generatedPosition: Position): Position;
private offsetInParent;
getGeneratedPosition(originalPosition: Position): Position;
isInGenerated(pos: Position): boolean;
getURL(): string;
}
export declare class SourceMapDocumentMapper implements DocumentMapper {
protected traceMap: TraceMap;
protected sourceUri: string;
private parent?;
constructor(traceMap: TraceMap, sourceUri: string, parent?: DocumentMapper | undefined);
getOriginalPosition(generatedPosition: Position): Position;
getGeneratedPosition(originalPosition: Position): Position;
isInGenerated(position: Position): boolean;
getURL(): string;
}
export declare class ConsumerDocumentMapper extends SourceMapDocumentMapper {
private nrPrependesLines;
constructor(traceMap: TraceMap, sourceUri: string, nrPrependesLines: number);
getOriginalPosition(generatedPosition: Position): Position;
getGeneratedPosition(originalPosition: Position): Position;
isInGenerated(): boolean;
}
export declare function mapRangeToOriginal(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, range: Range): Range;
export declare function mapRangeToGenerated(fragment: DocumentMapper, range: Range): Range;
export declare function mapCompletionItemToOriginal(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, item: CompletionItem): CompletionItem;
export declare function mapHoverToParent(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, hover: Hover): Hover;
export declare function mapObjWithRangeToOriginal<T extends {
range: Range;
}>(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, objWithRange: T): T;
export declare function mapInsertReplaceEditToOriginal(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, edit: InsertReplaceEdit): InsertReplaceEdit;
export declare function mapEditToOriginal(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, edit: TextEdit | InsertReplaceEdit): TextEdit | InsertReplaceEdit;
export declare function mapDiagnosticToGenerated(fragment: DocumentMapper, diagnostic: Diagnostic): Diagnostic;
export declare function mapColorPresentationToOriginal(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, presentation: ColorPresentation): ColorPresentation;
export declare function mapSymbolInformationToOriginal(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, info: SymbolInformation): SymbolInformation;
export declare function mapLocationLinkToOriginal(fragment: DocumentMapper, def: LocationLink): LocationLink;
export declare function mapTextDocumentEditToOriginal(fragment: DocumentMapper, edit: TextDocumentEdit): TextDocumentEdit;
export declare function mapCodeActionToOriginal(fragment: DocumentMapper, codeAction: CodeAction): CodeAction;
export declare function mapScriptSpanStartToSnapshot(span: ts.TextSpan, scriptTagSnapshot: ScriptTagDocumentSnapshot, tsSnapshot: DocumentSnapshot): number;
export declare function mapFoldingRangeToParent(fragment: DocumentMapper, foldingRange: FoldingRange): FoldingRange;
export declare function mapSelectionRangeToParent(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, selectionRange: SelectionRange): SelectionRange;

View file

@ -0,0 +1,264 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mapSelectionRangeToParent = exports.mapFoldingRangeToParent = exports.mapScriptSpanStartToSnapshot = exports.mapCodeActionToOriginal = exports.mapTextDocumentEditToOriginal = exports.mapLocationLinkToOriginal = exports.mapSymbolInformationToOriginal = exports.mapColorPresentationToOriginal = exports.mapDiagnosticToGenerated = exports.mapEditToOriginal = exports.mapInsertReplaceEditToOriginal = exports.mapObjWithRangeToOriginal = exports.mapHoverToParent = exports.mapCompletionItemToOriginal = exports.mapRangeToGenerated = exports.mapRangeToOriginal = exports.ConsumerDocumentMapper = exports.SourceMapDocumentMapper = exports.FragmentMapper = exports.IdentityMapper = void 0;
const trace_mapping_1 = require("@jridgewell/trace-mapping");
const vscode_languageserver_1 = require("vscode-languageserver");
const utils_1 = require("./utils");
/**
* Does not map, returns positions as is.
*/
class IdentityMapper {
constructor(url, parent) {
this.url = url;
this.parent = parent;
}
getOriginalPosition(generatedPosition) {
if (this.parent) {
generatedPosition = this.getOriginalPosition(generatedPosition);
}
return generatedPosition;
}
getGeneratedPosition(originalPosition) {
if (this.parent) {
originalPosition = this.getGeneratedPosition(originalPosition);
}
return originalPosition;
}
isInGenerated(position) {
if (this.parent && !this.parent.isInGenerated(position)) {
return false;
}
return true;
}
getURL() {
return this.url;
}
destroy() {
this.parent?.destroy?.();
}
}
exports.IdentityMapper = IdentityMapper;
/**
* Maps positions in a fragment relative to a parent.
*/
class FragmentMapper {
constructor(originalText, tagInfo, url) {
this.originalText = originalText;
this.tagInfo = tagInfo;
this.url = url;
this.lineOffsetsOriginal = (0, utils_1.getLineOffsets)(this.originalText);
this.lineOffsetsGenerated = (0, utils_1.getLineOffsets)(this.tagInfo.content);
}
getOriginalPosition(generatedPosition) {
const parentOffset = this.offsetInParent((0, utils_1.offsetAt)(generatedPosition, this.tagInfo.content, this.lineOffsetsGenerated));
return (0, utils_1.positionAt)(parentOffset, this.originalText, this.lineOffsetsOriginal);
}
offsetInParent(offset) {
return this.tagInfo.start + offset;
}
getGeneratedPosition(originalPosition) {
const fragmentOffset = (0, utils_1.offsetAt)(originalPosition, this.originalText, this.lineOffsetsOriginal) - this.tagInfo.start;
return (0, utils_1.positionAt)(fragmentOffset, this.tagInfo.content, this.lineOffsetsGenerated);
}
isInGenerated(pos) {
const offset = (0, utils_1.offsetAt)(pos, this.originalText, this.lineOffsetsOriginal);
return offset >= this.tagInfo.start && offset <= this.tagInfo.end;
}
getURL() {
return this.url;
}
}
exports.FragmentMapper = FragmentMapper;
class SourceMapDocumentMapper {
constructor(traceMap, sourceUri, parent) {
this.traceMap = traceMap;
this.sourceUri = sourceUri;
this.parent = parent;
}
getOriginalPosition(generatedPosition) {
if (this.parent) {
generatedPosition = this.parent.getOriginalPosition(generatedPosition);
}
if (generatedPosition.line < 0) {
return { line: -1, character: -1 };
}
const mapped = (0, trace_mapping_1.originalPositionFor)(this.traceMap, {
line: generatedPosition.line + 1,
column: generatedPosition.character,
});
if (!mapped) {
return { line: -1, character: -1 };
}
if (mapped.line === 0) {
// eslint-disable-next-line no-console
console.log('Got 0 mapped line from', generatedPosition, 'col was', mapped.column);
}
return {
line: (mapped.line || 0) - 1,
character: mapped.column || 0,
};
}
getGeneratedPosition(originalPosition) {
if (this.parent) {
originalPosition = this.parent.getGeneratedPosition(originalPosition);
}
const mapped = (0, trace_mapping_1.generatedPositionFor)(this.traceMap, {
line: originalPosition.line + 1,
column: originalPosition.character,
source: this.sourceUri,
});
if (!mapped) {
return { line: -1, character: -1 };
}
const result = {
line: (mapped.line || 0) - 1,
character: mapped.column || 0,
};
if (result.line < 0) {
return result;
}
return result;
}
isInGenerated(position) {
if (this.parent && !this.isInGenerated(position)) {
return false;
}
const generated = this.getGeneratedPosition(position);
return generated.line >= 0;
}
getURL() {
return this.sourceUri;
}
}
exports.SourceMapDocumentMapper = SourceMapDocumentMapper;
class ConsumerDocumentMapper extends SourceMapDocumentMapper {
constructor(traceMap, sourceUri, nrPrependesLines) {
super(traceMap, sourceUri);
this.nrPrependesLines = nrPrependesLines;
}
getOriginalPosition(generatedPosition) {
return super.getOriginalPosition(vscode_languageserver_1.Position.create(generatedPosition.line - this.nrPrependesLines, generatedPosition.character));
}
getGeneratedPosition(originalPosition) {
const result = super.getGeneratedPosition(originalPosition);
result.line += this.nrPrependesLines;
return result;
}
isInGenerated() {
// always return true and map outliers case by case
return true;
}
}
exports.ConsumerDocumentMapper = ConsumerDocumentMapper;
function mapRangeToOriginal(fragment, range) {
// DON'T use Range.create here! Positions might not be mapped
// and therefore return negative numbers, which makes Range.create throw.
// These invalid position need to be handled
// on a case-by-case basis in the calling functions.
const originalRange = {
start: fragment.getOriginalPosition(range.start),
end: fragment.getOriginalPosition(range.end),
};
// Range may be mapped one character short - reverse that for "in the same line" cases
if (originalRange.start.line === originalRange.end.line &&
range.start.line === range.end.line &&
originalRange.end.character - originalRange.start.character === range.end.character - range.start.character - 1) {
originalRange.end.character += 1;
}
return originalRange;
}
exports.mapRangeToOriginal = mapRangeToOriginal;
function mapRangeToGenerated(fragment, range) {
return vscode_languageserver_1.Range.create(fragment.getGeneratedPosition(range.start), fragment.getGeneratedPosition(range.end));
}
exports.mapRangeToGenerated = mapRangeToGenerated;
function mapCompletionItemToOriginal(fragment, item) {
if (!item.textEdit) {
return item;
}
return {
...item,
textEdit: mapEditToOriginal(fragment, item.textEdit),
};
}
exports.mapCompletionItemToOriginal = mapCompletionItemToOriginal;
function mapHoverToParent(fragment, hover) {
if (!hover.range) {
return hover;
}
return { ...hover, range: mapRangeToOriginal(fragment, hover.range) };
}
exports.mapHoverToParent = mapHoverToParent;
function mapObjWithRangeToOriginal(fragment, objWithRange) {
return { ...objWithRange, range: mapRangeToOriginal(fragment, objWithRange.range) };
}
exports.mapObjWithRangeToOriginal = mapObjWithRangeToOriginal;
function mapInsertReplaceEditToOriginal(fragment, edit) {
return {
...edit,
insert: mapRangeToOriginal(fragment, edit.insert),
replace: mapRangeToOriginal(fragment, edit.replace),
};
}
exports.mapInsertReplaceEditToOriginal = mapInsertReplaceEditToOriginal;
function mapEditToOriginal(fragment, edit) {
return vscode_languageserver_1.TextEdit.is(edit) ? mapObjWithRangeToOriginal(fragment, edit) : mapInsertReplaceEditToOriginal(fragment, edit);
}
exports.mapEditToOriginal = mapEditToOriginal;
function mapDiagnosticToGenerated(fragment, diagnostic) {
return { ...diagnostic, range: mapRangeToGenerated(fragment, diagnostic.range) };
}
exports.mapDiagnosticToGenerated = mapDiagnosticToGenerated;
function mapColorPresentationToOriginal(fragment, presentation) {
const item = {
...presentation,
};
if (item.textEdit) {
item.textEdit = mapObjWithRangeToOriginal(fragment, item.textEdit);
}
if (item.additionalTextEdits) {
item.additionalTextEdits = item.additionalTextEdits.map((edit) => mapObjWithRangeToOriginal(fragment, edit));
}
return item;
}
exports.mapColorPresentationToOriginal = mapColorPresentationToOriginal;
function mapSymbolInformationToOriginal(fragment, info) {
return { ...info, location: mapObjWithRangeToOriginal(fragment, info.location) };
}
exports.mapSymbolInformationToOriginal = mapSymbolInformationToOriginal;
function mapLocationLinkToOriginal(fragment, def) {
return vscode_languageserver_1.LocationLink.create(def.targetUri, fragment.getURL() === def.targetUri ? mapRangeToOriginal(fragment, def.targetRange) : def.targetRange, fragment.getURL() === def.targetUri
? mapRangeToOriginal(fragment, def.targetSelectionRange)
: def.targetSelectionRange, def.originSelectionRange ? mapRangeToOriginal(fragment, def.originSelectionRange) : undefined);
}
exports.mapLocationLinkToOriginal = mapLocationLinkToOriginal;
function mapTextDocumentEditToOriginal(fragment, edit) {
if (edit.textDocument.uri !== fragment.getURL()) {
return edit;
}
return vscode_languageserver_1.TextDocumentEdit.create(edit.textDocument, edit.edits.map((textEdit) => mapObjWithRangeToOriginal(fragment, textEdit)));
}
exports.mapTextDocumentEditToOriginal = mapTextDocumentEditToOriginal;
function mapCodeActionToOriginal(fragment, codeAction) {
return vscode_languageserver_1.CodeAction.create(codeAction.title, {
documentChanges: codeAction.edit.documentChanges.map((edit) => mapTextDocumentEditToOriginal(fragment, edit)),
}, codeAction.kind);
}
exports.mapCodeActionToOriginal = mapCodeActionToOriginal;
function mapScriptSpanStartToSnapshot(span, scriptTagSnapshot, tsSnapshot) {
const originalPosition = scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(span.start));
return tsSnapshot.offsetAt(tsSnapshot.getGeneratedPosition(originalPosition));
}
exports.mapScriptSpanStartToSnapshot = mapScriptSpanStartToSnapshot;
function mapFoldingRangeToParent(fragment, foldingRange) {
// Despite FoldingRange asking for a start and end line and a start and end character, FoldingRanges
// don't use the Range type, instead asking for 4 number. Not sure why, but it's not convenient
const range = mapRangeToOriginal(fragment, vscode_languageserver_1.Range.create(foldingRange.startLine, foldingRange.startCharacter || 0, foldingRange.endLine, foldingRange.endCharacter || 0));
return vscode_languageserver_1.FoldingRange.create(range.start.line, range.end.line, foldingRange.startCharacter ? range.start.character : undefined, foldingRange.endCharacter ? range.end.character : undefined, foldingRange.kind);
}
exports.mapFoldingRangeToParent = mapFoldingRangeToParent;
function mapSelectionRangeToParent(fragment, selectionRange) {
const { range, parent } = selectionRange;
return vscode_languageserver_1.SelectionRange.create(mapRangeToOriginal(fragment, range), parent && mapSelectionRangeToParent(fragment, parent));
}
exports.mapSelectionRangeToParent = mapSelectionRangeToParent;

View file

@ -0,0 +1,5 @@
export * from './AstroDocument';
export * from './DocumentBase';
export * from './DocumentManager';
export * from './DocumentMapper';
export * from './utils';

View file

@ -0,0 +1,21 @@
"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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./AstroDocument"), exports);
__exportStar(require("./DocumentBase"), exports);
__exportStar(require("./DocumentManager"), exports);
__exportStar(require("./DocumentMapper"), exports);
__exportStar(require("./utils"), exports);

View file

@ -0,0 +1,15 @@
interface Frontmatter {
state: null | 'open' | 'closed';
startOffset: null | number;
endOffset: null | number;
}
interface Content {
firstNonWhitespaceOffset: null | number;
}
export interface AstroMetadata {
frontmatter: Frontmatter;
content: Content;
}
/** Parses a document to collect metadata about Astro features */
export declare function parseAstro(content: string): AstroMetadata;
export {};

View file

@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseAstro = void 0;
const utils_1 = require("./utils");
/** Parses a document to collect metadata about Astro features */
function parseAstro(content) {
const frontmatter = getFrontmatter(content);
return {
frontmatter,
content: getContent(content, frontmatter),
};
}
exports.parseAstro = parseAstro;
/** Get frontmatter metadata */
function getFrontmatter(content) {
/** Quickly check how many `---` blocks are in the document */
function getFrontmatterState() {
const parts = content.trim().split('---').length;
switch (parts) {
case 1:
return null;
case 2:
return 'open';
default:
return 'closed';
}
}
const state = getFrontmatterState();
/** Construct a range containing the document's frontmatter */
function getFrontmatterOffsets() {
const startOffset = content.indexOf('---');
if (startOffset === -1)
return [null, null];
const endOffset = content.slice(startOffset + 3).indexOf('---') + 3;
if (endOffset === -1)
return [startOffset, null];
return [startOffset, endOffset];
}
const [startOffset, endOffset] = getFrontmatterOffsets();
return {
state,
startOffset,
endOffset,
};
}
/** Get content metadata */
function getContent(content, frontmatter) {
switch (frontmatter.state) {
case null: {
const offset = (0, utils_1.getFirstNonWhitespaceIndex)(content);
return { firstNonWhitespaceOffset: offset === -1 ? null : offset };
}
case 'open': {
return { firstNonWhitespaceOffset: null };
}
case 'closed': {
const { endOffset } = frontmatter;
const end = (endOffset ?? 0) + 3;
const offset = (0, utils_1.getFirstNonWhitespaceIndex)(content.slice(end));
return { firstNonWhitespaceOffset: end + offset };
}
}
}

View file

@ -0,0 +1,13 @@
import { HTMLDocument, Position } from 'vscode-html-languageservice';
import type { AstroDocument } from './AstroDocument';
import { AstroMetadata } from './parseAstro';
/**
* Parses text as HTML
*/
export declare function parseHtml(text: string, frontmatter: AstroMetadata): HTMLDocument;
export interface AttributeContext {
name: string;
inValue: boolean;
valueRange?: [number, number];
}
export declare function getAttributeContextAtPosition(document: AstroDocument, position: Position): AttributeContext | null;

View file

@ -0,0 +1,126 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAttributeContextAtPosition = exports.parseHtml = void 0;
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
const utils_1 = require("./utils");
const parser = (0, vscode_html_languageservice_1.getLanguageService)();
/**
* Parses text as HTML
*/
function parseHtml(text, frontmatter) {
const preprocessed = preprocess(text, frontmatter);
// We can safely only set getText because only this is used for parsing
const parsedDoc = parser.parseHTMLDocument({ getText: () => preprocessed });
return parsedDoc;
}
exports.parseHtml = parseHtml;
const createScanner = parser.createScanner;
/**
* scan the text and remove any `>` or `<` that cause the tag to end short,
*/
function preprocess(text, frontmatter) {
let scanner = createScanner(text);
let token = scanner.scan();
let currentStartTagStart = null;
const hasFrontmatter = frontmatter !== undefined;
while (token !== vscode_html_languageservice_1.TokenType.EOS) {
const offset = scanner.getTokenOffset();
if (hasFrontmatter &&
(scanner.getTokenText() === '>' || scanner.getTokenText() === '<') &&
offset < (frontmatter.content.firstNonWhitespaceOffset ?? 0)) {
blankStartOrEndTagLike(offset, vscode_html_languageservice_1.ScannerState.WithinContent);
}
if (token === vscode_html_languageservice_1.TokenType.StartTagOpen) {
currentStartTagStart = offset;
}
if (token === vscode_html_languageservice_1.TokenType.StartTagClose) {
if (shouldBlankStartOrEndTagLike(offset)) {
blankStartOrEndTagLike(offset);
}
else {
currentStartTagStart = null;
}
}
if (token === vscode_html_languageservice_1.TokenType.StartTagSelfClose) {
currentStartTagStart = null;
}
// <Foo checked={a < 1}>
// https://github.com/microsoft/vscode-html-languageservice/blob/71806ef57be07e1068ee40900ef8b0899c80e68a/src/parser/htmlScanner.ts#L327
if (token === vscode_html_languageservice_1.TokenType.Unknown &&
scanner.getScannerState() === vscode_html_languageservice_1.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 text;
function shouldBlankStartOrEndTagLike(offset) {
// not null rather than falsy, otherwise it won't work on first tag(0)
return currentStartTagStart !== null && (0, utils_1.isInsideExpression)(text, currentStartTagStart, offset);
}
function blankStartOrEndTagLike(offset, state) {
text = text.substring(0, offset) + ' ' + text.substring(offset + 1);
scanner = createScanner(text, offset, state ?? vscode_html_languageservice_1.ScannerState.WithinTag);
}
}
function getAttributeContextAtPosition(document, position) {
const offset = document.offsetAt(position);
const { html } = document;
const tag = html.findNodeAt(offset);
if (!inStartTag(offset, tag) || !tag.attributes) {
return null;
}
const text = document.getText();
const beforeStartTagEnd = text.substring(0, tag.start) + preprocess(text.substring(tag.start, tag.startTagEnd));
const scanner = createScanner(beforeStartTagEnd, tag.start);
let token = scanner.scan();
let currentAttributeName;
const inTokenRange = () => scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd();
while (token != vscode_html_languageservice_1.TokenType.EOS) {
// adopted from https://github.com/microsoft/vscode-html-languageservice/blob/2f7ae4df298ac2c299a40e9024d118f4a9dc0c68/src/services/htmlCompletion.ts#L402
if (token === vscode_html_languageservice_1.TokenType.AttributeName) {
currentAttributeName = scanner.getTokenText();
if (inTokenRange()) {
return {
name: currentAttributeName,
inValue: false,
};
}
}
else if (token === vscode_html_languageservice_1.TokenType.DelimiterAssign) {
if (scanner.getTokenEnd() === offset && currentAttributeName) {
const nextToken = scanner.scan();
return {
name: currentAttributeName,
inValue: true,
valueRange: [offset, nextToken === vscode_html_languageservice_1.TokenType.AttributeValue ? scanner.getTokenEnd() : offset],
};
}
}
else if (token === vscode_html_languageservice_1.TokenType.AttributeValue) {
if (inTokenRange() && currentAttributeName) {
let start = scanner.getTokenOffset();
let end = scanner.getTokenEnd();
const char = text[start];
if (char === '"' || char === "'") {
start++;
end--;
}
return {
name: currentAttributeName,
inValue: true,
valueRange: [start, end],
};
}
currentAttributeName = undefined;
}
token = scanner.scan();
}
return null;
}
exports.getAttributeContextAtPosition = getAttributeContextAtPosition;
function inStartTag(offset, node) {
return offset > node.start && node.startTagEnd != undefined && offset < node.startTagEnd;
}

View file

@ -0,0 +1,63 @@
import type { HTMLDocument, Node } from 'vscode-html-languageservice';
import { Position } from 'vscode-languageserver';
export interface TagInformation {
content: string;
attributes: Record<string, string>;
start: number;
end: number;
startPos: Position;
endPos: Position;
container: {
start: number;
end: number;
};
closed: boolean;
}
export declare function walk(node: Node): Generator<Node, void, unknown>;
export declare function extractStyleTags(source: string, html: HTMLDocument): TagInformation[];
export declare function extractScriptTags(source: string, html: HTMLDocument): TagInformation[];
export declare function getLineAtPosition(position: Position, text: string): string;
/**
* 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 offset is inside the name of a tag
*/
export declare function isInTagName(html: HTMLDocument, offset: number): boolean;
/**
* 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 the current position is in a specific tag
*/
export declare function isInTag(position: Position, tagInfo: TagInformation | null): tagInfo is TagInformation;
/**
* Return if a given position is inside a JSX expression
*/
export declare function isInsideExpression(html: string, tagStart: number, position: number): boolean;
/**
* Returns if a given offset is inside of the document frontmatter
*/
export declare function isInsideFrontmatter(text: string, offset: number): boolean;
/**
* Get the line and character based on the offset
* @param offset The index of the position
* @param text The text for which the position should be retrived
* @param lineOffsets number Array with offsets for each line. Computed if not given
*/
export declare function positionAt(offset: number, text: string, lineOffsets?: number[]): Position;
/**
* Get the offset of the line and character position
* @param position Line and character position
* @param text The text for which the offset should be retrived
* @param lineOffsets number Array with offsets for each line. Computed if not given
*/
export declare function offsetAt(position: Position, text: string, lineOffsets?: number[]): number;
export declare function getLineOffsets(text: string): number[];
/**
* Gets index of first-non-whitespace character.
*/
export declare function getFirstNonWhitespaceIndex(str: string): number;

View file

@ -0,0 +1,223 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFirstNonWhitespaceIndex = exports.getLineOffsets = exports.offsetAt = exports.positionAt = exports.isInsideFrontmatter = exports.isInsideExpression = exports.isInTag = exports.isPossibleComponent = exports.isInTagName = exports.isInComponentStartTag = exports.getLineAtPosition = exports.extractScriptTags = exports.extractStyleTags = exports.walk = void 0;
const vscode_languageserver_1 = require("vscode-languageserver");
const utils_1 = require("../../utils");
function* walk(node) {
for (let child of node.children) {
yield* walk(child);
}
yield node;
}
exports.walk = walk;
/**
* Extracts a tag (style or script) from the given text
* and returns its start, end and the attributes on that tag.
*
* @param source text content to extract tag from
* @param tag the tag to extract
*/
function extractTags(text, tag, html) {
const rootNodes = html.roots;
const matchedNodes = rootNodes.filter((node) => node.tag === tag);
if (tag === 'style' && !matchedNodes.length && rootNodes.length) {
for (let child of walk(rootNodes[0])) {
if (child.tag === 'style') {
matchedNodes.push(child);
}
}
}
if (tag === 'script' && !matchedNodes.length && rootNodes.length) {
for (let child of walk(rootNodes[0])) {
if (child.tag === 'script') {
matchedNodes.push(child);
}
}
}
return matchedNodes.map(transformToTagInfo);
function transformToTagInfo(matchedNode) {
const start = matchedNode.startTagEnd ?? matchedNode.start;
const end = matchedNode.endTagStart ?? matchedNode.end;
const startPos = positionAt(start, text);
const endPos = positionAt(end, text);
const container = {
start: matchedNode.start,
end: matchedNode.end,
};
const content = text.substring(start, end);
return {
content,
attributes: parseAttributes(matchedNode.attributes),
start,
end,
startPos,
endPos,
container,
// vscode-html-languageservice types does not contain this, despite it existing. Annoying
closed: matchedNode.closed,
};
}
}
function extractStyleTags(source, html) {
const styles = extractTags(source, 'style', html);
if (!styles.length) {
return [];
}
return styles;
}
exports.extractStyleTags = extractStyleTags;
function extractScriptTags(source, html) {
const scripts = extractTags(source, 'script', html);
if (!scripts.length) {
return [];
}
return scripts;
}
exports.extractScriptTags = extractScriptTags;
function parseAttributes(rawAttrs) {
const attrs = {};
if (!rawAttrs) {
return attrs;
}
Object.keys(rawAttrs).forEach((attrName) => {
const attrValue = rawAttrs[attrName];
attrs[attrName] = attrValue === null ? attrName : removeOuterQuotes(attrValue);
});
return attrs;
function removeOuterQuotes(attrValue) {
if ((attrValue.startsWith('"') && attrValue.endsWith('"')) ||
(attrValue.startsWith("'") && attrValue.endsWith("'"))) {
return attrValue.slice(1, attrValue.length - 1);
}
return attrValue;
}
}
function getLineAtPosition(position, text) {
return text.substring(offsetAt({ line: position.line, character: 0 }, text), offsetAt({ line: position.line, character: Number.MAX_VALUE }, text));
}
exports.getLineAtPosition = getLineAtPosition;
/**
* 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);
}
exports.isInComponentStartTag = isInComponentStartTag;
/**
* Return if a given offset is inside the name of a tag
*/
function isInTagName(html, offset) {
const node = html.findNodeAt(offset);
return offset > node.start && offset < node.start + (node.tag?.length ?? 0);
}
exports.isInTagName = isInTagName;
/**
* 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) {
return !!node.tag?.[0].match(/[A-Z]/) || !!node.tag?.match(/.+[.][A-Z]?/);
}
exports.isPossibleComponent = isPossibleComponent;
/**
* Return if the current position is in a specific tag
*/
function isInTag(position, tagInfo) {
return !!tagInfo && (0, utils_1.isInRange)(vscode_languageserver_1.Range.create(tagInfo.startPos, tagInfo.endPos), position);
}
exports.isInTag = isInTag;
/**
* 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('}');
}
exports.isInsideExpression = isInsideExpression;
/**
* Returns if a given offset is inside of the document frontmatter
*/
function isInsideFrontmatter(text, offset) {
let start = text.slice(0, offset).trim().split('---').length;
let end = text.slice(offset).trim().split('---').length;
return start > 1 && start < 3 && end >= 1;
}
exports.isInsideFrontmatter = isInsideFrontmatter;
/**
* Get the line and character based on the offset
* @param offset The index of the position
* @param text The text for which the position should be retrived
* @param lineOffsets number Array with offsets for each line. Computed if not given
*/
function positionAt(offset, text, lineOffsets = getLineOffsets(text)) {
offset = (0, utils_1.clamp)(offset, 0, text.length);
let low = 0;
let high = lineOffsets.length;
if (high === 0) {
return vscode_languageserver_1.Position.create(0, offset);
}
while (low <= high) {
const mid = Math.floor((low + high) / 2);
const lineOffset = lineOffsets[mid];
if (lineOffset === offset) {
return vscode_languageserver_1.Position.create(mid, 0);
}
else if (offset > lineOffset) {
low = mid + 1;
}
else {
high = mid - 1;
}
}
// low is the least x for which the line offset is larger than the current offset
// or array.length if no line offset is larger than the current offset
const line = low - 1;
return vscode_languageserver_1.Position.create(line, offset - lineOffsets[line]);
}
exports.positionAt = positionAt;
/**
* Get the offset of the line and character position
* @param position Line and character position
* @param text The text for which the offset should be retrived
* @param lineOffsets number Array with offsets for each line. Computed if not given
*/
function offsetAt(position, text, lineOffsets = getLineOffsets(text)) {
if (position.line >= lineOffsets.length) {
return text.length;
}
else if (position.line < 0) {
return 0;
}
const lineOffset = lineOffsets[position.line];
const nextLineOffset = position.line + 1 < lineOffsets.length ? lineOffsets[position.line + 1] : text.length;
return (0, utils_1.clamp)(nextLineOffset, lineOffset, lineOffset + position.character);
}
exports.offsetAt = offsetAt;
function getLineOffsets(text) {
const lineOffsets = [];
let isLineStart = true;
for (let i = 0; i < text.length; i++) {
if (isLineStart) {
lineOffsets.push(i);
isLineStart = false;
}
const ch = text.charAt(i);
isLineStart = ch === '\r' || ch === '\n';
if (ch === '\r' && i + 1 < text.length && text.charAt(i + 1) === '\n') {
i++;
}
}
if (isLineStart && text.length > 0) {
lineOffsets.push(text.length);
}
return lineOffsets;
}
exports.getLineOffsets = getLineOffsets;
/**
* Gets index of first-non-whitespace character.
*/
function getFirstNonWhitespaceIndex(str) {
return str.length - str.trimStart().length;
}
exports.getFirstNonWhitespaceIndex = getFirstNonWhitespaceIndex;

View file

@ -0,0 +1,9 @@
import type * as svelte from '@astrojs/svelte/dist/editor.cjs';
import type * as vue from '@astrojs/svelte/dist/editor.cjs';
import type * as prettier from 'prettier';
export declare function setIsTrusted(_isTrusted: boolean): void;
export declare function getPackagePath(packageName: string, fromPath: string[]): string | undefined;
export declare function importSvelteIntegration(fromPath: string): typeof svelte | undefined;
export declare function importVueIntegration(fromPath: string): typeof vue | undefined;
export declare function importPrettier(fromPath: string): typeof prettier;
export declare function getPrettierPluginPath(fromPath: string): string;

View file

@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPrettierPluginPath = exports.importPrettier = exports.importVueIntegration = exports.importSvelteIntegration = exports.getPackagePath = exports.setIsTrusted = void 0;
const path_1 = require("path");
let isTrusted = true;
function setIsTrusted(_isTrusted) {
isTrusted = _isTrusted;
}
exports.setIsTrusted = setIsTrusted;
function getPackagePath(packageName, fromPath) {
const paths = [];
if (isTrusted) {
paths.unshift(...fromPath);
}
try {
return (0, path_1.dirname)(require.resolve(packageName + '/package.json', { paths }));
}
catch (e) {
return undefined;
}
}
exports.getPackagePath = getPackagePath;
function importEditorIntegration(packageName, fromPath) {
const pkgPath = getPackagePath(packageName, [fromPath]);
if (pkgPath) {
try {
const main = (0, 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`);
return undefined;
}
}
return undefined;
}
function importSvelteIntegration(fromPath) {
return importEditorIntegration('@astrojs/svelte', fromPath);
}
exports.importSvelteIntegration = importSvelteIntegration;
function importVueIntegration(fromPath) {
return importEditorIntegration('@astrojs/vue', fromPath);
}
exports.importVueIntegration = importVueIntegration;
function importPrettier(fromPath) {
// This shouldn't ever fail, because we bundle Prettier in the extension itself
const prettierPkg = getPackagePath('prettier', [fromPath, __dirname]);
return require(prettierPkg);
}
exports.importPrettier = importPrettier;
function getPrettierPluginPath(fromPath) {
return getPackagePath('prettier-plugin-astro', [fromPath, __dirname]);
}
exports.getPrettierPluginPath = getPrettierPluginPath;

View file

@ -0,0 +1,2 @@
export { AstroCheck, Diagnostic, DiagnosticSeverity, GetDiagnosticsResult } from './check';
export { offsetAt } from './core/documents';

8
node_modules/@astrojs/language-server/dist/index.js generated vendored Normal file
View file

@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.offsetAt = exports.DiagnosticSeverity = exports.AstroCheck = void 0;
var check_1 = require("./check");
Object.defineProperty(exports, "AstroCheck", { enumerable: true, get: function () { return check_1.AstroCheck; } });
Object.defineProperty(exports, "DiagnosticSeverity", { enumerable: true, get: function () { return check_1.DiagnosticSeverity; } });
var documents_1 = require("./core/documents");
Object.defineProperty(exports, "offsetAt", { enumerable: true, get: function () { return documents_1.offsetAt; } });

1
node_modules/@astrojs/language-server/dist/node.d.ts generated vendored Normal file
View file

@ -0,0 +1 @@
export {};

43
node_modules/@astrojs/language-server/dist/node.js generated vendored Normal file
View file

@ -0,0 +1,43 @@
"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 (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const vscode = __importStar(require("vscode-languageserver/node"));
const server_1 = require("./server");
const connection = vscode.createConnection(vscode.ProposedFeatures.all);
(0, server_1.startLanguageServer)(connection, {
loadTypescript(options) {
if (options?.typescript?.serverPath) {
return require(options?.typescript?.serverPath);
}
},
loadTypescriptLocalized(options) {
if (options?.typescript?.localizedPath) {
try {
return require(options?.typescript?.localizedPath);
}
catch { }
}
},
});

View file

@ -0,0 +1,42 @@
import { CancellationToken, CodeAction, CodeActionContext, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FoldingRange, FormattingOptions, Hover, InlayHint, LinkedEditingRanges, Location, Position, Range, ReferenceContext, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, TextDocumentIdentifier, TextEdit, WorkspaceEdit } from 'vscode-languageserver';
import type { DocumentManager } from '../core/documents/DocumentManager';
import type { AppCompletionItem, Plugin } from './interfaces';
export interface PluginHostConfig {
filterIncompleteCompletions: boolean;
definitionLinkSupport: boolean;
}
export declare class PluginHost {
private docManager;
private plugins;
private pluginHostConfig;
constructor(docManager: DocumentManager);
initialize(pluginHostConfig: PluginHostConfig): void;
registerPlugin(plugin: Plugin): void;
getCompletions(textDocument: TextDocumentIdentifier, position: Position, completionContext?: CompletionContext, cancellationToken?: CancellationToken): Promise<CompletionList>;
resolveCompletion(textDocument: TextDocumentIdentifier, completionItem: AppCompletionItem): Promise<CompletionItem>;
getDiagnostics(textDocument: TextDocumentIdentifier): Promise<Diagnostic[]>;
doHover(textDocument: TextDocumentIdentifier, position: Position): Promise<Hover | null>;
formatDocument(textDocument: TextDocumentIdentifier, options: FormattingOptions): Promise<TextEdit[]>;
getCodeActions(textDocument: TextDocumentIdentifier, range: Range, context: CodeActionContext, cancellationToken?: CancellationToken): Promise<CodeAction[]>;
doTagComplete(textDocument: TextDocumentIdentifier, position: Position): Promise<string | null>;
getFoldingRanges(textDocument: TextDocumentIdentifier): Promise<FoldingRange[] | null>;
getDocumentSymbols(textDocument: TextDocumentIdentifier, cancellationToken?: CancellationToken): Promise<SymbolInformation[]>;
getSemanticTokens(textDocument: TextDocumentIdentifier, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
getLinkedEditingRanges(textDocument: TextDocumentIdentifier, position: Position): Promise<LinkedEditingRanges | null>;
fileReferences(textDocument: TextDocumentIdentifier): Promise<Location[] | null>;
getDefinitions(textDocument: TextDocumentIdentifier, position: Position): Promise<DefinitionLink[] | Location[]>;
getTypeDefinitions(textDocument: TextDocumentIdentifier, position: Position): Promise<Location[] | null>;
getImplementations(textDocument: TextDocumentIdentifier, position: Position): Promise<Location[] | null>;
getReferences(textdocument: TextDocumentIdentifier, position: Position, context: ReferenceContext): Promise<Location[] | null>;
prepareRename(textDocument: TextDocumentIdentifier, position: Position): Promise<Range | null>;
rename(textDocument: TextDocumentIdentifier, position: Position, newName: string): Promise<WorkspaceEdit | null>;
getDocumentColors(textDocument: TextDocumentIdentifier): Promise<ColorInformation[]>;
getColorPresentations(textDocument: TextDocumentIdentifier, range: Range, color: Color): Promise<ColorPresentation[]>;
getInlayHints(textDocument: TextDocumentIdentifier, range: Range, cancellationToken?: CancellationToken): Promise<InlayHint[]>;
getSignatureHelp(textDocument: TextDocumentIdentifier, position: Position, context: SignatureHelpContext | undefined, cancellationToken?: CancellationToken): Promise<SignatureHelp | null>;
onWatchFileChanges(onWatchFileChangesParams: any[]): Promise<void>;
updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[], text?: string): void;
private getDocument;
private execute;
private tryExecutePlugin;
}

View file

@ -0,0 +1,206 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluginHost = void 0;
const vscode_languageserver_1 = require("vscode-languageserver");
const documents_1 = require("../core/documents");
const utils_1 = require("../utils");
var ExecuteMode;
(function (ExecuteMode) {
ExecuteMode[ExecuteMode["None"] = 0] = "None";
ExecuteMode[ExecuteMode["FirstNonNull"] = 1] = "FirstNonNull";
ExecuteMode[ExecuteMode["Collect"] = 2] = "Collect";
})(ExecuteMode || (ExecuteMode = {}));
class PluginHost {
constructor(docManager) {
this.docManager = docManager;
this.plugins = [];
this.pluginHostConfig = {
filterIncompleteCompletions: true,
definitionLinkSupport: false,
};
}
initialize(pluginHostConfig) {
this.pluginHostConfig = pluginHostConfig;
}
registerPlugin(plugin) {
this.plugins.push(plugin);
}
async getCompletions(textDocument, position, completionContext, cancellationToken) {
const document = this.getDocument(textDocument.uri);
const completions = await Promise.all(this.plugins.map(async (plugin) => {
const result = await this.tryExecutePlugin(plugin, 'getCompletions', [document, position, completionContext, cancellationToken], null);
if (result) {
return { result: result, plugin: plugin.__name };
}
})).then((fullCompletions) => fullCompletions.filter(utils_1.isNotNullOrUndefined));
const html = completions.find((completion) => completion.plugin === 'html');
const ts = completions.find((completion) => completion.plugin === 'typescript');
const astro = completions.find((completion) => completion.plugin === 'astro');
if (html && ts) {
const inComponentStartTag = (0, documents_1.isInComponentStartTag)(document.html, document.offsetAt(position));
// If the HTML plugin returned completions, it's highly likely that TS ones are duplicate
if (html.result.items.length > 0) {
ts.result.items = [];
}
// Inside components, if the Astro plugin has completions we don't want the TS ones are they're duplicates
if (astro && astro.result.items.length > 0 && inComponentStartTag) {
ts.result.items = [];
}
}
let flattenedCompletions = completions.flatMap((completion) => completion.result.items);
const isIncomplete = completions.reduce((incomplete, completion) => incomplete || completion.result.isIncomplete, false);
// If the result is incomplete, we need to filter the results ourselves
// to throw out non-matching results. VSCode does filter client-side,
// but other IDEs might not.
if (isIncomplete && this.pluginHostConfig.filterIncompleteCompletions) {
const offset = document.offsetAt(position);
// Assumption for performance reasons:
// Noone types import names longer than 20 characters and still expects perfect autocompletion.
const text = document.getText().substring(Math.max(0, offset - 20), offset);
const start = (0, utils_1.regexLastIndexOf)(text, /[\W\s]/g) + 1;
const filterValue = text.substring(start).toLowerCase();
flattenedCompletions = flattenedCompletions.filter((comp) => comp.label.toLowerCase().includes(filterValue));
}
return vscode_languageserver_1.CompletionList.create(flattenedCompletions, isIncomplete);
}
async resolveCompletion(textDocument, completionItem) {
const document = this.getDocument(textDocument.uri);
const result = await this.execute('resolveCompletion', [document, completionItem], ExecuteMode.FirstNonNull);
return result ?? completionItem;
}
async getDiagnostics(textDocument) {
const document = this.getDocument(textDocument.uri);
const diagnostics = await this.execute('getDiagnostics', [document], ExecuteMode.Collect);
return diagnostics;
}
async doHover(textDocument, position) {
const document = this.getDocument(textDocument.uri);
return this.execute('doHover', [document, position], ExecuteMode.FirstNonNull);
}
async formatDocument(textDocument, options) {
const document = this.getDocument(textDocument.uri);
return await this.execute('formatDocument', [document, options], ExecuteMode.Collect);
}
async getCodeActions(textDocument, range, context, cancellationToken) {
const document = this.getDocument(textDocument.uri);
return await this.execute('getCodeActions', [document, range, context, cancellationToken], ExecuteMode.Collect);
}
async doTagComplete(textDocument, position) {
const document = this.getDocument(textDocument.uri);
return this.execute('doTagComplete', [document, position], ExecuteMode.FirstNonNull);
}
async getFoldingRanges(textDocument) {
const document = this.getDocument(textDocument.uri);
return await this.execute('getFoldingRanges', [document], ExecuteMode.Collect);
}
async getDocumentSymbols(textDocument, cancellationToken) {
const document = this.getDocument(textDocument.uri);
return await this.execute('getDocumentSymbols', [document, cancellationToken], ExecuteMode.Collect);
}
async getSemanticTokens(textDocument, range, cancellationToken) {
const document = this.getDocument(textDocument.uri);
return await this.execute('getSemanticTokens', [document, range, cancellationToken], ExecuteMode.FirstNonNull);
}
async getLinkedEditingRanges(textDocument, position) {
const document = this.getDocument(textDocument.uri);
return await this.execute('getLinkedEditingRanges', [document, position], ExecuteMode.FirstNonNull);
}
async fileReferences(textDocument) {
const document = this.getDocument(textDocument.uri);
return await this.execute('fileReferences', [document], ExecuteMode.FirstNonNull);
}
async getDefinitions(textDocument, position) {
const document = this.getDocument(textDocument.uri);
const definitions = await this.execute('getDefinitions', [document, position], ExecuteMode.Collect);
if (this.pluginHostConfig.definitionLinkSupport) {
return definitions;
}
else {
return definitions.map((def) => ({ range: def.targetSelectionRange, uri: def.targetUri }));
}
}
getTypeDefinitions(textDocument, position) {
const document = this.getDocument(textDocument.uri);
return this.execute('getTypeDefinitions', [document, position], ExecuteMode.FirstNonNull);
}
getImplementations(textDocument, position) {
const document = this.getDocument(textDocument.uri);
return this.execute('getImplementation', [document, position], ExecuteMode.FirstNonNull);
}
getReferences(textdocument, position, context) {
const document = this.getDocument(textdocument.uri);
return this.execute('findReferences', [document, position, context], ExecuteMode.FirstNonNull);
}
async prepareRename(textDocument, position) {
const document = this.getDocument(textDocument.uri);
return await this.execute('prepareRename', [document, position], ExecuteMode.FirstNonNull);
}
async rename(textDocument, position, newName) {
const document = this.getDocument(textDocument.uri);
return this.execute('rename', [document, position, newName], ExecuteMode.FirstNonNull);
}
async getDocumentColors(textDocument) {
const document = this.getDocument(textDocument.uri);
return await this.execute('getDocumentColors', [document], ExecuteMode.Collect);
}
async getColorPresentations(textDocument, range, color) {
const document = this.getDocument(textDocument.uri);
return await this.execute('getColorPresentations', [document, range, color], ExecuteMode.Collect);
}
async getInlayHints(textDocument, range, cancellationToken) {
const document = this.getDocument(textDocument.uri);
return (await this.execute('getInlayHints', [document, range], ExecuteMode.FirstNonNull)) ?? [];
}
async getSignatureHelp(textDocument, position, context, cancellationToken) {
const document = this.getDocument(textDocument.uri);
return await this.execute('getSignatureHelp', [document, position, context, cancellationToken], ExecuteMode.FirstNonNull);
}
async onWatchFileChanges(onWatchFileChangesParams) {
for (const support of this.plugins) {
await support.onWatchFileChanges?.(onWatchFileChangesParams);
}
}
updateNonAstroFile(fileName, changes, text) {
for (const support of this.plugins) {
support.updateNonAstroFile?.(fileName, changes, text);
}
}
getDocument(uri) {
const document = this.docManager.get(uri);
if (!document) {
throw new Error('Cannot call methods on an unopened document');
}
return document;
}
async execute(name, args, mode) {
const plugins = this.plugins.filter((plugin) => typeof plugin[name] === 'function');
switch (mode) {
case ExecuteMode.FirstNonNull:
for (const plugin of plugins) {
const res = await this.tryExecutePlugin(plugin, name, args, null);
if (res != null) {
return res;
}
}
return null;
case ExecuteMode.Collect:
return (await Promise.all(plugins.map((plugin) => {
let ret = this.tryExecutePlugin(plugin, name, args, []);
return ret;
}))).flat();
case ExecuteMode.None:
await Promise.all(plugins.map((plugin) => this.tryExecutePlugin(plugin, name, args, null)));
return;
}
}
async tryExecutePlugin(plugin, fnName, args, failValue) {
try {
return await plugin[fnName](...args);
}
catch (e) {
console.error(e);
return failValue;
}
}
}
exports.PluginHost = PluginHost;

View file

@ -0,0 +1,17 @@
import { CompletionContext, Diagnostic, FoldingRange, FormattingOptions, Position, TextEdit } from 'vscode-languageserver';
import type { ConfigManager } from '../../core/config';
import type { AstroDocument } from '../../core/documents';
import type { AppCompletionList, Plugin } from '../interfaces';
import type { LanguageServiceManager } from '../typescript/LanguageServiceManager';
export declare class AstroPlugin implements Plugin {
__name: string;
private configManager;
private readonly languageServiceManager;
private readonly completionProvider;
private readonly diagnosticsProvider;
constructor(configManager: ConfigManager, languageServiceManager: LanguageServiceManager);
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
getDiagnostics(document: AstroDocument): Promise<Diagnostic[]>;
formatDocument(document: AstroDocument, options: FormattingOptions): Promise<TextEdit[]>;
getFoldingRanges(document: AstroDocument): FoldingRange[];
}

View file

@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AstroPlugin = void 0;
const vscode_languageserver_1 = require("vscode-languageserver");
const importPackage_1 = require("../../importPackage");
const CompletionsProvider_1 = require("./features/CompletionsProvider");
const DiagnosticsProvider_1 = require("./features/DiagnosticsProvider");
class AstroPlugin {
constructor(configManager, languageServiceManager) {
this.__name = 'astro';
this.configManager = configManager;
this.languageServiceManager = languageServiceManager;
this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager);
this.diagnosticsProvider = new DiagnosticsProvider_1.DiagnosticsProviderImpl(this.languageServiceManager);
}
async getCompletions(document, position, completionContext) {
const completions = this.completionProvider.getCompletions(document, position, completionContext);
return completions;
}
async getDiagnostics(document) {
return await this.diagnosticsProvider.getDiagnostics(document);
}
async formatDocument(document, options) {
const filePath = document.getFilePath();
if (!filePath) {
return [];
}
const prettier = (0, importPackage_1.importPrettier)(filePath);
const prettierConfig = (await prettier.resolveConfig(filePath, { editorconfig: true, useCache: false })) ?? {};
const prettierVSConfig = await this.configManager.getPrettierVSConfig(document);
const editorFormatConfig = options !== undefined // We need to check for options existing here because some editors might not have it
? {
tabWidth: options.tabSize,
useTabs: !options.insertSpaces,
}
: {};
// 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 resultConfig = returnObjectIfHasKeys(prettierConfig) || returnObjectIfHasKeys(prettierVSConfig) || editorFormatConfig;
const fileInfo = await prettier.getFileInfo(filePath, { ignorePath: '.prettierignore' });
if (fileInfo.ignored) {
return [];
}
const result = prettier.format(document.getText(), {
...resultConfig,
plugins: [...getAstroPrettierPlugin(), ...(resultConfig.plugins ?? [])],
parser: 'astro',
});
return document.getText() === result
? []
: [vscode_languageserver_1.TextEdit.replace(vscode_languageserver_1.Range.create(document.positionAt(0), document.positionAt(document.getTextLength())), result)];
function getAstroPrettierPlugin() {
const hasPluginLoadedAlready = prettier.getSupportInfo().languages.some((l) => l.name === 'astro');
return hasPluginLoadedAlready ? [] : [(0, importPackage_1.getPrettierPluginPath)(filePath)];
}
}
getFoldingRanges(document) {
const foldingRanges = [];
const { frontmatter } = document.astroMeta;
// Currently editing frontmatter, don't fold
if (frontmatter.state !== 'closed')
return foldingRanges;
// The way folding ranges work is by folding anything between the starting position and the ending one, as such
// the start in this case should be after the frontmatter start (after the starting ---) until the last character
// of the last line of the frontmatter before its ending (before the closing ---)
// ---
// ^ -- start
// console.log("Astro")
// --- ^ -- end
const start = document.positionAt(frontmatter.startOffset + 3);
const end = document.positionAt(frontmatter.endOffset - 1);
return [
{
startLine: start.line,
startCharacter: start.character,
endLine: end.line,
endCharacter: end.character,
kind: vscode_languageserver_1.FoldingRangeKind.Imports,
},
];
}
}
exports.AstroPlugin = AstroPlugin;
function returnObjectIfHasKeys(obj) {
if (Object.keys(obj || {}).length > 0) {
return obj;
}
}

View file

@ -0,0 +1,17 @@
import { CompletionContext, Position } from 'vscode-languageserver';
import type { AstroDocument } from '../../../core/documents';
import type { AppCompletionList, CompletionsProvider } from '../../interfaces';
import type { LanguageServiceManager } from '../../typescript/LanguageServiceManager';
export declare class CompletionsProviderImpl implements CompletionsProvider {
private readonly languageServiceManager;
private readonly ts;
private lastCompletion;
directivesHTMLLang: import("vscode-html-languageservice").LanguageService;
constructor(languageServiceManager: LanguageServiceManager);
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
private getComponentScriptCompletion;
private getPropCompletionsAndFilePath;
private getImportedSymbol;
private getPropType;
private getCompletionItemForProperty;
}

View file

@ -0,0 +1,242 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompletionsProviderImpl = void 0;
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
const vscode_languageserver_1 = require("vscode-languageserver");
const utils_1 = require("../../../core/documents/utils");
const astro_attributes_1 = require("../../html/features/astro-attributes");
const utils_2 = require("../../html/utils");
const utils_3 = require("../../typescript/utils");
class CompletionsProviderImpl {
constructor(languageServiceManager) {
this.lastCompletion = null;
this.directivesHTMLLang = (0, vscode_html_languageservice_1.getLanguageService)({
customDataProviders: [astro_attributes_1.astroDirectives],
useDefaultDataProvider: false,
});
this.languageServiceManager = languageServiceManager;
this.ts = languageServiceManager.docContext.ts;
}
async getCompletions(document, position, completionContext) {
let items = [];
const html = document.html;
const offset = document.offsetAt(position);
const node = html.findNodeAt(offset);
const insideExpression = (0, utils_1.isInsideExpression)(document.getText(), node.start, offset);
if (completionContext?.triggerCharacter === '-' && node.parent === undefined && !insideExpression) {
const frontmatter = this.getComponentScriptCompletion(document, position);
if (frontmatter)
items.push(frontmatter);
}
if ((0, utils_1.isInComponentStartTag)(html, offset) && !insideExpression) {
const { completions: props, componentFilePath } = await this.getPropCompletionsAndFilePath(document, position, completionContext);
if (props.length) {
items.push(...props);
}
const isAstro = componentFilePath?.endsWith('.astro');
if (!isAstro && node.tag !== 'Fragment') {
const directives = (0, utils_2.removeDataAttrCompletion)(this.directivesHTMLLang.doComplete(document, position, html).items);
items.push(...directives);
}
}
return vscode_languageserver_1.CompletionList.create(items, true);
}
getComponentScriptCompletion(document, position) {
const base = {
kind: vscode_languageserver_1.CompletionItemKind.Snippet,
label: '---',
sortText: '\0',
preselect: true,
detail: 'Create component script block',
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
commitCharacters: [],
};
const prefix = document.getLineUntilOffset(document.offsetAt(position));
if (document.astroMeta.frontmatter.state === null) {
return {
...base,
insertText: '---\n$0\n---',
textEdit: prefix.match(/^\s*\-+/)
? vscode_languageserver_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, '---\n$0\n---')
: undefined,
};
}
if (document.astroMeta.frontmatter.state === '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: prefix.match(/^\s*\-+/)
? vscode_languageserver_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, insertText)
: undefined,
};
}
return null;
}
async getPropCompletionsAndFilePath(document, position, completionContext) {
const offset = document.offsetAt(position);
const html = document.html;
const node = html.findNodeAt(offset);
if (!(0, utils_1.isPossibleComponent)(node)) {
return { completions: [], componentFilePath: null };
}
const inAttribute = node.start + node.tag.length < offset;
if (!inAttribute) {
return { completions: [], componentFilePath: null };
}
if (completionContext?.triggerCharacter === '/' || completionContext?.triggerCharacter === '>') {
return { completions: [], componentFilePath: null };
}
// If inside of attribute value, skip.
if (completionContext &&
completionContext.triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter &&
completionContext.triggerCharacter === '"') {
return { completions: [], componentFilePath: null };
}
const componentName = node.tag;
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
// Get the source file
const tsFilePath = tsDoc.filePath;
const program = lang.getProgram();
const sourceFile = program?.getSourceFile(tsFilePath);
const typeChecker = program?.getTypeChecker();
if (!sourceFile || !typeChecker) {
return { completions: [], componentFilePath: null };
}
// Get the import statement
const imp = this.getImportedSymbol(sourceFile, componentName);
const importType = imp && typeChecker.getTypeAtLocation(imp);
if (!importType) {
return { completions: [], componentFilePath: null };
}
const symbol = importType.getSymbol();
if (!symbol) {
return { completions: [], componentFilePath: null };
}
const symbolDeclaration = symbol.declarations;
if (!symbolDeclaration) {
return { completions: [], componentFilePath: null };
}
const filePath = symbolDeclaration[0].getSourceFile().fileName;
const componentSnapshot = await this.languageServiceManager.getSnapshot(filePath);
if (this.lastCompletion) {
if (this.lastCompletion.tag === componentName &&
this.lastCompletion.documentVersion == componentSnapshot.version) {
return { completions: this.lastCompletion.completions, componentFilePath: filePath };
}
}
// Get the component's props type
const componentType = this.getPropType(symbolDeclaration, typeChecker);
if (!componentType) {
return { completions: [], componentFilePath: null };
}
let completionItems = [];
// Add completions for this component's props type properties
const properties = componentType.getProperties().filter((property) => property.name !== 'children') || [];
properties.forEach((property) => {
const type = typeChecker.getTypeOfSymbolAtLocation(property, imp);
let completionItem = this.getCompletionItemForProperty(property, typeChecker, type);
completionItems.push(completionItem);
});
this.lastCompletion = {
tag: componentName,
documentVersion: componentSnapshot.version,
completions: completionItems,
};
return { completions: completionItems, componentFilePath: filePath };
}
getImportedSymbol(sourceFile, identifier) {
for (let list of sourceFile.getChildren()) {
for (let node of list.getChildren()) {
if (this.ts.isImportDeclaration(node)) {
let clauses = node.importClause;
if (!clauses)
continue;
let namedImport = clauses.getChildAt(0);
if (this.ts.isNamedImports(namedImport)) {
for (let imp of namedImport.elements) {
// Iterate the named imports
if (imp.name.getText() === identifier) {
return imp;
}
}
}
else if (this.ts.isIdentifier(namedImport)) {
if (namedImport.getText() === identifier) {
return namedImport;
}
}
}
}
}
return null;
}
getPropType(declarations, typeChecker) {
for (const decl of declarations) {
const fileName = (0, utils_3.toVirtualFilePath)(decl.getSourceFile().fileName);
if (fileName.endsWith('.tsx') || fileName.endsWith('.jsx') || fileName.endsWith('.d.ts')) {
if (!this.ts.isFunctionDeclaration(decl) && !this.ts.isFunctionTypeNode(decl)) {
console.error(`We only support functions declarations at the moment`);
continue;
}
const fn = decl;
if (!fn.parameters.length)
continue;
const param1 = fn.parameters[0];
const propType = typeChecker.getTypeAtLocation(param1);
return propType;
}
}
return null;
}
getCompletionItemForProperty(mem, typeChecker, type) {
const typeString = typeChecker.typeToString(type);
let insertText = mem.name;
switch (typeString) {
case 'string':
insertText = `${mem.name}="$1"`;
break;
case 'boolean':
insertText = mem.name;
break;
default:
insertText = `${mem.name}={$1}`;
break;
}
let item = {
label: mem.name,
detail: typeString,
insertText: insertText,
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
commitCharacters: [],
// Ensure that props shows up first as a completion, despite this plugin being ran after the HTML one
sortText: '\0',
};
if (mem.flags & this.ts.SymbolFlags.Optional) {
item.filterText = item.label;
item.label += '?';
// Put optional props at a lower priority
item.sortText = '_';
}
mem.getDocumentationComment(typeChecker);
let description = mem
.getDocumentationComment(typeChecker)
.map((val) => val.text)
.join('\n');
if (description) {
let docs = {
kind: vscode_languageserver_1.MarkupKind.Markdown,
value: description,
};
item.documentation = docs;
}
return item;
}
}
exports.CompletionsProviderImpl = CompletionsProviderImpl;

View file

@ -0,0 +1,10 @@
import { Diagnostic } from 'vscode-languageserver-types';
import { AstroDocument } from '../../../core/documents';
import { DiagnosticsProvider } from '../../interfaces';
import { LanguageServiceManager } from '../../typescript/LanguageServiceManager';
export declare class DiagnosticsProviderImpl implements DiagnosticsProvider {
private languageServiceManager;
constructor(languageServiceManager: LanguageServiceManager);
getDiagnostics(document: AstroDocument): Promise<Diagnostic[]>;
private compilerMessageToDiagnostic;
}

View file

@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DiagnosticsProviderImpl = void 0;
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
class DiagnosticsProviderImpl {
constructor(languageServiceManager) {
this.languageServiceManager = languageServiceManager;
}
async getDiagnostics(document) {
const { tsDoc } = (await this.languageServiceManager.getLSAndTSDoc(document));
return tsDoc.compilerDiagnostics.map(this.compilerMessageToDiagnostic);
}
compilerMessageToDiagnostic(message) {
return {
message: message.text + '\n\n' + message.hint,
range: vscode_languageserver_types_1.Range.create(message.location.line - 1, message.location.column - 1, message.location.line, message.location.length),
code: message.code,
severity: message.severity,
source: 'astro',
};
}
}
exports.DiagnosticsProviderImpl = DiagnosticsProviderImpl;

View file

@ -0,0 +1,45 @@
import type { Stylesheet, TextDocument } from 'vscode-css-languageservice';
import type { Position } from 'vscode-languageserver';
import { AstroDocument, DocumentMapper, ReadableDocument, TagInformation } from '../../core/documents';
export interface CSSDocumentBase extends DocumentMapper, TextDocument {
languageId: string;
stylesheet: Stylesheet;
}
export declare class CSSDocument extends ReadableDocument implements DocumentMapper {
private parent;
private styleInfo;
readonly version: number;
stylesheet: Stylesheet;
languageId: string;
constructor(parent: AstroDocument, styleInfo: Pick<TagInformation, 'attributes' | 'start' | 'end'>);
/**
* Get the fragment position relative to the parent
* @param pos Position in fragment
*/
getOriginalPosition(pos: Position): Position;
/**
* Get the position relative to the start of the fragment
* @param pos Position in parent
*/
getGeneratedPosition(pos: Position): Position;
/**
* Returns true if the given parent position is inside of this fragment
* @param pos Position in parent
*/
isInGenerated(pos: Position): boolean;
/**
* Get the fragment text from the parent
*/
getText(): string;
/**
* Returns the length of the fragment as calculated from the start and end position
*/
getTextLength(): number;
/**
* Return the parent file path
*/
getFilePath(): string | null;
getURL(): string;
getAttributes(): Record<string, string>;
private get language();
}

View file

@ -0,0 +1,68 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CSSDocument = void 0;
const documents_1 = require("../../core/documents");
const language_service_1 = require("./language-service");
class CSSDocument extends documents_1.ReadableDocument {
constructor(parent, styleInfo) {
super();
this.parent = parent;
this.styleInfo = styleInfo;
this.version = this.parent.version;
this.languageId = this.language;
this.stylesheet = (0, language_service_1.getLanguageService)(this.language).parseStylesheet(this);
}
/**
* Get the fragment position relative to the parent
* @param pos Position in fragment
*/
getOriginalPosition(pos) {
const parentOffset = this.styleInfo.start + this.offsetAt(pos);
return this.parent.positionAt(parentOffset);
}
/**
* Get the position relative to the start of the fragment
* @param pos Position in parent
*/
getGeneratedPosition(pos) {
const fragmentOffset = this.parent.offsetAt(pos) - this.styleInfo.start;
return this.positionAt(fragmentOffset);
}
/**
* Returns true if the given parent position is inside of this fragment
* @param pos Position in parent
*/
isInGenerated(pos) {
const offset = this.parent.offsetAt(pos);
return offset >= this.styleInfo.start && offset <= this.styleInfo.end;
}
/**
* Get the fragment text from the parent
*/
getText() {
return this.parent.getText().slice(this.styleInfo.start, this.styleInfo.end);
}
/**
* Returns the length of the fragment as calculated from the start and end position
*/
getTextLength() {
return this.styleInfo.end - this.styleInfo.start;
}
/**
* Return the parent file path
*/
getFilePath() {
return this.parent.getFilePath();
}
getURL() {
return this.parent.getURL();
}
getAttributes() {
return this.styleInfo.attributes;
}
get language() {
const attrs = this.getAttributes();
return attrs.lang || attrs.type || 'css';
}
}
exports.CSSDocument = CSSDocument;

View file

@ -0,0 +1,39 @@
import { Color, ColorInformation, ColorPresentation, CompletionContext, CompletionList, FoldingRange, Hover, Position, Range, SymbolInformation, WorkspaceEdit } from 'vscode-languageserver';
import type { ConfigManager } from '../../core/config/ConfigManager';
import { AstroDocument } from '../../core/documents';
import type { Plugin } from '../interfaces';
export declare class CSSPlugin implements Plugin {
__name: string;
private configManager;
private cssDocuments;
private triggerCharacters;
constructor(configManager: ConfigManager);
doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
private doHoverInternal;
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<CompletionList | null>;
private getCompletionsInternal;
getDocumentColors(document: AstroDocument): Promise<ColorInformation[]>;
getColorPresentations(document: AstroDocument, range: Range, color: Color): Promise<ColorPresentation[]>;
prepareRename(document: AstroDocument, position: Position): Range | null;
rename(document: AstroDocument, position: Position, newName: string): WorkspaceEdit | null;
getFoldingRanges(document: AstroDocument): FoldingRange[] | null;
getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
private inStyleAttributeWithoutInterpolation;
/**
* Get the associated CSS Document for a style tag
*/
private getCSSDocumentForStyleTag;
/**
* Get all the CSSDocuments in a document
*/
private getCSSDocumentsForDocument;
/**
* Get all the stylesheets (Stylesheet type) in a document
*/
private getStylesheetsForDocument;
/**
* Get style tag at position for a document
*/
private getStyleTagForPosition;
private featureEnabled;
}

View file

@ -0,0 +1,274 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CSSPlugin = void 0;
const emmet_helper_1 = require("@vscode/emmet-helper");
const vscode_languageserver_1 = require("vscode-languageserver");
const documents_1 = require("../../core/documents");
const parseHtml_1 = require("../../core/documents/parseHtml");
const CSSDocument_1 = require("./CSSDocument");
const getIdClassCompletions_1 = require("./features/getIdClassCompletions");
const language_service_1 = require("./language-service");
const StyleAttributeDocument_1 = require("./StyleAttributeDocument");
class CSSPlugin {
constructor(configManager) {
this.__name = 'css';
this.cssDocuments = new WeakMap();
this.triggerCharacters = new Set(['.', ':', '-', '/']);
this.configManager = configManager;
}
async doHover(document, position) {
if (!(await this.featureEnabled(document, 'hover'))) {
return null;
}
if ((0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
return null;
}
const styleTag = this.getStyleTagForPosition(document, position);
// We technically can return results even for open tags, however, a lot of the info returned is not valid
// Since most editors will automatically close the tag before the user start working in them, this shouldn't be a problem
if (styleTag && !styleTag.closed) {
return null;
}
// If we don't have a style tag at this position, we might be in a style property instead, let's check
if (!styleTag) {
const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
if (!attributeContext) {
return null;
}
if (this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText())) {
const [start, end] = attributeContext.valueRange;
return this.doHoverInternal(new StyleAttributeDocument_1.StyleAttributeDocument(document, start, end), position);
}
return null;
}
const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
const cssLang = extractLanguage(cssDocument);
if (!isSupportedByLangService(cssLang)) {
return null;
}
return this.doHoverInternal(cssDocument, position);
}
doHoverInternal(cssDocument, position) {
const hoverInfo = (0, language_service_1.getLanguageService)(extractLanguage(cssDocument)).doHover(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
return hoverInfo ? (0, documents_1.mapHoverToParent)(cssDocument, hoverInfo) : hoverInfo;
}
async getCompletions(document, position, completionContext) {
if (!(await this.featureEnabled(document, 'completions'))) {
return null;
}
if ((0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
return null;
}
const triggerCharacter = completionContext?.triggerCharacter;
const triggerKind = completionContext?.triggerKind;
const isCustomTriggerCharacter = triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter;
if (isCustomTriggerCharacter && triggerCharacter && !this.triggerCharacters.has(triggerCharacter)) {
return null;
}
const styleTag = this.getStyleTagForPosition(document, position);
if (styleTag && !styleTag.closed) {
return null;
}
if (!styleTag) {
const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
if (!attributeContext) {
return null;
}
if (this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText())) {
const [start, end] = attributeContext.valueRange;
return await this.getCompletionsInternal(document, position, new StyleAttributeDocument_1.StyleAttributeDocument(document, start, end));
}
// If we're not in a style attribute, instead give completions for ids and classes used in the current document
else if ((attributeContext.name == 'id' || attributeContext.name == 'class') && attributeContext.inValue) {
const stylesheets = this.getStylesheetsForDocument(document);
return (0, getIdClassCompletions_1.getIdClassCompletion)(stylesheets, attributeContext);
}
return null;
}
const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
return await this.getCompletionsInternal(document, position, cssDocument);
}
async getCompletionsInternal(document, position, cssDocument) {
const emmetConfig = await this.configManager.getEmmetConfig(document);
if (isSASS(cssDocument)) {
// The CSS language service does not support SASS (not to be confused with SCSS)
// however we can at least still at least provide Emmet completions in SASS blocks
return (0, emmet_helper_1.doComplete)(document, position, 'sass', emmetConfig) || null;
}
const cssLang = extractLanguage(cssDocument);
const langService = (0, language_service_1.getLanguageService)(cssLang);
let emmetResults = {
isIncomplete: false,
items: [],
};
const extensionConfig = await this.configManager.getConfig('astro', document.uri);
if (extensionConfig?.css?.completions?.emmet ?? true) {
langService.setCompletionParticipants([
{
onCssProperty: (context) => {
if (context?.propertyName) {
emmetResults =
(0, emmet_helper_1.doComplete)(cssDocument, cssDocument.getGeneratedPosition(position), (0, language_service_1.getLanguage)(cssLang), emmetConfig) || emmetResults;
}
},
onCssPropertyValue: (context) => {
if (context?.propertyValue) {
emmetResults =
(0, emmet_helper_1.doComplete)(cssDocument, cssDocument.getGeneratedPosition(position), (0, language_service_1.getLanguage)(cssLang), emmetConfig) || emmetResults;
}
},
},
]);
}
const results = langService.doComplete(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
return vscode_languageserver_1.CompletionList.create([...(results ? results.items : []), ...emmetResults.items].map((completionItem) => (0, documents_1.mapCompletionItemToOriginal)(cssDocument, completionItem)),
// Emmet completions change on every keystroke, so they are never complete
emmetResults.items.length > 0);
}
async getDocumentColors(document) {
if (!(await this.featureEnabled(document, 'documentColors'))) {
return [];
}
const allColorInfo = this.getCSSDocumentsForDocument(document).flatMap((cssDoc) => {
const cssLang = extractLanguage(cssDoc);
const langService = (0, language_service_1.getLanguageService)(cssLang);
if (!isSupportedByLangService(cssLang)) {
return [];
}
return langService
.findDocumentColors(cssDoc, cssDoc.stylesheet)
.map((colorInfo) => (0, documents_1.mapObjWithRangeToOriginal)(cssDoc, colorInfo));
});
return allColorInfo;
}
async getColorPresentations(document, range, color) {
if (!(await this.featureEnabled(document, 'documentColors'))) {
return [];
}
const allColorPres = this.getCSSDocumentsForDocument(document).flatMap((cssDoc) => {
const cssLang = extractLanguage(cssDoc);
const langService = (0, language_service_1.getLanguageService)(cssLang);
if ((!cssDoc.isInGenerated(range.start) && !cssDoc.isInGenerated(range.end)) ||
!isSupportedByLangService(cssLang)) {
return [];
}
return langService
.getColorPresentations(cssDoc, cssDoc.stylesheet, color, (0, documents_1.mapRangeToGenerated)(cssDoc, range))
.map((colorPres) => (0, documents_1.mapColorPresentationToOriginal)(cssDoc, colorPres));
});
return allColorPres;
}
prepareRename(document, position) {
const styleTag = this.getStyleTagForPosition(document, position);
if (!styleTag) {
return null;
}
const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
const cssLang = extractLanguage(cssDocument);
const langService = (0, language_service_1.getLanguageService)(cssLang);
const range = langService.prepareRename(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
if (!range) {
return null;
}
return (0, documents_1.mapRangeToOriginal)(cssDocument, range);
}
rename(document, position, newName) {
const styleTag = this.getStyleTagForPosition(document, position);
if (!styleTag) {
return null;
}
const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
const cssLang = extractLanguage(cssDocument);
const langService = (0, language_service_1.getLanguageService)(cssLang);
const renames = langService.doRename(cssDocument, cssDocument.getGeneratedPosition(position), newName, cssDocument.stylesheet);
if (renames?.changes?.[document.uri]) {
renames.changes[document.uri] = renames?.changes?.[document.uri].map((edit) => (0, documents_1.mapObjWithRangeToOriginal)(cssDocument, edit));
}
return renames;
}
getFoldingRanges(document) {
const allFoldingRanges = this.getCSSDocumentsForDocument(document).flatMap((cssDoc) => {
const cssLang = extractLanguage(cssDoc);
const langService = (0, language_service_1.getLanguageService)(cssLang);
return langService.getFoldingRanges(cssDoc).map((foldingRange) => (0, documents_1.mapFoldingRangeToParent)(cssDoc, foldingRange));
});
return allFoldingRanges;
}
async getDocumentSymbols(document) {
if (!(await this.featureEnabled(document, 'documentSymbols'))) {
return [];
}
const allDocumentSymbols = this.getCSSDocumentsForDocument(document).flatMap((cssDoc) => {
return (0, language_service_1.getLanguageService)(extractLanguage(cssDoc))
.findDocumentSymbols(cssDoc, cssDoc.stylesheet)
.map((symbol) => (0, documents_1.mapSymbolInformationToOriginal)(cssDoc, symbol));
});
return allDocumentSymbols;
}
inStyleAttributeWithoutInterpolation(attrContext, text) {
return (attrContext.name === 'style' &&
!!attrContext.valueRange &&
!text.substring(attrContext.valueRange[0], attrContext.valueRange[1]).includes('{'));
}
/**
* Get the associated CSS Document for a style tag
*/
getCSSDocumentForStyleTag(tag, document) {
let cssDoc = this.cssDocuments.get(tag);
if (!cssDoc || cssDoc.version < document.version) {
cssDoc = new CSSDocument_1.CSSDocument(document, tag);
this.cssDocuments.set(tag, cssDoc);
}
return cssDoc;
}
/**
* Get all the CSSDocuments in a document
*/
getCSSDocumentsForDocument(document) {
return document.styleTags.map((tag) => this.getCSSDocumentForStyleTag(tag, document));
}
/**
* Get all the stylesheets (Stylesheet type) in a document
*/
getStylesheetsForDocument(document) {
return this.getCSSDocumentsForDocument(document).map((cssDoc) => cssDoc.stylesheet);
}
/**
* Get style tag at position for a document
*/
getStyleTagForPosition(document, position) {
return document.styleTags.find((styleTag) => {
return (0, documents_1.isInTag)(position, styleTag);
});
}
async featureEnabled(document, feature) {
return ((await this.configManager.isEnabled(document, 'css')) &&
(await this.configManager.isEnabled(document, 'css', feature)));
}
}
exports.CSSPlugin = CSSPlugin;
/**
* Check is a CSSDocument's language is supported by the CSS language service
*/
function isSupportedByLangService(language) {
switch (language) {
case 'css':
case 'scss':
case 'less':
return true;
default:
return false;
}
}
function isSASS(document) {
switch (extractLanguage(document)) {
case 'sass':
return true;
default:
return false;
}
}
function extractLanguage(document) {
const lang = document.languageId;
return lang.replace(/^text\//, '');
}

View file

@ -0,0 +1,40 @@
import type { Stylesheet } from 'vscode-css-languageservice';
import type { Position } from 'vscode-languageserver';
import { AstroDocument, DocumentMapper, ReadableDocument } from '../../core/documents';
export declare class StyleAttributeDocument extends ReadableDocument implements DocumentMapper {
private readonly parent;
private readonly attrStart;
private readonly attrEnd;
readonly version: number;
stylesheet: Stylesheet;
languageId: string;
constructor(parent: AstroDocument, attrStart: number, attrEnd: number);
/**
* Get the fragment position relative to the parent
* @param pos Position in fragment
*/
getOriginalPosition(pos: Position): Position;
/**
* Get the position relative to the start of the fragment
* @param pos Position in parent
*/
getGeneratedPosition(pos: Position): Position;
/**
* Returns true if the given parent position is inside of this fragment
* @param pos Position in parent
*/
isInGenerated(pos: Position): boolean;
/**
* Get the fragment text from the parent
*/
getText(): string;
/**
* Returns the length of the fragment as calculated from the start and end position
*/
getTextLength(): number;
/**
* Return the parent file path
*/
getFilePath(): string | null;
getURL(): string;
}

View file

@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StyleAttributeDocument = void 0;
const documents_1 = require("../../core/documents");
const language_service_1 = require("./language-service");
const PREFIX = '__ {';
const SUFFIX = '}';
class StyleAttributeDocument extends documents_1.ReadableDocument {
constructor(parent, attrStart, attrEnd) {
super();
this.parent = parent;
this.attrStart = attrStart;
this.attrEnd = attrEnd;
this.version = this.parent.version;
this.languageId = 'css';
this.stylesheet = (0, language_service_1.getLanguageService)(this.languageId).parseStylesheet(this);
}
/**
* Get the fragment position relative to the parent
* @param pos Position in fragment
*/
getOriginalPosition(pos) {
const parentOffset = this.attrStart + this.offsetAt(pos) - PREFIX.length;
return this.parent.positionAt(parentOffset);
}
/**
* Get the position relative to the start of the fragment
* @param pos Position in parent
*/
getGeneratedPosition(pos) {
const fragmentOffset = this.parent.offsetAt(pos) - this.attrStart + PREFIX.length;
return this.positionAt(fragmentOffset);
}
/**
* Returns true if the given parent position is inside of this fragment
* @param pos Position in parent
*/
isInGenerated(pos) {
const offset = this.parent.offsetAt(pos);
return offset >= this.attrStart && offset <= this.attrEnd;
}
/**
* Get the fragment text from the parent
*/
getText() {
return PREFIX + this.parent.getText().slice(this.attrStart, this.attrEnd) + SUFFIX;
}
/**
* Returns the length of the fragment as calculated from the start and end position
*/
getTextLength() {
return PREFIX.length + this.attrEnd - this.attrStart + SUFFIX.length;
}
/**
* Return the parent file path
*/
getFilePath() {
return this.parent.getFilePath();
}
getURL() {
return this.parent.getURL();
}
}
exports.StyleAttributeDocument = StyleAttributeDocument;

View file

@ -0,0 +1,2 @@
import type { IPseudoClassData } from 'vscode-css-languageservice';
export declare const pseudoClass: IPseudoClassData[];

View file

@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pseudoClass = void 0;
exports.pseudoClass = [
{
name: ':global()',
description: 'Apply styles to a selector globally',
references: [
{
name: 'Astro documentation',
url: 'https://docs.astro.build/en/guides/styling/#global-styles-within-style-tag',
},
],
},
];

View file

@ -0,0 +1,19 @@
import type { Stylesheet } from 'vscode-css-languageservice';
import { CompletionItem, CompletionList } from 'vscode-languageserver';
import type { AttributeContext } from '../../../core/documents/parseHtml';
export declare function getIdClassCompletion(stylesheets: Stylesheet[], attributeContext: AttributeContext): CompletionList | null;
/**
* incomplete see
* https://github.com/microsoft/vscode-css-languageservice/blob/master/src/parser/cssNodes.ts#L14
* The enum is not exported. we have to update this whenever it changes
*/
export declare enum NodeType {
ClassSelector = 14,
IdentifierSelector = 15
}
export type CSSNode = {
type: number;
children: CSSNode[] | undefined;
getText(): string;
};
export declare function collectSelectors(stylesheets: CSSNode[], type: number): CompletionItem[];

View file

@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.collectSelectors = exports.NodeType = exports.getIdClassCompletion = void 0;
const vscode_languageserver_1 = require("vscode-languageserver");
function getIdClassCompletion(stylesheets, attributeContext) {
const collectingType = getCollectingType(attributeContext);
if (!collectingType) {
return null;
}
const items = collectSelectors(stylesheets, collectingType);
return vscode_languageserver_1.CompletionList.create(items);
}
exports.getIdClassCompletion = getIdClassCompletion;
function getCollectingType(attributeContext) {
if (attributeContext.inValue) {
if (attributeContext.name === 'class') {
return NodeType.ClassSelector;
}
if (attributeContext.name === 'id') {
return NodeType.IdentifierSelector;
}
}
else if (attributeContext.name.startsWith('class:')) {
return NodeType.ClassSelector;
}
}
/**
* incomplete see
* https://github.com/microsoft/vscode-css-languageservice/blob/master/src/parser/cssNodes.ts#L14
* The enum is not exported. we have to update this whenever it changes
*/
var NodeType;
(function (NodeType) {
NodeType[NodeType["ClassSelector"] = 14] = "ClassSelector";
NodeType[NodeType["IdentifierSelector"] = 15] = "IdentifierSelector";
})(NodeType = exports.NodeType || (exports.NodeType = {}));
function collectSelectors(stylesheets, type) {
const result = [];
stylesheets.forEach((stylesheet) => {
walk(stylesheet, (node) => {
if (node.type === type) {
result.push(node);
}
});
});
return result.map((node) => ({
label: node.getText().substring(1),
kind: vscode_languageserver_1.CompletionItemKind.Keyword,
}));
}
exports.collectSelectors = collectSelectors;
function walk(node, callback) {
callback(node);
if (node.children) {
node.children.forEach((childrenNode) => walk(childrenNode, callback));
}
}

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