summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/config.json5
-rw-r--r--.prettierignore1
-rw-r--r--.vscode/launch.json62
-rw-r--r--.vscode/tasks.json29
-rw-r--r--README.md7
-rw-r--r--docs/cli.md2
-rw-r--r--docs/dev.md9
-rw-r--r--docs/syntax.md33
-rw-r--r--examples/kitchen-sink/src/components/PreactCounter.tsx20
-rw-r--r--examples/kitchen-sink/src/components/ReactCounter.jsx20
-rw-r--r--examples/snowpack/README.md26
-rw-r--r--examples/snowpack/src/components/CompanyLogo.jsx2
-rw-r--r--examples/snowpack/src/components/PluginSearchPage.jsx6
-rw-r--r--examples/snowpack/src/components/docsearch.js31
-rw-r--r--examples/snowpack/src/data/version.js4
-rw-r--r--examples/snowpack/src/pages/guides/web-worker.md2
-rw-r--r--lerna.json5
-rw-r--r--package.json4
-rw-r--r--packages/astro/internal.d.ts18
-rw-r--r--packages/astro/src/build.ts5
-rw-r--r--packages/astro/src/cli.ts4
-rw-r--r--packages/astro/src/compiler/index.ts2
-rw-r--r--packages/astro/src/config.ts4
-rw-r--r--packages/astro/src/dev.ts2
-rw-r--r--packages/astro/src/frontend/render/utils.ts2
-rw-r--r--packages/astro/src/logger.ts10
-rw-r--r--packages/astro/src/runtime.ts4
-rw-r--r--packages/astro/src/search.ts6
-rw-r--r--packages/astro/test/astro-doctype.test.js1
-rw-r--r--packages/astro/test/config-path.test.js2
-rw-r--r--packages/astro/test/config-port.test.js2
-rw-r--r--packages/astro/test/fixtures/astro-basic/src/pages/nested-md/index.md2
-rw-r--r--packages/astro/test/fixtures/astro-children/src/components/Component.jsx2
-rw-r--r--packages/astro/test/fixtures/astro-dynamic/src/components/Counter.jsx6
-rw-r--r--packages/astro/test/fixtures/astro-expr/src/components/Color.jsx6
-rw-r--r--packages/astro/test/fixtures/astro-fallback/src/components/Client.jsx8
-rw-r--r--packages/astro/test/fixtures/astro-markdown/src/components/Example.jsx6
-rw-r--r--packages/astro/test/fixtures/astro-markdown/src/components/Hello.jsx6
-rw-r--r--packages/astro/test/fixtures/astro-markdown/src/pages/complex.md2
-rw-r--r--packages/astro/test/test-utils.js1
-rw-r--r--packages/create-astro/CHANGELOG.md3
-rw-r--r--packages/create-astro/README.md3
-rw-r--r--packages/create-astro/src/components/App.tsx149
-rw-r--r--packages/create-astro/src/components/Confirm.tsx2
-rw-r--r--packages/create-astro/src/components/Emoji.tsx2
-rw-r--r--packages/create-astro/src/components/Exit.tsx11
-rw-r--r--packages/create-astro/src/components/Finalize.tsx19
-rw-r--r--packages/create-astro/src/components/Header.tsx34
-rw-r--r--packages/create-astro/src/components/Help.tsx124
-rw-r--r--packages/create-astro/src/components/Install.tsx12
-rw-r--r--packages/create-astro/src/components/ProjectName.tsx8
-rw-r--r--packages/create-astro/src/components/Select.tsx34
-rw-r--r--packages/create-astro/src/components/Spacer.tsx2
-rw-r--r--packages/create-astro/src/components/Spinner.tsx170
-rw-r--r--packages/create-astro/src/components/Template.tsx2
-rw-r--r--packages/create-astro/src/config.ts78
-rw-r--r--packages/create-astro/src/index.tsx62
-rw-r--r--packages/create-astro/src/templates/blank/meta.json4
-rw-r--r--packages/create-astro/src/templates/starter/README.md2
-rw-r--r--packages/create-astro/src/templates/starter/meta.json6
-rw-r--r--packages/create-astro/src/utils.ts93
-rw-r--r--scripts/package.json28
-rw-r--r--scripts/utils/svelte-plugin.js91
-rw-r--r--tools/prettier-plugin-astro/index.js56
-rw-r--r--tools/prettier-plugin-astro/test/astro-prettier.test.js4
-rw-r--r--tools/prettier-plugin-astro/test/package.json2
-rw-r--r--tools/vscode/languages/astro-language-configuration.json68
-rw-r--r--tools/vscode/package.json188
-rw-r--r--tools/vscode/packages/client/package.json20
-rw-r--r--tools/vscode/packages/client/src/html/autoClose.ts153
-rw-r--r--tools/vscode/packages/client/tsconfig.json18
-rw-r--r--tools/vscode/packages/server/src/core/config/ConfigManager.ts16
-rw-r--r--tools/vscode/packages/server/src/core/documents/Document.ts272
-rw-r--r--tools/vscode/packages/server/src/core/documents/DocumentManager.ts150
-rw-r--r--tools/vscode/packages/server/src/core/documents/parseAstro.ts99
-rw-r--r--tools/vscode/packages/server/src/core/documents/parseHtml.ts230
-rw-r--r--tools/vscode/packages/server/src/core/documents/utils.ts156
-rw-r--r--tools/vscode/packages/server/src/index.ts10
-rw-r--r--tools/vscode/packages/server/src/plugins/PluginHost.ts214
-rw-r--r--tools/vscode/packages/server/src/plugins/astro/AstroPlugin.ts2
-rw-r--r--tools/vscode/packages/server/src/plugins/html/HTMLPlugin.ts13
-rw-r--r--tools/vscode/packages/server/src/plugins/interfaces.ts210
-rw-r--r--tools/vscode/packages/server/src/plugins/typescript/LanguageServiceManager.ts2
-rw-r--r--tools/vscode/packages/server/src/plugins/typescript/SnapshotManager.ts544
-rw-r--r--tools/vscode/packages/server/src/plugins/typescript/TypeScriptPlugin.ts110
-rw-r--r--tools/vscode/packages/server/src/plugins/typescript/astro-sys.ts62
-rw-r--r--tools/vscode/packages/server/src/plugins/typescript/features/CompletionsProvider.ts2
-rw-r--r--tools/vscode/packages/server/src/plugins/typescript/languageService.ts61
-rw-r--r--tools/vscode/packages/server/src/plugins/typescript/utils.ts270
-rw-r--r--tools/vscode/packages/server/src/utils.ts83
-rw-r--r--tools/vscode/packages/server/tsconfig.json14
-rw-r--r--tools/vscode/syntaxes/astro.tmLanguage.json1406
-rw-r--r--tools/vscode/tsconfig.base.json31
-rw-r--r--tools/vscode/tsconfig.json23
-rw-r--r--www/snowpack.config.js5
-rw-r--r--yarn.lock8
96 files changed, 2792 insertions, 3018 deletions
diff --git a/.changeset/config.json b/.changeset/config.json
index 26edf6fe8..51e0c0af5 100644
--- a/.changeset/config.json
+++ b/.changeset/config.json
@@ -6,8 +6,5 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
- "ignore": [
- "@example/*",
- "www"
- ]
+ "ignore": ["@example/*", "www"]
}
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 000000000..752101540
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1 @@
+**/dist/*
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 35e13d1aa..b458758c8 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,36 +1,32 @@
// A launch configuration that compiles the extension and then opens it inside a new window
{
- "version": "0.2.0",
- "configurations": [
- {
- "type": "extensionHost",
- "request": "launch",
- "name": "Launch Client",
- "runtimeExecutable": "${execPath}",
- "args": [
- "--extensionDevelopmentPath=${workspaceRoot}/vscode"
- ],
- "outFiles": [
- "${workspaceRoot}/vscode/dist/**/*.js"
- ],
- "preLaunchTask": {
- "type": "npm",
- "script": "build:extension"
- }
- },
- {
- "type": "node",
- "request": "attach",
- "name": "Attach to Server",
- "port": 6040,
- "restart": true,
- "outFiles": ["${workspaceRoot}/vscode/dist/**/*.js"]
- },
- ],
- "compounds": [
- {
- "name": "Launch Extension",
- "configurations": ["Launch Client", "Attach to Server"]
- }
- ]
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "extensionHost",
+ "request": "launch",
+ "name": "Launch Client",
+ "runtimeExecutable": "${execPath}",
+ "args": ["--extensionDevelopmentPath=${workspaceRoot}/vscode"],
+ "outFiles": ["${workspaceRoot}/vscode/dist/**/*.js"],
+ "preLaunchTask": {
+ "type": "npm",
+ "script": "build:extension"
+ }
+ },
+ {
+ "type": "node",
+ "request": "attach",
+ "name": "Attach to Server",
+ "port": 6040,
+ "restart": true,
+ "outFiles": ["${workspaceRoot}/vscode/dist/**/*.js"]
+ }
+ ],
+ "compounds": [
+ {
+ "name": "Launch Extension",
+ "configurations": ["Launch Client", "Attach to Server"]
+ }
+ ]
}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 073d95220..3b066f021 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -1,18 +1,15 @@
-
{
- "version": "2.0.0",
- "tasks": [
- {
- "type": "npm",
- "script": "build:extension",
- "group": "build",
- "presentation": {
- "panel": "dedicated",
- "reveal": "never"
- },
- "problemMatcher": [
- "$tsc"
- ]
- }
- ]
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "type": "npm",
+ "script": "build:extension",
+ "group": "build",
+ "presentation": {
+ "panel": "dedicated",
+ "reveal": "never"
+ },
+ "problemMatcher": ["$tsc"]
+ }
+ ]
}
diff --git a/README.md b/README.md
index a89ed9a70..0311c26b9 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,6 @@ npm run build
To deploy your Astro site to production, upload the contents of `/dist` to your favorite static site host.
-
## 🥾 Guides
### 🚀 Basic Usage
@@ -66,8 +65,8 @@ Even though nearly-everything [is configurable][docs-config], we recommend start
Routing happens in `src/pages/*`. Every `.astro` or `.md.astro` file in this folder corresponds with a public URL. For example:
-| Local file | Public URL |
-| :--------------------------------------- | :------------------------------ |
+| Local file | Public URL |
+| :------------------------------------- | :------------------------------ |
| `src/pages/index.astro` | `/index.html` |
| `src/pages/post/my-blog-post.md.astro` | `/post/my-blog-post/index.html` |
@@ -164,10 +163,10 @@ Astro will automatically create a `/sitemap.xml` for you for SEO! Be sure to set
👉 [**Collections API**][docs-collections]
-
## ⚙️ Config
👉 [**`astro.config.mjs` Reference**][docs-config]
+
## 📚 API
👉 [**Full API Reference**][docs-api]
diff --git a/docs/cli.md b/docs/cli.md
index 592cf1635..2ef0592a5 100644
--- a/docs/cli.md
+++ b/docs/cli.md
@@ -36,7 +36,7 @@ Runs the Astro development server. This starts an HTTP server that responds to r
See the [dev server](./dev.md) docs for more information on how the dev server works.
-__Flags__
+**Flags**
##### `--port`
diff --git a/docs/dev.md b/docs/dev.md
index 15687d1bb..d9223cbbd 100644
--- a/docs/dev.md
+++ b/docs/dev.md
@@ -14,7 +14,7 @@ The dev server will serve the following special routes:
### /400
-This is a custom __400__ status code page. You can add this route by adding a page component to your `src/pages` folder:
+This is a custom **400** status code page. You can add this route by adding a page component to your `src/pages` folder:
```
├── src/
@@ -27,13 +27,10 @@ For any URL you visit that doesn't have a corresponding page, the `400.astro` fi
### /500
-This is a custom __500__ status code page. You can add this route by adding a page component to your `src/pages` folder:
+This is a custom **500** status code page. You can add this route by adding a page component to your `src/pages` folder:
```astro
-├── src/
-│ ├── components/
-│ └── pages/
-│ └── 500.astro
+├── src/ │ ├── components/ │ └── pages/ │ └── 500.astro
```
This page is used any time an error occurs in the dev server.
diff --git a/docs/syntax.md b/docs/syntax.md
index 21f964569..505abeb9b 100644
--- a/docs/syntax.md
+++ b/docs/syntax.md
@@ -116,26 +116,25 @@ export let name;
`.astro` files can end up looking very similar to `.jsx` files, but there are a few key differences. Here's a comparison between the two formats.
-| Feature | Astro | JSX |
-|------------------------- |------------------------------------------ |---------------------------------------------------- |
-| File extension | `.astro` | `.jsx` or `.tsx` |
-| User-Defined Components | `<Capitalized>` | `<Capitalized>` |
-| Expression Syntax | `{}` | `{}` |
-| Spread Attributes | `{...props}` | `{...props}` |
-| Boolean Attributes | `autocomplete` === `autocomplete={true}` | `autocomplete` === `autocomplete={true}` |
-| Inline Functions | `{items.map(item => <li>{item}</li>)}` | `{items.map(item => <li>{item}</li>)}` |
-| IDE Support | WIP - [VS Code][code-ext] | Phenomenal |
-| Requires JS import | No | Yes, `jsxPragma` (`React` or `h`) must be in scope |
-| Fragments | Automatic | Wrap with `<Fragment>` or `<>` |
-| Multiple frameworks per-file | Yes | No |
-| Modifying `<head>` | Just use `<head>` | Per-framework (`<Head>`, `<svelte:head>`, etc) |
-| Comment Style | `<!-- HTML -->` | `{/* JavaScript */}` |
-| Special Characters | `&nbsp;` | `{'\xa0'}` or `{String.fromCharCode(160)}` |
-| Attributes | `dash-case` | `camelCase` |
+| Feature | Astro | JSX |
+| ---------------------------- | ---------------------------------------- | -------------------------------------------------- |
+| File extension | `.astro` | `.jsx` or `.tsx` |
+| User-Defined Components | `<Capitalized>` | `<Capitalized>` |
+| Expression Syntax | `{}` | `{}` |
+| Spread Attributes | `{...props}` | `{...props}` |
+| Boolean Attributes | `autocomplete` === `autocomplete={true}` | `autocomplete` === `autocomplete={true}` |
+| Inline Functions | `{items.map(item => <li>{item}</li>)}` | `{items.map(item => <li>{item}</li>)}` |
+| IDE Support | WIP - [VS Code][code-ext] | Phenomenal |
+| Requires JS import | No | Yes, `jsxPragma` (`React` or `h`) must be in scope |
+| Fragments | Automatic | Wrap with `<Fragment>` or `<>` |
+| Multiple frameworks per-file | Yes | No |
+| Modifying `<head>` | Just use `<head>` | Per-framework (`<Head>`, `<svelte:head>`, etc) |
+| Comment Style | `<!-- HTML -->` | `{/* JavaScript */}` |
+| Special Characters | `&nbsp;` | `{'\xa0'}` or `{String.fromCharCode(160)}` |
+| Attributes | `dash-case` | `camelCase` |
### TODO: Styling
### TODO: Composition (Slots)
-
[code-ext]: https://marketplace.visualstudio.com/items?itemName=astro-build.astro
diff --git a/examples/kitchen-sink/src/components/PreactCounter.tsx b/examples/kitchen-sink/src/components/PreactCounter.tsx
index 9f1e8d887..e3761643f 100644
--- a/examples/kitchen-sink/src/components/PreactCounter.tsx
+++ b/examples/kitchen-sink/src/components/PreactCounter.tsx
@@ -3,18 +3,18 @@ import { useState } from 'preact/hooks';
/** a counter written in Preact */
export default function PreactCounter({ children }) {
- const [count, setCount] = useState(0)
- const add = () => setCount(i => i + 1);
- const subtract = () => setCount(i => i - 1);
+ const [count, setCount] = useState(0);
+ const add = () => setCount((i) => i + 1);
+ const subtract = () => setCount((i) => i - 1);
- return <>
- <div className="counter">
+ return (
+ <>
+ <div className="counter">
<button onClick={subtract}>-</button>
<pre>{count}</pre>
<button onClick={add}>+</button>
- </div>
- <div className="children">
- {children}
- </div>
- </>
+ </div>
+ <div className="children">{children}</div>
+ </>
+ );
}
diff --git a/examples/kitchen-sink/src/components/ReactCounter.jsx b/examples/kitchen-sink/src/components/ReactCounter.jsx
index 384dd9918..92871a8d8 100644
--- a/examples/kitchen-sink/src/components/ReactCounter.jsx
+++ b/examples/kitchen-sink/src/components/ReactCounter.jsx
@@ -2,18 +2,18 @@ import React, { useState } from 'react';
/** a counter written in React */
export default function ReactCounter({ children }) {
- const [count, setCount] = useState(0)
- const add = () => setCount(i => i + 1);
- const subtract = () => setCount(i => i - 1);
+ const [count, setCount] = useState(0);
+ const add = () => setCount((i) => i + 1);
+ const subtract = () => setCount((i) => i - 1);
- return <>
- <div className="counter">
+ return (
+ <>
+ <div className="counter">
<button onClick={subtract}>-</button>
<pre>{count}</pre>
<button onClick={add}>+</button>
- </div>
- <div className="children">
- {children}
- </div>
- </>
+ </div>
+ <div className="children">{children}</div>
+ </>
+ );
}
diff --git a/examples/snowpack/README.md b/examples/snowpack/README.md
index 11e615e1a..c3a71d6f8 100644
--- a/examples/snowpack/README.md
+++ b/examples/snowpack/README.md
@@ -1,21 +1,21 @@
# Astro Demo
-## Getting setup
+## Getting set up
-1. Checkout Astro at: https://github.com/snowpackjs/astro
-
- 1. Install and build Astro:
+1. Check out Astro at: https://github.com/snowpackjs/astro
- ```shell
- npm install
- npm run build
- ```
+ 1. Install and build Astro:
- 2. Link Astro:
+ ```shell
+ npm install
+ npm run build
+ ```
- ```shell
- npm link
- ```
+ 2. Link Astro:
+
+ ```shell
+ npm link
+ ```
2. In this project link Astro and install other deps:
@@ -34,4 +34,4 @@ npm run start
```shell
npm run build
-``` \ No newline at end of file
+```
diff --git a/examples/snowpack/src/components/CompanyLogo.jsx b/examples/snowpack/src/components/CompanyLogo.jsx
index 98be3f2eb..fc652f864 100644
--- a/examples/snowpack/src/components/CompanyLogo.jsx
+++ b/examples/snowpack/src/components/CompanyLogo.jsx
@@ -1,4 +1,4 @@
-import {h} from 'preact';
+import { h } from 'preact';
export default function CompanyLogo({ user }) {
return (
diff --git a/examples/snowpack/src/components/PluginSearchPage.jsx b/examples/snowpack/src/components/PluginSearchPage.jsx
index 51c7e6b0f..4ed46cb74 100644
--- a/examples/snowpack/src/components/PluginSearchPage.jsx
+++ b/examples/snowpack/src/components/PluginSearchPage.jsx
@@ -117,5 +117,9 @@ function PluginSearchPageLive() {
}
export default function PluginSearchPage(props) {
- return import.meta.env.astro ? <div>Loading...</div> : <PluginSearchPageLive {...props} />
+ return import.meta.env.astro ? (
+ <div>Loading...</div>
+ ) : (
+ <PluginSearchPageLive {...props} />
+ );
}
diff --git a/examples/snowpack/src/components/docsearch.js b/examples/snowpack/src/components/docsearch.js
index d7ae95f30..f2b9e6441 100644
--- a/examples/snowpack/src/components/docsearch.js
+++ b/examples/snowpack/src/components/docsearch.js
@@ -1,17 +1,20 @@
import docsearch from 'docsearch.js/dist/cdn/docsearch.min.js';
-customElements.define('doc-search', class extends HTMLElement {
- connectedCallback() {
- if(!this._setup) {
- const apiKey = this.getAttribute('api-key');
- const selector = this.getAttribute('selector');
- docsearch({
- apiKey: apiKey,
- indexName: 'snowpack',
- inputSelector: selector,
- debug: true // Set debug to true if you want to inspect the dropdown
- });
- this._setup = true;
+customElements.define(
+ 'doc-search',
+ class extends HTMLElement {
+ connectedCallback() {
+ if (!this._setup) {
+ const apiKey = this.getAttribute('api-key');
+ const selector = this.getAttribute('selector');
+ docsearch({
+ apiKey: apiKey,
+ indexName: 'snowpack',
+ inputSelector: selector,
+ debug: true, // Set debug to true if you want to inspect the dropdown
+ });
+ this._setup = true;
+ }
}
- }
-}); \ No newline at end of file
+ },
+);
diff --git a/examples/snowpack/src/data/version.js b/examples/snowpack/src/data/version.js
index 19a63491c..53f8ca53e 100644
--- a/examples/snowpack/src/data/version.js
+++ b/examples/snowpack/src/data/version.js
@@ -1,2 +1,4 @@
-const snowpackManifest = JSON.parse(fs.readFileSync(path.join(__dirname, '../../snowpack/package.json'), 'utf8'));
+const snowpackManifest = JSON.parse(
+ fs.readFileSync(path.join(__dirname, '../../snowpack/package.json'), 'utf8'),
+);
export default snowpackManifest.version;
diff --git a/examples/snowpack/src/pages/guides/web-worker.md b/examples/snowpack/src/pages/guides/web-worker.md
index 4329c489a..56bce9774 100644
--- a/examples/snowpack/src/pages/guides/web-worker.md
+++ b/examples/snowpack/src/pages/guides/web-worker.md
@@ -28,4 +28,4 @@ const worker = new Worker(new URL('./esm-worker.js', import.meta.url), {
name: 'my-worker',
type: 'module',
});
-``` \ No newline at end of file
+```
diff --git a/lerna.json b/lerna.json
index 6b98ebda7..ae71dbae7 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,8 +1,5 @@
{
- "ignoreChanges": [
- "**/test/**",
- "**/*.md"
- ],
+ "ignoreChanges": ["**/test/**", "**/*.md"],
"useWorkspaces": true,
"version": "4.0.0"
}
diff --git a/package.json b/package.json
index b7c9232a7..0fa802270 100644
--- a/package.json
+++ b/package.json
@@ -5,11 +5,11 @@
"release": "yarn build && yarn changeset publish",
"build": "yarn build:core",
"build:core": "lerna run build --scope astro --scope astro-parser --scope create-astro",
+ "format": "prettier -w '**/*.{js,jsx,ts,tsx,md,json}'",
"lint": "eslint 'packages/**/*.ts'",
"test": "yarn test:core && yarn test:prettier",
"test:core": "cd packages/astro && npm test",
- "test:prettier": "cd tools/prettier-plugin-astro && npm test",
- "format": "prettier -w '**/*.{js,jsx,ts,tsx,md,json}'"
+ "test:prettier": "cd tools/prettier-plugin-astro && npm test"
},
"workspaces": [
"packages/*",
diff --git a/packages/astro/internal.d.ts b/packages/astro/internal.d.ts
index 5d0f0d123..40b65ffb3 100644
--- a/packages/astro/internal.d.ts
+++ b/packages/astro/internal.d.ts
@@ -1,27 +1,27 @@
declare module '#astro/compiler' {
- export * from 'astro/dist/types/compiler';
+ export * from 'astro/dist/types/compiler';
}
declare module '#astro/ast' {
- export * from 'astro/dist/types/ast';
+ export * from 'astro/dist/types/ast';
}
declare module '#astro/build' {
- export * from 'astro/dist/types/build';
+ export * from 'astro/dist/types/build';
}
declare module '#astro/cli' {
- export * from 'astro/dist/types/cli';
+ export * from 'astro/dist/types/cli';
}
declare module '#astro/config' {
- export * from 'astro/dist/types/config';
+ export * from 'astro/dist/types/config';
}
declare module '#astro/dev' {
- export * from 'astro/dist/types/dev';
+ export * from 'astro/dist/types/dev';
}
declare module '#astro/logger' {
- export * from 'astro/dist/types/logger';
+ export * from 'astro/dist/types/logger';
}
declare module '#astro/runtime' {
- export * from 'astro/dist/types/runtime';
+ export * from 'astro/dist/types/runtime';
}
declare module '#astro/search' {
- export * from 'astro/dist/types/search';
+ export * from 'astro/dist/types/search';
}
diff --git a/packages/astro/src/build.ts b/packages/astro/src/build.ts
index fb603641d..b7cca32e5 100644
--- a/packages/astro/src/build.ts
+++ b/packages/astro/src/build.ts
@@ -16,7 +16,6 @@ import { generateRSS } from './build/rss.js';
import { generateSitemap } from './build/sitemap.js';
import { collectStatics } from './build/static.js';
import { canonicalURL } from './build/util.js';
-import { pathToFileURL } from 'node:url';
const { mkdir, readFile, writeFile } = fsPromises;
@@ -69,8 +68,8 @@ async function writeFilep(outPath: URL, bytes: string | Buffer, encoding: 'utf8'
interface WriteResultOptions {
srcPath: string;
result: LoadResult;
- outPath: URL,
- encoding: null|'utf8'
+ outPath: URL;
+ encoding: null | 'utf8';
}
/** Utility for writing a build result to disk */
diff --git a/packages/astro/src/cli.ts b/packages/astro/src/cli.ts
index b028d754c..16f67fd60 100644
--- a/packages/astro/src/cli.ts
+++ b/packages/astro/src/cli.ts
@@ -31,10 +31,10 @@ interface CLIState {
/** Determine which action the user requested */
function resolveArgs(flags: Arguments): CLIState {
const options: CLIState['options'] = {
- projectRoot: typeof flags.projectRoot === 'string' ? flags.projectRoot: undefined,
+ projectRoot: typeof flags.projectRoot === 'string' ? flags.projectRoot : undefined,
sitemap: typeof flags.sitemap === 'boolean' ? flags.sitemap : undefined,
port: typeof flags.port === 'number' ? flags.port : undefined,
- config: typeof flags.config === 'string' ? flags.config : undefined
+ config: typeof flags.config === 'string' ? flags.config : undefined,
};
if (flags.version) {
diff --git a/packages/astro/src/compiler/index.ts b/packages/astro/src/compiler/index.ts
index 6a9e8dbe6..a1a9bde36 100644
--- a/packages/astro/src/compiler/index.ts
+++ b/packages/astro/src/compiler/index.ts
@@ -15,7 +15,7 @@ import { encodeAstroMdx } from './markdown/micromark-mdx-astro.js';
import { transform } from './transform/index.js';
import { codegen } from './codegen/index.js';
-export { scopeRule } from './transform/postcss-scoped-styles/index.js'
+export { scopeRule } from './transform/postcss-scoped-styles/index.js';
/** Return Astro internal import URL */
function internalImport(internalPath: string) {
diff --git a/packages/astro/src/config.ts b/packages/astro/src/config.ts
index cf4b5b229..d774d6b9e 100644
--- a/packages/astro/src/config.ts
+++ b/packages/astro/src/config.ts
@@ -26,8 +26,8 @@ function validateConfig(config: any): void {
}
}
- if(typeof config.devOptions?.port !== 'number') {
- throw new Error(`[astro config] devOptions.port: Expected number, received ${type(config.devOptions?.port)}`)
+ if (typeof config.devOptions?.port !== 'number') {
+ throw new Error(`[astro config] devOptions.port: Expected number, received ${type(config.devOptions?.port)}`);
}
}
diff --git a/packages/astro/src/dev.ts b/packages/astro/src/dev.ts
index 2522ab645..7aa4ba07d 100644
--- a/packages/astro/src/dev.ts
+++ b/packages/astro/src/dev.ts
@@ -75,7 +75,7 @@ export default async function dev(astroConfig: AstroConfig) {
res.statusCode = 500;
let errorResult = await runtime.load(`/500?error=${encodeURIComponent(result.error.stack || result.error.toString())}`);
- if(errorResult.statusCode === 200) {
+ if (errorResult.statusCode === 200) {
if (errorResult.contentType) {
res.setHeader('Content-Type', errorResult.contentType);
}
diff --git a/packages/astro/src/frontend/render/utils.ts b/packages/astro/src/frontend/render/utils.ts
index 5d13ca136..2dddf083e 100644
--- a/packages/astro/src/frontend/render/utils.ts
+++ b/packages/astro/src/frontend/render/utils.ts
@@ -49,6 +49,6 @@ export const childrenToH = moize.deep(function childrenToH(renderer: ComponentRe
};
return tree.map((subtree) => {
if (subtree.type === 'text') return JSON.stringify(subtree.value);
- return toH(innerH, subtree).__SERIALIZED
+ return toH(innerH, subtree).__SERIALIZED;
});
});
diff --git a/packages/astro/src/logger.ts b/packages/astro/src/logger.ts
index f700e91e1..a97482459 100644
--- a/packages/astro/src/logger.ts
+++ b/packages/astro/src/logger.ts
@@ -16,13 +16,13 @@ export const defaultLogDestination = new Writable({
dest = process.stdout;
}
let type = event.type;
- if(type !== null) {
+ if (type !== null) {
if (event.level === 'info') {
type = bold(blue(type));
} else if (event.level === 'error') {
type = bold(red(type));
}
-
+
dest.write(`[${type}] `);
}
@@ -135,10 +135,10 @@ export const logger = {
};
// For silencing libraries that go directly to console.warn
-export function trapWarn(cb: (...args: any[]) => void = () =>{}) {
+export function trapWarn(cb: (...args: any[]) => void = () => {}) {
const warn = console.warn;
- console.warn = function(...args: any[]) {
+ console.warn = function (...args: any[]) {
cb(...args);
};
- return () => console.warn = warn;
+ return () => (console.warn = warn);
}
diff --git a/packages/astro/src/runtime.ts b/packages/astro/src/runtime.ts
index d08c0f387..76e27516d 100644
--- a/packages/astro/src/runtime.ts
+++ b/packages/astro/src/runtime.ts
@@ -200,14 +200,14 @@ async function load(config: RuntimeConfig, rawPathname: string | undefined): Pro
// For first release query params are not passed to components.
// An exception is made for dev server specific routes.
- if(reqPath !== '/500') {
+ if (reqPath !== '/500') {
requestURL.search = '';
}
let html = (await mod.exports.__renderPage({
request: {
// params should go here when implemented
- url: requestURL
+ url: requestURL,
},
children: [],
props: { collection },
diff --git a/packages/astro/src/search.ts b/packages/astro/src/search.ts
index f097751b1..96338dd0c 100644
--- a/packages/astro/src/search.ts
+++ b/packages/astro/src/search.ts
@@ -92,14 +92,14 @@ export function searchForPage(url: URL, astroRoot: URL): SearchResult {
}
}
- if(reqPath === '/500') {
+ if (reqPath === '/500') {
return {
statusCode: 200,
location: {
fileURL: new URL('./frontend/500.astro', import.meta.url),
- snowpackURL: `/_astro_internal/500.astro.js`
+ snowpackURL: `/_astro_internal/500.astro.js`,
},
- pathname: reqPath
+ pathname: reqPath,
};
}
diff --git a/packages/astro/test/astro-doctype.test.js b/packages/astro/test/astro-doctype.test.js
index 91d422665..c1b94908b 100644
--- a/packages/astro/test/astro-doctype.test.js
+++ b/packages/astro/test/astro-doctype.test.js
@@ -4,7 +4,6 @@ import * as assert from 'uvu/assert';
import { loadConfig } from '#astro/config';
import { createRuntime } from '#astro/runtime';
-
const DType = suite('doctype');
let runtime, setupError;
diff --git a/packages/astro/test/config-path.test.js b/packages/astro/test/config-path.test.js
index 33e2cf3b7..5d78e7027 100644
--- a/packages/astro/test/config-path.test.js
+++ b/packages/astro/test/config-path.test.js
@@ -12,7 +12,7 @@ ConfigPath('can be passed via --config', async (context) => {
process.stdout.setEncoding('utf8');
for await (const chunk of process.stdout) {
- if(/Server started/.test(chunk)) {
+ if (/Server started/.test(chunk)) {
break;
}
}
diff --git a/packages/astro/test/config-port.test.js b/packages/astro/test/config-port.test.js
index d8e4fdf14..000c5575b 100644
--- a/packages/astro/test/config-port.test.js
+++ b/packages/astro/test/config-port.test.js
@@ -17,7 +17,7 @@ ConfigPort('can be specified via --port flag', async (context) => {
process.stdout.setEncoding('utf8');
for await (const chunk of process.stdout) {
- if(/Local:/.test(chunk)) {
+ if (/Local:/.test(chunk)) {
assert.ok(/:3002/.test(chunk), 'Using the right port');
break;
}
diff --git a/packages/astro/test/fixtures/astro-basic/src/pages/nested-md/index.md b/packages/astro/test/fixtures/astro-basic/src/pages/nested-md/index.md
index 23374f9b8..611660c4c 100644
--- a/packages/astro/test/fixtures/astro-basic/src/pages/nested-md/index.md
+++ b/packages/astro/test/fixtures/astro-basic/src/pages/nested-md/index.md
@@ -3,4 +3,4 @@ layout: ../../layouts/base.astro
title: My Page
---
-Hello world \ No newline at end of file
+Hello world
diff --git a/packages/astro/test/fixtures/astro-children/src/components/Component.jsx b/packages/astro/test/fixtures/astro-children/src/components/Component.jsx
index bf9280f86..f25176192 100644
--- a/packages/astro/test/fixtures/astro-children/src/components/Component.jsx
+++ b/packages/astro/test/fixtures/astro-children/src/components/Component.jsx
@@ -1,5 +1,5 @@
import { h } from 'preact';
export default function PreactComponent({ children }) {
- return <div id="preact">{children}</div>
+ return <div id="preact">{children}</div>;
}
diff --git a/packages/astro/test/fixtures/astro-dynamic/src/components/Counter.jsx b/packages/astro/test/fixtures/astro-dynamic/src/components/Counter.jsx
index 31472c3ac..7a7d6ea1f 100644
--- a/packages/astro/test/fixtures/astro-dynamic/src/components/Counter.jsx
+++ b/packages/astro/test/fixtures/astro-dynamic/src/components/Counter.jsx
@@ -1,9 +1,9 @@
import React from 'react';
-export default function() {
+export default function () {
return (
<div>
<button type="button">Increment -</button>
</div>
- )
-} \ No newline at end of file
+ );
+}
diff --git a/packages/astro/test/fixtures/astro-expr/src/components/Color.jsx b/packages/astro/test/fixtures/astro-expr/src/components/Color.jsx
index c2681cc9b..9f7f40733 100644
--- a/packages/astro/test/fixtures/astro-expr/src/components/Color.jsx
+++ b/packages/astro/test/fixtures/astro-expr/src/components/Color.jsx
@@ -1,5 +1,5 @@
import { h } from 'preact';
-export default function({ name }) {
- return <div id={name}>{name}</div>
-} \ No newline at end of file
+export default function ({ name }) {
+ return <div id={name}>{name}</div>;
+}
diff --git a/packages/astro/test/fixtures/astro-fallback/src/components/Client.jsx b/packages/astro/test/fixtures/astro-fallback/src/components/Client.jsx
index d79536e27..4cc5ea252 100644
--- a/packages/astro/test/fixtures/astro-fallback/src/components/Client.jsx
+++ b/packages/astro/test/fixtures/astro-fallback/src/components/Client.jsx
@@ -1,7 +1,5 @@
import { h } from 'preact';
-export default function(props) {
- return (
- <div id="fallback">{import.meta.env.astro ? 'static' : 'dynamic'}</div>
- );
-}; \ No newline at end of file
+export default function (props) {
+ return <div id="fallback">{import.meta.env.astro ? 'static' : 'dynamic'}</div>;
+}
diff --git a/packages/astro/test/fixtures/astro-markdown/src/components/Example.jsx b/packages/astro/test/fixtures/astro-markdown/src/components/Example.jsx
index 57bde3a95..e1f67ee50 100644
--- a/packages/astro/test/fixtures/astro-markdown/src/components/Example.jsx
+++ b/packages/astro/test/fixtures/astro-markdown/src/components/Example.jsx
@@ -1,5 +1,5 @@
import { h } from 'preact';
-export default function() {
- return <div id="test">Testing</div>
-} \ No newline at end of file
+export default function () {
+ return <div id="test">Testing</div>;
+}
diff --git a/packages/astro/test/fixtures/astro-markdown/src/components/Hello.jsx b/packages/astro/test/fixtures/astro-markdown/src/components/Hello.jsx
index 787ca587b..d30dec516 100644
--- a/packages/astro/test/fixtures/astro-markdown/src/components/Hello.jsx
+++ b/packages/astro/test/fixtures/astro-markdown/src/components/Hello.jsx
@@ -1,5 +1,5 @@
import { h } from 'preact';
-export default function({ name }) {
- return <div id="test">Hello {name}</div>
-} \ No newline at end of file
+export default function ({ name }) {
+ return <div id="test">Hello {name}</div>;
+}
diff --git a/packages/astro/test/fixtures/astro-markdown/src/pages/complex.md b/packages/astro/test/fixtures/astro-markdown/src/pages/complex.md
index 6367948b9..f55a11ad6 100644
--- a/packages/astro/test/fixtures/astro-markdown/src/pages/complex.md
+++ b/packages/astro/test/fixtures/astro-markdown/src/pages/complex.md
@@ -10,4 +10,4 @@ import:
## Interesting Topic
<Hello name={`world`} />
-<Counter:load /> \ No newline at end of file
+<Counter:load />
diff --git a/packages/astro/test/test-utils.js b/packages/astro/test/test-utils.js
index 1afab6a20..b53ff2f0f 100644
--- a/packages/astro/test/test-utils.js
+++ b/packages/astro/test/test-utils.js
@@ -4,4 +4,3 @@ import cheerio from 'cheerio';
export function doc(html) {
return cheerio.load(html);
}
-
diff --git a/packages/create-astro/CHANGELOG.md b/packages/create-astro/CHANGELOG.md
index 0029af7d4..59abb17c5 100644
--- a/packages/create-astro/CHANGELOG.md
+++ b/packages/create-astro/CHANGELOG.md
@@ -1,8 +1,9 @@
# create-astro
## 0.1.0
+
### Minor Changes
- ed63132: Added **interactive mode** with a fesh new UI.
-
+
Included a new **blank** starter to get up and running even faster.
diff --git a/packages/create-astro/README.md b/packages/create-astro/README.md
index cc7d1619f..ff0c9993b 100644
--- a/packages/create-astro/README.md
+++ b/packages/create-astro/README.md
@@ -1,12 +1,15 @@
# create-astro
+
## Scaffolding for Astro projects
**With NPM:**
+
```bash
npm init astro
```
**With Yarn:**
+
```bash
yarn create astro
```
diff --git a/packages/create-astro/src/components/App.tsx b/packages/create-astro/src/components/App.tsx
index fd9192bb6..deb9b252a 100644
--- a/packages/create-astro/src/components/App.tsx
+++ b/packages/create-astro/src/components/App.tsx
@@ -1,4 +1,4 @@
-import React, {FC, useEffect} from 'react';
+import React, { FC, useEffect } from 'react';
import { prepareTemplate, isEmpty, emptyDir } from '../utils';
import Header from './Header';
import Install from './Install';
@@ -8,86 +8,91 @@ import Confirm from './Confirm';
import Finalize from './Finalize';
interface Context {
- use: 'npm'|'yarn';
- run: boolean;
- projectExists?: boolean;
- force?: boolean;
- projectName?: string;
- template?: string;
- templates: string[];
- ready?: boolean;
+ use: 'npm' | 'yarn';
+ run: boolean;
+ projectExists?: boolean;
+ force?: boolean;
+ projectName?: string;
+ template?: string;
+ templates: string[];
+ ready?: boolean;
}
const getStep = ({ projectName, projectExists: exists, template, force, ready }: Context) => {
- switch (true) {
- case !projectName: return {
- key: 'projectName',
- Component: ProjectName
- };
- case projectName && exists === true && typeof force === 'undefined': return {
- key: 'force',
- Component: Confirm
- }
- case (exists === false || force) && !template: return {
- key: 'template',
- Component: Template
- };
- case !ready: return {
- key: 'install',
- Component: Install
- };
- default: return {
- key: 'final',
- Component: Finalize
- }
- }
-}
+ switch (true) {
+ case !projectName:
+ return {
+ key: 'projectName',
+ Component: ProjectName,
+ };
+ case projectName && exists === true && typeof force === 'undefined':
+ return {
+ key: 'force',
+ Component: Confirm,
+ };
+ case (exists === false || force) && !template:
+ return {
+ key: 'template',
+ Component: Template,
+ };
+ case !ready:
+ return {
+ key: 'install',
+ Component: Install,
+ };
+ default:
+ return {
+ key: 'final',
+ Component: Finalize,
+ };
+ }
+};
const App: FC<{ context: Context }> = ({ context }) => {
- const [state, setState] = React.useState(context);
- const step = React.useRef(getStep(context));
- const onSubmit = (value: string|boolean) => {
- const { key } = step.current;
- const newState = { ...state, [key]: value };
- step.current = getStep(newState)
- setState(newState)
- }
+ const [state, setState] = React.useState(context);
+ const step = React.useRef(getStep(context));
+ const onSubmit = (value: string | boolean) => {
+ const { key } = step.current;
+ const newState = { ...state, [key]: value };
+ step.current = getStep(newState);
+ setState(newState);
+ };
- useEffect(() => {
- let isSubscribed = true
- if (state.projectName && typeof state.projectExists === 'undefined') {
- const newState = { ...state, projectExists: !isEmpty(state.projectName) };
- step.current = getStep(newState)
- if (isSubscribed) {
- setState(newState);
- }
- }
+ useEffect(() => {
+ let isSubscribed = true;
+ if (state.projectName && typeof state.projectExists === 'undefined') {
+ const newState = { ...state, projectExists: !isEmpty(state.projectName) };
+ step.current = getStep(newState);
+ if (isSubscribed) {
+ setState(newState);
+ }
+ }
- if (state.projectName && (state.projectExists === false || state.force) && state.template) {
- if (state.force) emptyDir(state.projectName);
- prepareTemplate(context.use, state.template, state.projectName).then(() => {
- if (isSubscribed) {
- setState(v => {
- const newState = {...v, ready: true };
- step.current = getStep(newState);
- return newState;
- });
- }
- });
- }
+ if (state.projectName && (state.projectExists === false || state.force) && state.template) {
+ if (state.force) emptyDir(state.projectName);
+ prepareTemplate(context.use, state.template, state.projectName).then(() => {
+ if (isSubscribed) {
+ setState((v) => {
+ const newState = { ...v, ready: true };
+ step.current = getStep(newState);
+ return newState;
+ });
+ }
+ });
+ }
- return () => {
- isSubscribed = false;
- }
- }, [state]);
- const { Component } = step.current;
+ return () => {
+ isSubscribed = false;
+ };
+ }, [state]);
+ const { Component } = step.current;
- return (
- <>
- <Header context={state}/>
- <Component context={state} onSubmit={onSubmit} />
- </>
- )
+ return (
+ <>
+ <Header context={state} />
+ <Component context={state} onSubmit={onSubmit} />
+ </>
+ );
};
export default App;
diff --git a/packages/create-astro/src/components/Confirm.tsx b/packages/create-astro/src/components/Confirm.tsx
index 1fd1aa862..84d83ed8f 100644
--- a/packages/create-astro/src/components/Confirm.tsx
+++ b/packages/create-astro/src/components/Confirm.tsx
@@ -31,7 +31,7 @@ const Confirm: FC<{ message?: any; context: any; onSubmit: (value: boolean) => v
items={[
{
value: false,
- label: 'no'
+ label: 'no',
},
{
value: true,
diff --git a/packages/create-astro/src/components/Emoji.tsx b/packages/create-astro/src/components/Emoji.tsx
index 3af9ae508..4a294f5db 100644
--- a/packages/create-astro/src/components/Emoji.tsx
+++ b/packages/create-astro/src/components/Emoji.tsx
@@ -2,4 +2,4 @@ import React from 'react';
import { Text } from 'ink';
import { isWin } from '../utils';
-export default ({ children }) => isWin() ? null : <Text>{children}</Text>
+export default ({ children }) => (isWin() ? null : <Text>{children}</Text>);
diff --git a/packages/create-astro/src/components/Exit.tsx b/packages/create-astro/src/components/Exit.tsx
index cc3096705..b108fb36f 100644
--- a/packages/create-astro/src/components/Exit.tsx
+++ b/packages/create-astro/src/components/Exit.tsx
@@ -2,8 +2,11 @@ import React, { FC } from 'react';
import { Box, Text } from 'ink';
import { isDone } from '../utils';
-const Exit: FC<{ didError?: boolean }> = ({ didError }) => isDone ? null : <Box marginTop={1} display="flex">
- <Text color={didError ? "#FF1639" : "#FFBE2D"}>[abort]</Text>
- <Text> astro cancelled</Text>
-</Box>
+const Exit: FC<{ didError?: boolean }> = ({ didError }) =>
+ isDone ? null : (
+ <Box marginTop={1} display="flex">
+ <Text color={didError ? '#FF1639' : '#FFBE2D'}>[abort]</Text>
+ <Text> astro cancelled</Text>
+ </Box>
+ );
export default Exit;
diff --git a/packages/create-astro/src/components/Finalize.tsx b/packages/create-astro/src/components/Finalize.tsx
index 8d2a2103a..933a8844e 100644
--- a/packages/create-astro/src/components/Finalize.tsx
+++ b/packages/create-astro/src/components/Finalize.tsx
@@ -7,21 +7,26 @@ const Finalize: FC<{ context: any }> = ({ context: { use, projectName } }) => {
cancelProcessListeners();
process.exit(0);
}, []);
-
- return <>
+
+ return (
+ <>
<Box display="flex">
<Text color="#17C083">{'[ yes ]'}</Text>
- <Text> Project initialized at <Text color="#3894FF">./{projectName}</Text></Text>
+ <Text>
+ {' '}
+ Project initialized at <Text color="#3894FF">./{projectName}</Text>
+ </Text>
</Box>
<Box display="flex" marginY={1}>
<Text dimColor>{'[ tip ]'}</Text>
<Box display="flex" marginLeft={1} flexDirection="column">
- <Text>Get started by running</Text>
- <Text color="#3894FF">cd ./{projectName}</Text>
- <Text color="#3894FF">{use} start</Text>
+ <Text>Get started by running</Text>
+ <Text color="#3894FF">cd ./{projectName}</Text>
+ <Text color="#3894FF">{use} start</Text>
</Box>
</Box>
- </>;
+ </>
+ );
};
export default Finalize;
diff --git a/packages/create-astro/src/components/Header.tsx b/packages/create-astro/src/components/Header.tsx
index 1d894a60e..0684d1b3c 100644
--- a/packages/create-astro/src/components/Header.tsx
+++ b/packages/create-astro/src/components/Header.tsx
@@ -2,19 +2,27 @@ import React from 'react';
import { Box, Text } from 'ink';
const getMessage = ({ projectName, template }) => {
- switch (true) {
- case !projectName: return <Text dimColor>Gathering mission details</Text>;
- case !template: return <Text dimColor>Optimizing navigational system</Text>;
- default: return <Text color="black" backgroundColor="white"> {projectName} </Text>
- }
-}
+ switch (true) {
+ case !projectName:
+ return <Text dimColor>Gathering mission details</Text>;
+ case !template:
+ return <Text dimColor>Optimizing navigational system</Text>;
+ default:
+ return (
+ <Text color="black" backgroundColor="white">
+ {' '}
+ {projectName}{' '}
+ </Text>
+ );
+ }
+};
const Header: React.FC<{ context: any }> = ({ context }) => (
- <Box width={48} display="flex" marginY={1}>
- <Text backgroundColor="#882DE7" color="white">{' astro '}</Text>
- <Box marginLeft={1}>
- {getMessage(context)}
- </Box>
- </Box>
-)
+ <Box width={48} display="flex" marginY={1}>
+ <Text backgroundColor="#882DE7" color="white">
+ {' astro '}
+ </Text>
+ <Box marginLeft={1}>{getMessage(context)}</Box>
+ </Box>
+);
export default Header;
diff --git a/packages/create-astro/src/components/Help.tsx b/packages/create-astro/src/components/Help.tsx
index 88fcf5633..5991664f1 100644
--- a/packages/create-astro/src/components/Help.tsx
+++ b/packages/create-astro/src/components/Help.tsx
@@ -2,61 +2,79 @@ import React, { FC } from 'react';
import { Box, Text } from 'ink';
import { ARGS, ARG } from '../config';
-const Type: FC<{ type: any, enum?: string[] }> = ({ type, enum: e }) => {
- if (type === Boolean) {
- return <>
- <Text color="#3894FF">true</Text>
- <Text dimColor>|</Text>
- <Text color="#3894FF">false</Text>
- </>
- }
- if (e?.length > 0) {
- return <>
- {e.map((item, i, { length: len}) => {
- if (i !== len - 1) {
- return <Box key={item}>
- <Text color="#17C083">{item}</Text>
- <Text dimColor>|</Text>
- </Box>
- }
-
- return <Text color="#17C083" key={item}>{item}</Text>
- })}
- </>
- }
-
- return <Text color="#3894FF">string</Text>;
-}
-
-const Command: FC<{ name: string, info: ARG }> = ({ name, info: { alias, description, type, enum: e } }) => {
+const Type: FC<{ type: any; enum?: string[] }> = ({ type, enum: e }) => {
+ if (type === Boolean) {
return (
- <Box display="flex" alignItems="flex-start">
- <Box width={24} display="flex" flexGrow={0}>
- <Text color="whiteBright">--{name}</Text>{alias && <Text dimColor> -{alias}</Text>}
- </Box>
- <Box width={24}>
- <Type type={type} enum={e} />
- </Box>
- <Box>
- <Text>{description}</Text>
- </Box>
- </Box>
+ <>
+ <Text color="#3894FF">true</Text>
+ <Text dimColor>|</Text>
+ <Text color="#3894FF">false</Text>
+ </>
);
-}
-
-const Help: FC<{ context: any }> = ({ context: { templates }}) => {
+ }
+ if (e?.length > 0) {
return (
- <>
- <Box width={48} display="flex" marginY={1}>
- <Text backgroundColor="#882DE7" color="white">{' astro '}</Text>
- <Box marginLeft={1}>
- <Text color="black" backgroundColor="white"> help </Text>
- </Box>
- </Box>
- <Box marginBottom={1} marginLeft={2} display="flex" flexDirection="column">
- {Object.entries(ARGS).map(([name, info]) => <Command key={name} name={name} info={name === 'template' ? { ...info, enum: templates.map(({ value }) => value) } : info} /> )}
- </Box>
- </>
- )
+ <>
+ {e.map((item, i, { length: len }) => {
+ if (i !== len - 1) {
+ return (
+ <Box key={item}>
+ <Text color="#17C083">{item}</Text>
+ <Text dimColor>|</Text>
+ </Box>
+ );
+ }
+
+ return (
+ <Text color="#17C083" key={item}>
+ {item}
+ </Text>
+ );
+ })}
+ </>
+ );
+ }
+
+ return <Text color="#3894FF">string</Text>;
+};
+
+const Command: FC<{ name: string; info: ARG }> = ({ name, info: { alias, description, type, enum: e } }) => {
+ return (
+ <Box display="flex" alignItems="flex-start">
+ <Box width={24} display="flex" flexGrow={0}>
+ <Text color="whiteBright">--{name}</Text>
+ {alias && <Text dimColor> -{alias}</Text>}
+ </Box>
+ <Box width={24}>
+ <Type type={type} enum={e} />
+ </Box>
+ <Box>
+ <Text>{description}</Text>
+ </Box>
+ </Box>
+ );
+};
+
+const Help: FC<{ context: any }> = ({ context: { templates } }) => {
+ return (
+ <>
+ <Box width={48} display="flex" marginY={1}>
+ <Text backgroundColor="#882DE7" color="white">
+ {' astro '}
+ </Text>
+ <Box marginLeft={1}>
+ <Text color="black" backgroundColor="white">
+ {' '}
+ help{' '}
+ </Text>
+ </Box>
+ </Box>
+ <Box marginBottom={1} marginLeft={2} display="flex" flexDirection="column">
+ {Object.entries(ARGS).map(([name, info]) => (
+ <Command key={name} name={name} info={name === 'template' ? { ...info, enum: templates.map(({ value }) => value) } : info} />
+ ))}
+ </Box>
+ </>
+ );
};
export default Help;
diff --git a/packages/create-astro/src/components/Install.tsx b/packages/create-astro/src/components/Install.tsx
index d9d2bc9b6..776c0cc34 100644
--- a/packages/create-astro/src/components/Install.tsx
+++ b/packages/create-astro/src/components/Install.tsx
@@ -4,16 +4,20 @@ import Spacer from './Spacer';
import Spinner from './Spinner';
const Install: FC<{ context: any }> = ({ context: { use } }) => {
- return <>
+ return (
+ <>
<Box display="flex">
- <Spinner/>
+ <Spinner />
<Text> Initiating launch sequence...</Text>
</Box>
<Box>
<Spacer />
- <Text color="white" dimColor>(aka running <Text color="#17C083">{use === 'npm' ? 'npm install' : 'yarn'}</Text>)</Text>
+ <Text color="white" dimColor>
+ (aka running <Text color="#17C083">{use === 'npm' ? 'npm install' : 'yarn'}</Text>)
+ </Text>
</Box>
- </>;
+ </>
+ );
};
export default Install;
diff --git a/packages/create-astro/src/components/ProjectName.tsx b/packages/create-astro/src/components/ProjectName.tsx
index 87b976494..d09a33d82 100644
--- a/packages/create-astro/src/components/ProjectName.tsx
+++ b/packages/create-astro/src/components/ProjectName.tsx
@@ -8,8 +8,9 @@ const { default: Input } = TextInput;
const ProjectName: FC<{ onSubmit: (value: string) => void }> = ({ onSubmit }) => {
const [value, setValue] = React.useState('');
const handleSubmit = (v: string) => onSubmit(v);
-
- return <>
+
+ return (
+ <>
<Box display="flex">
<Text color="#17C083">{'[query]'}</Text>
<Text> What is your project name?</Text>
@@ -18,7 +19,8 @@ const ProjectName: FC<{ onSubmit: (value: string) => void }> = ({ onSubmit }) =>
<Spacer />
<Input value={value} onChange={setValue} onSubmit={handleSubmit} placeholder="my-project" />
</Box>
- </>;
+ </>
+ );
};
export default ProjectName;
diff --git a/packages/create-astro/src/components/Select.tsx b/packages/create-astro/src/components/Select.tsx
index acf8eb29f..08d588f4f 100644
--- a/packages/create-astro/src/components/Select.tsx
+++ b/packages/create-astro/src/components/Select.tsx
@@ -5,28 +5,28 @@ import { Text, Box } from 'ink';
const { default: Select } = SelectInput;
interface Props {
- isSelected?: boolean;
- label: string;
- description?: string;
+ isSelected?: boolean;
+ label: string;
+ description?: string;
}
-const Indicator: FC<Props> = ({ isSelected }) => isSelected ? <Text color="#3894FF">[ </Text> : <Text> </Text>
-const Item: FC<Props> = ({isSelected = false, label, description }) => (
- <Box display="flex">
- <Text color={isSelected ? '#3894FF' : 'white'} dimColor={!isSelected}>{label}</Text>
- {isSelected && description && typeof description === 'string' && <Text> {description}</Text>}
- {isSelected && description && typeof description !== 'string' && <Box marginLeft={1}>{description}</Box>}
- </Box>
+const Indicator: FC<Props> = ({ isSelected }) => (isSelected ? <Text color="#3894FF">[ </Text> : <Text> </Text>);
+const Item: FC<Props> = ({ isSelected = false, label, description }) => (
+ <Box display="flex">
+ <Text color={isSelected ? '#3894FF' : 'white'} dimColor={!isSelected}>
+ {label}
+ </Text>
+ {isSelected && description && typeof description === 'string' && <Text> {description}</Text>}
+ {isSelected && description && typeof description !== 'string' && <Box marginLeft={1}>{description}</Box>}
+ </Box>
);
interface SelectProps {
- items: { value: string|number|boolean, label: string, description?: any }[]
- onSelect(value: string|number|boolean): void;
+ items: { value: string | number | boolean; label: string; description?: any }[];
+ onSelect(value: string | number | boolean): void;
}
const CustomSelect: FC<SelectProps> = ({ items, onSelect }) => {
- const handleSelect = ({ value }) => onSelect(value);
- return (
- <Select indicatorComponent={Indicator} itemComponent={Item} items={items} onSelect={handleSelect} />
- )
-}
+ const handleSelect = ({ value }) => onSelect(value);
+ return <Select indicatorComponent={Indicator} itemComponent={Item} items={items} onSelect={handleSelect} />;
+};
export default CustomSelect;
diff --git a/packages/create-astro/src/components/Spacer.tsx b/packages/create-astro/src/components/Spacer.tsx
index 1e4e14561..15ef71d7c 100644
--- a/packages/create-astro/src/components/Spacer.tsx
+++ b/packages/create-astro/src/components/Spacer.tsx
@@ -1,5 +1,5 @@
import React, { FC } from 'react';
import { Box } from 'ink';
-const Spacer: FC<{ width?: number }> = ({ width = 8 }) => <Box width={width} />
+const Spacer: FC<{ width?: number }> = ({ width = 8 }) => <Box width={width} />;
export default Spacer;
diff --git a/packages/create-astro/src/components/Spinner.tsx b/packages/create-astro/src/components/Spinner.tsx
index 2d3335e1c..fa62b614f 100644
--- a/packages/create-astro/src/components/Spinner.tsx
+++ b/packages/create-astro/src/components/Spinner.tsx
@@ -6,14 +6,14 @@ const Spinner: FC<{ type?: keyof typeof spinners }> = ({ type = 'countdown' }) =
const [i, setI] = useState(0);
useEffect(() => {
const _ = setInterval(() => {
- setI(v => (v < frames.length - 1) ? v + 1 : 0)
- }, interval)
+ setI((v) => (v < frames.length - 1 ? v + 1 : 0));
+ }, interval);
return () => clearInterval(_);
- }, [])
+ }, []);
- return frames[i]
-}
+ return frames[i];
+};
const spinners = {
countdown: {
@@ -35,73 +35,73 @@ const spinners = {
<Text backgroundColor="#882DE7">{' '}</Text>
</Box>,
<Box display="flex">
- <Text backgroundColor="#6858F1">{' '}</Text>
+ <Text backgroundColor="#6858F1"> </Text>
<Text backgroundColor="#882DE7">{' '}</Text>
</Box>,
<Box display="flex">
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#6858F1"> </Text>
<Text backgroundColor="#882DE7">{' '}</Text>
</Box>,
<Box display="flex">
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#6858F1"> </Text>
<Text backgroundColor="#882DE7">{' '}</Text>
</Box>,
<Box display="flex">
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#6858F1"> </Text>
<Text backgroundColor="#882DE7">{' '}</Text>
</Box>,
<Box display="flex">
- <Text backgroundColor="#23B1AF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
+ <Text backgroundColor="#23B1AF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#6858F1"> </Text>
<Text backgroundColor="#882DE7">{' '}</Text>
</Box>,
- <Box display="flex">
- <Text backgroundColor="#17C083">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
- <Text backgroundColor="#882DE7">{' '}</Text>
+ <Box display="flex">
+ <Text backgroundColor="#17C083"> </Text>
+ <Text backgroundColor="#23B1AF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#6858F1"> </Text>
+ <Text backgroundColor="#882DE7"> </Text>
</Box>,
- <Box display="flex">
+ <Box display="flex">
<Text backgroundColor="#17C083">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
+ <Text backgroundColor="#23B1AF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#6858F1"> </Text>
</Box>,
- <Box display="flex">
+ <Box display="flex">
<Text backgroundColor="#17C083">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
+ <Text backgroundColor="#23B1AF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
</Box>,
<Box display="flex">
<Text backgroundColor="#17C083">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
+ <Text backgroundColor="#23B1AF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
</Box>,
<Box display="flex">
<Text backgroundColor="#17C083">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
+ <Text backgroundColor="#23B1AF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
</Box>,
<Box display="flex">
<Text backgroundColor="#17C083">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
+ <Text backgroundColor="#23B1AF"> </Text>
</Box>,
<Box display="flex">
<Text backgroundColor="#17C083">{' '}</Text>
@@ -122,79 +122,79 @@ const spinners = {
<Text backgroundColor="#17C083">{' '}</Text>
</Box>,
<Box display="flex">
- <Text backgroundColor="#23B1AF">{' '}</Text>
+ <Text backgroundColor="#23B1AF"> </Text>
<Text backgroundColor="#17C083">{' '}</Text>
</Box>,
<Box display="flex">
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#23B1AF"> </Text>
<Text backgroundColor="#17C083">{' '}</Text>
</Box>,
<Box display="flex">
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#23B1AF"> </Text>
<Text backgroundColor="#17C083">{' '}</Text>
</Box>,
<Box display="flex">
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#23B1AF"> </Text>
<Text backgroundColor="#17C083">{' '}</Text>
</Box>,
<Box display="flex">
- <Text backgroundColor="#6858F1">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
+ <Text backgroundColor="#6858F1"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#23B1AF"> </Text>
<Text backgroundColor="#17C083">{' '}</Text>
</Box>,
<Box display="flex">
- <Text backgroundColor="#882DE7">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
- <Text backgroundColor="#17C083">{' '}</Text>
+ <Text backgroundColor="#882DE7"> </Text>
+ <Text backgroundColor="#6858F1"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#23B1AF"> </Text>
+ <Text backgroundColor="#17C083"> </Text>
</Box>,
<Box display="flex">
<Text backgroundColor="#882DE7">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
- <Text backgroundColor="#23B1AF">{' '}</Text>
+ <Text backgroundColor="#6858F1"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
+ <Text backgroundColor="#23B1AF"> </Text>
</Box>,
<Box display="flex">
<Text backgroundColor="#882DE7">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
- <Text backgroundColor="#2CA5D2">{' '}</Text>
+ <Text backgroundColor="#6858F1"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
+ <Text backgroundColor="#2CA5D2"> </Text>
</Box>,
<Box display="flex">
<Text backgroundColor="#882DE7">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
- <Text backgroundColor="#3894FF">{' '}</Text>
+ <Text backgroundColor="#6858F1"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
+ <Text backgroundColor="#3894FF"> </Text>
</Box>,
<Box display="flex">
<Text backgroundColor="#882DE7">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
- <Text backgroundColor="#5076F9">{' '}</Text>
+ <Text backgroundColor="#6858F1"> </Text>
+ <Text backgroundColor="#5076F9"> </Text>
</Box>,
<Box display="flex">
<Text backgroundColor="#882DE7">{' '}</Text>
- <Text backgroundColor="#6858F1">{' '}</Text>
+ <Text backgroundColor="#6858F1"> </Text>
</Box>,
<Box display="flex">
<Text backgroundColor="#882DE7">{' '}</Text>
</Box>,
- ]
- }
-}
+ ],
+ },
+};
export default Spinner;
diff --git a/packages/create-astro/src/components/Template.tsx b/packages/create-astro/src/components/Template.tsx
index 7fbab035d..23ff905f2 100644
--- a/packages/create-astro/src/components/Template.tsx
+++ b/packages/create-astro/src/components/Template.tsx
@@ -3,7 +3,7 @@ import { Box, Text } from 'ink';
import Spacer from './Spacer';
import Select from './Select';
-const Template: FC<{ context: any, onSubmit: (value: string) => void }> = ({ context: { templates }, onSubmit }) => {
+const Template: FC<{ context: any; onSubmit: (value: string) => void }> = ({ context: { templates }, onSubmit }) => {
const items = templates.map(({ title: label, ...rest }) => ({ ...rest, label }));
return (
diff --git a/packages/create-astro/src/config.ts b/packages/create-astro/src/config.ts
index 3d3c07912..8216fd1ab 100644
--- a/packages/create-astro/src/config.ts
+++ b/packages/create-astro/src/config.ts
@@ -1,49 +1,49 @@
import type * as arg from 'arg';
export interface ARG {
- type: any;
- description: string;
- enum?: string[];
- alias?: string;
+ type: any;
+ description: string;
+ enum?: string[];
+ alias?: string;
}
export const ARGS: Record<string, ARG> = {
- 'template': {
- type: String,
- description: 'specifies template to use'
- },
- 'use': {
- type: String,
- enum: ['npm', 'yarn'],
- description: 'specifies package manager to use'
- },
- 'run': {
- type: Boolean,
- description: 'should dependencies be installed automatically?'
- },
- 'force': {
- type: Boolean,
- alias: 'f',
- description: 'should existing files be overwritten?'
- },
- 'version': {
- type: Boolean,
- alias: 'v',
- description: 'prints current version'
- },
- 'help': {
- type: Boolean,
- alias: 'h',
- description: 'prints this message'
- }
-}
+ template: {
+ type: String,
+ description: 'specifies template to use',
+ },
+ use: {
+ type: String,
+ enum: ['npm', 'yarn'],
+ description: 'specifies package manager to use',
+ },
+ run: {
+ type: Boolean,
+ description: 'should dependencies be installed automatically?',
+ },
+ force: {
+ type: Boolean,
+ alias: 'f',
+ description: 'should existing files be overwritten?',
+ },
+ version: {
+ type: Boolean,
+ alias: 'v',
+ description: 'prints current version',
+ },
+ help: {
+ type: Boolean,
+ alias: 'h',
+ description: 'prints this message',
+ },
+};
export const args = Object.entries(ARGS).reduce((acc, [name, info]) => {
- const key = `--${name}`;
- const spec = { ...acc, [key]: info.type };
+ const key = `--${name}`;
+ const spec = { ...acc, [key]: info.type };
- if (info.alias) {
- spec[`-${info.alias}`] = key;
- }
- return spec
+ if (info.alias) {
+ spec[`-${info.alias}`] = key;
+ }
+ return spec;
}, {} as arg.Spec);
diff --git a/packages/create-astro/src/index.tsx b/packages/create-astro/src/index.tsx
index 0927eaae9..9a510d7b7 100644
--- a/packages/create-astro/src/index.tsx
+++ b/packages/create-astro/src/index.tsx
@@ -3,7 +3,7 @@ import React from 'react';
import App from './components/App';
import Version from './components/Version';
import Exit from './components/Exit';
-import {render} from 'ink';
+import { render } from 'ink';
import { getTemplates, addProcessListeners } from './utils';
import { args as argsConfig } from './config';
import arg from 'arg';
@@ -11,36 +11,36 @@ import Help from './components/Help';
/** main `create-astro` CLI */
export default async function createAstro() {
- const args = arg(argsConfig);
- const projectName = args._[0];
- if (args['--version']) {
- return render(<Version />);
- }
- const templates = await getTemplates();
- if (args['--help']) {
- return render(<Help context={{ templates }} />)
- }
+ const args = arg(argsConfig);
+ const projectName = args._[0];
+ if (args['--version']) {
+ return render(<Version />);
+ }
+ const templates = await getTemplates();
+ if (args['--help']) {
+ return render(<Help context={{ templates }} />);
+ }
- const pkgManager = /yarn/.test(process.env.npm_execpath) ? 'yarn' : 'npm';
- const use = (args['--use'] ?? pkgManager) as 'npm'|'yarn';
- const template = args['--template'];
- const force = args['--force'];
- const run = args['--run'] ?? true;
-
- const app = render(<App context={{ projectName, template, templates, force, run, use }} />);
+ const pkgManager = /yarn/.test(process.env.npm_execpath) ? 'yarn' : 'npm';
+ const use = (args['--use'] ?? pkgManager) as 'npm' | 'yarn';
+ const template = args['--template'];
+ const force = args['--force'];
+ const run = args['--run'] ?? true;
- const onError = () => {
- if (app) app.clear();
- render(<Exit didError />);
- }
- const onExit = () => {
- if (app) app.clear();
- render(<Exit />);
- }
- addProcessListeners([
- ['uncaughtException', onError],
- ['exit', onExit],
- ['SIGINT', onExit],
- ['SIGTERM', onExit],
- ])
+ const app = render(<App context={{ projectName, template, templates, force, run, use }} />);
+
+ const onError = () => {
+ if (app) app.clear();
+ render(<Exit didError />);
+ };
+ const onExit = () => {
+ if (app) app.clear();
+ render(<Exit />);
+ };
+ addProcessListeners([
+ ['uncaughtException', onError],
+ ['exit', onExit],
+ ['SIGINT', onExit],
+ ['SIGTERM', onExit],
+ ]);
}
diff --git a/packages/create-astro/src/templates/blank/meta.json b/packages/create-astro/src/templates/blank/meta.json
index ca942e99f..41a259d53 100644
--- a/packages/create-astro/src/templates/blank/meta.json
+++ b/packages/create-astro/src/templates/blank/meta.json
@@ -1,4 +1,4 @@
{
- "title": "Blank",
- "description": "a bare-bones, ultra-minimal template"
+ "title": "Blank",
+ "description": "a bare-bones, ultra-minimal template"
}
diff --git a/packages/create-astro/src/templates/starter/README.md b/packages/create-astro/src/templates/starter/README.md
index 59940918f..70ff237f6 100644
--- a/packages/create-astro/src/templates/starter/README.md
+++ b/packages/create-astro/src/templates/starter/README.md
@@ -20,10 +20,8 @@ Inside of your Astro project, you'll see the following folders and files:
```
Astro looks for `.astro` or `.md.astro` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
-
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
-
Any static assets, like images, can be placed in the `public/` directory.
diff --git a/packages/create-astro/src/templates/starter/meta.json b/packages/create-astro/src/templates/starter/meta.json
index ba775af32..e9f3778c7 100644
--- a/packages/create-astro/src/templates/starter/meta.json
+++ b/packages/create-astro/src/templates/starter/meta.json
@@ -1,5 +1,5 @@
{
- "title": "Getting Started",
- "description": "a friendly starting point for new astronauts",
- "rank": 999
+ "title": "Getting Started",
+ "description": "a friendly starting point for new astronauts",
+ "rank": 999
}
diff --git a/packages/create-astro/src/utils.ts b/packages/create-astro/src/utils.ts
index 790a64cf9..52e56f5f0 100644
--- a/packages/create-astro/src/utils.ts
+++ b/packages/create-astro/src/utils.ts
@@ -6,8 +6,8 @@ import decompress from 'decompress';
const listeners = new Map();
-export async function addProcessListeners(handlers: [NodeJS.Signals|string, NodeJS.SignalsListener][]) {
- for (const [event,handler] of handlers) {
+export async function addProcessListeners(handlers: [NodeJS.Signals | string, NodeJS.SignalsListener][]) {
+ for (const [event, handler] of handlers) {
listeners.set(event, handler);
process.once(event as NodeJS.Signals, handler);
}
@@ -21,18 +21,20 @@ export async function cancelProcessListeners() {
}
export async function getTemplates() {
- const templatesRoot = fileURLToPath(new URL('./templates', import.meta.url));
- const templateFiles = await fs.readdir(templatesRoot, 'utf8');
- const templates = templateFiles.filter(t => t.endsWith('.tgz'));
- const metafile = templateFiles.find(t => t.endsWith('meta.json'));
+ const templatesRoot = fileURLToPath(new URL('./templates', import.meta.url));
+ const templateFiles = await fs.readdir(templatesRoot, 'utf8');
+ const templates = templateFiles.filter((t) => t.endsWith('.tgz'));
+ const metafile = templateFiles.find((t) => t.endsWith('meta.json'));
- const meta = await fs.readFile(resolve(templatesRoot, metafile)).then(r => JSON.parse(r.toString()));
+ const meta = await fs.readFile(resolve(templatesRoot, metafile)).then((r) => JSON.parse(r.toString()));
- return templates.map(template => {
+ return templates
+ .map((template) => {
const value = basename(template, '.tgz');
if (meta[value]) return { ...meta[value], value };
return { value };
- }).sort((a, b) => {
+ })
+ .sort((a, b) => {
const aRank = a.rank ?? 0;
const bRank = b.rank ?? 0;
if (aRank > bRank) return -1;
@@ -49,28 +51,29 @@ export async function rewriteFiles(projectName: string) {
const tasks = [];
tasks.push(fs.rename(resolve(dest, '_gitignore'), resolve(dest, '.gitignore')));
tasks.push(
- fs.readFile(resolve(dest, 'package.json'))
- .then(res => JSON.parse(res.toString()))
- .then(json => JSON.stringify({ ...json, name: getValidPackageName(projectName) }, null, 2))
- .then(res => fs.writeFile(resolve(dest, 'package.json'), res))
+ fs
+ .readFile(resolve(dest, 'package.json'))
+ .then((res) => JSON.parse(res.toString()))
+ .then((json) => JSON.stringify({ ...json, name: getValidPackageName(projectName) }, null, 2))
+ .then((res) => fs.writeFile(resolve(dest, 'package.json'), res))
);
return Promise.all(tasks);
}
-export async function prepareTemplate(use: 'npm'|'yarn', name: string, dest: string) {
- const projectName = dest;
- dest = resolve(dest);
- const template = fileURLToPath(new URL(`./templates/${name}.tgz`, import.meta.url));
- await decompress(template, dest);
- await rewriteFiles(projectName);
- try {
- await run(use, use === 'npm' ? 'i' : null, dest);
- } catch (e) {
- cleanup(true);
- }
- isDone = true;
- return;
+export async function prepareTemplate(use: 'npm' | 'yarn', name: string, dest: string) {
+ const projectName = dest;
+ dest = resolve(dest);
+ const template = fileURLToPath(new URL(`./templates/${name}.tgz`, import.meta.url));
+ await decompress(template, dest);
+ await rewriteFiles(projectName);
+ try {
+ await run(use, use === 'npm' ? 'i' : null, dest);
+ } catch (e) {
+ cleanup(true);
+ }
+ isDone = true;
+ return;
}
export function cleanup(didError = false) {
@@ -81,10 +84,10 @@ export function cleanup(didError = false) {
}
export function killChildren() {
- childrenProcesses.forEach(p => p.kill('SIGINT'));
+ childrenProcesses.forEach((p) => p.kill('SIGINT'));
}
-export function run(pkgManager: 'npm'|'yarn', command: string, projectPath: string, stdio: any = 'ignore'): Promise<void> {
+export function run(pkgManager: 'npm' | 'yarn', command: string, projectPath: string, stdio: any = 'ignore'): Promise<void> {
return new Promise((resolve, reject) => {
const p = spawn(pkgManager, command ? [command] : [], {
shell: true,
@@ -102,40 +105,40 @@ export function isWin() {
}
export function isEmpty(path) {
- try {
- const files = readdirSync(resolve(path));
- if (files.length > 0) {
- return false;
- } else {
- return true;
- }
- } catch (err) {
- if (err.code !== 'ENOENT') throw err;
+ try {
+ const files = readdirSync(resolve(path));
+ if (files.length > 0) {
+ return false;
+ } else {
+ return true;
}
- return true;
+ } catch (err) {
+ if (err.code !== 'ENOENT') throw err;
+ }
+ return true;
}
export function emptyDir(dir) {
dir = resolve(dir);
if (!existsSync(dir)) {
- return
+ return;
}
for (const file of readdirSync(dir)) {
- const abs = resolve(dir, file)
+ const abs = resolve(dir, file);
if (lstatSync(abs).isDirectory()) {
- emptyDir(abs)
- rmdirSync(abs)
+ emptyDir(abs);
+ rmdirSync(abs);
} else {
- unlinkSync(abs)
+ unlinkSync(abs);
}
}
}
export function getValidPackageName(projectName: string) {
- const packageNameRegExp = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/
+ const packageNameRegExp = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
if (packageNameRegExp.test(projectName)) {
- return projectName
+ return projectName;
}
return projectName
diff --git a/scripts/package.json b/scripts/package.json
index 4ece70b11..ed2142e0d 100644
--- a/scripts/package.json
+++ b/scripts/package.json
@@ -1,16 +1,16 @@
{
- "name": "astro-scripts",
- "version": "0.0.1",
- "private": true,
- "type": "module",
- "main": "./index.js",
- "bin": {
- "astro-scripts": "./index.js"
- },
- "dependencies": {
- "arg": "^5.0.0",
- "esbuild": "^0.11.16",
- "globby": "^11.0.3",
- "tar": "^6.1.0"
- }
+ "name": "astro-scripts",
+ "version": "0.0.1",
+ "private": true,
+ "type": "module",
+ "main": "./index.js",
+ "bin": {
+ "astro-scripts": "./index.js"
+ },
+ "dependencies": {
+ "arg": "^5.0.0",
+ "esbuild": "^0.11.16",
+ "globby": "^11.0.3",
+ "tar": "^6.1.0"
+ }
}
diff --git a/scripts/utils/svelte-plugin.js b/scripts/utils/svelte-plugin.js
index 84839ffd7..cd65a5fdf 100644
--- a/scripts/utils/svelte-plugin.js
+++ b/scripts/utils/svelte-plugin.js
@@ -4,57 +4,58 @@ import { relative, isAbsolute, join, dirname } from 'path';
import { promises as fs } from 'fs';
const convertMessage = ({ message, start, end, filename, frame }) => ({
- text: message,
- location: start && end && {
- file: filename,
- line: start.line,
- column: start.column,
- length: start.line === end.line ? end.column - start.column : 0,
- lineText: frame,
+ text: message,
+ location: start &&
+ end && {
+ file: filename,
+ line: start.line,
+ column: start.column,
+ length: start.line === end.line ? end.column - start.column : 0,
+ lineText: frame,
},
-})
+});
const handleLoad = async (args, generate) => {
- const { path } = args;
- const source = await fs.readFile(path, 'utf8');
- const filename = relative(process.cwd(), path)
+ const { path } = args;
+ const source = await fs.readFile(path, 'utf8');
+ const filename = relative(process.cwd(), path);
- try {
- let compileOptions = { css: false, generate, hydratable: true };
+ try {
+ let compileOptions = { css: false, generate, hydratable: true };
- let { js, warnings } = compile(source, { ...compileOptions, filename })
- let contents = js.code + `\n//# sourceMappingURL=` + js.map.toUrl()
+ let { js, warnings } = compile(source, { ...compileOptions, filename });
+ let contents = js.code + `\n//# sourceMappingURL=` + js.map.toUrl();
- return { loader: 'js', contents, resolveDir: dirname(path), warnings: warnings.map(w => convertMessage(w)) };
- } catch (e) {
- return { errors: [convertMessage(e)] }
- }
-}
+ return { loader: 'js', contents, resolveDir: dirname(path), warnings: warnings.map((w) => convertMessage(w)) };
+ } catch (e) {
+ return { errors: [convertMessage(e)] };
+ }
+};
export default function sveltePlugin() {
- return {
- name: 'svelte-esbuild',
- setup(build) {
- build.onResolve({ filter: /\.svelte$/ }, args => {
- let path = args.path.replace(/\.(?:client|server)/, '');
- path = isAbsolute(path) ? path : join(args.resolveDir, path)
-
- if (/\.client\.svelte$/.test(args.path)) {
- return {
- path,
- namespace: 'svelte:client',
- }
- }
-
- if (/\.server\.svelte$/.test(args.path)) {
- return {
- path,
- namespace: 'svelte:server',
- }
- }
- });
- build.onLoad({ filter: /.*/, namespace: 'svelte:client' }, (args) => handleLoad(args, 'dom'))
- build.onLoad({ filter: /.*/, namespace: 'svelte:server' }, (args) => handleLoad(args, 'ssr'))
- },
- }
+ return {
+ name: 'svelte-esbuild',
+ setup(build) {
+ build.onResolve({ filter: /\.svelte$/ }, (args) => {
+ let path = args.path.replace(/\.(?:client|server)/, '');
+ path = isAbsolute(path) ? path : join(args.resolveDir, path);
+
+ if (/\.client\.svelte$/.test(args.path)) {
+ return {
+ path,
+ namespace: 'svelte:client',
+ };
+ }
+
+ if (/\.server\.svelte$/.test(args.path)) {
+ return {
+ path,
+ namespace: 'svelte:server',
+ };
+ }
+ });
+ build.onLoad({ filter: /.*/, namespace: 'svelte:client' }, (args) => handleLoad(args, 'dom'));
+ build.onLoad({ filter: /.*/, namespace: 'svelte:server' }, (args) => handleLoad(args, 'ssr'));
+ },
+ };
}
diff --git a/tools/prettier-plugin-astro/index.js b/tools/prettier-plugin-astro/index.js
index 54163459c..8bfdcd3e8 100644
--- a/tools/prettier-plugin-astro/index.js
+++ b/tools/prettier-plugin-astro/index.js
@@ -42,7 +42,7 @@ module.exports.parsers = {
return node.end;
},
astFormat: 'astro-expression',
- }
+ },
};
const findExpressionsInAST = (node, collect = []) => {
@@ -50,24 +50,24 @@ const findExpressionsInAST = (node, collect = []) => {
return collect.concat(node);
}
if (node.children) {
- collect.push(...[].concat(...node.children.map(child => findExpressionsInAST(child))));
+ collect.push(...[].concat(...node.children.map((child) => findExpressionsInAST(child))));
}
return collect;
-}
+};
-const formatExpression = ({ expression: { codeChunks, children }}, text, options) => {
+const formatExpression = ({ expression: { codeChunks, children } }, text, options) => {
if (children.length === 0) {
const codeStart = codeChunks[0]; // If no children, there should only exist a single chunk.
if (codeStart && [`'`, `"`].includes(codeStart[0])) {
- return `<script $ lang="ts">${codeChunks.join('')}</script>`
+ return `<script $ lang="ts">${codeChunks.join('')}</script>`;
}
return `{${codeChunks.join('')}}`;
}
return `<script $ lang="ts">${text}</script>`;
-}
+};
-const isAstroScript = (node) => node.type === 'concat' && node.parts[0] === '<script' && node.parts[1].type === 'indent' && node.parts[1].contents.parts.find(v => v === '$');
+const isAstroScript = (node) => node.type === 'concat' && node.parts[0] === '<script' && node.parts[1].type === 'indent' && node.parts[1].contents.parts.find((v) => v === '$');
const walkDoc = (doc) => {
let inAstroScript = false;
@@ -77,38 +77,38 @@ const walkDoc = (doc) => {
inAstroScript = true;
parent.contents = { type: 'concat', parts: ['{'] };
}
- return node.parts.map(part => recurse(part, { parent: node }));
+ return node.parts.map((part) => recurse(part, { parent: node }));
}
if (inAstroScript) {
if (node.type === 'break-parent') {
- parent.parts = parent.parts.filter(part => !['break-parent', 'line'].includes(part.type));
+ parent.parts = parent.parts.filter((part) => !['break-parent', 'line'].includes(part.type));
}
if (node.type === 'indent') {
- parent.parts = parent.parts.map(part => {
+ parent.parts = parent.parts.map((part) => {
if (part.type !== 'indent') return part;
return {
type: 'concat',
- parts: [part.contents]
- }
- })
+ parts: [part.contents],
+ };
+ });
}
if (typeof node === 'string' && node.endsWith(';')) {
- parent.parts = parent.parts.map(part => {
+ parent.parts = parent.parts.map((part) => {
if (typeof part === 'string' && part.endsWith(';')) return part.slice(0, -1);
return part;
});
}
if (node === '</script>') {
- parent.parts = parent.parts.map(part => part === '</script>' ? '}' : part);
+ parent.parts = parent.parts.map((part) => (part === '</script>' ? '}' : part));
inAstroScript = false;
}
}
if (['group', 'indent'].includes(node.type)) {
return recurse(node.contents, { parent: node });
}
- }
+ };
recurse(doc, { parent: null });
-}
+};
/** @type {Record<string, import('prettier').Printer>} */
module.exports.printers = {
@@ -129,18 +129,20 @@ module.exports.printers = {
if (node.type === 'Fragment' && node.isRoot) {
const expressions = findExpressionsInAST(node);
if (expressions.length > 0) {
- const parts = [].concat(...expressions.map((expr, i, all) => {
- const prev = all[i - 1];
- const start = node.text.slice((prev?.end ?? node.start) - node.start, expr.start - node.start);
- const exprText = formatExpression(expr, node.text.slice(expr.start - node.start + 1, expr.end - node.start - 1), options);
+ const parts = [].concat(
+ ...expressions.map((expr, i, all) => {
+ const prev = all[i - 1];
+ const start = node.text.slice((prev?.end ?? node.start) - node.start, expr.start - node.start);
+ const exprText = formatExpression(expr, node.text.slice(expr.start - node.start + 1, expr.end - node.start - 1), options);
- if (i === all.length - 1) {
- const end = node.text.slice(expr.end - node.start);
- return [start, exprText, end]
- }
+ if (i === all.length - 1) {
+ const end = node.text.slice(expr.end - node.start);
+ return [start, exprText, end];
+ }
- return [start, exprText]
- }));
+ return [start, exprText];
+ })
+ );
const html = parts.join('\n');
const doc = textToDoc(html, { parser: 'html' });
walkDoc(doc);
diff --git a/tools/prettier-plugin-astro/test/astro-prettier.test.js b/tools/prettier-plugin-astro/test/astro-prettier.test.js
index 99ece2a30..cf0f0c87c 100644
--- a/tools/prettier-plugin-astro/test/astro-prettier.test.js
+++ b/tools/prettier-plugin-astro/test/astro-prettier.test.js
@@ -2,10 +2,10 @@ import { suite } from 'uvu';
import * as assert from 'uvu/assert';
import { format } from './test-utils.js';
import { promises as fs } from 'fs';
-import { fileURLToPath } from 'url'
+import { fileURLToPath } from 'url';
const Prettier = suite('Prettier formatting');
-const readFile = (path) => fs.readFile(fileURLToPath(new URL(`./fixtures${path}`, import.meta.url))).then(res => res.toString())
+const readFile = (path) => fs.readFile(fileURLToPath(new URL(`./fixtures${path}`, import.meta.url))).then((res) => res.toString());
/**
* Utility to get `[src, out]` files
diff --git a/tools/prettier-plugin-astro/test/package.json b/tools/prettier-plugin-astro/test/package.json
index 472002573..3dbc1ca59 100644
--- a/tools/prettier-plugin-astro/test/package.json
+++ b/tools/prettier-plugin-astro/test/package.json
@@ -1,3 +1,3 @@
{
- "type": "module"
+ "type": "module"
}
diff --git a/tools/vscode/languages/astro-language-configuration.json b/tools/vscode/languages/astro-language-configuration.json
index a6e9cae46..fef8c8c7b 100644
--- a/tools/vscode/languages/astro-language-configuration.json
+++ b/tools/vscode/languages/astro-language-configuration.json
@@ -1,36 +1,36 @@
{
- "comments": {
- "blockComment": [ "<!--", "-->" ]
- },
- "brackets": [
- ["---", "---"],
- ["<!--", "-->"],
- ["<", ">"],
- ["{", "}"],
- ["(", ")"]
- ],
- "autoClosingPairs": [
- { "open": "{", "close": "}"},
- { "open": "[", "close": "]"},
- { "open": "(", "close": ")" },
- { "open": "'", "close": "'" },
- { "open": "\"", "close": "\"" },
- { "open": "<!--", "close": "-->", "notIn": [ "comment", "string" ]},
- { "open": "/**", "close": " */", "notIn": ["string"] }
- ],
- "autoCloseBefore": ";:.,=}])>` \n\t",
- "surroundingPairs": [
- { "open": "'", "close": "'" },
- { "open": "\"", "close": "\"" },
- { "open": "{", "close": "}"},
- { "open": "[", "close": "]"},
- { "open": "(", "close": ")" },
- { "open": "<", "close": ">" }
- ],
- "folding": {
- "markers": {
- "start": "^\\s*<!--\\s*#region\\b.*-->",
- "end": "^\\s*<!--\\s*#endregion\\b.*-->"
- }
- }
+ "comments": {
+ "blockComment": ["<!--", "-->"]
+ },
+ "brackets": [
+ ["---", "---"],
+ ["<!--", "-->"],
+ ["<", ">"],
+ ["{", "}"],
+ ["(", ")"]
+ ],
+ "autoClosingPairs": [
+ { "open": "{", "close": "}" },
+ { "open": "[", "close": "]" },
+ { "open": "(", "close": ")" },
+ { "open": "'", "close": "'" },
+ { "open": "\"", "close": "\"" },
+ { "open": "<!--", "close": "-->", "notIn": ["comment", "string"] },
+ { "open": "/**", "close": " */", "notIn": ["string"] }
+ ],
+ "autoCloseBefore": ";:.,=}])>` \n\t",
+ "surroundingPairs": [
+ { "open": "'", "close": "'" },
+ { "open": "\"", "close": "\"" },
+ { "open": "{", "close": "}" },
+ { "open": "[", "close": "]" },
+ { "open": "(", "close": ")" },
+ { "open": "<", "close": ">" }
+ ],
+ "folding": {
+ "markers": {
+ "start": "^\\s*<!--\\s*#region\\b.*-->",
+ "end": "^\\s*<!--\\s*#endregion\\b.*-->"
+ }
+ }
}
diff --git a/tools/vscode/package.json b/tools/vscode/package.json
index 75e1eb507..f663d8bcb 100644
--- a/tools/vscode/package.json
+++ b/tools/vscode/package.json
@@ -1,96 +1,96 @@
{
- "name": "@astro.build/vscode",
- "displayName": "Astro",
- "description": "Language support for Astro",
- "icon": "assets/icon.png",
- "galleryBanner": {
- "color": "#FF5D01",
- "theme": "dark"
- },
- "version": "0.3.0",
- "author": "Astro",
- "publisher": "astro-build",
- "license": "MIT",
- "scripts": {
- "vscode:prepublish": "npm run build",
- "bootstrap": "cd packages/client && yarn && cd ../server && yarn",
- "build": "node scripts/build.mjs",
- "watch": "node scripts/watch.mjs"
- },
- "engines": {
- "vscode": "^1.52.0"
- },
- "activationEvents": [
- "onLanguage:astro"
- ],
- "dependencies": {
- "vscode-html-languageservice": "^3.0.3",
- "vscode-emmet-helper": "2.1.2"
- },
- "devDependencies": {
- "esbuild": "0.10.0",
- "@astro-vscode/client": "file:./packages/client",
- "@astro-vscode/server": "file:./packages/server"
- },
- "main": "./dist/index.js",
- "files": [
- "dist/",
- "languages/",
- "syntaxes/"
- ],
- "repository": {
- "type": "git",
- "directory": "vscode",
- "url": "https://github.com/snowpackjs/astro"
- },
- "contributes": {
- "configuration": {
- "type": "object",
- "title": "Astro configuration",
- "properties": {
- "astro.trace.server": {
- "scope": "window",
- "type": "string",
- "enum": [
- "off",
- "messages",
- "verbose"
- ],
- "default": "off",
- "description": "Traces the communication between VS Code and the language server."
- }
- }
- },
- "languages": [
- {
- "id": "astro",
- "extensions": [
- ".astro"
- ],
- "aliases": [
- "Astro"
- ],
- "configuration": "./languages/astro-language-configuration.json"
- }
- ],
- "grammars": [
- {
- "language": "astro",
- "scopeName": "text.html.astro",
- "path": "./syntaxes/astro.tmLanguage.json",
- "injectTo": [
- "text.html.markdown"
- ],
- "embeddedLanguages": {
- "text.html.astro": "astro",
- "text.html": "html",
- "source.css": "css",
- "source.scss": "scss",
- "source.sass": "sass",
- "source.tsx": "typescriptreact",
- "meta.embedded.block.frontmatter": "typescriptreact"
- }
- }
- ]
- }
+ "name": "@astro.build/vscode",
+ "displayName": "Astro",
+ "description": "Language support for Astro",
+ "icon": "assets/icon.png",
+ "galleryBanner": {
+ "color": "#FF5D01",
+ "theme": "dark"
+ },
+ "version": "0.3.0",
+ "author": "Astro",
+ "publisher": "astro-build",
+ "license": "MIT",
+ "scripts": {
+ "vscode:prepublish": "npm run build",
+ "bootstrap": "cd packages/client && yarn && cd ../server && yarn",
+ "build": "node scripts/build.mjs",
+ "watch": "node scripts/watch.mjs"
+ },
+ "engines": {
+ "vscode": "^1.52.0"
+ },
+ "activationEvents": [
+ "onLanguage:astro"
+ ],
+ "dependencies": {
+ "vscode-html-languageservice": "^3.0.3",
+ "vscode-emmet-helper": "2.1.2"
+ },
+ "devDependencies": {
+ "esbuild": "0.10.0",
+ "@astro-vscode/client": "file:./packages/client",
+ "@astro-vscode/server": "file:./packages/server"
+ },
+ "main": "./dist/index.js",
+ "files": [
+ "dist/",
+ "languages/",
+ "syntaxes/"
+ ],
+ "repository": {
+ "type": "git",
+ "directory": "vscode",
+ "url": "https://github.com/snowpackjs/astro"
+ },
+ "contributes": {
+ "configuration": {
+ "type": "object",
+ "title": "Astro configuration",
+ "properties": {
+ "astro.trace.server": {
+ "scope": "window",
+ "type": "string",
+ "enum": [
+ "off",
+ "messages",
+ "verbose"
+ ],
+ "default": "off",
+ "description": "Traces the communication between VS Code and the language server."
+ }
+ }
+ },
+ "languages": [
+ {
+ "id": "astro",
+ "extensions": [
+ ".astro"
+ ],
+ "aliases": [
+ "Astro"
+ ],
+ "configuration": "./languages/astro-language-configuration.json"
+ }
+ ],
+ "grammars": [
+ {
+ "language": "astro",
+ "scopeName": "text.html.astro",
+ "path": "./syntaxes/astro.tmLanguage.json",
+ "injectTo": [
+ "text.html.markdown"
+ ],
+ "embeddedLanguages": {
+ "text.html.astro": "astro",
+ "text.html": "html",
+ "source.css": "css",
+ "source.scss": "scss",
+ "source.sass": "sass",
+ "source.tsx": "typescriptreact",
+ "meta.embedded.block.frontmatter": "typescriptreact"
+ }
+ }
+ ]
+ }
}
diff --git a/tools/vscode/packages/client/package.json b/tools/vscode/packages/client/package.json
index 3a693790d..991f538dc 100644
--- a/tools/vscode/packages/client/package.json
+++ b/tools/vscode/packages/client/package.json
@@ -1,12 +1,12 @@
{
- "name": "@astro-vscode/client",
- "version": "0.1.0",
- "author": "Skypack",
- "license": "MIT",
- "dependencies": {
- "vscode-languageclient": "next"
- },
- "devDependencies": {
- "@types/vscode": "latest"
- }
+ "name": "@astro-vscode/client",
+ "version": "0.1.0",
+ "author": "Skypack",
+ "license": "MIT",
+ "dependencies": {
+ "vscode-languageclient": "next"
+ },
+ "devDependencies": {
+ "@types/vscode": "latest"
+ }
}
diff --git a/tools/vscode/packages/client/src/html/autoClose.ts b/tools/vscode/packages/client/src/html/autoClose.ts
index 0dbce66c8..a3b90f615 100644
--- a/tools/vscode/packages/client/src/html/autoClose.ts
+++ b/tools/vscode/packages/client/src/html/autoClose.ts
@@ -12,97 +12,78 @@ import { TextDocumentContentChangeEvent } from 'vscode-languageserver-protocol';
/** */
export function activateTagClosing(
- tagProvider: (document: TextDocument, position: Position) => Thenable<string>,
- supportedLanguages: { [id: string]: boolean },
- configName: string
+ tagProvider: (document: TextDocument, position: Position) => Thenable<string>,
+ supportedLanguages: { [id: string]: boolean },
+ configName: string
): Disposable {
- const disposables: Disposable[] = [];
- workspace.onDidChangeTextDocument(
- (event) => onDidChangeTextDocument(event.document, event.contentChanges),
- null,
- disposables
- );
+ const disposables: Disposable[] = [];
+ workspace.onDidChangeTextDocument((event) => onDidChangeTextDocument(event.document, event.contentChanges), null, disposables);
- let isEnabled = false;
- updateEnabledState();
- window.onDidChangeActiveTextEditor(updateEnabledState, null, disposables);
+ let isEnabled = false;
+ updateEnabledState();
+ window.onDidChangeActiveTextEditor(updateEnabledState, null, disposables);
- let timeout: NodeJS.Timer | undefined = void 0;
+ let timeout: NodeJS.Timer | undefined = void 0;
- /** Check if this feature is enabled */
- function updateEnabledState() {
- isEnabled = false;
- const editor = window.activeTextEditor;
- if (!editor) {
- return;
- }
- const document = editor.document;
- if (!supportedLanguages[document.languageId]) {
- return;
- }
- if (!workspace.getConfiguration(void 0, document.uri).get<boolean>(configName)) {
- return;
- }
- isEnabled = true;
+ /** Check if this feature is enabled */
+ function updateEnabledState() {
+ isEnabled = false;
+ const editor = window.activeTextEditor;
+ if (!editor) {
+ return;
+ }
+ const document = editor.document;
+ if (!supportedLanguages[document.languageId]) {
+ return;
}
+ if (!workspace.getConfiguration(void 0, document.uri).get<boolean>(configName)) {
+ return;
+ }
+ isEnabled = true;
+ }
- /** Handle text document changes */
- function onDidChangeTextDocument(
- document: TextDocument,
- changes: readonly TextDocumentContentChangeEvent[]
- ) {
- if (!isEnabled) {
- return;
- }
- const activeDocument = window.activeTextEditor && window.activeTextEditor.document;
- if (document !== activeDocument || changes.length === 0) {
- return;
- }
- if (typeof timeout !== 'undefined') {
- clearTimeout(timeout);
- }
- const lastChange = changes[changes.length - 1];
- const lastCharacter = lastChange.text[lastChange.text.length - 1];
- if (
- ('range' in lastChange && (lastChange.rangeLength ?? 0) > 0) ||
- (lastCharacter !== '>' && lastCharacter !== '/')
- ) {
- return;
- }
- const rangeStart =
- 'range' in lastChange
- ? lastChange.range.start
- : new Position(0, document.getText().length);
- const version = document.version;
- timeout = setTimeout(() => {
- const position = new Position(
- rangeStart.line,
- rangeStart.character + lastChange.text.length
- );
- tagProvider(document, position).then((text) => {
- if (text && isEnabled) {
- const activeEditor = window.activeTextEditor;
- if (activeEditor) {
- const activeDocument = activeEditor.document;
- if (document === activeDocument && activeDocument.version === version) {
- const selections = activeEditor.selections;
- if (
- selections.length &&
- selections.some((s) => s.active.isEqual(position))
- ) {
- activeEditor.insertSnippet(
- new SnippetString(text),
- selections.map((s) => s.active)
- );
- } else {
- activeEditor.insertSnippet(new SnippetString(text), position);
- }
- }
- }
- }
- });
- timeout = void 0;
- }, 100);
+ /** Handle text document changes */
+ function onDidChangeTextDocument(document: TextDocument, changes: readonly TextDocumentContentChangeEvent[]) {
+ if (!isEnabled) {
+ return;
+ }
+ const activeDocument = window.activeTextEditor && window.activeTextEditor.document;
+ if (document !== activeDocument || changes.length === 0) {
+ return;
}
- return Disposable.from(...disposables);
+ if (typeof timeout !== 'undefined') {
+ clearTimeout(timeout);
+ }
+ const lastChange = changes[changes.length - 1];
+ const lastCharacter = lastChange.text[lastChange.text.length - 1];
+ if (('range' in lastChange && (lastChange.rangeLength ?? 0) > 0) || (lastCharacter !== '>' && lastCharacter !== '/')) {
+ return;
+ }
+ const rangeStart = 'range' in lastChange ? lastChange.range.start : new Position(0, document.getText().length);
+ const version = document.version;
+ timeout = setTimeout(() => {
+ const position = new Position(rangeStart.line, rangeStart.character + lastChange.text.length);
+ tagProvider(document, position).then((text) => {
+ if (text && isEnabled) {
+ const activeEditor = window.activeTextEditor;
+ if (activeEditor) {
+ const activeDocument = activeEditor.document;
+ if (document === activeDocument && activeDocument.version === version) {
+ const selections = activeEditor.selections;
+ if (selections.length && selections.some((s) => s.active.isEqual(position))) {
+ activeEditor.insertSnippet(
+ new SnippetString(text),
+ selections.map((s) => s.active)
+ );
+ } else {
+ activeEditor.insertSnippet(new SnippetString(text), position);
+ }
+ }
+ }
+ }
+ });
+ timeout = void 0;
+ }, 100);
+ }
+ return Disposable.from(...disposables);
}
diff --git a/tools/vscode/packages/client/tsconfig.json b/tools/vscode/packages/client/tsconfig.json
index 51e95f536..417801227 100644
--- a/tools/vscode/packages/client/tsconfig.json
+++ b/tools/vscode/packages/client/tsconfig.json
@@ -1,12 +1,10 @@
{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "outDir": "dist",
- "rootDir": "src",
- },
- "include": ["src"],
- "exclude": ["node_modules"],
- "references": [
- { "path": "../server" }
- ]
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "dist",
+ "rootDir": "src"
+ },
+ "include": ["src"],
+ "exclude": ["node_modules"],
+ "references": [{ "path": "../server" }]
}
diff --git a/tools/vscode/packages/server/src/core/config/ConfigManager.ts b/tools/vscode/packages/server/src/core/config/ConfigManager.ts
index 4c1c23b13..1e795ab96 100644
--- a/tools/vscode/packages/server/src/core/config/ConfigManager.ts
+++ b/tools/vscode/packages/server/src/core/config/ConfigManager.ts
@@ -1,13 +1,13 @@
import { VSCodeEmmetConfig } from 'vscode-emmet-helper';
export class ConfigManager {
- private emmetConfig: VSCodeEmmetConfig = {};
-
- updateEmmetConfig(config: VSCodeEmmetConfig): void {
- this.emmetConfig = config || {};
- }
+ private emmetConfig: VSCodeEmmetConfig = {};
- getEmmetConfig(): VSCodeEmmetConfig {
- return this.emmetConfig;
- }
+ updateEmmetConfig(config: VSCodeEmmetConfig): void {
+ this.emmetConfig = config || {};
+ }
+
+ getEmmetConfig(): VSCodeEmmetConfig {
+ return this.emmetConfig;
+ }
}
diff --git a/tools/vscode/packages/server/src/core/documents/Document.ts b/tools/vscode/packages/server/src/core/documents/Document.ts
index 4f90813ee..93217e891 100644
--- a/tools/vscode/packages/server/src/core/documents/Document.ts
+++ b/tools/vscode/packages/server/src/core/documents/Document.ts
@@ -7,153 +7,147 @@ import { parseHtml } from './parseHtml';
import { parseAstro, AstroDocument } from './parseAstro';
export class Document implements TextDocument {
-
- private content: string;
-
- languageId = 'astro';
- version = 0;
- html!: HTMLDocument;
- astro!: AstroDocument;
-
- constructor(public uri: string, text: string) {
- this.content = text;
- this.updateDocInfo();
+ private content: string;
+
+ languageId = 'astro';
+ version = 0;
+ html!: HTMLDocument;
+ astro!: AstroDocument;
+
+ constructor(public uri: string, text: string) {
+ this.content = text;
+ this.updateDocInfo();
+ }
+
+ private updateDocInfo() {
+ this.html = parseHtml(this.content);
+ this.astro = parseAstro(this.content);
+ }
+
+ setText(text: string) {
+ this.content = text;
+ this.version++;
+ this.updateDocInfo();
+ }
+
+ /**
+ * 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 {
+ const content = this.getText();
+ this.setText(content.slice(0, start) + text + content.slice(end));
+ }
+
+ getText(): string {
+ return this.content;
+ }
+
+ /**
+ * Get the line and character based on the offset
+ * @param offset The index of the position
+ */
+ positionAt(offset: number): Position {
+ offset = clamp(offset, 0, this.getTextLength());
+
+ const lineOffsets = this.getLineOffsets();
+ let low = 0;
+ let high = lineOffsets.length;
+ if (high === 0) {
+ return Position.create(0, offset);
}
- private updateDocInfo() {
- this.html = parseHtml(this.content);
- this.astro = parseAstro(this.content);
+ while (low < high) {
+ const mid = Math.floor((low + high) / 2);
+ if (lineOffsets[mid] > offset) {
+ high = mid;
+ } else {
+ low = mid + 1;
+ }
}
- setText(text: string) {
- this.content = text;
- this.version++;
- this.updateDocInfo();
+ // 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 Position.create(line, offset - lineOffsets[line]);
+ }
+
+ /**
+ * Get the index of the line and character position
+ * @param position Line and character position
+ */
+ offsetAt(position: Position): number {
+ const lineOffsets = this.getLineOffsets();
+
+ if (position.line >= lineOffsets.length) {
+ return this.getTextLength();
+ } else if (position.line < 0) {
+ return 0;
}
- /**
- * 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 {
- const content = this.getText();
- this.setText(content.slice(0, start) + text + content.slice(end));
+ const lineOffset = lineOffsets[position.line];
+ const nextLineOffset = position.line + 1 < lineOffsets.length ? lineOffsets[position.line + 1] : this.getTextLength();
+
+ return clamp(nextLineOffset, lineOffset, lineOffset + position.character);
+ }
+
+ getLineUntilOffset(offset: number): string {
+ const { line, character } = this.positionAt(offset);
+ return this.lines[line].slice(0, character);
+ }
+
+ private getLineOffsets() {
+ const lineOffsets = [];
+ const text = this.getText();
+ 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++;
+ }
}
- getText(): string {
- return this.content
- }
-
- /**
- * Get the line and character based on the offset
- * @param offset The index of the position
- */
- positionAt(offset: number): Position {
- offset = clamp(offset, 0, this.getTextLength());
-
- const lineOffsets = this.getLineOffsets();
- let low = 0;
- let high = lineOffsets.length;
- if (high === 0) {
- return Position.create(0, offset);
- }
-
- while (low < high) {
- const mid = Math.floor((low + high) / 2);
- if (lineOffsets[mid] > offset) {
- high = mid;
- } else {
- low = 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 Position.create(line, offset - lineOffsets[line]);
- }
-
- /**
- * Get the index of the line and character position
- * @param position Line and character position
- */
- offsetAt(position: Position): number {
- const lineOffsets = this.getLineOffsets();
-
- if (position.line >= lineOffsets.length) {
- return this.getTextLength();
- } else if (position.line < 0) {
- return 0;
- }
-
- const lineOffset = lineOffsets[position.line];
- const nextLineOffset =
- position.line + 1 < lineOffsets.length
- ? lineOffsets[position.line + 1]
- : this.getTextLength();
-
- return clamp(nextLineOffset, lineOffset, lineOffset + position.character);
- }
-
- getLineUntilOffset(offset: number): string {
- const { line, character } = this.positionAt(offset);
- return this.lines[line].slice(0, character);
- }
-
- private getLineOffsets() {
- const lineOffsets = [];
- const text = this.getText();
- 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;
- }
-
- /**
- * Get the length of the document's content
- */
- getTextLength(): number {
- return this.getText().length;
- }
-
- /**
- * Returns the file path if the url scheme is file
- */
- getFilePath(): string | null {
- return urlToPath(this.uri);
- }
-
- /**
- * Get URL file path.
- */
- getURL() {
- return this.uri;
- }
-
-
- get lines(): string[] {
- return this.getText().split(/\r?\n/);
- }
-
- get lineCount(): number {
- return this.lines.length;
+ if (isLineStart && text.length > 0) {
+ lineOffsets.push(text.length);
}
+ return lineOffsets;
+ }
+
+ /**
+ * Get the length of the document's content
+ */
+ getTextLength(): number {
+ return this.getText().length;
+ }
+
+ /**
+ * Returns the file path if the url scheme is file
+ */
+ getFilePath(): string | null {
+ return urlToPath(this.uri);
+ }
+
+ /**
+ * Get URL file path.
+ */
+ getURL() {
+ return this.uri;
+ }
+
+ get lines(): string[] {
+ return this.getText().split(/\r?\n/);
+ }
+
+ get lineCount(): number {
+ return this.lines.length;
+ }
}
diff --git a/tools/vscode/packages/server/src/core/documents/DocumentManager.ts b/tools/vscode/packages/server/src/core/documents/DocumentManager.ts
index 6195514d8..7c9c168c1 100644
--- a/tools/vscode/packages/server/src/core/documents/DocumentManager.ts
+++ b/tools/vscode/packages/server/src/core/documents/DocumentManager.ts
@@ -1,104 +1,94 @@
import { EventEmitter } from 'events';
-import {
- TextDocumentContentChangeEvent,
- TextDocumentItem
-} from 'vscode-languageserver';
+import { TextDocumentContentChangeEvent, TextDocumentItem } from 'vscode-languageserver';
import { Document } from './Document';
import { normalizeUri } from '../../utils';
export type DocumentEvent = 'documentOpen' | 'documentChange' | 'documentClose';
export class DocumentManager {
- private emitter = new EventEmitter();
- private openedInClient = new Set<string>();
- private documents: Map<string, Document> = new Map();
- private locked = new Set<string>();
- private deleteCandidates = new Set<string>();
-
- constructor(
- private createDocument: (textDocument: { uri: string, text: string }) => Document
- ) {}
-
- get(uri: string) {
- return this.documents.get(normalizeUri(uri));
+ private emitter = new EventEmitter();
+ private openedInClient = new Set<string>();
+ private documents: Map<string, Document> = new Map();
+ private locked = new Set<string>();
+ private deleteCandidates = new Set<string>();
+
+ constructor(private createDocument: (textDocument: { uri: string; text: string }) => Document) {}
+
+ get(uri: string) {
+ return this.documents.get(normalizeUri(uri));
+ }
+
+ openDocument(textDocument: TextDocumentItem) {
+ let document: Document;
+ if (this.documents.has(textDocument.uri)) {
+ document = this.get(textDocument.uri) as Document;
+ document.setText(textDocument.text);
+ } else {
+ document = this.createDocument(textDocument);
+ this.documents.set(normalizeUri(textDocument.uri), document);
+ this.notify('documentOpen', document);
}
- openDocument(textDocument: TextDocumentItem) {
- let document: Document;
- if (this.documents.has(textDocument.uri)) {
- document = this.get(textDocument.uri) as Document;
- document.setText(textDocument.text);
- } else {
- document = this.createDocument(textDocument);
- this.documents.set(normalizeUri(textDocument.uri), document);
- this.notify('documentOpen', document);
- }
+ this.notify('documentChange', document);
- this.notify('documentChange', document);
+ return document;
+ }
- return document;
- }
+ closeDocument(uri: string) {
+ uri = normalizeUri(uri);
- closeDocument(uri: string) {
- uri = normalizeUri(uri);
+ const document = this.documents.get(uri);
+ if (!document) {
+ throw new Error('Cannot call methods on an unopened document');
+ }
- const document = this.documents.get(uri);
- if (!document) {
- throw new Error('Cannot call methods on an unopened document');
- }
+ this.notify('documentClose', 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);
+ }
- // 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);
+ }
- this.openedInClient.delete(uri);
+ updateDocument(uri: string, changes: TextDocumentContentChangeEvent[]) {
+ const document = this.documents.get(normalizeUri(uri));
+ if (!document) {
+ throw new Error('Cannot call methods on an unopened document');
}
- updateDocument(
- uri: string,
- changes: TextDocumentContentChangeEvent[]
- ) {
- const document = this.documents.get(normalizeUri(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);
+ 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);
}
- markAsOpenedInClient(uri: string) {
- this.openedInClient.add(normalizeUri(uri));
- }
+ this.notify('documentChange', document);
+ }
- getAllOpenedByClient() {
- return Array.from(this.documents.entries()).filter((doc) =>
- this.openedInClient.has(doc[0])
- );
- }
+ markAsOpenedInClient(uri: string) {
+ this.openedInClient.add(normalizeUri(uri));
+ }
- on(name: DocumentEvent, listener: (document: Document) => void) {
- this.emitter.on(name, listener);
- }
+ getAllOpenedByClient() {
+ return Array.from(this.documents.entries()).filter((doc) => this.openedInClient.has(doc[0]));
+ }
- private notify(name: DocumentEvent, document: Document) {
- this.emitter.emit(name, document);
- }
+ on(name: DocumentEvent, listener: (document: Document) => void) {
+ this.emitter.on(name, listener);
+ }
+
+ private notify(name: DocumentEvent, document: Document) {
+ this.emitter.emit(name, document);
+ }
}
diff --git a/tools/vscode/packages/server/src/core/documents/parseAstro.ts b/tools/vscode/packages/server/src/core/documents/parseAstro.ts
index e4f71721a..71c7764d8 100644
--- a/tools/vscode/packages/server/src/core/documents/parseAstro.ts
+++ b/tools/vscode/packages/server/src/core/documents/parseAstro.ts
@@ -1,74 +1,77 @@
import { getFirstNonWhitespaceIndex } from './utils';
interface Frontmatter {
- state: null | 'open' | 'closed';
- startOffset: null | number;
- endOffset: null | number;
+ state: null | 'open' | 'closed';
+ startOffset: null | number;
+ endOffset: null | number;
}
interface Content {
- firstNonWhitespaceOffset: null | number;
+ firstNonWhitespaceOffset: null | number;
}
export interface AstroDocument {
- frontmatter: Frontmatter
- content: Content;
+ frontmatter: Frontmatter;
+ content: Content;
}
/** Parses a document to collect metadata about Astro features */
export function parseAstro(content: string): AstroDocument {
- const frontmatter = getFrontmatter(content)
- return {
- frontmatter,
- content: getContent(content, frontmatter)
- }
+ const frontmatter = getFrontmatter(content);
+ return {
+ frontmatter,
+ content: getContent(content, frontmatter),
+ };
}
/** Get frontmatter metadata */
function getFrontmatter(content: string): Frontmatter {
- /** Quickly check how many `---` blocks are in the document */
- function getFrontmatterState(): Frontmatter['state'] {
- const parts = content.trim().split('---').length;
- switch (parts) {
- case 1: return null;
- case 2: return 'open';
- default: return 'closed';
- }
+ /** Quickly check how many `---` blocks are in the document */
+ function getFrontmatterState(): Frontmatter['state'] {
+ const parts = content.trim().split('---').length;
+ switch (parts) {
+ case 1:
+ return null;
+ case 2:
+ return 'open';
+ default:
+ return 'closed';
}
- const state = getFrontmatterState();
+ }
+ const state = getFrontmatterState();
- /** Construct a range containing the document's frontmatter */
- function getFrontmatterOffsets(): [number|null, number|null] {
- 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();
+ /** Construct a range containing the document's frontmatter */
+ function getFrontmatterOffsets(): [number | null, number | null] {
+ 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
- };
+ return {
+ state,
+ startOffset,
+ endOffset,
+ };
}
/** Get content metadata */
function getContent(content: string, frontmatter: Frontmatter): Content {
- switch (frontmatter.state) {
- case null: {
- const offset = 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 = getFirstNonWhitespaceIndex(content.slice(end))
- return { firstNonWhitespaceOffset: end + offset }
- }
+ switch (frontmatter.state) {
+ case null: {
+ const offset = 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 = getFirstNonWhitespaceIndex(content.slice(end));
+ return { firstNonWhitespaceOffset: end + offset };
}
+ }
}
diff --git a/tools/vscode/packages/server/src/core/documents/parseHtml.ts b/tools/vscode/packages/server/src/core/documents/parseHtml.ts
index 86af06008..f5de5f292 100644
--- a/tools/vscode/packages/server/src/core/documents/parseHtml.ts
+++ b/tools/vscode/packages/server/src/core/documents/parseHtml.ts
@@ -1,12 +1,4 @@
-import {
- getLanguageService,
- HTMLDocument,
- TokenType,
- ScannerState,
- Scanner,
- Node,
- Position
-} from 'vscode-html-languageservice';
+import { getLanguageService, HTMLDocument, TokenType, ScannerState, Scanner, Node, Position } from 'vscode-html-languageservice';
import { Document } from './Document';
import { isInsideExpression } from './utils';
@@ -16,154 +8,134 @@ const parser = getLanguageService();
* Parses text as HTML
*/
export function parseHtml(text: string): HTMLDocument {
- const preprocessed = preprocess(text);
+ const preprocessed = preprocess(text);
- // We can safely only set getText because only this is used for parsing
- const parsedDoc = parser.parseHTMLDocument(<any>{ getText: () => preprocessed });
+ // We can safely only set getText because only this is used for parsing
+ const parsedDoc = parser.parseHTMLDocument(<any>{ getText: () => preprocessed });
- return parsedDoc;
+ return parsedDoc;
}
-const createScanner = parser.createScanner as (
- input: string,
- initialOffset?: number,
- initialState?: ScannerState
-) => Scanner;
+const createScanner = parser.createScanner as (input: string, initialOffset?: number, initialState?: ScannerState) => Scanner;
/**
* scan the text and remove any `>` or `<` that cause the tag to end short,
*/
function preprocess(text: string) {
- let scanner = createScanner(text);
- let token = scanner.scan();
- let currentStartTagStart: number | null = null;
+ let scanner = createScanner(text);
+ let token = scanner.scan();
+ let currentStartTagStart: number | null = null;
- while (token !== TokenType.EOS) {
- const offset = scanner.getTokenOffset();
+ while (token !== TokenType.EOS) {
+ const offset = scanner.getTokenOffset();
- if (token === TokenType.StartTagOpen) {
- currentStartTagStart = offset;
- }
-
- if (token === TokenType.StartTagClose) {
- if (shouldBlankStartOrEndTagLike(offset)) {
- blankStartOrEndTagLike(offset);
- } else {
- currentStartTagStart = null;
- }
- }
+ if (token === TokenType.StartTagOpen) {
+ currentStartTagStart = offset;
+ }
- if (token === TokenType.StartTagSelfClose) {
- currentStartTagStart = null;
- }
+ if (token === TokenType.StartTagClose) {
+ if (shouldBlankStartOrEndTagLike(offset)) {
+ blankStartOrEndTagLike(offset);
+ } else {
+ currentStartTagStart = null;
+ }
+ }
- // <Foo checked={a < 1}>
- // https://github.com/microsoft/vscode-html-languageservice/blob/71806ef57be07e1068ee40900ef8b0899c80e68a/src/parser/htmlScanner.ts#L327
- if (
- token === TokenType.Unknown &&
- scanner.getScannerState() === ScannerState.WithinTag &&
- scanner.getTokenText() === '<' &&
- shouldBlankStartOrEndTagLike(offset)
- ) {
- blankStartOrEndTagLike(offset);
- }
+ if (token === TokenType.StartTagSelfClose) {
+ currentStartTagStart = null;
+ }
- token = scanner.scan();
+ // <Foo checked={a < 1}>
+ // https://github.com/microsoft/vscode-html-languageservice/blob/71806ef57be07e1068ee40900ef8b0899c80e68a/src/parser/htmlScanner.ts#L327
+ if (token === TokenType.Unknown && scanner.getScannerState() === ScannerState.WithinTag && scanner.getTokenText() === '<' && shouldBlankStartOrEndTagLike(offset)) {
+ blankStartOrEndTagLike(offset);
}
- return text;
+ token = scanner.scan();
+ }
- function shouldBlankStartOrEndTagLike(offset: number) {
- // not null rather than falsy, otherwise it won't work on first tag(0)
- return (
- currentStartTagStart !== null &&
- isInsideExpression(text, currentStartTagStart, offset)
- );
- }
+ return text;
- function blankStartOrEndTagLike(offset: number) {
- text = text.substring(0, offset) + ' ' + text.substring(offset + 1);
- scanner = createScanner(text, offset, ScannerState.WithinTag);
- }
+ function shouldBlankStartOrEndTagLike(offset: number) {
+ // not null rather than falsy, otherwise it won't work on first tag(0)
+ return currentStartTagStart !== null && isInsideExpression(text, currentStartTagStart, offset);
+ }
+
+ function blankStartOrEndTagLike(offset: number) {
+ text = text.substring(0, offset) + ' ' + text.substring(offset + 1);
+ scanner = createScanner(text, offset, ScannerState.WithinTag);
+ }
}
export interface AttributeContext {
- name: string;
- inValue: boolean;
- valueRange?: [number, number];
+ name: string;
+ inValue: boolean;
+ valueRange?: [number, number];
}
-export function getAttributeContextAtPosition(
- document: Document,
- position: Position
-): AttributeContext | null {
- const offset = document.offsetAt(position);
- const { html } = document;
- const tag = html.findNodeAt(offset);
-
- if (!inStartTag(offset, tag) || !tag.attributes) {
- return null;
- }
+export function getAttributeContextAtPosition(document: Document, position: Position): AttributeContext | null {
+ const offset = document.offsetAt(position);
+ const { html } = document;
+ const tag = html.findNodeAt(offset);
- 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: string | undefined;
- const inTokenRange = () =>
- scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd();
- while (token != TokenType.EOS) {
- // adopted from https://github.com/microsoft/vscode-html-languageservice/blob/2f7ae4df298ac2c299a40e9024d118f4a9dc0c68/src/services/htmlCompletion.ts#L402
- if (token === TokenType.AttributeName) {
- currentAttributeName = scanner.getTokenText();
-
- if (inTokenRange()) {
- return {
- name: currentAttributeName,
- inValue: false
- };
- }
- } else if (token === TokenType.DelimiterAssign) {
- if (scanner.getTokenEnd() === offset && currentAttributeName) {
- const nextToken = scanner.scan();
-
- return {
- name: currentAttributeName,
- inValue: true,
- valueRange: [
- offset,
- nextToken === TokenType.AttributeValue ? scanner.getTokenEnd() : offset
- ]
- };
- }
- } else if (token === 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;
+ 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: string | undefined;
+ const inTokenRange = () => scanner.getTokenOffset() <= offset && offset <= scanner.getTokenEnd();
+ while (token != TokenType.EOS) {
+ // adopted from https://github.com/microsoft/vscode-html-languageservice/blob/2f7ae4df298ac2c299a40e9024d118f4a9dc0c68/src/services/htmlCompletion.ts#L402
+ if (token === TokenType.AttributeName) {
+ currentAttributeName = scanner.getTokenText();
+
+ if (inTokenRange()) {
+ return {
+ name: currentAttributeName,
+ inValue: false,
+ };
+ }
+ } else if (token === TokenType.DelimiterAssign) {
+ if (scanner.getTokenEnd() === offset && currentAttributeName) {
+ const nextToken = scanner.scan();
+
+ return {
+ name: currentAttributeName,
+ inValue: true,
+ valueRange: [offset, nextToken === TokenType.AttributeValue ? scanner.getTokenEnd() : offset],
+ };
+ }
+ } else if (token === TokenType.AttributeValue) {
+ if (inTokenRange() && currentAttributeName) {
+ let start = scanner.getTokenOffset();
+ let end = scanner.getTokenEnd();
+ const char = text[start];
+
+ if (char === '"' || char === "'") {
+ start++;
+ end--;
}
- token = scanner.scan();
+
+ return {
+ name: currentAttributeName,
+ inValue: true,
+ valueRange: [start, end],
+ };
+ }
+ currentAttributeName = undefined;
}
+ token = scanner.scan();
+ }
- return null;
+ return null;
}
function inStartTag(offset: number, node: Node) {
- return offset > node.start && node.startTagEnd != undefined && offset < node.startTagEnd;
+ return offset > node.start && node.startTagEnd != undefined && offset < node.startTagEnd;
}
diff --git a/tools/vscode/packages/server/src/core/documents/utils.ts b/tools/vscode/packages/server/src/core/documents/utils.ts
index 6c69014d5..3d12f35a3 100644
--- a/tools/vscode/packages/server/src/core/documents/utils.ts
+++ b/tools/vscode/packages/server/src/core/documents/utils.ts
@@ -5,63 +5,52 @@ import { clamp } from '../../utils';
* Gets word range at position.
* Delimiter is by default a whitespace, but can be adjusted.
*/
-export function getWordRangeAt(
- str: string,
- pos: number,
- delimiterRegex = { left: /\S+$/, right: /\s/ }
-): { start: number; end: number } {
- let start = str.slice(0, pos).search(delimiterRegex.left);
- if (start < 0) {
- start = pos;
- }
-
- let end = str.slice(pos).search(delimiterRegex.right);
- if (end < 0) {
- end = str.length;
- } else {
- end = end + pos;
- }
-
- return { start, end };
+export function getWordRangeAt(str: string, pos: number, delimiterRegex = { left: /\S+$/, right: /\s/ }): { start: number; end: number } {
+ let start = str.slice(0, pos).search(delimiterRegex.left);
+ if (start < 0) {
+ start = pos;
+ }
+
+ let end = str.slice(pos).search(delimiterRegex.right);
+ if (end < 0) {
+ end = str.length;
+ } else {
+ end = end + pos;
+ }
+
+ return { start, end };
}
/**
* Gets word at position.
* Delimiter is by default a whitespace, but can be adjusted.
*/
-export function getWordAt(
- str: string,
- pos: number,
- delimiterRegex = { left: /\S+$/, right: /\s/ }
-): string {
- const { start, end } = getWordRangeAt(str, pos, delimiterRegex);
- return str.slice(start, end);
+export function getWordAt(str: string, pos: number, delimiterRegex = { left: /\S+$/, right: /\s/ }): string {
+ const { start, end } = getWordRangeAt(str, pos, delimiterRegex);
+ return str.slice(start, end);
}
/**
* Gets index of first-non-whitespace character.
*/
export function getFirstNonWhitespaceIndex(str: string): number {
- return str.length - str.trimStart().length;
+ return str.length - str.trimStart().length;
}
/** checks if a position is currently inside of an expression */
export function isInsideExpression(html: string, tagStart: number, position: number) {
- const charactersInNode = html.substring(tagStart, position);
- return charactersInNode.lastIndexOf('{') > charactersInNode.lastIndexOf('}');
+ const charactersInNode = html.substring(tagStart, position);
+ return charactersInNode.lastIndexOf('{') > charactersInNode.lastIndexOf('}');
}
/**
- * Returns if a given offset is inside of the document frontmatter
+ * Returns if a given offset is inside of the document frontmatter
*/
-export function isInsideFrontmatter(
- text: string,
- offset: number
-): boolean {
- let start = text.slice(0, offset).trim().split('---').length;
- let end = text.slice(offset).trim().split('---').length;
-
- return start > 1 && start < 3 && end >= 1;
+export function isInsideFrontmatter(text: string, offset: number): boolean {
+ let start = text.slice(0, offset).trim().split('---').length;
+ let end = text.slice(offset).trim().split('---').length;
+
+ return start > 1 && start < 3 && end >= 1;
}
/**
@@ -70,28 +59,28 @@ export function isInsideFrontmatter(
* @param text The text for which the position should be retrived
*/
export function positionAt(offset: number, text: string): Position {
- offset = clamp(offset, 0, text.length);
-
- const lineOffsets = getLineOffsets(text);
- let low = 0;
- let high = lineOffsets.length;
- if (high === 0) {
- return Position.create(0, offset);
- }
-
- while (low < high) {
- const mid = Math.floor((low + high) / 2);
- if (lineOffsets[mid] > offset) {
- high = mid;
- } else {
- low = mid + 1;
- }
+ offset = clamp(offset, 0, text.length);
+
+ const lineOffsets = getLineOffsets(text);
+ let low = 0;
+ let high = lineOffsets.length;
+ if (high === 0) {
+ return Position.create(0, offset);
+ }
+
+ while (low < high) {
+ const mid = Math.floor((low + high) / 2);
+ if (lineOffsets[mid] > offset) {
+ high = mid;
+ } else {
+ low = 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 Position.create(line, offset - lineOffsets[line]);
+ // 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 Position.create(line, offset - lineOffsets[line]);
}
/**
@@ -100,40 +89,39 @@ export function positionAt(offset: number, text: string): Position {
* @param text The text for which the offset should be retrived
*/
export function offsetAt(position: Position, text: string): number {
- const lineOffsets = getLineOffsets(text);
+ const lineOffsets = getLineOffsets(text);
- if (position.line >= lineOffsets.length) {
- return text.length;
- } else if (position.line < 0) {
- return 0;
- }
+ 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;
+ const lineOffset = lineOffsets[position.line];
+ const nextLineOffset = position.line + 1 < lineOffsets.length ? lineOffsets[position.line + 1] : text.length;
- return clamp(nextLineOffset, lineOffset, lineOffset + position.character);
+ return clamp(nextLineOffset, lineOffset, lineOffset + position.character);
}
function getLineOffsets(text: string) {
- 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++;
- }
- }
+ const lineOffsets = [];
+ let isLineStart = true;
- if (isLineStart && text.length > 0) {
- lineOffsets.push(text.length);
+ 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;
+ return lineOffsets;
}
diff --git a/tools/vscode/packages/server/src/index.ts b/tools/vscode/packages/server/src/index.ts
index f72ad550b..528d3cb9d 100644
--- a/tools/vscode/packages/server/src/index.ts
+++ b/tools/vscode/packages/server/src/index.ts
@@ -71,10 +71,12 @@ export function startServer() {
connection.onDidChangeTextDocument((evt) => docManager.updateDocument(evt.textDocument.uri, evt.contentChanges));
connection.onDidChangeWatchedFiles((evt) => {
- const params = evt.changes.map(change => ({
- fileName: urlToPath(change.uri),
- changeType: change.type
- })).filter(change => !!change.fileName)
+ const params = evt.changes
+ .map((change) => ({
+ fileName: urlToPath(change.uri),
+ changeType: change.type,
+ }))
+ .filter((change) => !!change.fileName);
pluginHost.onWatchFileChanges(params);
});
diff --git a/tools/vscode/packages/server/src/plugins/PluginHost.ts b/tools/vscode/packages/server/src/plugins/PluginHost.ts
index 72f098ca1..037dd6e07 100644
--- a/tools/vscode/packages/server/src/plugins/PluginHost.ts
+++ b/tools/vscode/packages/server/src/plugins/PluginHost.ts
@@ -1,11 +1,4 @@
-
-import {
- CompletionContext,
- CompletionItem,
- CompletionList,
- Position,
- TextDocumentIdentifier,
-} from 'vscode-languageserver';
+import { CompletionContext, CompletionItem, CompletionList, Position, TextDocumentIdentifier } from 'vscode-languageserver';
import type { DocumentManager } from '../core/documents';
import type * as d from './interfaces';
import { flatten } from '../utils';
@@ -13,154 +6,107 @@ import { FoldingRange } from 'vscode-languageserver-types';
// eslint-disable-next-line no-shadow
enum ExecuteMode {
- None,
- FirstNonNull,
- Collect
+ None,
+ FirstNonNull,
+ Collect,
}
export class PluginHost {
- private plugins: d.Plugin[] = [];
-
- constructor(private documentsManager: DocumentManager) {}
+ private plugins: d.Plugin[] = [];
- register(plugin: d.Plugin) {
- this.plugins.push(plugin);
- }
+ constructor(private documentsManager: DocumentManager) {}
- async getCompletions(
- textDocument: TextDocumentIdentifier,
- position: Position,
- completionContext?: CompletionContext
- ): Promise<CompletionList> {
- const document = this.getDocument(textDocument.uri);
- if (!document) {
- throw new Error('Cannot call methods on an unopened document');
- }
+ register(plugin: d.Plugin) {
+ this.plugins.push(plugin);
+ }
- const completions = (
- await this.execute<CompletionList>(
- 'getCompletions',
- [document, position, completionContext],
- ExecuteMode.Collect
- )
- ).filter((completion) => completion != null);
-
- let flattenedCompletions = flatten(completions.map((completion) => completion.items));
- const isIncomplete = completions.reduce(
- (incomplete, completion) => incomplete || completion.isIncomplete,
- false as boolean
- );
-
- return CompletionList.create(flattenedCompletions, isIncomplete);
+ async getCompletions(textDocument: TextDocumentIdentifier, position: Position, completionContext?: CompletionContext): Promise<CompletionList> {
+ const document = this.getDocument(textDocument.uri);
+ if (!document) {
+ throw new Error('Cannot call methods on an unopened document');
}
- async resolveCompletion(
- textDocument: TextDocumentIdentifier,
- completionItem: d.AppCompletionItem
- ): Promise<CompletionItem> {
- const document = this.getDocument(textDocument.uri);
+ const completions = (await this.execute<CompletionList>('getCompletions', [document, position, completionContext], ExecuteMode.Collect)).filter(
+ (completion) => completion != null
+ );
- if (!document) {
- throw new Error('Cannot call methods on an unopened document');
- }
-
- const result = await this.execute<CompletionItem>(
- 'resolveCompletion',
- [document, completionItem],
- ExecuteMode.FirstNonNull
- );
+ let flattenedCompletions = flatten(completions.map((completion) => completion.items));
+ const isIncomplete = completions.reduce((incomplete, completion) => incomplete || completion.isIncomplete, false as boolean);
- return result ?? completionItem;
- }
+ return CompletionList.create(flattenedCompletions, isIncomplete);
+ }
- async doTagComplete(
- textDocument: TextDocumentIdentifier,
- position: Position
- ): Promise<string | null> {
- const document = this.getDocument(textDocument.uri);
- if (!document) {
- throw new Error('Cannot call methods on an unopened document');
- }
+ async resolveCompletion(textDocument: TextDocumentIdentifier, completionItem: d.AppCompletionItem): Promise<CompletionItem> {
+ const document = this.getDocument(textDocument.uri);
- return this.execute<string | null>(
- 'doTagComplete',
- [document, position],
- ExecuteMode.FirstNonNull
- );
+ if (!document) {
+ throw new Error('Cannot call methods on an unopened document');
}
- async getFoldingRanges(
- textDocument: TextDocumentIdentifier
- ): Promise<FoldingRange[]|null> {
- const document = this.getDocument(textDocument.uri);
- if (!document) {
- throw new Error('Cannot call methods on an unopened document');
- }
+ const result = await this.execute<CompletionItem>('resolveCompletion', [document, completionItem], ExecuteMode.FirstNonNull);
- const foldingRanges = flatten(await this.execute<FoldingRange[]>(
- 'getFoldingRanges',
- [document],
- ExecuteMode.Collect
- )).filter((completion) => completion != null)
+ return result ?? completionItem;
+ }
- return foldingRanges;
+ async doTagComplete(textDocument: TextDocumentIdentifier, position: Position): Promise<string | null> {
+ const document = this.getDocument(textDocument.uri);
+ if (!document) {
+ throw new Error('Cannot call methods on an unopened document');
}
- onWatchFileChanges(onWatchFileChangesParams: any[]): void {
- for (const support of this.plugins) {
- support.onWatchFileChanges?.(onWatchFileChangesParams);
- }
- }
+ return this.execute<string | null>('doTagComplete', [document, position], ExecuteMode.FirstNonNull);
+ }
- private getDocument(uri: string) {
- return this.documentsManager.get(uri);
+ async getFoldingRanges(textDocument: TextDocumentIdentifier): Promise<FoldingRange[] | null> {
+ const document = this.getDocument(textDocument.uri);
+ if (!document) {
+ throw new Error('Cannot call methods on an unopened document');
}
- private execute<T>(
- name: keyof d.LSProvider,
- args: any[],
- mode: ExecuteMode.FirstNonNull
- ): Promise<T | null>;
- private execute<T>(
- name: keyof d.LSProvider,
- args: any[],
- mode: ExecuteMode.Collect
- ): Promise<T[]>;
- private execute(name: keyof d.LSProvider, args: any[], mode: ExecuteMode.None): Promise<void>;
- private async execute<T>(
- name: keyof d.LSProvider,
- args: any[],
- mode: ExecuteMode
- ): Promise<(T | null) | T[] | void> {
- 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 Promise.all(
- plugins.map((plugin) => this.tryExecutePlugin(plugin, name, args, []))
- );
- case ExecuteMode.None:
- await Promise.all(
- plugins.map((plugin) => this.tryExecutePlugin(plugin, name, args, null))
- );
- return;
- }
- }
+ const foldingRanges = flatten(await this.execute<FoldingRange[]>('getFoldingRanges', [document], ExecuteMode.Collect)).filter((completion) => completion != null);
+
+ return foldingRanges;
+ }
- private async tryExecutePlugin(plugin: any, fnName: string, args: any[], failValue: any) {
- try {
- return await plugin[fnName](...args);
- } catch (e) {
- console.error(e);
- return failValue;
+ onWatchFileChanges(onWatchFileChangesParams: any[]): void {
+ for (const support of this.plugins) {
+ support.onWatchFileChanges?.(onWatchFileChangesParams);
+ }
+ }
+
+ private getDocument(uri: string) {
+ return this.documentsManager.get(uri);
+ }
+
+ private execute<T>(name: keyof d.LSProvider, args: any[], mode: ExecuteMode.FirstNonNull): Promise<T | null>;
+ private execute<T>(name: keyof d.LSProvider, args: any[], mode: ExecuteMode.Collect): Promise<T[]>;
+ private execute(name: keyof d.LSProvider, args: any[], mode: ExecuteMode.None): Promise<void>;
+ private async execute<T>(name: keyof d.LSProvider, args: any[], mode: ExecuteMode): Promise<(T | null) | T[] | void> {
+ 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 Promise.all(plugins.map((plugin) => this.tryExecutePlugin(plugin, name, args, [])));
+ case ExecuteMode.None:
+ await Promise.all(plugins.map((plugin) => this.tryExecutePlugin(plugin, name, args, null)));
+ return;
+ }
+ }
+
+ private async tryExecutePlugin(plugin: any, fnName: string, args: any[], failValue: any) {
+ try {
+ return await plugin[fnName](...args);
+ } catch (e) {
+ console.error(e);
+ return failValue;
}
+ }
}
diff --git a/tools/vscode/packages/server/src/plugins/astro/AstroPlugin.ts b/tools/vscode/packages/server/src/plugins/astro/AstroPlugin.ts
index 0696504fc..6baf407a5 100644
--- a/tools/vscode/packages/server/src/plugins/astro/AstroPlugin.ts
+++ b/tools/vscode/packages/server/src/plugins/astro/AstroPlugin.ts
@@ -49,7 +49,7 @@ export class AstroPlugin implements CompletionsProvider, FoldingRangeProvider {
endLine: end.line,
endCharacter: end.character,
kind: FoldingRangeKind.Imports,
- }
+ },
];
}
diff --git a/tools/vscode/packages/server/src/plugins/html/HTMLPlugin.ts b/tools/vscode/packages/server/src/plugins/html/HTMLPlugin.ts
index 5114eda1c..7e0ab4861 100644
--- a/tools/vscode/packages/server/src/plugins/html/HTMLPlugin.ts
+++ b/tools/vscode/packages/server/src/plugins/html/HTMLPlugin.ts
@@ -34,15 +34,7 @@ export class HTMLPlugin implements CompletionsProvider, FoldingRangeProvider {
isIncomplete: true,
items: [],
};
- this.lang.setCompletionParticipants([
- getEmmetCompletionParticipants(
- document,
- position,
- 'html',
- this.configManager.getEmmetConfig(),
- emmetResults
- )
- ]);
+ this.lang.setCompletionParticipants([getEmmetCompletionParticipants(document, position, 'html', this.configManager.getEmmetConfig(), emmetResults)]);
const results = this.lang.doComplete(document, position, html);
const items = this.toCompletionItems(results.items);
@@ -54,14 +46,13 @@ export class HTMLPlugin implements CompletionsProvider, FoldingRangeProvider {
);
}
- getFoldingRanges(document: Document): FoldingRange[]|null {
+ getFoldingRanges(document: Document): FoldingRange[] | null {
const html = this.documents.get(document);
if (!html) {
return null;
}
return this.lang.getFoldingRanges(document);
-
}
doTagComplete(document: Document, position: Position): string | null {
diff --git a/tools/vscode/packages/server/src/plugins/interfaces.ts b/tools/vscode/packages/server/src/plugins/interfaces.ts
index 31aafdc3e..b68100de1 100644
--- a/tools/vscode/packages/server/src/plugins/interfaces.ts
+++ b/tools/vscode/packages/server/src/plugins/interfaces.ts
@@ -1,217 +1,167 @@
+import { CompletionContext, FileChangeType, LinkedEditingRanges, SemanticTokens, SignatureHelpContext, TextDocumentContentChangeEvent } from 'vscode-languageserver';
import {
- CompletionContext,
- FileChangeType,
- LinkedEditingRanges,
- SemanticTokens,
- SignatureHelpContext,
- TextDocumentContentChangeEvent
-} from 'vscode-languageserver';
-import {
- CodeAction,
- CodeActionContext,
- Color,
- ColorInformation,
- ColorPresentation,
- CompletionItem,
- CompletionList,
- DefinitionLink,
- Diagnostic,
- FormattingOptions,
- Hover,
- Location,
- Position,
- Range,
- ReferenceContext,
- SymbolInformation,
- TextDocumentIdentifier,
- TextEdit,
- WorkspaceEdit,
- SelectionRange,
- SignatureHelp,
- FoldingRange
+ CodeAction,
+ CodeActionContext,
+ Color,
+ ColorInformation,
+ ColorPresentation,
+ CompletionItem,
+ CompletionList,
+ DefinitionLink,
+ Diagnostic,
+ FormattingOptions,
+ Hover,
+ Location,
+ Position,
+ Range,
+ ReferenceContext,
+ SymbolInformation,
+ TextDocumentIdentifier,
+ TextEdit,
+ WorkspaceEdit,
+ SelectionRange,
+ SignatureHelp,
+ FoldingRange,
} from 'vscode-languageserver-types';
import { Document } from '../core/documents';
export type Resolvable<T> = T | Promise<T>;
export interface AppCompletionItem<T extends TextDocumentIdentifier = any> extends CompletionItem {
- data?: T;
+ data?: T;
}
export interface AppCompletionList<T extends TextDocumentIdentifier = any> extends CompletionList {
- items: Array<AppCompletionItem<T>>;
+ items: Array<AppCompletionItem<T>>;
}
export interface DiagnosticsProvider {
- getDiagnostics(document: Document): Resolvable<Diagnostic[]>;
+ getDiagnostics(document: Document): Resolvable<Diagnostic[]>;
}
export interface HoverProvider {
- doHover(document: Document, position: Position): Resolvable<Hover | null>;
+ doHover(document: Document, position: Position): Resolvable<Hover | null>;
}
export interface FoldingRangeProvider {
- getFoldingRanges(document: Document): Resolvable<FoldingRange[]|null>;
+ getFoldingRanges(document: Document): Resolvable<FoldingRange[] | null>;
}
export interface CompletionsProvider<T extends TextDocumentIdentifier = any> {
- getCompletions(
- document: Document,
- position: Position,
- completionContext?: CompletionContext
- ): Resolvable<AppCompletionList<T> | null>;
+ getCompletions(document: Document, position: Position, completionContext?: CompletionContext): Resolvable<AppCompletionList<T> | null>;
- resolveCompletion?(
- document: Document,
- completionItem: AppCompletionItem<T>
- ): Resolvable<AppCompletionItem<T>>;
+ resolveCompletion?(document: Document, completionItem: AppCompletionItem<T>): Resolvable<AppCompletionItem<T>>;
}
export interface FormattingProvider {
- formatDocument(document: Document, options: FormattingOptions): Resolvable<TextEdit[]>;
+ formatDocument(document: Document, options: FormattingOptions): Resolvable<TextEdit[]>;
}
export interface TagCompleteProvider {
- doTagComplete(document: Document, position: Position): Resolvable<string | null>;
+ doTagComplete(document: Document, position: Position): Resolvable<string | null>;
}
export interface DocumentColorsProvider {
- getDocumentColors(document: Document): Resolvable<ColorInformation[]>;
+ getDocumentColors(document: Document): Resolvable<ColorInformation[]>;
}
export interface ColorPresentationsProvider {
- getColorPresentations(
- document: Document,
- range: Range,
- color: Color
- ): Resolvable<ColorPresentation[]>;
+ getColorPresentations(document: Document, range: Range, color: Color): Resolvable<ColorPresentation[]>;
}
export interface DocumentSymbolsProvider {
- getDocumentSymbols(document: Document): Resolvable<SymbolInformation[]>;
+ getDocumentSymbols(document: Document): Resolvable<SymbolInformation[]>;
}
export interface DefinitionsProvider {
- getDefinitions(document: Document, position: Position): Resolvable<DefinitionLink[]>;
+ getDefinitions(document: Document, position: Position): Resolvable<DefinitionLink[]>;
}
export interface BackwardsCompatibleDefinitionsProvider {
- getDefinitions(
- document: Document,
- position: Position
- ): Resolvable<DefinitionLink[] | Location[]>;
+ getDefinitions(document: Document, position: Position): Resolvable<DefinitionLink[] | Location[]>;
}
export interface CodeActionsProvider {
- getCodeActions(
- document: Document,
- range: Range,
- context: CodeActionContext
- ): Resolvable<CodeAction[]>;
- executeCommand?(
- document: Document,
- command: string,
- args?: any[]
- ): Resolvable<WorkspaceEdit | string | null>;
+ getCodeActions(document: Document, range: Range, context: CodeActionContext): Resolvable<CodeAction[]>;
+ executeCommand?(document: Document, command: string, args?: any[]): Resolvable<WorkspaceEdit | string | null>;
}
export interface FileRename {
- oldUri: string;
- newUri: string;
+ oldUri: string;
+ newUri: string;
}
export interface UpdateImportsProvider {
- updateImports(fileRename: FileRename): Resolvable<WorkspaceEdit | null>;
+ updateImports(fileRename: FileRename): Resolvable<WorkspaceEdit | null>;
}
export interface RenameProvider {
- rename(
- document: Document,
- position: Position,
- newName: string
- ): Resolvable<WorkspaceEdit | null>;
- prepareRename(document: Document, position: Position): Resolvable<Range | null>;
+ rename(document: Document, position: Position, newName: string): Resolvable<WorkspaceEdit | null>;
+ prepareRename(document: Document, position: Position): Resolvable<Range | null>;
}
export interface FindReferencesProvider {
- findReferences(
- document: Document,
- position: Position,
- context: ReferenceContext
- ): Promise<Location[] | null>;
+ findReferences(document: Document, position: Position, context: ReferenceContext): Promise<Location[] | null>;
}
export interface SignatureHelpProvider {
- getSignatureHelp(
- document: Document,
- position: Position,
- context: SignatureHelpContext | undefined
- ): Resolvable<SignatureHelp | null>;
+ getSignatureHelp(document: Document, position: Position, context: SignatureHelpContext | undefined): Resolvable<SignatureHelp | null>;
}
export interface SelectionRangeProvider {
- getSelectionRange(document: Document, position: Position): Resolvable<SelectionRange | null>;
+ getSelectionRange(document: Document, position: Position): Resolvable<SelectionRange | null>;
}
export interface SemanticTokensProvider {
- getSemanticTokens(textDocument: Document, range?: Range): Resolvable<SemanticTokens | null>;
+ getSemanticTokens(textDocument: Document, range?: Range): Resolvable<SemanticTokens | null>;
}
export interface LinkedEditingRangesProvider {
- getLinkedEditingRanges(
- document: Document,
- position: Position
- ): Resolvable<LinkedEditingRanges | null>;
+ getLinkedEditingRanges(document: Document, position: Position): Resolvable<LinkedEditingRanges | null>;
}
export interface OnWatchFileChangesPara {
- fileName: string;
- changeType: FileChangeType;
+ fileName: string;
+ changeType: FileChangeType;
}
export interface OnWatchFileChanges {
- onWatchFileChanges(onWatchFileChangesParas: OnWatchFileChangesPara[]): void;
+ onWatchFileChanges(onWatchFileChangesParas: OnWatchFileChangesPara[]): void;
}
export interface UpdateTsOrJsFile {
- updateTsOrJsFile(fileName: string, changes: TextDocumentContentChangeEvent[]): void;
+ updateTsOrJsFile(fileName: string, changes: TextDocumentContentChangeEvent[]): void;
}
type ProviderBase = DiagnosticsProvider &
- HoverProvider &
- CompletionsProvider &
- FormattingProvider &
- FoldingRangeProvider &
- TagCompleteProvider &
- DocumentColorsProvider &
- ColorPresentationsProvider &
- DocumentSymbolsProvider &
- UpdateImportsProvider &
- CodeActionsProvider &
- FindReferencesProvider &
- RenameProvider &
- SignatureHelpProvider &
- SemanticTokensProvider &
- LinkedEditingRangesProvider;
+ HoverProvider &
+ CompletionsProvider &
+ FormattingProvider &
+ FoldingRangeProvider &
+ TagCompleteProvider &
+ DocumentColorsProvider &
+ ColorPresentationsProvider &
+ DocumentSymbolsProvider &
+ UpdateImportsProvider &
+ CodeActionsProvider &
+ FindReferencesProvider &
+ RenameProvider &
+ SignatureHelpProvider &
+ SemanticTokensProvider &
+ LinkedEditingRangesProvider;
export type LSProvider = ProviderBase & BackwardsCompatibleDefinitionsProvider;
export interface LSPProviderConfig {
- /**
- * Whether or not completion lists that are marked as imcomplete
- * should be filtered server side.
- */
- filterIncompleteCompletions: boolean;
- /**
- * Whether or not getDefinitions supports the LocationLink interface.
- */
- definitionLinkSupport: boolean;
-}
-
-export type Plugin = Partial<
- ProviderBase &
- DefinitionsProvider &
- OnWatchFileChanges &
- SelectionRangeProvider &
- UpdateTsOrJsFile
->;
+ /**
+ * Whether or not completion lists that are marked as imcomplete
+ * should be filtered server side.
+ */
+ filterIncompleteCompletions: boolean;
+ /**
+ * Whether or not getDefinitions supports the LocationLink interface.
+ */
+ definitionLinkSupport: boolean;
+}
+
+export type Plugin = Partial<ProviderBase & DefinitionsProvider & OnWatchFileChanges & SelectionRangeProvider & UpdateTsOrJsFile>;
diff --git a/tools/vscode/packages/server/src/plugins/typescript/LanguageServiceManager.ts b/tools/vscode/packages/server/src/plugins/typescript/LanguageServiceManager.ts
index 60dec606c..529ab2b4c 100644
--- a/tools/vscode/packages/server/src/plugins/typescript/LanguageServiceManager.ts
+++ b/tools/vscode/packages/server/src/plugins/typescript/LanguageServiceManager.ts
@@ -38,7 +38,7 @@ export class LanguageServiceManager {
const url = urlToPath(curr) as string;
if (fileName.startsWith(url) && curr.length < url.length) return url;
return found;
- }, '')
+ }, '');
}
private createDocument = (fileName: string, content: string) => {
diff --git a/tools/vscode/packages/server/src/plugins/typescript/SnapshotManager.ts b/tools/vscode/packages/server/src/plugins/typescript/SnapshotManager.ts
index aac26d96e..47d44838d 100644
--- a/tools/vscode/packages/server/src/plugins/typescript/SnapshotManager.ts
+++ b/tools/vscode/packages/server/src/plugins/typescript/SnapshotManager.ts
@@ -6,328 +6,298 @@ import { pathToUrl } from '../../utils';
import { getScriptKindFromFileName, isAstroFilePath, toVirtualAstroFilePath } from './utils';
export interface TsFilesSpec {
- include?: readonly string[];
- exclude?: readonly string[];
+ include?: readonly string[];
+ exclude?: readonly string[];
}
export class SnapshotManager {
- private documents: Map<string, DocumentSnapshot> = new Map();
- private lastLogged = new Date(new Date().getTime() - 60_001);
-
- private readonly watchExtensions = [
- ts.Extension.Dts,
- ts.Extension.Js,
- ts.Extension.Jsx,
- ts.Extension.Ts,
- ts.Extension.Tsx,
- ts.Extension.Json
- ];
-
- constructor(
- private projectFiles: string[],
- private fileSpec: TsFilesSpec,
- private workspaceRoot: string
- ) {
-
- }
+ private documents: Map<string, DocumentSnapshot> = new Map();
+ private lastLogged = new Date(new Date().getTime() - 60_001);
- updateProjectFiles() {
- const { include, exclude } = this.fileSpec;
-
- if (include?.length === 0) return;
+ private readonly watchExtensions = [ts.Extension.Dts, ts.Extension.Js, ts.Extension.Jsx, ts.Extension.Ts, ts.Extension.Tsx, ts.Extension.Json];
- const projectFiles = ts.sys.readDirectory(
- this.workspaceRoot,
- this.watchExtensions,
- exclude,
- include
- );
+ constructor(private projectFiles: string[], private fileSpec: TsFilesSpec, private workspaceRoot: string) {}
- this.projectFiles = Array.from(new Set([...this.projectFiles, ...projectFiles]));
- }
+ updateProjectFiles() {
+ const { include, exclude } = this.fileSpec;
- updateProjectFile(fileName: string, changes?: TextDocumentContentChangeEvent[]): void {
- const previousSnapshot = this.get(fileName);
-
- if (changes) {
- if (!(previousSnapshot instanceof TypeScriptDocumentSnapshot)) {
- return;
- }
- previousSnapshot.update(changes);
- } else {
- const newSnapshot = createDocumentSnapshot(fileName);
-
- if (previousSnapshot) {
- newSnapshot.version = previousSnapshot.version + 1;
- } else {
- // ensure it's greater than initial version
- // so that ts server picks up the change
- newSnapshot.version += 1;
- }
- this.set(fileName, newSnapshot);
- }
- }
+ if (include?.length === 0) return;
- has(fileName: string) {
- return this.projectFiles.includes(fileName) || this.getFileNames().includes(fileName);
- }
+ const projectFiles = ts.sys.readDirectory(this.workspaceRoot, this.watchExtensions, exclude, include);
- get(fileName: string) {
- return this.documents.get(fileName);
- }
-
- set(fileName: string, snapshot: DocumentSnapshot) {
- // const prev = this.get(fileName);
- this.logStatistics();
- return this.documents.set(fileName, snapshot);
- }
-
- delete(fileName: string) {
- this.projectFiles = this.projectFiles.filter((s) => s !== fileName);
- return this.documents.delete(fileName);
- }
+ this.projectFiles = Array.from(new Set([...this.projectFiles, ...projectFiles]));
+ }
- getFileNames() {
- return Array.from(this.documents.keys()).map(fileName => toVirtualAstroFilePath(fileName));
- }
+ updateProjectFile(fileName: string, changes?: TextDocumentContentChangeEvent[]): void {
+ const previousSnapshot = this.get(fileName);
- getProjectFileNames() {
- return [...this.projectFiles];
- }
-
- private logStatistics() {
- const date = new Date();
- // Don't use setInterval because that will keep tests running forever
- if (date.getTime() - this.lastLogged.getTime() > 60_000) {
- this.lastLogged = date;
-
- const projectFiles = this.getProjectFileNames();
- const allFiles = Array.from(new Set([...projectFiles, ...this.getFileNames()]));
- console.log(
- 'SnapshotManager File Statistics:\n' +
- `Project files: ${projectFiles.length}\n` +
- `Astro files: ${
- allFiles.filter((name) => name.endsWith('.astro')).length
- }\n` +
- `From node_modules: ${
- allFiles.filter((name) => name.includes('node_modules')).length
- }\n` +
- `Total: ${allFiles.length}`
- );
- }
- }
+ if (changes) {
+ if (!(previousSnapshot instanceof TypeScriptDocumentSnapshot)) {
+ return;
+ }
+ previousSnapshot.update(changes);
+ } else {
+ const newSnapshot = createDocumentSnapshot(fileName);
+
+ if (previousSnapshot) {
+ newSnapshot.version = previousSnapshot.version + 1;
+ } else {
+ // ensure it's greater than initial version
+ // so that ts server picks up the change
+ newSnapshot.version += 1;
+ }
+ this.set(fileName, newSnapshot);
+ }
+ }
+
+ has(fileName: string) {
+ return this.projectFiles.includes(fileName) || this.getFileNames().includes(fileName);
+ }
+
+ get(fileName: string) {
+ return this.documents.get(fileName);
+ }
+
+ set(fileName: string, snapshot: DocumentSnapshot) {
+ // const prev = this.get(fileName);
+ this.logStatistics();
+ return this.documents.set(fileName, snapshot);
+ }
+
+ delete(fileName: string) {
+ this.projectFiles = this.projectFiles.filter((s) => s !== fileName);
+ return this.documents.delete(fileName);
+ }
+
+ getFileNames() {
+ return Array.from(this.documents.keys()).map((fileName) => toVirtualAstroFilePath(fileName));
+ }
+
+ getProjectFileNames() {
+ return [...this.projectFiles];
+ }
+
+ private logStatistics() {
+ const date = new Date();
+ // Don't use setInterval because that will keep tests running forever
+ if (date.getTime() - this.lastLogged.getTime() > 60_000) {
+ this.lastLogged = date;
+
+ const projectFiles = this.getProjectFileNames();
+ const allFiles = Array.from(new Set([...projectFiles, ...this.getFileNames()]));
+ console.log(
+ 'SnapshotManager File Statistics:\n' +
+ `Project files: ${projectFiles.length}\n` +
+ `Astro files: ${allFiles.filter((name) => name.endsWith('.astro')).length}\n` +
+ `From node_modules: ${allFiles.filter((name) => name.includes('node_modules')).length}\n` +
+ `Total: ${allFiles.length}`
+ );
+ }
+ }
}
export interface DocumentSnapshot extends ts.IScriptSnapshot {
- version: number;
- filePath: string;
- scriptKind: ts.ScriptKind;
- positionAt(offset: number): Position;
- /**
- * Instantiates a source mapper.
- * `destroyFragment` needs to be called when
- * it's no longer needed / the class should be cleaned up
- * in order to prevent memory leaks.
- */
- getFragment(): Promise<DocumentFragmentSnapshot>;
- /**
- * Needs to be called when source mapper
- * is no longer needed / the class should be cleaned up
- * in order to prevent memory leaks.
- */
- destroyFragment(): void;
- /**
- * Convenience function for getText(0, getLength())
- */
- getFullText(): string;
+ version: number;
+ filePath: string;
+ scriptKind: ts.ScriptKind;
+ positionAt(offset: number): Position;
+ /**
+ * Instantiates a source mapper.
+ * `destroyFragment` needs to be called when
+ * it's no longer needed / the class should be cleaned up
+ * in order to prevent memory leaks.
+ */
+ getFragment(): Promise<DocumentFragmentSnapshot>;
+ /**
+ * Needs to be called when source mapper
+ * is no longer needed / the class should be cleaned up
+ * in order to prevent memory leaks.
+ */
+ destroyFragment(): void;
+ /**
+ * Convenience function for getText(0, getLength())
+ */
+ getFullText(): string;
}
export const createDocumentSnapshot = (filePath: string, createDocument?: (_filePath: string, text: string) => Document): DocumentSnapshot => {
- const text = ts.sys.readFile(filePath) ?? '';
+ const text = ts.sys.readFile(filePath) ?? '';
- if (isAstroFilePath(filePath)) {
- if (!createDocument) throw new Error('Astro documents require the "createDocument" utility to be provided');
- const snapshot = new AstroDocumentSnapshot(createDocument(filePath, text));
- return snapshot;
- }
-
- return new TypeScriptDocumentSnapshot(0, filePath, text);
+ if (isAstroFilePath(filePath)) {
+ if (!createDocument) throw new Error('Astro documents require the "createDocument" utility to be provided');
+ const snapshot = new AstroDocumentSnapshot(createDocument(filePath, text));
+ return snapshot;
+ }
-}
+ return new TypeScriptDocumentSnapshot(0, filePath, text);
+};
class AstroDocumentSnapshot implements DocumentSnapshot {
-
- version = this.doc.version;
- scriptKind = ts.ScriptKind.Unknown;
-
- constructor(private doc: Document) {}
-
- async getFragment(): Promise<DocumentFragmentSnapshot> {
- return new DocumentFragmentSnapshot(this.doc);
- }
+ version = this.doc.version;
+ scriptKind = ts.ScriptKind.Unknown;
- async destroyFragment() {
- return;
- }
+ constructor(private doc: Document) {}
- get text() {
- return this.doc.getText();
- }
+ async getFragment(): Promise<DocumentFragmentSnapshot> {
+ return new DocumentFragmentSnapshot(this.doc);
+ }
- get filePath() {
- return this.doc.getFilePath() || '';
- }
+ async destroyFragment() {
+ return;
+ }
- getText(start: number, end: number) {
- return this.text.substring(start, end);
- }
+ get text() {
+ return this.doc.getText();
+ }
- getLength() {
- return this.text.length;
- }
+ get filePath() {
+ return this.doc.getFilePath() || '';
+ }
- getFullText() {
- return this.text;
- }
+ getText(start: number, end: number) {
+ return this.text.substring(start, end);
+ }
- getChangeRange() {
- return undefined;
- }
+ getLength() {
+ return this.text.length;
+ }
- positionAt(offset: number) {
- return positionAt(offset, this.text);
- }
+ getFullText() {
+ return this.text;
+ }
- getLineContainingOffset(offset: number) {
- const chunks = this.getText(0, offset).split('\n');
- return chunks[chunks.length - 1];
- }
-
- offsetAt(position: Position) {
- return offsetAt(position, this.text);
- }
-
-}
+ getChangeRange() {
+ return undefined;
+ }
-class DocumentFragmentSnapshot implements Omit<DocumentSnapshot, 'getFragment'|'destroyFragment'> {
-
- version: number;
- filePath: string;
- url: string;
- text: string;
-
- scriptKind = ts.ScriptKind.TSX;
- scriptInfo = null;
-
- constructor(
- private doc: Document
- ) {
- const filePath = doc.getFilePath();
- if (!filePath) throw new Error('Cannot create a document fragment from a non-local document');
- const text = doc.getText();
- this.version = doc.version;
- this.filePath = toVirtualAstroFilePath(filePath);
- this.url = toVirtualAstroFilePath(filePath);
- this.text = this.transformContent(text);
- }
+ positionAt(offset: number) {
+ return positionAt(offset, this.text);
+ }
- /** @internal */
- private transformContent(content: string) {
- return content.replace(/---/g, '///');
- }
+ getLineContainingOffset(offset: number) {
+ const chunks = this.getText(0, offset).split('\n');
+ return chunks[chunks.length - 1];
+ }
- getText(start: number, end: number) {
- return this.text.substring(start, end);
- }
-
- getLength() {
- return this.text.length;
- }
-
- getFullText() {
- return this.text;
- }
-
- getChangeRange() {
- return undefined;
- }
-
- positionAt(offset: number) {
- return positionAt(offset, this.text);
- }
-
- getLineContainingOffset(offset: number) {
- const chunks = this.getText(0, offset).split('\n');
- return chunks[chunks.length - 1];
- }
+ offsetAt(position: Position) {
+ return offsetAt(position, this.text);
+ }
+}
- offsetAt(position: Position): number {
- return offsetAt(position, this.text);
- }
+class DocumentFragmentSnapshot implements Omit<DocumentSnapshot, 'getFragment' | 'destroyFragment'> {
+ version: number;
+ filePath: string;
+ url: string;
+ text: string;
+
+ scriptKind = ts.ScriptKind.TSX;
+ scriptInfo = null;
+
+ constructor(private doc: Document) {
+ const filePath = doc.getFilePath();
+ if (!filePath) throw new Error('Cannot create a document fragment from a non-local document');
+ const text = doc.getText();
+ this.version = doc.version;
+ this.filePath = toVirtualAstroFilePath(filePath);
+ this.url = toVirtualAstroFilePath(filePath);
+ this.text = this.transformContent(text);
+ }
+
+ /** @internal */
+ private transformContent(content: string) {
+ return content.replace(/---/g, '///');
+ }
+
+ getText(start: number, end: number) {
+ return this.text.substring(start, end);
+ }
+
+ getLength() {
+ return this.text.length;
+ }
+
+ getFullText() {
+ return this.text;
+ }
+
+ getChangeRange() {
+ return undefined;
+ }
+
+ positionAt(offset: number) {
+ return positionAt(offset, this.text);
+ }
+
+ getLineContainingOffset(offset: number) {
+ const chunks = this.getText(0, offset).split('\n');
+ return chunks[chunks.length - 1];
+ }
+
+ offsetAt(position: Position): number {
+ return offsetAt(position, this.text);
+ }
}
class TypeScriptDocumentSnapshot implements DocumentSnapshot {
-
- scriptKind = getScriptKindFromFileName(this.filePath);
- scriptInfo = null;
- url: string;
-
-
- constructor(public version: number, public readonly filePath: string, private text: string) {
- this.url = pathToUrl(filePath)
- }
-
- getText(start: number, end: number) {
- return this.text.substring(start, end);
- }
-
- getLength() {
- return this.text.length;
- }
-
- getFullText() {
- return this.text;
- }
-
- getChangeRange() {
- return undefined;
- }
-
- positionAt(offset: number) {
- return positionAt(offset, this.text);
- }
-
- offsetAt(position: Position): number {
- return offsetAt(position, this.text);
- }
-
- async getFragment(): Promise<DocumentFragmentSnapshot> {
- return this as unknown as any;
- }
-
- destroyFragment() {
- // nothing to clean up
- }
-
- getLineContainingOffset(offset: number) {
- const chunks = this.getText(0, offset).split('\n');
- return chunks[chunks.length - 1];
- }
-
- update(changes: TextDocumentContentChangeEvent[]): void {
- for (const change of changes) {
- let start = 0;
- let end = 0;
- if ('range' in change) {
- start = this.offsetAt(change.range.start);
- end = this.offsetAt(change.range.end);
- } else {
- end = this.getLength();
- }
-
- this.text = this.text.slice(0, start) + change.text + this.text.slice(end);
- }
-
- this.version++;
- }
+ scriptKind = getScriptKindFromFileName(this.filePath);
+ scriptInfo = null;
+ url: string;
+
+ constructor(public version: number, public readonly filePath: string, private text: string) {
+ this.url = pathToUrl(filePath);
+ }
+
+ getText(start: number, end: number) {
+ return this.text.substring(start, end);
+ }
+
+ getLength() {
+ return this.text.length;
+ }
+
+ getFullText() {
+ return this.text;
+ }
+
+ getChangeRange() {
+ return undefined;
+ }
+
+ positionAt(offset: number) {
+ return positionAt(offset, this.text);
+ }
+
+ offsetAt(position: Position): number {
+ return offsetAt(position, this.text);
+ }
+
+ async getFragment(): Promise<DocumentFragmentSnapshot> {
+ return (this as unknown) as any;
+ }
+
+ destroyFragment() {
+ // nothing to clean up
+ }
+
+ getLineContainingOffset(offset: number) {
+ const chunks = this.getText(0, offset).split('\n');
+ return chunks[chunks.length - 1];
+ }
+
+ update(changes: TextDocumentContentChangeEvent[]): void {
+ for (const change of changes) {
+ let start = 0;
+ let end = 0;
+ if ('range' in change) {
+ start = this.offsetAt(change.range.start);
+ end = this.offsetAt(change.range.end);
+ } else {
+ end = this.getLength();
+ }
+
+ this.text = this.text.slice(0, start) + change.text + this.text.slice(end);
+ }
+
+ this.version++;
+ }
}
diff --git a/tools/vscode/packages/server/src/plugins/typescript/TypeScriptPlugin.ts b/tools/vscode/packages/server/src/plugins/typescript/TypeScriptPlugin.ts
index 018e8bfda..aab758bdb 100644
--- a/tools/vscode/packages/server/src/plugins/typescript/TypeScriptPlugin.ts
+++ b/tools/vscode/packages/server/src/plugins/typescript/TypeScriptPlugin.ts
@@ -1,11 +1,7 @@
import type { Document, DocumentManager } from '../../core/documents';
import type { ConfigManager } from '../../core/config';
import type { CompletionsProvider, AppCompletionItem, AppCompletionList } from '../interfaces';
-import {
- CompletionContext,
- Position,
- FileChangeType
-} from 'vscode-languageserver';
+import { CompletionContext, Position, FileChangeType } from 'vscode-languageserver';
import * as ts from 'typescript';
import { CompletionsProviderImpl, CompletionEntryWithIdentifer } from './features/CompletionsProvider';
import { LanguageServiceManager } from './LanguageServiceManager';
@@ -13,77 +9,61 @@ import { SnapshotManager } from './SnapshotManager';
import { getScriptKindFromFileName } from './utils';
export class TypeScriptPlugin implements CompletionsProvider {
- private readonly docManager: DocumentManager;
- private readonly configManager: ConfigManager;
- private readonly languageServiceManager: LanguageServiceManager;
+ private readonly docManager: DocumentManager;
+ private readonly configManager: ConfigManager;
+ private readonly languageServiceManager: LanguageServiceManager;
- private readonly completionProvider: CompletionsProviderImpl;
+ private readonly completionProvider: CompletionsProviderImpl;
- constructor(
- docManager: DocumentManager,
- configManager: ConfigManager,
- workspaceUris: string[]
- ) {
- this.docManager = docManager;
- this.configManager = configManager;
- this.languageServiceManager = new LanguageServiceManager(docManager, configManager, workspaceUris);
-
- this.completionProvider = new CompletionsProviderImpl(this.languageServiceManager);
- }
+ constructor(docManager: DocumentManager, configManager: ConfigManager, workspaceUris: string[]) {
+ this.docManager = docManager;
+ this.configManager = configManager;
+ this.languageServiceManager = new LanguageServiceManager(docManager, configManager, workspaceUris);
- async getCompletions(
- document: Document,
- position: Position,
- completionContext?: CompletionContext
- ): Promise<AppCompletionList<CompletionEntryWithIdentifer> | null> {
- const completions = await this.completionProvider.getCompletions(
- document,
- position,
- completionContext
- );
+ this.completionProvider = new CompletionsProviderImpl(this.languageServiceManager);
+ }
- return completions;
- }
+ async getCompletions(document: Document, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList<CompletionEntryWithIdentifer> | null> {
+ const completions = await this.completionProvider.getCompletions(document, position, completionContext);
- async resolveCompletion(
- document: Document,
- completionItem: AppCompletionItem<CompletionEntryWithIdentifer>
- ): Promise<AppCompletionItem<CompletionEntryWithIdentifer>> {
- return this.completionProvider.resolveCompletion(document, completionItem);
- }
+ return completions;
+ }
- async onWatchFileChanges(onWatchFileChangesParams: any[]): Promise<void> {
- const doneUpdateProjectFiles = new Set<SnapshotManager>();
+ async resolveCompletion(document: Document, completionItem: AppCompletionItem<CompletionEntryWithIdentifer>): Promise<AppCompletionItem<CompletionEntryWithIdentifer>> {
+ return this.completionProvider.resolveCompletion(document, completionItem);
+ }
- for (const { fileName, changeType } of onWatchFileChangesParams) {
- const scriptKind = getScriptKindFromFileName(fileName);
+ async onWatchFileChanges(onWatchFileChangesParams: any[]): Promise<void> {
+ const doneUpdateProjectFiles = new Set<SnapshotManager>();
- if (scriptKind === ts.ScriptKind.Unknown) {
- // We don't deal with svelte files here
- continue;
- }
+ for (const { fileName, changeType } of onWatchFileChangesParams) {
+ const scriptKind = getScriptKindFromFileName(fileName);
- const snapshotManager = await this.getSnapshotManager(fileName);
- if (changeType === FileChangeType.Created) {
- if (!doneUpdateProjectFiles.has(snapshotManager)) {
- snapshotManager.updateProjectFiles();
- doneUpdateProjectFiles.add(snapshotManager);
- }
- } else if (changeType === FileChangeType.Deleted) {
- snapshotManager.delete(fileName);
- return;
- }
+ if (scriptKind === ts.ScriptKind.Unknown) {
+ // We don't deal with svelte files here
+ continue;
+ }
- snapshotManager.updateProjectFile(fileName);
+ const snapshotManager = await this.getSnapshotManager(fileName);
+ if (changeType === FileChangeType.Created) {
+ if (!doneUpdateProjectFiles.has(snapshotManager)) {
+ snapshotManager.updateProjectFiles();
+ doneUpdateProjectFiles.add(snapshotManager);
}
- }
+ } else if (changeType === FileChangeType.Deleted) {
+ snapshotManager.delete(fileName);
+ return;
+ }
- /**
- *
- * @internal
- */
- public async getSnapshotManager(fileName: string) {
- return this.languageServiceManager.getSnapshotManager(fileName);
+ snapshotManager.updateProjectFile(fileName);
}
-}
+ }
+ /**
+ *
+ * @internal
+ */
+ public async getSnapshotManager(fileName: string) {
+ return this.languageServiceManager.getSnapshotManager(fileName);
+ }
+}
diff --git a/tools/vscode/packages/server/src/plugins/typescript/astro-sys.ts b/tools/vscode/packages/server/src/plugins/typescript/astro-sys.ts
index 0459528c5..36d009eb6 100644
--- a/tools/vscode/packages/server/src/plugins/typescript/astro-sys.ts
+++ b/tools/vscode/packages/server/src/plugins/typescript/astro-sys.ts
@@ -6,37 +6,37 @@ import { ensureRealAstroFilePath, isAstroFilePath, isVirtualAstroFilePath, toRea
* This should only be accessed by TS Astro module resolution.
*/
export function createAstroSys(getSnapshot: (fileName: string) => DocumentSnapshot) {
- const AstroSys: ts.System = {
- ...ts.sys,
- fileExists(path: string) {
- if (isAstroFilePath(path) || isVirtualAstroFilePath(path)) {
- console.log('fileExists', path, ts.sys.fileExists(ensureRealAstroFilePath(path)));
- }
- return ts.sys.fileExists(ensureRealAstroFilePath(path));
- },
- readFile(path: string) {
- if (isAstroFilePath(path) || isVirtualAstroFilePath(path)) {
- console.log('readFile', path);
- }
- const snapshot = getSnapshot(path);
- return snapshot.getFullText();
- },
- readDirectory(path, extensions, exclude, include, depth) {
- const extensionsWithAstro = (extensions ?? []).concat(...['.astro']);
- const result = ts.sys.readDirectory(path, extensionsWithAstro, exclude, include, depth);;
- return result;
- }
- };
+ const AstroSys: ts.System = {
+ ...ts.sys,
+ fileExists(path: string) {
+ if (isAstroFilePath(path) || isVirtualAstroFilePath(path)) {
+ console.log('fileExists', path, ts.sys.fileExists(ensureRealAstroFilePath(path)));
+ }
+ return ts.sys.fileExists(ensureRealAstroFilePath(path));
+ },
+ readFile(path: string) {
+ if (isAstroFilePath(path) || isVirtualAstroFilePath(path)) {
+ console.log('readFile', path);
+ }
+ const snapshot = getSnapshot(path);
+ return snapshot.getFullText();
+ },
+ readDirectory(path, extensions, exclude, include, depth) {
+ const extensionsWithAstro = (extensions ?? []).concat(...['.astro']);
+ const result = ts.sys.readDirectory(path, extensionsWithAstro, exclude, include, depth);
+ return result;
+ },
+ };
- if (ts.sys.realpath) {
- const realpath = ts.sys.realpath;
- AstroSys.realpath = function (path) {
- if (isVirtualAstroFilePath(path)) {
- return realpath(toRealAstroFilePath(path)) + '.ts';
- }
- return realpath(path);
- };
- }
+ if (ts.sys.realpath) {
+ const realpath = ts.sys.realpath;
+ AstroSys.realpath = function (path) {
+ if (isVirtualAstroFilePath(path)) {
+ return realpath(toRealAstroFilePath(path)) + '.ts';
+ }
+ return realpath(path);
+ };
+ }
- return AstroSys;
+ return AstroSys;
}
diff --git a/tools/vscode/packages/server/src/plugins/typescript/features/CompletionsProvider.ts b/tools/vscode/packages/server/src/plugins/typescript/features/CompletionsProvider.ts
index ebbc16e31..348f3e4ae 100644
--- a/tools/vscode/packages/server/src/plugins/typescript/features/CompletionsProvider.ts
+++ b/tools/vscode/packages/server/src/plugins/typescript/features/CompletionsProvider.ts
@@ -99,7 +99,7 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionEn
data: {
...comp,
uri,
- position
+ position,
},
};
}
diff --git a/tools/vscode/packages/server/src/plugins/typescript/languageService.ts b/tools/vscode/packages/server/src/plugins/typescript/languageService.ts
index 4de703b2a..098c335e7 100644
--- a/tools/vscode/packages/server/src/plugins/typescript/languageService.ts
+++ b/tools/vscode/packages/server/src/plugins/typescript/languageService.ts
@@ -53,30 +53,22 @@ async function createLanguageService(tsconfigPath: string, workspaceRoot: string
return ts.sys.readDirectory(path, [...extensions, '.vue', '.svelte', '.astro', '.js', '.jsx'], exclude, include, depth);
},
};
-
+
let configJson = (tsconfigPath && ts.readConfigFile(tsconfigPath, ts.sys.readFile).config) || getDefaultJsConfig();
if (!configJson.extends) {
- configJson = Object.assign(
- {
- exclude: getDefaultExclude()
- },
- configJson
- );
+ configJson = Object.assign(
+ {
+ exclude: getDefaultExclude(),
+ },
+ configJson
+ );
}
- const project = ts.parseJsonConfigFileContent(
- configJson,
- parseConfigHost,
- workspaceRoot,
- {},
- basename(tsconfigPath),
- undefined,
- [
- { extension: '.vue', isMixedContent: true, scriptKind: ts.ScriptKind.Deferred },
- { extension: '.svelte', isMixedContent: true, scriptKind: ts.ScriptKind.Deferred },
- { extension: '.astro', isMixedContent: true, scriptKind: ts.ScriptKind.Deferred }
- ]
- );
+ const project = ts.parseJsonConfigFileContent(configJson, parseConfigHost, workspaceRoot, {}, basename(tsconfigPath), undefined, [
+ { extension: '.vue', isMixedContent: true, scriptKind: ts.ScriptKind.Deferred },
+ { extension: '.svelte', isMixedContent: true, scriptKind: ts.ScriptKind.Deferred },
+ { extension: '.astro', isMixedContent: true, scriptKind: ts.ScriptKind.Deferred },
+ ]);
let projectVersion = 0;
const snapshotManager = new SnapshotManager(project.fileNames, { exclude: ['node_modules', 'dist'], include: ['astro'] }, workspaceRoot || process.cwd());
@@ -100,15 +92,15 @@ async function createLanguageService(tsconfigPath: string, workspaceRoot: string
getProjectVersion: () => `${projectVersion}`,
getScriptFileNames: () => Array.from(new Set([...snapshotManager.getFileNames(), ...snapshotManager.getProjectFileNames()])),
getScriptSnapshot,
- getScriptVersion: (fileName: string) => getScriptSnapshot(fileName).version.toString()
+ getScriptVersion: (fileName: string) => getScriptSnapshot(fileName).version.toString(),
};
const languageService = ts.createLanguageService(host);
const languageServiceProxy = new Proxy(languageService, {
get(target, prop) {
return Reflect.get(target, prop);
- }
- })
+ },
+ });
return {
tsconfigPath,
@@ -141,19 +133,16 @@ async function createLanguageService(tsconfigPath: string, workspaceRoot: string
}
function getScriptSnapshot(fileName: string): DocumentSnapshot {
- fileName = ensureRealAstroFilePath(fileName);
-
- let doc = snapshotManager.get(fileName);
- if (doc) {
- return doc;
- }
-
- doc = createDocumentSnapshot(
- fileName,
- docContext.createDocument,
- );
- snapshotManager.set(fileName, doc);
+ fileName = ensureRealAstroFilePath(fileName);
+
+ let doc = snapshotManager.get(fileName);
+ if (doc) {
return doc;
+ }
+
+ doc = createDocumentSnapshot(fileName, docContext.createDocument);
+ snapshotManager.set(fileName, doc);
+ return doc;
}
}
@@ -168,7 +157,7 @@ function getDefaultJsConfig(): {
compilerOptions: {
maxNodeModuleJsDepth: 2,
allowSyntheticDefaultImports: true,
- allowJs: true
+ allowJs: true,
},
include: ['astro'],
};
diff --git a/tools/vscode/packages/server/src/plugins/typescript/utils.ts b/tools/vscode/packages/server/src/plugins/typescript/utils.ts
index 058868474..1f42e7d0a 100644
--- a/tools/vscode/packages/server/src/plugins/typescript/utils.ts
+++ b/tools/vscode/packages/server/src/plugins/typescript/utils.ts
@@ -3,180 +3,172 @@ import { CompletionItemKind, DiagnosticSeverity } from 'vscode-languageserver';
import { dirname } from 'path';
import { pathToUrl } from '../../utils';
-export function scriptElementKindToCompletionItemKind(
- kind: ts.ScriptElementKind
-): CompletionItemKind {
- switch (kind) {
- case ts.ScriptElementKind.primitiveType:
- case ts.ScriptElementKind.keyword:
- return CompletionItemKind.Keyword;
- case ts.ScriptElementKind.constElement:
- return CompletionItemKind.Constant;
- case ts.ScriptElementKind.letElement:
- case ts.ScriptElementKind.variableElement:
- case ts.ScriptElementKind.localVariableElement:
- case ts.ScriptElementKind.alias:
- return CompletionItemKind.Variable;
- case ts.ScriptElementKind.memberVariableElement:
- case ts.ScriptElementKind.memberGetAccessorElement:
- case ts.ScriptElementKind.memberSetAccessorElement:
- return CompletionItemKind.Field;
- case ts.ScriptElementKind.functionElement:
- return CompletionItemKind.Function;
- case ts.ScriptElementKind.memberFunctionElement:
- case ts.ScriptElementKind.constructSignatureElement:
- case ts.ScriptElementKind.callSignatureElement:
- case ts.ScriptElementKind.indexSignatureElement:
- return CompletionItemKind.Method;
- case ts.ScriptElementKind.enumElement:
- return CompletionItemKind.Enum;
- case ts.ScriptElementKind.moduleElement:
- case ts.ScriptElementKind.externalModuleName:
- return CompletionItemKind.Module;
- case ts.ScriptElementKind.classElement:
- case ts.ScriptElementKind.typeElement:
- return CompletionItemKind.Class;
- case ts.ScriptElementKind.interfaceElement:
- return CompletionItemKind.Interface;
- case ts.ScriptElementKind.warning:
- case ts.ScriptElementKind.scriptElement:
- return CompletionItemKind.File;
- case ts.ScriptElementKind.directory:
- return CompletionItemKind.Folder;
- case ts.ScriptElementKind.string:
- return CompletionItemKind.Constant;
- }
- return CompletionItemKind.Property;
+export function scriptElementKindToCompletionItemKind(kind: ts.ScriptElementKind): CompletionItemKind {
+ switch (kind) {
+ case ts.ScriptElementKind.primitiveType:
+ case ts.ScriptElementKind.keyword:
+ return CompletionItemKind.Keyword;
+ case ts.ScriptElementKind.constElement:
+ return CompletionItemKind.Constant;
+ case ts.ScriptElementKind.letElement:
+ case ts.ScriptElementKind.variableElement:
+ case ts.ScriptElementKind.localVariableElement:
+ case ts.ScriptElementKind.alias:
+ return CompletionItemKind.Variable;
+ case ts.ScriptElementKind.memberVariableElement:
+ case ts.ScriptElementKind.memberGetAccessorElement:
+ case ts.ScriptElementKind.memberSetAccessorElement:
+ return CompletionItemKind.Field;
+ case ts.ScriptElementKind.functionElement:
+ return CompletionItemKind.Function;
+ case ts.ScriptElementKind.memberFunctionElement:
+ case ts.ScriptElementKind.constructSignatureElement:
+ case ts.ScriptElementKind.callSignatureElement:
+ case ts.ScriptElementKind.indexSignatureElement:
+ return CompletionItemKind.Method;
+ case ts.ScriptElementKind.enumElement:
+ return CompletionItemKind.Enum;
+ case ts.ScriptElementKind.moduleElement:
+ case ts.ScriptElementKind.externalModuleName:
+ return CompletionItemKind.Module;
+ case ts.ScriptElementKind.classElement:
+ case ts.ScriptElementKind.typeElement:
+ return CompletionItemKind.Class;
+ case ts.ScriptElementKind.interfaceElement:
+ return CompletionItemKind.Interface;
+ case ts.ScriptElementKind.warning:
+ case ts.ScriptElementKind.scriptElement:
+ return CompletionItemKind.File;
+ case ts.ScriptElementKind.directory:
+ return CompletionItemKind.Folder;
+ case ts.ScriptElementKind.string:
+ return CompletionItemKind.Constant;
+ }
+ return CompletionItemKind.Property;
}
-export function getCommitCharactersForScriptElement(
- kind: ts.ScriptElementKind
-): string[] | undefined {
- const commitCharacters: string[] = [];
- switch (kind) {
- case ts.ScriptElementKind.memberGetAccessorElement:
- case ts.ScriptElementKind.memberSetAccessorElement:
- case ts.ScriptElementKind.constructSignatureElement:
- case ts.ScriptElementKind.callSignatureElement:
- case ts.ScriptElementKind.indexSignatureElement:
- case ts.ScriptElementKind.enumElement:
- case ts.ScriptElementKind.interfaceElement:
- commitCharacters.push('.');
- break;
-
- case ts.ScriptElementKind.moduleElement:
- case ts.ScriptElementKind.alias:
- case ts.ScriptElementKind.constElement:
- case ts.ScriptElementKind.letElement:
- case ts.ScriptElementKind.variableElement:
- case ts.ScriptElementKind.localVariableElement:
- case ts.ScriptElementKind.memberVariableElement:
- case ts.ScriptElementKind.classElement:
- case ts.ScriptElementKind.functionElement:
- case ts.ScriptElementKind.memberFunctionElement:
- commitCharacters.push('.', ',');
- commitCharacters.push('(');
- break;
- }
-
- return commitCharacters.length === 0 ? undefined : commitCharacters;
+export function getCommitCharactersForScriptElement(kind: ts.ScriptElementKind): string[] | undefined {
+ const commitCharacters: string[] = [];
+ switch (kind) {
+ case ts.ScriptElementKind.memberGetAccessorElement:
+ case ts.ScriptElementKind.memberSetAccessorElement:
+ case ts.ScriptElementKind.constructSignatureElement:
+ case ts.ScriptElementKind.callSignatureElement:
+ case ts.ScriptElementKind.indexSignatureElement:
+ case ts.ScriptElementKind.enumElement:
+ case ts.ScriptElementKind.interfaceElement:
+ commitCharacters.push('.');
+ break;
+
+ case ts.ScriptElementKind.moduleElement:
+ case ts.ScriptElementKind.alias:
+ case ts.ScriptElementKind.constElement:
+ case ts.ScriptElementKind.letElement:
+ case ts.ScriptElementKind.variableElement:
+ case ts.ScriptElementKind.localVariableElement:
+ case ts.ScriptElementKind.memberVariableElement:
+ case ts.ScriptElementKind.classElement:
+ case ts.ScriptElementKind.functionElement:
+ case ts.ScriptElementKind.memberFunctionElement:
+ commitCharacters.push('.', ',');
+ commitCharacters.push('(');
+ break;
+ }
+
+ return commitCharacters.length === 0 ? undefined : commitCharacters;
}
export function mapSeverity(category: ts.DiagnosticCategory): DiagnosticSeverity {
- switch (category) {
- case ts.DiagnosticCategory.Error:
- return DiagnosticSeverity.Error;
- case ts.DiagnosticCategory.Warning:
- return DiagnosticSeverity.Warning;
- case ts.DiagnosticCategory.Suggestion:
- return DiagnosticSeverity.Hint;
- case ts.DiagnosticCategory.Message:
- return DiagnosticSeverity.Information;
- }
-
- return DiagnosticSeverity.Error;
+ switch (category) {
+ case ts.DiagnosticCategory.Error:
+ return DiagnosticSeverity.Error;
+ case ts.DiagnosticCategory.Warning:
+ return DiagnosticSeverity.Warning;
+ case ts.DiagnosticCategory.Suggestion:
+ return DiagnosticSeverity.Hint;
+ case ts.DiagnosticCategory.Message:
+ return DiagnosticSeverity.Information;
+ }
+
+ return DiagnosticSeverity.Error;
}
export function getScriptKindFromFileName(fileName: string): ts.ScriptKind {
- const ext = fileName.substr(fileName.lastIndexOf('.'));
- switch (ext.toLowerCase()) {
- case ts.Extension.Js:
- return ts.ScriptKind.JS;
- case ts.Extension.Jsx:
- return ts.ScriptKind.JSX;
- case ts.Extension.Ts:
- return ts.ScriptKind.TS;
- case ts.Extension.Tsx:
- return ts.ScriptKind.TSX;
- case ts.Extension.Json:
- return ts.ScriptKind.JSON;
- default:
- return ts.ScriptKind.Unknown;
- }
+ const ext = fileName.substr(fileName.lastIndexOf('.'));
+ switch (ext.toLowerCase()) {
+ case ts.Extension.Js:
+ return ts.ScriptKind.JS;
+ case ts.Extension.Jsx:
+ return ts.ScriptKind.JSX;
+ case ts.Extension.Ts:
+ return ts.ScriptKind.TS;
+ case ts.Extension.Tsx:
+ return ts.ScriptKind.TSX;
+ case ts.Extension.Json:
+ return ts.ScriptKind.JSON;
+ default:
+ return ts.ScriptKind.Unknown;
+ }
}
export function isAstroFilePath(filePath: string) {
- return filePath.endsWith('.astro');
+ return filePath.endsWith('.astro');
}
export function isVirtualAstroFilePath(filePath: string) {
- return filePath.endsWith('.astro.ts');
+ return filePath.endsWith('.astro.ts');
}
export function toVirtualAstroFilePath(filePath: string) {
- return `${filePath}.ts`;
+ return `${filePath}.ts`;
}
export function toRealAstroFilePath(filePath: string) {
- return filePath.slice(0, -'.ts'.length);
+ return filePath.slice(0, -'.ts'.length);
}
export function ensureRealAstroFilePath(filePath: string) {
- return isVirtualAstroFilePath(filePath) ? toRealAstroFilePath(filePath) : filePath;
+ return isVirtualAstroFilePath(filePath) ? toRealAstroFilePath(filePath) : filePath;
}
export function findTsConfigPath(fileName: string, rootUris: string[]) {
- const searchDir = dirname(fileName);
- const path =
- ts.findConfigFile(searchDir, ts.sys.fileExists, 'tsconfig.json') ||
- ts.findConfigFile(searchDir, ts.sys.fileExists, 'jsconfig.json') ||
- '';
- // Don't return config files that exceed the current workspace context.
- return !!path && rootUris.some((rootUri) => isSubPath(rootUri, path)) ? path : '';
+ const searchDir = dirname(fileName);
+ const path = ts.findConfigFile(searchDir, ts.sys.fileExists, 'tsconfig.json') || ts.findConfigFile(searchDir, ts.sys.fileExists, 'jsconfig.json') || '';
+ // Don't return config files that exceed the current workspace context.
+ return !!path && rootUris.some((rootUri) => isSubPath(rootUri, path)) ? path : '';
}
/** */
export function isSubPath(uri: string, possibleSubPath: string): boolean {
- return pathToUrl(possibleSubPath).startsWith(uri);
+ return pathToUrl(possibleSubPath).startsWith(uri);
}
-
/** Substitutes */
export function substituteWithWhitespace(result: string, start: number, end: number, oldContent: string, before: string, after: string) {
- let accumulatedWS = 0;
- result += before;
- for (let i = start + before.length; i < end; i++) {
- let ch = oldContent[i];
- if (ch === '\n' || ch === '\r') {
- // only write new lines, skip the whitespace
- accumulatedWS = 0;
- result += ch;
- } else {
- accumulatedWS++;
- }
- }
- result = append(result, ' ', accumulatedWS - after.length);
- result += after;
- return result;
+ let accumulatedWS = 0;
+ result += before;
+ for (let i = start + before.length; i < end; i++) {
+ let ch = oldContent[i];
+ if (ch === '\n' || ch === '\r') {
+ // only write new lines, skip the whitespace
+ accumulatedWS = 0;
+ result += ch;
+ } else {
+ accumulatedWS++;
+ }
+ }
+ result = append(result, ' ', accumulatedWS - after.length);
+ result += after;
+ return result;
}
function append(result: string, str: string, n: number): string {
- while (n > 0) {
- if (n & 1) {
- result += str;
- }
- n >>= 1;
- str += str;
- }
- return result;
+ while (n > 0) {
+ if (n & 1) {
+ result += str;
+ }
+ n >>= 1;
+ str += str;
+ }
+ return result;
}
diff --git a/tools/vscode/packages/server/src/utils.ts b/tools/vscode/packages/server/src/utils.ts
index c764aae13..f9f1acf34 100644
--- a/tools/vscode/packages/server/src/utils.ts
+++ b/tools/vscode/packages/server/src/utils.ts
@@ -4,68 +4,61 @@ import { Node } from 'vscode-html-languageservice';
/** Normalizes a document URI */
export function normalizeUri(uri: string): string {
- return URI.parse(uri).toString();
+ return URI.parse(uri).toString();
}
/** Turns a URL into a normalized FS Path */
export function urlToPath(stringUrl: string): string | null {
- const url = URI.parse(stringUrl);
- if (url.scheme !== 'file') {
- return null;
- }
- return url.fsPath.replace(/\\/g, '/');
+ const url = URI.parse(stringUrl);
+ if (url.scheme !== 'file') {
+ return null;
+ }
+ return url.fsPath.replace(/\\/g, '/');
}
/** Converts a path to a URL */
export function pathToUrl(path: string) {
- return URI.file(path).toString();
+ return URI.file(path).toString();
}
-
/**
-*
-* The language service is case insensitive, and would provide
-* hover info for Svelte components like `Option` which have
-* the same name like a html tag.
-*/
+ *
+ * The language service is case insensitive, and would provide
+ * hover info for Svelte components like `Option` which have
+ * the same name like a html tag.
+ */
export function isPossibleComponent(node: Node): boolean {
- return !!node.tag?.[0].match(/[A-Z]/);
+ return !!node.tag?.[0].match(/[A-Z]/);
}
/**
-*
-* The language service is case insensitive, and would provide
-* hover info for Svelte components like `Option` which have
-* the same name like a html tag.
-*/
+ *
+ * The language service is case insensitive, and would provide
+ * hover info for Svelte components like `Option` which have
+ * the same name like a html tag.
+ */
export function isPossibleClientComponent(node: Node): boolean {
- return isPossibleComponent(node) && (node.tag?.indexOf(':') ?? -1) > -1;
+ return isPossibleComponent(node) && (node.tag?.indexOf(':') ?? -1) > -1;
}
/** Flattens an array */
export function flatten<T>(arr: T[][]): T[] {
- return arr.reduce((all, item) => [...all, ...item], []);
+ return arr.reduce((all, item) => [...all, ...item], []);
}
/** Clamps a number between min and max */
export function clamp(num: number, min: number, max: number): number {
- return Math.max(min, Math.min(max, num));
+ return Math.max(min, Math.min(max, num));
}
/** Checks if a position is inside range */
export function isInRange(positionToTest: Position, range: Range): boolean {
- return (
- isBeforeOrEqualToPosition(range.end, positionToTest) &&
- isBeforeOrEqualToPosition(positionToTest, range.start)
- );
+ return isBeforeOrEqualToPosition(range.end, positionToTest) && isBeforeOrEqualToPosition(positionToTest, range.start);
}
/** */
export function isBeforeOrEqualToPosition(position: Position, positionToTest: Position): boolean {
- return (
- positionToTest.line < position.line ||
- (positionToTest.line === position.line && positionToTest.character <= position.character)
- );
+ return positionToTest.line < position.line || (positionToTest.line === position.line && positionToTest.character <= position.character);
}
/**
@@ -76,23 +69,19 @@ export function isBeforeOrEqualToPosition(position: Position, positionToTest: Po
* @param determineIfSame The function which determines if the previous invocation should be canceld or not
* @param miliseconds Number of miliseconds to debounce
*/
-export function debounceSameArg<T>(
- fn: (arg: T) => void,
- shouldCancelPrevious: (newArg: T, prevArg?: T) => boolean,
- miliseconds: number
-): (arg: T) => void {
- let timeout: any;
- let prevArg: T | undefined;
+export function debounceSameArg<T>(fn: (arg: T) => void, shouldCancelPrevious: (newArg: T, prevArg?: T) => boolean, miliseconds: number): (arg: T) => void {
+ let timeout: any;
+ let prevArg: T | undefined;
- return (arg: T) => {
- if (shouldCancelPrevious(arg, prevArg)) {
- clearTimeout(timeout);
- }
+ return (arg: T) => {
+ if (shouldCancelPrevious(arg, prevArg)) {
+ clearTimeout(timeout);
+ }
- prevArg = arg;
- timeout = setTimeout(() => {
- fn(arg);
- prevArg = undefined;
- }, miliseconds);
- };
+ prevArg = arg;
+ timeout = setTimeout(() => {
+ fn(arg);
+ prevArg = undefined;
+ }, miliseconds);
+ };
}
diff --git a/tools/vscode/packages/server/tsconfig.json b/tools/vscode/packages/server/tsconfig.json
index 6af42d0b2..7b2ff1ea2 100644
--- a/tools/vscode/packages/server/tsconfig.json
+++ b/tools/vscode/packages/server/tsconfig.json
@@ -1,9 +1,9 @@
{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "outDir": "dist",
- "rootDir": "src",
- },
- "include": ["src"],
- "exclude": ["node_modules"],
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "dist",
+ "rootDir": "src"
+ },
+ "include": ["src"],
+ "exclude": ["node_modules"]
}
diff --git a/tools/vscode/syntaxes/astro.tmLanguage.json b/tools/vscode/syntaxes/astro.tmLanguage.json
index 9c09d0e71..225b023ca 100644
--- a/tools/vscode/syntaxes/astro.tmLanguage.json
+++ b/tools/vscode/syntaxes/astro.tmLanguage.json
@@ -1,704 +1,706 @@
{
- "fileTypes": [
- "astro"
- ],
- "foldingStartMarker": "(?x)\n(<(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|li|form|dl)\\b.*?>\n|<!--(?!.*--\\s*>)\n|^<!--\\ \\#tminclude\\ (?>.*?-->)$\n|<\\?(?:php)?.*\\b(if|for(each)?|while)\\b.+:\n|\\{\\{?(if|foreach|capture|literal|foreach|php|section|strip)\n|\\{\\s*($|\\?>\\s*$|\/\/|\/\\*(.*\\*\/\\s*$|(?!.*?\\*\/)))\n)",
- "foldingStopMarker": "(?x)\n(<\/(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|li|form|dl)>\n|^(?!.*?<!--).*?--\\s*>\n|^<!--\\ end\\ tminclude\\ -->$\n|<\\?(?:php)?.*\\bend(if|for(each)?|while)\\b\n|\\{\\{?\/(if|foreach|capture|literal|foreach|php|section|strip)\n|^[^{]*\\}\n)",
- "keyEquivalent": "^~H",
- "name": "Astro",
- "patterns": [
- {
- "include": "#astro-expressions"
- },
- {
- "begin": "(<)([a-zA-Z0-9:-]++)(?=[^>]*><\/\\2>)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.html"
- }
- },
- "end": "(>)(<)(\/)(\\2)(>)",
- "endCaptures": {
- "1": {
- "name": "punctuation.definition.tag.end.html"
- },
- "2": {
- "name": "punctuation.definition.tag.begin.html meta.scope.between-tag-pair.html"
- },
- "3": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "4": {
- "name": "entity.name.tag.html"
- },
- "5": {
- "name": "punctuation.definition.tag.end.html"
- }
- },
- "name": "meta.tag.any.html",
- "patterns": [
- {
- "include": "#tag-stuff"
- }
- ]
- },
- {
- "begin": "(<\\?)(xml)",
- "captures": {
- "1": {
- "name": "punctuation.definition.tag.html"
- },
- "2": {
- "name": "entity.name.tag.xml.html"
- }
- },
- "end": "(\\?>)",
- "name": "meta.tag.preprocessor.xml.html",
- "patterns": [
- {
- "include": "#tag-generic-attribute"
- },
- {
- "include": "#string-double-quoted"
- },
- {
- "include": "#string-single-quoted"
- }
- ]
- },
- {
- "begin": "<!--",
- "captures": [
- {
- "name": "punctuation.definition.comment.html"
- }
- ],
- "end": "--\\s*>",
- "name": "comment.block.html",
- "patterns": [
- {
- "match": "--",
- "name": "invalid.illegal.bad-comments-or-CDATA.html"
- }
- ]
- },
- {
- "begin": "<!",
- "captures": [
- {
- "name": "punctuation.definition.tag.html"
- }
- ],
- "end": ">",
- "name": "meta.tag.sgml.html",
- "patterns": [
- {
- "begin": "(?i:DOCTYPE|doctype)",
- "captures": {
- "1": {
- "name": "entity.name.tag.doctype.html"
- }
- },
- "end": "(?=>)",
- "name": "meta.tag.sgml.doctype.html",
- "patterns": [
- {
- "match": "\"[^\">]*\"",
- "name": "string.quoted.double.doctype.identifiers-and-DTDs.html"
- }
- ]
- },
- {
- "begin": "\\[CDATA\\[",
- "end": "]](?=>)",
- "name": "constant.other.inline-data.html"
- },
- {
- "match": "(\\s*)(?!--|>)\\S(\\s*)",
- "name": "invalid.illegal.bad-comments-or-CDATA.html"
- }
- ]
- },
- {
- "begin": "(?:^\\s+)?(<)((?i:style))\\b(?=[^>]*lang=(['\"])css\\1?)",
- "captures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.style.html"
- },
- "3": {
- "name": "punctuation.definition.tag.html"
- }
- },
- "end": "(<\/)((?i:style))(>)(?:\\s*\\n)?",
- "name": "source.css.embedded.html",
- "patterns": [
- {
- "include": "#tag-stuff"
- },
- {
- "begin": "(>)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.tag.end.html"
- }
- },
- "end": "(?=<\/(?i:style))",
- "patterns": [
- {
- "include": "source.css"
- }
- ]
- }
- ]
- },
- {
- "begin": "(?:^\\s+)?(<)((?i:style))\\b(?=[^>]*lang=(['\"])sass\\1?)",
- "captures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.style.html"
- },
- "3": {
- "name": "punctuation.definition.tag.html"
- }
- },
- "end": "(<\/)((?i:style))(>)(?:\\s*\\n)?",
- "name": "source.sass.embedded.html",
- "patterns": [
- {
- "include": "#tag-stuff"
- },
- {
- "begin": "(>)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.tag.end.html"
- }
- },
- "end": "(?=<\/(?i:style))",
- "patterns": [
- {
- "include": "source.sass"
- }
- ]
- }
- ]
- },
- {
- "begin": "(?:^\\s+)?(<)((?i:style))\\b(?=[^>]*lang=(['\"])scss\\1?)",
- "captures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.style.html"
- },
- "3": {
- "name": "punctuation.definition.tag.html"
- }
- },
- "end": "(<\/)((?i:style))(>)(?:\\s*\\n)?",
- "name": "source.scss.embedded.html",
- "patterns": [
- {
- "include": "#tag-stuff"
- },
- {
- "begin": "(>)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.tag.end.html"
- }
- },
- "end": "(?=<\/(?i:style))",
- "patterns": [
- {
- "include": "source.css.scss"
- }
- ]
- }
- ]
- },
- {
- "begin": "(?:^\\s+)?(<)((?i:style))\\b(?![^>]*\/>)",
- "captures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.style.html"
- },
- "3": {
- "name": "punctuation.definition.tag.html"
- }
- },
- "end": "(<\/)((?i:style))(>)(?:\\s*\\n)?",
- "__DEFAULT_STYLE_NAME_START__": null,"name": "source.css.embedded.html","__DEFAULT_STYLE_NAME_END__": null,
- "patterns": [
- {
- "include": "#tag-stuff"
- },
- {
- "begin": "(>)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.tag.end.html"
- }
- },
- "end": "(?=<\/(?i:style))",
- "patterns": [
- {
- "__DEFAULT_STYLE_INCLUDE_START__": null,"include": "source.css","__DEFAULT_STYLE_INCLUDE_END__": null
- }
- ]
- }
- ]
- },
- {
- "begin": "(?:^\\s+)?(<)((?i:script))\\b(?=[^>]*lang=(['\"])tsx\\1?)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.script.html"
- }
- },
- "end": "(?<=<\/(script|SCRIPT))(>)(?:\\s*\\n)?",
- "endCaptures": {
- "2": {
- "name": "punctuation.definition.tag.html"
- }
- },
- "name": "source.tsx.embedded.html",
- "patterns": [
- {
- "include": "#tag-stuff"
- },
- {
- "begin": "(?<!<\/(?:script|SCRIPT))(>)",
- "captures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.script.html"
- }
- },
- "end": "(<\/)((?i:script))",
- "patterns": [
- {
- "include": "source.tsx"
- }
- ]
- }
- ]
- },
- {
- "begin": "(?:^\\s+)?(<)((?i:script))\\b(?=[^>]*lang=(['\"])ts\\1?)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.script.html"
- }
- },
- "end": "(?<=<\/(script|SCRIPT))(>)(?:\\s*\\n)?",
- "endCaptures": {
- "2": {
- "name": "punctuation.definition.tag.html"
- }
- },
- "name": "source.tsx.embedded.html",
- "patterns": [
- {
- "include": "#tag-stuff"
- },
- {
- "begin": "(?<!<\/(?:script|SCRIPT))(>)",
- "captures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.script.html"
- }
- },
- "end": "(<\/)((?i:script))",
- "patterns": [
- {
- "include": "source.tsx"
- }
- ]
- }
- ]
- },
- {
- "begin": "(<)((?i:script))\\b(?![^>]*\/>)(?![^>]*(?i:type.?=.?text\/((?!javascript|babel|ecmascript).*)))",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.script.html"
- }
- },
- "end": "(?<=<\/(script|SCRIPT))(>)(?:\\s*\\n)?",
- "endCaptures": {
- "2": {
- "name": "punctuation.definition.tag.html"
- }
- },
- "name": "source.tsx.embedded.html",
- "patterns": [
- {
- "include": "#tag-stuff"
- },
- {
- "begin": "(?<!<\/(?:script|SCRIPT))(>)",
- "captures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.script.html"
- }
- },
- "end": "(<\/)((?i:script))",
- "patterns": [
- {
- "captures": {
- "1": {
- "name": "punctuation.definition.comment.js"
- }
- },
- "match": "(\/\/).*?((?=<\/script)|$\\n?)",
- "name": "comment.line.double-slash.js"
- },
- {
- "begin": "\/\\*",
- "captures": [
- {
- "name": "punctuation.definition.comment.js"
- }
- ],
- "end": "\\*\/|(?=<\/script)",
- "name": "comment.block.js"
- },
- {
- "include": "source.tsx"
- }
- ]
- }
- ]
- },
- {
- "begin": "(<\/?)((?i:body|head|html)\\b)",
- "captures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.structure.any.html"
- }
- },
- "end": "(>)",
- "endCaptures": {
- "1": {
- "name": "punctuation.definition.tag.end.html"
- }
- },
- "name": "meta.tag.structure.any.html",
- "patterns": [
- {
- "include": "#tag-stuff"
- }
- ]
- },
- {
- "begin": "(<\/?)((?i:address|blockquote|dd|div|dl|dt|fieldset|form|frame|frameset|h1|h2|h3|h4|h5|h6|iframe|noframes|object|ol|p|ul|applet|center|dir|hr|menu|pre)\\b)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.block.any.html"
- }
- },
- "end": "(>)",
- "endCaptures": {
- "1": {
- "name": "punctuation.definition.tag.end.html"
- }
- },
- "name": "meta.tag.block.any.html",
- "patterns": [
- {
- "include": "#tag-stuff"
- }
- ]
- },
- {
- "begin": "(<\/?)((?i:a|abbr|acronym|area|b|base|basefont|bdo|big|br|button|caption|cite|code|col|colgroup|del|dfn|em|font|head|html|i|img|input|ins|isindex|kbd|label|legend|li|link|map|meta|noscript|optgroup|option|param|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|var)\\b)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.inline.any.html"
- }
- },
- "end": "((?: ?\/)?>)",
- "endCaptures": {
- "1": {
- "name": "punctuation.definition.tag.end.html"
- }
- },
- "name": "meta.tag.inline.any.html",
- "patterns": [
- {
- "include": "#tag-stuff"
- }
- ]
- },
- {
- "begin": "(<\/?)([a-zA-Z0-9:-]+)",
- "beginCaptures": {
- "1": {
- "name": "punctuation.definition.tag.begin.html"
- },
- "2": {
- "name": "entity.name.tag.other.html"
- }
- },
- "end": "(/?>)",
- "endCaptures": {
- "1": {
- "name": "punctuation.definition.tag.end.html"
- }
- },
- "name": "meta.tag.other.html",
- "patterns": [
- {
- "include": "#tag-stuff"
- }
- ]
- },
- {
- "include": "#entities"
- },
- {
- "include": "#frontmatter"
- },
- {
- "match": "<>",
- "name": "invalid.illegal.incomplete.html"
- },
- {
- "match": "<",
- "name": "invalid.illegal.bad-angle-bracket.html"
- }
- ],
- "repository": {
- "frontmatter": {
- "begin": "\\A(-{3})\\s*$",
- "beginCaptures": {
- "1": {
- "name": "comment.block.html"
- }
- },
- "contentName": "meta.embedded.block.frontmatter",
- "patterns": [
- {
- "include": "source.tsx"
- }
- ],
- "end": "(^|\\G)(-{3})|\\.{3}\\s*$",
- "endCaptures": {
- "2": {
- "name": "comment.block.html"
- }
- }
- },
- "entities": {
- "patterns": [
- {
- "captures": {
- "1": {
- "name": "punctuation.definition.entity.html"
- },
- "3": {
- "name": "punctuation.definition.entity.html"
- }
- },
- "match": "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)",
- "name": "constant.character.entity.html"
- },
- {
- "match": "&",
- "name": "invalid.illegal.bad-ampersand.html"
- }
- ]
- },
- "string-double-quoted": {
- "begin": "\"",
- "beginCaptures": [
- {
- "name": "punctuation.definition.string.begin.html"
- }
- ],
- "end": "\"",
- "endCaptures": [
- {
- "name": "punctuation.definition.string.end.html"
- }
- ],
- "name": "string.quoted.double.html",
- "patterns": [
- {
- "include": "#entities"
- }
- ]
- },
- "string-single-quoted": {
- "begin": "'",
- "beginCaptures": [
- {
- "name": "punctuation.definition.string.begin.html"
- }
- ],
- "end": "'",
- "endCaptures": [
- {
- "name": "punctuation.definition.string.end.html"
- }
- ],
- "name": "string.quoted.single.html",
- "patterns": [
- {
- "include": "#entities"
- }
- ]
- },
- "tag-generic-attribute": {
- "match": "\\b([a-zA-Z\\-:]+)",
- "name": "entity.other.attribute-name.html"
- },
- "tag-id-attribute": {
- "begin": "\\b(id)\\b\\s*(=)",
- "captures": {
- "1": {
- "name": "entity.other.attribute-name.id.html"
- },
- "2": {
- "name": "punctuation.separator.key-value.html"
- }
- },
- "end": "(?<='|\")",
- "name": "meta.attribute-with-value.id.html",
- "patterns": [
- {
- "begin": "\"",
- "beginCaptures": [
- {
- "name": "punctuation.definition.string.begin.html"
- }
- ],
- "contentName": "meta.toc-list.id.html",
- "end": "\"",
- "endCaptures": [
- {
- "name": "punctuation.definition.string.end.html"
- }
- ],
- "name": "string.quoted.double.html",
- "patterns": [
- {
- "include": "#astro-expressions"
- },
- {
- "include": "#entities"
- }
- ]
- },
- {
- "begin": "'",
- "beginCaptures": [
- {
- "name": "punctuation.definition.string.begin.html"
- }
- ],
- "contentName": "meta.toc-list.id.html",
- "end": "'",
- "endCaptures": [
- {
- "name": "punctuation.definition.string.end.html"
- }
- ],
- "name": "string.quoted.single.html",
- "patterns": [
- {
- "include": "#astro-expressions"
- },
- {
- "include": "#entities"
- }
- ]
- }
- ]
- },
- "tag-stuff": {
- "patterns": [
- {
- "include": "#tag-id-attribute"
- },
- {
- "include": "#tag-generic-attribute"
- },
- {
- "include": "#string-double-quoted"
- },
- {
- "include": "#string-single-quoted"
- },
- {
- "include": "#astro-expressions"
- }
- ]
- },
- "astro-expressions": {
- "patterns": [
- {
- "begin": "\\{",
- "beginCaptures": [
- {
- "name": "punctuation.definition.generic.begin.html"
- }
- ],
- "end": "\\}",
- "endCaptures": [
- {
- "name": "punctuation.definition.generic.end.html"
- }
- ],
- "name": "expression.embbeded.astro",
- "patterns": [
- {
- "include": "source.tsx"
- }
- ]
- }
- ]
- }
- },
- "scopeName": "text.html.astro"
+ "fileTypes": ["astro"],
+ "foldingStartMarker": "(?x)\n(<(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|li|form|dl)\\b.*?>\n|<!--(?!.*--\\s*>)\n|^<!--\\ \\#tminclude\\ (?>.*?-->)$\n|<\\?(?:php)?.*\\b(if|for(each)?|while)\\b.+:\n|\\{\\{?(if|foreach|capture|literal|foreach|php|section|strip)\n|\\{\\s*($|\\?>\\s*$|//|/\\*(.*\\*/\\s*$|(?!.*?\\*/)))\n)",
+ "foldingStopMarker": "(?x)\n(</(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|li|form|dl)>\n|^(?!.*?<!--).*?--\\s*>\n|^<!--\\ end\\ tminclude\\ -->$\n|<\\?(?:php)?.*\\bend(if|for(each)?|while)\\b\n|\\{\\{?/(if|foreach|capture|literal|foreach|php|section|strip)\n|^[^{]*\\}\n)",
+ "keyEquivalent": "^~H",
+ "name": "Astro",
+ "patterns": [
+ {
+ "include": "#astro-expressions"
+ },
+ {
+ "begin": "(<)([a-zA-Z0-9:-]++)(?=[^>]*></\\2>)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.html"
+ }
+ },
+ "end": "(>)(<)(/)(\\2)(>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html"
+ },
+ "2": {
+ "name": "punctuation.definition.tag.begin.html meta.scope.between-tag-pair.html"
+ },
+ "3": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "4": {
+ "name": "entity.name.tag.html"
+ },
+ "5": {
+ "name": "punctuation.definition.tag.end.html"
+ }
+ },
+ "name": "meta.tag.any.html",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ }
+ ]
+ },
+ {
+ "begin": "(<\\?)(xml)",
+ "captures": {
+ "1": {
+ "name": "punctuation.definition.tag.html"
+ },
+ "2": {
+ "name": "entity.name.tag.xml.html"
+ }
+ },
+ "end": "(\\?>)",
+ "name": "meta.tag.preprocessor.xml.html",
+ "patterns": [
+ {
+ "include": "#tag-generic-attribute"
+ },
+ {
+ "include": "#string-double-quoted"
+ },
+ {
+ "include": "#string-single-quoted"
+ }
+ ]
+ },
+ {
+ "begin": "<!--",
+ "captures": [
+ {
+ "name": "punctuation.definition.comment.html"
+ }
+ ],
+ "end": "--\\s*>",
+ "name": "comment.block.html",
+ "patterns": [
+ {
+ "match": "--",
+ "name": "invalid.illegal.bad-comments-or-CDATA.html"
+ }
+ ]
+ },
+ {
+ "begin": "<!",
+ "captures": [
+ {
+ "name": "punctuation.definition.tag.html"
+ }
+ ],
+ "end": ">",
+ "name": "meta.tag.sgml.html",
+ "patterns": [
+ {
+ "begin": "(?i:DOCTYPE|doctype)",
+ "captures": {
+ "1": {
+ "name": "entity.name.tag.doctype.html"
+ }
+ },
+ "end": "(?=>)",
+ "name": "meta.tag.sgml.doctype.html",
+ "patterns": [
+ {
+ "match": "\"[^\">]*\"",
+ "name": "string.quoted.double.doctype.identifiers-and-DTDs.html"
+ }
+ ]
+ },
+ {
+ "begin": "\\[CDATA\\[",
+ "end": "]](?=>)",
+ "name": "constant.other.inline-data.html"
+ },
+ {
+ "match": "(\\s*)(?!--|>)\\S(\\s*)",
+ "name": "invalid.illegal.bad-comments-or-CDATA.html"
+ }
+ ]
+ },
+ {
+ "begin": "(?:^\\s+)?(<)((?i:style))\\b(?=[^>]*lang=(['\"])css\\1?)",
+ "captures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.style.html"
+ },
+ "3": {
+ "name": "punctuation.definition.tag.html"
+ }
+ },
+ "end": "(</)((?i:style))(>)(?:\\s*\\n)?",
+ "name": "source.css.embedded.html",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(>)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html"
+ }
+ },
+ "end": "(?=</(?i:style))",
+ "patterns": [
+ {
+ "include": "source.css"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?:^\\s+)?(<)((?i:style))\\b(?=[^>]*lang=(['\"])sass\\1?)",
+ "captures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.style.html"
+ },
+ "3": {
+ "name": "punctuation.definition.tag.html"
+ }
+ },
+ "end": "(</)((?i:style))(>)(?:\\s*\\n)?",
+ "name": "source.sass.embedded.html",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(>)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html"
+ }
+ },
+ "end": "(?=</(?i:style))",
+ "patterns": [
+ {
+ "include": "source.sass"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?:^\\s+)?(<)((?i:style))\\b(?=[^>]*lang=(['\"])scss\\1?)",
+ "captures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.style.html"
+ },
+ "3": {
+ "name": "punctuation.definition.tag.html"
+ }
+ },
+ "end": "(</)((?i:style))(>)(?:\\s*\\n)?",
+ "name": "source.scss.embedded.html",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(>)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html"
+ }
+ },
+ "end": "(?=</(?i:style))",
+ "patterns": [
+ {
+ "include": "source.css.scss"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?:^\\s+)?(<)((?i:style))\\b(?![^>]*/>)",
+ "captures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.style.html"
+ },
+ "3": {
+ "name": "punctuation.definition.tag.html"
+ }
+ },
+ "end": "(</)((?i:style))(>)(?:\\s*\\n)?",
+ "__DEFAULT_STYLE_NAME_START__": null,
+ "name": "source.css.embedded.html",
+ "__DEFAULT_STYLE_NAME_END__": null,
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(>)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html"
+ }
+ },
+ "end": "(?=</(?i:style))",
+ "patterns": [
+ {
+ "__DEFAULT_STYLE_INCLUDE_START__": null,
+ "include": "source.css",
+ "__DEFAULT_STYLE_INCLUDE_END__": null
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?:^\\s+)?(<)((?i:script))\\b(?=[^>]*lang=(['\"])tsx\\1?)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.script.html"
+ }
+ },
+ "end": "(?<=</(script|SCRIPT))(>)(?:\\s*\\n)?",
+ "endCaptures": {
+ "2": {
+ "name": "punctuation.definition.tag.html"
+ }
+ },
+ "name": "source.tsx.embedded.html",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<!</(?:script|SCRIPT))(>)",
+ "captures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.script.html"
+ }
+ },
+ "end": "(</)((?i:script))",
+ "patterns": [
+ {
+ "include": "source.tsx"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?:^\\s+)?(<)((?i:script))\\b(?=[^>]*lang=(['\"])ts\\1?)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.script.html"
+ }
+ },
+ "end": "(?<=</(script|SCRIPT))(>)(?:\\s*\\n)?",
+ "endCaptures": {
+ "2": {
+ "name": "punctuation.definition.tag.html"
+ }
+ },
+ "name": "source.tsx.embedded.html",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<!</(?:script|SCRIPT))(>)",
+ "captures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.script.html"
+ }
+ },
+ "end": "(</)((?i:script))",
+ "patterns": [
+ {
+ "include": "source.tsx"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(<)((?i:script))\\b(?![^>]*/>)(?![^>]*(?i:type.?=.?text/((?!javascript|babel|ecmascript).*)))",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.script.html"
+ }
+ },
+ "end": "(?<=</(script|SCRIPT))(>)(?:\\s*\\n)?",
+ "endCaptures": {
+ "2": {
+ "name": "punctuation.definition.tag.html"
+ }
+ },
+ "name": "source.tsx.embedded.html",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<!</(?:script|SCRIPT))(>)",
+ "captures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.script.html"
+ }
+ },
+ "end": "(</)((?i:script))",
+ "patterns": [
+ {
+ "captures": {
+ "1": {
+ "name": "punctuation.definition.comment.js"
+ }
+ },
+ "match": "(//).*?((?=</script)|$\\n?)",
+ "name": "comment.line.double-slash.js"
+ },
+ {
+ "begin": "/\\*",
+ "captures": [
+ {
+ "name": "punctuation.definition.comment.js"
+ }
+ ],
+ "end": "\\*/|(?=</script)",
+ "name": "comment.block.js"
+ },
+ {
+ "include": "source.tsx"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(</?)((?i:body|head|html)\\b)",
+ "captures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.structure.any.html"
+ }
+ },
+ "end": "(>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html"
+ }
+ },
+ "name": "meta.tag.structure.any.html",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ }
+ ]
+ },
+ {
+ "begin": "(</?)((?i:address|blockquote|dd|div|dl|dt|fieldset|form|frame|frameset|h1|h2|h3|h4|h5|h6|iframe|noframes|object|ol|p|ul|applet|center|dir|hr|menu|pre)\\b)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.block.any.html"
+ }
+ },
+ "end": "(>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html"
+ }
+ },
+ "name": "meta.tag.block.any.html",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ }
+ ]
+ },
+ {
+ "begin": "(</?)((?i:a|abbr|acronym|area|b|base|basefont|bdo|big|br|button|caption|cite|code|col|colgroup|del|dfn|em|font|head|html|i|img|input|ins|isindex|kbd|label|legend|li|link|map|meta|noscript|optgroup|option|param|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|var)\\b)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.inline.any.html"
+ }
+ },
+ "end": "((?: ?/)?>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html"
+ }
+ },
+ "name": "meta.tag.inline.any.html",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ }
+ ]
+ },
+ {
+ "begin": "(</?)([a-zA-Z0-9:-]+)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ },
+ "2": {
+ "name": "entity.name.tag.other.html"
+ }
+ },
+ "end": "(/?>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html"
+ }
+ },
+ "name": "meta.tag.other.html",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ }
+ ]
+ },
+ {
+ "include": "#entities"
+ },
+ {
+ "include": "#frontmatter"
+ },
+ {
+ "match": "<>",
+ "name": "invalid.illegal.incomplete.html"
+ },
+ {
+ "match": "<",
+ "name": "invalid.illegal.bad-angle-bracket.html"
+ }
+ ],
+ "repository": {
+ "frontmatter": {
+ "begin": "\\A(-{3})\\s*$",
+ "beginCaptures": {
+ "1": {
+ "name": "comment.block.html"
+ }
+ },
+ "contentName": "meta.embedded.block.frontmatter",
+ "patterns": [
+ {
+ "include": "source.tsx"
+ }
+ ],
+ "end": "(^|\\G)(-{3})|\\.{3}\\s*$",
+ "endCaptures": {
+ "2": {
+ "name": "comment.block.html"
+ }
+ }
+ },
+ "entities": {
+ "patterns": [
+ {
+ "captures": {
+ "1": {
+ "name": "punctuation.definition.entity.html"
+ },
+ "3": {
+ "name": "punctuation.definition.entity.html"
+ }
+ },
+ "match": "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)",
+ "name": "constant.character.entity.html"
+ },
+ {
+ "match": "&",
+ "name": "invalid.illegal.bad-ampersand.html"
+ }
+ ]
+ },
+ "string-double-quoted": {
+ "begin": "\"",
+ "beginCaptures": [
+ {
+ "name": "punctuation.definition.string.begin.html"
+ }
+ ],
+ "end": "\"",
+ "endCaptures": [
+ {
+ "name": "punctuation.definition.string.end.html"
+ }
+ ],
+ "name": "string.quoted.double.html",
+ "patterns": [
+ {
+ "include": "#entities"
+ }
+ ]
+ },
+ "string-single-quoted": {
+ "begin": "'",
+ "beginCaptures": [
+ {
+ "name": "punctuation.definition.string.begin.html"
+ }
+ ],
+ "end": "'",
+ "endCaptures": [
+ {
+ "name": "punctuation.definition.string.end.html"
+ }
+ ],
+ "name": "string.quoted.single.html",
+ "patterns": [
+ {
+ "include": "#entities"
+ }
+ ]
+ },
+ "tag-generic-attribute": {
+ "match": "\\b([a-zA-Z\\-:]+)",
+ "name": "entity.other.attribute-name.html"
+ },
+ "tag-id-attribute": {
+ "begin": "\\b(id)\\b\\s*(=)",
+ "captures": {
+ "1": {
+ "name": "entity.other.attribute-name.id.html"
+ },
+ "2": {
+ "name": "punctuation.separator.key-value.html"
+ }
+ },
+ "end": "(?<='|\")",
+ "name": "meta.attribute-with-value.id.html",
+ "patterns": [
+ {
+ "begin": "\"",
+ "beginCaptures": [
+ {
+ "name": "punctuation.definition.string.begin.html"
+ }
+ ],
+ "contentName": "meta.toc-list.id.html",
+ "end": "\"",
+ "endCaptures": [
+ {
+ "name": "punctuation.definition.string.end.html"
+ }
+ ],
+ "name": "string.quoted.double.html",
+ "patterns": [
+ {
+ "include": "#astro-expressions"
+ },
+ {
+ "include": "#entities"
+ }
+ ]
+ },
+ {
+ "begin": "'",
+ "beginCaptures": [
+ {
+ "name": "punctuation.definition.string.begin.html"
+ }
+ ],
+ "contentName": "meta.toc-list.id.html",
+ "end": "'",
+ "endCaptures": [
+ {
+ "name": "punctuation.definition.string.end.html"
+ }
+ ],
+ "name": "string.quoted.single.html",
+ "patterns": [
+ {
+ "include": "#astro-expressions"
+ },
+ {
+ "include": "#entities"
+ }
+ ]
+ }
+ ]
+ },
+ "tag-stuff": {
+ "patterns": [
+ {
+ "include": "#tag-id-attribute"
+ },
+ {
+ "include": "#tag-generic-attribute"
+ },
+ {
+ "include": "#string-double-quoted"
+ },
+ {
+ "include": "#string-single-quoted"
+ },
+ {
+ "include": "#astro-expressions"
+ }
+ ]
+ },
+ "astro-expressions": {
+ "patterns": [
+ {
+ "begin": "\\{",
+ "beginCaptures": [
+ {
+ "name": "punctuation.definition.generic.begin.html"
+ }
+ ],
+ "end": "\\}",
+ "endCaptures": [
+ {
+ "name": "punctuation.definition.generic.end.html"
+ }
+ ],
+ "name": "expression.embbeded.astro",
+ "patterns": [
+ {
+ "include": "source.tsx"
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "scopeName": "text.html.astro"
}
diff --git a/tools/vscode/tsconfig.base.json b/tools/vscode/tsconfig.base.json
index 8b7556d77..0f560706f 100644
--- a/tools/vscode/tsconfig.base.json
+++ b/tools/vscode/tsconfig.base.json
@@ -1,18 +1,17 @@
-
{
- "compilerOptions": {
- "target": "es2019",
- "lib": ["ESNext"],
- "module": "commonjs",
- "moduleResolution": "node",
- "sourceMap": true,
- "composite": true,
- "declaration": true,
- "strict": true,
- "skipLibCheck": true,
- "baseUrl": "./",
- "paths": {
- "@astro-vscode/*": ["packages/*/src"]
- },
- },
+ "compilerOptions": {
+ "target": "es2019",
+ "lib": ["ESNext"],
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "composite": true,
+ "declaration": true,
+ "strict": true,
+ "skipLibCheck": true,
+ "baseUrl": "./",
+ "paths": {
+ "@astro-vscode/*": ["packages/*/src"]
+ }
+ }
}
diff --git a/tools/vscode/tsconfig.json b/tools/vscode/tsconfig.json
index 56c433fea..1791849bb 100644
--- a/tools/vscode/tsconfig.json
+++ b/tools/vscode/tsconfig.json
@@ -1,14 +1,13 @@
-
{
- "extends": "./tsconfig.base.json",
- "files": [],
- "include": [],
- "references": [
- {
- "path": "./packages/client"
- },
- {
- "path": "./packages/server"
- }
- ]
+ "extends": "./tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./packages/client"
+ },
+ {
+ "path": "./packages/server"
+ }
+ ]
}
diff --git a/www/snowpack.config.js b/www/snowpack.config.js
index 17bde9fe3..15ffb35e7 100644
--- a/www/snowpack.config.js
+++ b/www/snowpack.config.js
@@ -1,4 +1,3 @@
-
module.exports = {
- workspaceRoot: '../'
-}; \ No newline at end of file
+ workspaceRoot: '../',
+};
diff --git a/yarn.lock b/yarn.lock
index db87d1d56..0a80fe6f9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1656,7 +1656,7 @@
resolved "https://registry.npmjs.org/@types/yoga-layout/-/yoga-layout-1.9.2.tgz"
integrity sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==
-"@typescript-eslint/eslint-plugin@^4.18.0":
+"@typescript-eslint/eslint-plugin@^4.22.0":
version "4.22.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.0.tgz#3d5f29bb59e61a9dba1513d491b059e536e16dbc"
integrity sha512-U8SP9VOs275iDXaL08Ln1Fa/wLXfj5aTr/1c0t0j6CdbOnxh+TruXu1p4I0NAvdPBQgoPjHsgKn28mOi0FzfoA==
@@ -4278,12 +4278,12 @@ escape-string-regexp@^2.0.0:
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz"
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
-eslint-config-prettier@^8.1.0:
+eslint-config-prettier@^8.3.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a"
integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==
-eslint-plugin-prettier@^3.3.1:
+eslint-plugin-prettier@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz#cdbad3bf1dbd2b177e9825737fe63b476a08f0c7"
integrity sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==
@@ -4315,7 +4315,7 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
-eslint@^7.22.0:
+eslint@^7.25.0:
version "7.25.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.25.0.tgz#1309e4404d94e676e3e831b3a3ad2b050031eb67"
integrity sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw==