mirror of
https://github.com/danbulant/monaco-yaml
synced 2026-06-24 17:11:59 +00:00
Compare commits
No commits in common. "main" and "v2.5.0" have entirely different histories.
79 changed files with 17293 additions and 10471 deletions
|
|
@ -3,12 +3,12 @@ root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
end_of_line = lf
|
|
||||||
indent_size = 2
|
|
||||||
indent_style = space
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
max_line_length = 100
|
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
end_of_line = lf
|
||||||
|
|
||||||
[COMMIT_EDITMSG]
|
[*.md]
|
||||||
max_line_length = 72
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
extends:
|
|
||||||
- remcohaszing
|
|
||||||
- remcohaszing/typechecking
|
|
||||||
rules:
|
|
||||||
no-restricted-globals: off
|
|
||||||
|
|
||||||
'@typescript-eslint/no-misused-promises': off
|
|
||||||
'@typescript-eslint/no-shadow': off
|
|
||||||
'@typescript-eslint/no-unnecessary-condition': off
|
|
||||||
|
|
||||||
import/extensions: off
|
|
||||||
import/no-extraneous-dependencies: off
|
|
||||||
import/no-unresolved: off
|
|
||||||
|
|
||||||
jsdoc/require-jsdoc: off
|
|
||||||
|
|
||||||
node/no-extraneous-import: off
|
|
||||||
node/no-unsupported-features/es-syntax: off
|
|
||||||
node/no-unsupported-features/node-builtins: off
|
|
||||||
66
.github/workflows/ci.yaml
vendored
66
.github/workflows/ci.yaml
vendored
|
|
@ -1,66 +0,0 @@
|
||||||
name: ci
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
tags: ['*']
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
eslint:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with: { node-version: 16 }
|
|
||||||
- run: npm ci
|
|
||||||
- run: npx eslint .
|
|
||||||
|
|
||||||
examples:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with: { node-version: 16 }
|
|
||||||
- run: npm ci
|
|
||||||
- run: npm run prepack
|
|
||||||
- run: npm run build --workspaces
|
|
||||||
|
|
||||||
pack:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with: { node-version: 16 }
|
|
||||||
- run: npm ci
|
|
||||||
- run: npm pack
|
|
||||||
|
|
||||||
prettier:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with: { node-version: 16 }
|
|
||||||
- run: npm ci
|
|
||||||
- run: npx prettier --check .
|
|
||||||
|
|
||||||
tsc:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with: { node-version: 16 }
|
|
||||||
- run: npm ci
|
|
||||||
- run: npx tsc
|
|
||||||
# release:
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# needs: [eslint, pack, prettier, tsc]
|
|
||||||
# if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
# steps:
|
|
||||||
# - uses: actions/checkout@v2
|
|
||||||
# - uses: actions/setup-node@v2
|
|
||||||
# with: { node-version: 16 }
|
|
||||||
# - run: npm ci
|
|
||||||
# - run: npm publish
|
|
||||||
# env:
|
|
||||||
# NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
||||||
10
.gitignore
vendored
10
.gitignore
vendored
|
|
@ -1,7 +1,5 @@
|
||||||
dist/
|
/node_modules/
|
||||||
node_modules/
|
/out/
|
||||||
/index.js
|
/lib/
|
||||||
/yaml.worker.js
|
|
||||||
*.log
|
*.log
|
||||||
*.map
|
/src/languageservice
|
||||||
*.tgz
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
npx lint-staged
|
|
||||||
12
.npmignore
Normal file
12
.npmignore
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
/.vscode/
|
||||||
|
/out/
|
||||||
|
/scripts/
|
||||||
|
/examples/
|
||||||
|
/patches/
|
||||||
|
/src/
|
||||||
|
/test/
|
||||||
|
/.gitignore
|
||||||
|
/.npmignore
|
||||||
|
/examples
|
||||||
|
/test-demo.png
|
||||||
|
/.editorconfig
|
||||||
1
.npmrc
1
.npmrc
|
|
@ -1 +0,0 @@
|
||||||
lockfile-version = 3
|
|
||||||
1
.nvmrc
1
.nvmrc
|
|
@ -1 +0,0 @@
|
||||||
16
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
dist/
|
|
||||||
/index.js
|
|
||||||
/yaml.worker.js
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
proseWrap: always
|
|
||||||
singleQuote: true
|
|
||||||
trailingComma: all
|
|
||||||
18
.vscode/launch.json
vendored
Normal file
18
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"name": "vscode-jest-tests",
|
||||||
|
"request": "launch",
|
||||||
|
"args": ["--runInBand"],
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"internalConsoleOptions": "neverOpen",
|
||||||
|
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
11
.vscode/settings.json
vendored
Normal file
11
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Place your settings in this file to overwrite default and user settings.
|
||||||
|
{
|
||||||
|
"files.trimTrailingWhitespace": true,
|
||||||
|
"search.exclude": {
|
||||||
|
"**/node_modules": true,
|
||||||
|
"**/lib": true,
|
||||||
|
"**/out": true
|
||||||
|
},
|
||||||
|
"javascript.preferences.quoteStyle": "single",
|
||||||
|
"typescript.preferences.quoteStyle": "single"
|
||||||
|
}
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
# Contributing
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
The following are required to start working on this project:
|
|
||||||
|
|
||||||
- [Git](https://git-scm.com)
|
|
||||||
- [NodeJS](https://nodejs.org) 16 or higher
|
|
||||||
- [npm](https://github.com/npm/cli) 8.1.2 or higher
|
|
||||||
|
|
||||||
## Getting started
|
|
||||||
|
|
||||||
To get started with contributing, clone the repository and install its dependencies.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/remcohaszing/monaco-yaml
|
|
||||||
cd monaco-yaml
|
|
||||||
npm ci
|
|
||||||
```
|
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
To build the repository, run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run prepack
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running
|
|
||||||
|
|
||||||
To test it, run one of the
|
|
||||||
[examples](https://github.com/remcohaszing/monaco-yaml/tree/main/examples).
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm --workspace demo start
|
|
||||||
```
|
|
||||||
25
LICENSE.md
25
LICENSE.md
|
|
@ -2,17 +2,20 @@ The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) Microsoft Corporation
|
Copyright (c) Microsoft Corporation
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
associated documentation files (the "Software"), to deal in the Software without restriction,
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
in the Software without restriction, including without limitation the rights
|
||||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
The above copyright notice and this permission notice shall be included in all
|
||||||
portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
235
README.md
235
README.md
|
|
@ -1,219 +1,42 @@
|
||||||
# Monaco YAML
|
# Monaco YAML
|
||||||
|
|
||||||
[](https://github.com/remcohaszing/monaco-yaml/actions/workflows/ci.yaml)
|
YAML language plugin for the Monaco Editor. It provides the following features when editing YAML files:
|
||||||
[](https://www.npmjs.com/package/monaco-yaml)
|
* Code completion, based on JSON schemas or by looking at similar objects in the same file
|
||||||
[](https://prettier.io)
|
* Hovers, based on JSON schemas
|
||||||
[](https://monaco-yaml.js.org)
|
* Validation: Syntax errors and schema validation
|
||||||
[](https://app.netlify.com/sites/monaco-yaml/deploys)
|
* Formatting
|
||||||
|
* Document Symbols
|
||||||
|
* Syntax highlighting
|
||||||
|
* Automatically load remote schema files (by enabling DiagnosticsOptions.enableSchemaRequest)
|
||||||
|
|
||||||
YAML language plugin for the Monaco Editor. It provides the following features when editing YAML
|
Schemas can also be provided by configuration. See [here](https://github.com/Microsoft/monaco-json/blob/master/src/monaco.d.ts)
|
||||||
files:
|
for the API that the JSON plugin offers to configure the JSON language support.
|
||||||
|
|
||||||
- Code completion, based on JSON schemas or by looking at similar objects in the same file
|
## Installing
|
||||||
- Hovers, based on JSON schemas
|
|
||||||
- Validation: Syntax errors and schema validation
|
|
||||||
- Formatting using Prettier
|
|
||||||
- Document Symbols
|
|
||||||
- Automatically load remote schema files (by enabling DiagnosticsOptions.enableSchemaRequest)
|
|
||||||
- Links from JSON references.
|
|
||||||
- Links and hover effects from YAML anchors.
|
|
||||||
|
|
||||||
Schemas can also be provided by configuration. See
|
`yarn add monaco-yaml`
|
||||||
[here](https://github.com/remcohaszing/monaco-yaml/blob/main/index.d.ts) for the API that the plugin
|
Both vs loader and ESM are supported.
|
||||||
offers to configure the YAML language support.
|
See `examples` directory for esm and umd examples.
|
||||||
|
|
||||||
## Installation
|
## Development
|
||||||
|
|
||||||
```sh
|
* `git clone https://github.com/pengx17/monaco-yaml`
|
||||||
npm install monaco-yaml
|
* `cd monaco-yaml`
|
||||||
```
|
* `yarn`
|
||||||
|
* open `$/monaco-yaml/demo/index.html` in your favorite browser.
|
||||||
|
|
||||||
## Usage
|
A running example:
|
||||||
|

|
||||||
Import `monaco-yaml` and configure it before an editor instance is created.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { editor, Uri } from 'monaco-editor';
|
|
||||||
import { setDiagnosticsOptions } from 'monaco-yaml';
|
|
||||||
|
|
||||||
// The uri is used for the schema file match.
|
|
||||||
const modelUri = Uri.parse('a://b/foo.yaml');
|
|
||||||
|
|
||||||
setDiagnosticsOptions({
|
|
||||||
enableSchemaRequest: true,
|
|
||||||
hover: true,
|
|
||||||
completion: true,
|
|
||||||
validate: true,
|
|
||||||
format: true,
|
|
||||||
schemas: [
|
|
||||||
{
|
|
||||||
// Id of the first schema
|
|
||||||
uri: 'http://myserver/foo-schema.json',
|
|
||||||
// Associate with our model
|
|
||||||
fileMatch: [String(modelUri)],
|
|
||||||
schema: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
p1: {
|
|
||||||
enum: ['v1', 'v2'],
|
|
||||||
},
|
|
||||||
p2: {
|
|
||||||
// Reference the second schema
|
|
||||||
$ref: 'http://myserver/bar-schema.json',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Id of the first schema
|
|
||||||
uri: 'http://myserver/bar-schema.json',
|
|
||||||
schema: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
q1: {
|
|
||||||
enum: ['x1', 'x2'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
editor.create(document.createElement('editor'), {
|
|
||||||
// Monaco-yaml features should just work if the editor language is set to 'yaml'.
|
|
||||||
language: 'yaml',
|
|
||||||
model: editor.createModel('p1: \n', 'yaml', modelUri),
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Also make sure to register the web worker. When using Webpack 5, this looks like the code below.
|
|
||||||
Other bundlers may use a different syntax, but the idea is the same. Languages you don’t used can be
|
|
||||||
omitted.
|
|
||||||
|
|
||||||
```js
|
|
||||||
window.MonacoEnvironment = {
|
|
||||||
getWorker(moduleId, label) {
|
|
||||||
switch (label) {
|
|
||||||
case 'editorWorkerService':
|
|
||||||
return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker', import.meta.url));
|
|
||||||
case 'css':
|
|
||||||
case 'less':
|
|
||||||
case 'scss':
|
|
||||||
return new Worker(new URL('monaco-editor/esm/vs/language/css/css.worker', import.meta.url));
|
|
||||||
case 'handlebars':
|
|
||||||
case 'html':
|
|
||||||
case 'razor':
|
|
||||||
return new Worker(
|
|
||||||
new URL('monaco-editor/esm/vs/language/html/html.worker', import.meta.url),
|
|
||||||
);
|
|
||||||
case 'json':
|
|
||||||
return new Worker(
|
|
||||||
new URL('monaco-editor/esm/vs/language/json/json.worker', import.meta.url),
|
|
||||||
);
|
|
||||||
case 'javascript':
|
|
||||||
case 'typescript':
|
|
||||||
return new Worker(
|
|
||||||
new URL('monaco-editor/esm/vs/language/typescript/ts.worker', import.meta.url),
|
|
||||||
);
|
|
||||||
case 'yaml':
|
|
||||||
return new Worker(new URL('monaco-yaml/yaml.worker', import.meta.url));
|
|
||||||
default:
|
|
||||||
throw new Error(`Unknown label ${label}`);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
A demo is available on [monaco-yaml.js.org](https://monaco-yaml.js.org).
|
|
||||||
|
|
||||||
A running example: 
|
|
||||||
|
|
||||||
Some usage examples can be found in the
|
|
||||||
[examples](https://github.com/remcohaszing/monaco-yaml/tree/main/examples) directory.
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
### Does this work with the Monaco UMD bundle?
|
|
||||||
|
|
||||||
No. Only ESM is supported.
|
|
||||||
|
|
||||||
### Does this work with Monaco Editor from a CDN?
|
|
||||||
|
|
||||||
No, because these use a UMD bundle, which isn’t supported.
|
|
||||||
|
|
||||||
### Does this work with `@monaco-editor/loader` or `@monaco-editor/react`?
|
|
||||||
|
|
||||||
No. These packages pull in the Monaco UMD bundle from a CDN. Because UMD isn’t supported, neither
|
|
||||||
are these packages.
|
|
||||||
|
|
||||||
### Is the web worker necessary?
|
|
||||||
|
|
||||||
Yes. The web worker provides the core functionality of `monaco-yaml`.
|
|
||||||
|
|
||||||
### Does it work without a bundler?
|
|
||||||
|
|
||||||
No. `monaco-yaml` uses dependencies from `node_modules`, so they can be deduped and your bundle size
|
|
||||||
is decreased. This comes at the cost of not being able to use it without a bundler.
|
|
||||||
|
|
||||||
### How do I integrate `monaco-yaml` with a framework? (Angular, React, Vue, etc.)
|
|
||||||
|
|
||||||
`monaco-yaml` only uses the Monaco Editor. It’s not tied to a framework, all that’s needed is a DOM
|
|
||||||
node to attach the Monaco Editor to. See the
|
|
||||||
[Monaco Editor examples](https://github.com/microsoft/monaco-editor/tree/main/monaco-editor-samples)
|
|
||||||
for examples on how to integrate Monaco Editor in your project, then configure `monaco-yaml` as
|
|
||||||
described above.
|
|
||||||
|
|
||||||
### Does `monaco-yaml` work with `create-react-app`?
|
|
||||||
|
|
||||||
Yes, but you’ll have to eject. See
|
|
||||||
[#92 (comment)](https://github.com/remcohaszing/monaco-yaml/issues/92#issuecomment-905836058) for
|
|
||||||
details.
|
|
||||||
|
|
||||||
### Why isn’t `monaco-yaml` working? Official Monaco language extensions do work.
|
|
||||||
|
|
||||||
This is most likely due to the fact that `monaco-yaml` is using a different instance of the
|
|
||||||
`monaco-editor` package than you are. This is something you’ll want to avoid regardless of
|
|
||||||
`monaco-editor`, because it means your bundle is significantly larger than it needs to be. This is
|
|
||||||
likely caused by one of the following issues:
|
|
||||||
|
|
||||||
- A code splitting misconfiguration
|
|
||||||
|
|
||||||
To solve this, try inspecting your bundle using for example
|
|
||||||
[webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer). If
|
|
||||||
`monaco-editor` is in there twice, this is the issue. It’s up to you to solve this, as it’s
|
|
||||||
project-specific.
|
|
||||||
|
|
||||||
- You’re using a package which imports `monaco-editor` for you, but it’s using a different version.
|
|
||||||
|
|
||||||
You can find out why the `monaco-editor` is installed using `npm ls monaco-editor` or
|
|
||||||
`yarn why monaco-editor`. It should exist only once, but it’s ok if it’s deduped.
|
|
||||||
|
|
||||||
You may be able to solve this by deleting your `node_modules` folder and `package-lock.json` or
|
|
||||||
`yarn.lock`, then running `npm install` or `yarn install` respectively.
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Please see our [contributing guidelines](CONTRIBUTING.md)
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
- https://github.com/redhat-developer/yaml-language-server
|
||||||
|
|
||||||
Originally [@kpdecker](https://github.com/kpdecker) forked this repository from
|
### Maintain
|
||||||
[`monaco-json`](https://github.com/microsoft/monaco-json) by
|
Manually clone dependencies list below and update the project files accordingly:
|
||||||
[@microsoft](https://github.com/microsoft) and rewrote it to work with
|
- `src/languageservice`: https://github.com/redhat-developer/yaml-language-server
|
||||||
[`yaml-language-server`](https://github.com/redhat-developer/yaml-language-server) instead. Later
|
- `cp yaml-language-server/src/languageservice monaco-yaml/src/languageservice`
|
||||||
the repository maintenance was taken over by [@pengx17](https://github.com/pengx17). Eventually the
|
- Modify the import paths, go to the test page and see if it still works
|
||||||
repository was tranferred to the account of [@remcohaszing](https://github.com/remcohaszing), who is
|
- `src/yaml-ast-parser-custom-tags`: https://github.com/JPinkney/yaml-ast-parser/tree/master/src
|
||||||
currently maintaining this repository with the help of [@fleon](https://github.com/fleon) and
|
|
||||||
[@yazaabed](https://github.com/yazaabed).
|
|
||||||
|
|
||||||
The heavy processing is done in
|
|
||||||
[`yaml-language-server`](https://github.com/redhat-developer/yaml-language-server), best known for
|
|
||||||
being the backbone for [`vscode-yaml`](https://github.com/redhat-developer/vscode-yaml). This
|
|
||||||
repository provides a thin layer to add functionality provided by `yaml-language-server` into
|
|
||||||
`monaco-editor`.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
[MIT](https://github.com/pengx17/monaco-yaml/blob/master/LICENSE.md)
|
||||||
[MIT](https://github.com/remcohaszing/monaco-yaml/blob/main/LICENSE.md)
|
|
||||||
|
|
|
||||||
58
build.js
58
build.js
|
|
@ -1,58 +0,0 @@
|
||||||
const { build } = require('esbuild');
|
|
||||||
|
|
||||||
const { dependencies, peerDependencies } = require('./package.json');
|
|
||||||
|
|
||||||
build({
|
|
||||||
entryPoints: ['src/index.ts', 'src/yaml.worker.ts'],
|
|
||||||
bundle: true,
|
|
||||||
external: Object.keys({ ...dependencies, ...peerDependencies }),
|
|
||||||
logLevel: 'info',
|
|
||||||
outdir: '.',
|
|
||||||
sourcemap: true,
|
|
||||||
format: 'esm',
|
|
||||||
target: ['es2019'],
|
|
||||||
plugins: [
|
|
||||||
{
|
|
||||||
name: 'alias',
|
|
||||||
setup({ onResolve }) {
|
|
||||||
// The file monaco-yaml/lib/esm/schemaSelectionHandlers.js imports code from the language
|
|
||||||
// server part that we don’t want.
|
|
||||||
onResolve({ filter: /\/schemaSelectionHandlers$/ }, () => ({
|
|
||||||
path: require.resolve('./src/fillers/schemaSelectionHandlers.ts'),
|
|
||||||
}));
|
|
||||||
// The yaml language service only imports re-exports of vscode-languageserver-types from
|
|
||||||
// vscode-languageserver.
|
|
||||||
onResolve({ filter: /^vscode-languageserver(\/node|-protocol)?$/ }, () => ({
|
|
||||||
path: 'vscode-languageserver-types',
|
|
||||||
external: true,
|
|
||||||
}));
|
|
||||||
// The yaml language service uses path. We can stub it using path-browserify.
|
|
||||||
onResolve({ filter: /^path$/ }, () => ({
|
|
||||||
path: 'path-browserify',
|
|
||||||
external: true,
|
|
||||||
}));
|
|
||||||
// The main prettier entry point contains all of Prettier.
|
|
||||||
// The standalone bundle is smaller and works fine for us.
|
|
||||||
onResolve({ filter: /^prettier/ }, ({ path }) => ({
|
|
||||||
path: path === 'prettier' ? 'prettier/standalone.js' : `${path}.js`,
|
|
||||||
external: true,
|
|
||||||
}));
|
|
||||||
// This tiny filler implementation serves all our needs.
|
|
||||||
onResolve({ filter: /vscode-nls/ }, () => ({
|
|
||||||
path: require.resolve('./src/fillers/vscode-nls.ts'),
|
|
||||||
}));
|
|
||||||
// The language server dependencies tend to write both ESM and UMD output alongside each
|
|
||||||
// other, then use UMD for imports. We prefer ESM.
|
|
||||||
onResolve({ filter: /\/umd\// }, (args) => ({
|
|
||||||
path: require.resolve(args.path.replace(/\/umd\//, '/esm/'), {
|
|
||||||
paths: [args.resolveDir],
|
|
||||||
}),
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}).catch((error) => {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(error);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
# Demo
|
|
||||||
|
|
||||||
This demo is deployed to [monaco-yaml.js.org](https://monaco-yaml.js.org). It shows how
|
|
||||||
`monaco-editor` and `monaco-yaml` can be used with
|
|
||||||
[Webpack 5](https://webpack.js.org/concepts/entry-points).
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
- [NodeJS](https://nodejs.org) 16 or higher
|
|
||||||
- [npm](https://github.com/npm/cli) 8.1.2 or higher
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
To run the project locally, clone the repository and set it up:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/remcohaszing/monaco-yaml
|
|
||||||
cd monaco-yaml
|
|
||||||
npm ci
|
|
||||||
npm run prepack
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running
|
|
||||||
|
|
||||||
To start it, simply run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm --workspace demo start
|
|
||||||
```
|
|
||||||
|
|
||||||
The demo will open in your browser.
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
{
|
|
||||||
"name": "demo",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"start": "webpack serve --open --mode development",
|
|
||||||
"build": "webpack --mode production"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-free": "^6.0.0",
|
|
||||||
"@schemastore/schema-catalog": "^0.0.5",
|
|
||||||
"css-loader": "^6.0.0",
|
|
||||||
"css-minimizer-webpack-plugin": "^3.0.0",
|
|
||||||
"html-webpack-plugin": "^5.0.0",
|
|
||||||
"mini-css-extract-plugin": "^2.0.0",
|
|
||||||
"monaco-editor": "^0.31.0",
|
|
||||||
"monaco-yaml": "file:../..",
|
|
||||||
"ts-loader": "^9.0.0",
|
|
||||||
"typescript": "^4.0.0",
|
|
||||||
"webpack": "^5.0.0",
|
|
||||||
"webpack-cli": "^4.0.0",
|
|
||||||
"webpack-dev-server": "^4.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 512 470.647">
|
|
||||||
<style>
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
.char {
|
|
||||||
fill: #ffffff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<polygon class="char" points="512 422.735 395.638 422.735 395.638 250.125 347.442 250.125 347.442 469.647 512 469.647 512 422.737 512 422.735" />
|
|
||||||
<polygon class="char" points="87.701 250.177 87.701 470.647 135.004 470.647 135.004 318.569 184.509 420.789 221.743 420.789 272.939 314.976 272.939 470.602 318.318 470.602 318.318 250.177 256.358 250.177 201.381 349.883 149.021 250.177 87.701 250.177 87.701 250.177" />
|
|
||||||
<path fill="#cb171e" d="M330.294,195.39H228.433l-20.717,50.024H162.61L257.99,20.465h46.137l91.51,224.949h-48.2L330.293,195.39Zm-16.92-44.911-31.226-82.55-34.837,82.55h66.063Z" transform="translate(0 -19.939)" />
|
|
||||||
<polygon class="char" points="235.793 0 143.978 137.674 143.978 224.949 87.702 224.949 87.702 137.674 0 0 63.25 0 119.018 88.646 175.243 0 235.793 0 235.793 0" />
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1 KiB |
|
|
@ -1,122 +0,0 @@
|
||||||
:root {
|
|
||||||
--background-color: hsl(0, 0%, 96%);
|
|
||||||
--editor-background: hsl(60, 100%, 100%);
|
|
||||||
--foreground-color: hsl(0, 0%, 0%);
|
|
||||||
--primary-color: hsl(189, 100%, 63%);
|
|
||||||
--shadow-color: hsla(0, 0%, 27%, 0.239);
|
|
||||||
--warning-color: hsl(49, 100%, 40%);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--background-color: hsl(0, 0%, 23%);
|
|
||||||
--editor-background: hsl(0, 0%, 12%);
|
|
||||||
--foreground-color: hsl(0, 0%, 100%);
|
|
||||||
--shadow-color: hsl(0, 0%, 43%);
|
|
||||||
--warning-color: hsl(49, 100%, 40%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background: var(--background-color);
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
font-family: sans-serif;
|
|
||||||
height: 100vh;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
margin: 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav {
|
|
||||||
align-items: center;
|
|
||||||
background-color: var(--primary-color);
|
|
||||||
box-shadow: 0px 5px 5px var(--shadow-color);
|
|
||||||
display: flex;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
height: 3rem;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-icon {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-icon > img {
|
|
||||||
height: 2rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor-wrapper {
|
|
||||||
background: var(--editor-background);
|
|
||||||
box-shadow: 0 0 10px var(--shadow-color);
|
|
||||||
display: flex;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
flex-flow: column;
|
|
||||||
margin: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#schema-selection {
|
|
||||||
background-color: var(--editor-background);
|
|
||||||
border: none;
|
|
||||||
border-bottom: 1px solid var(--shadow-color);
|
|
||||||
color: var(--foreground-color);
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#breadcrumbs {
|
|
||||||
border-bottom: 1px solid var(--shadow-color);
|
|
||||||
color: var(--foreground-color);
|
|
||||||
flex: 0 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.breadcrumb {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
#breadcrumbs::before,
|
|
||||||
.breadcrumb:not(:last-child)::after {
|
|
||||||
content: '›';
|
|
||||||
margin: 0 0.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.breadcrumb.array::before {
|
|
||||||
content: '[]';
|
|
||||||
}
|
|
||||||
|
|
||||||
.breadcrumb.object::before {
|
|
||||||
content: '{}';
|
|
||||||
}
|
|
||||||
|
|
||||||
#editor {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#problems {
|
|
||||||
border-top: 1px solid var(--shadow-color);
|
|
||||||
flex: 0 0 20vh;
|
|
||||||
color: var(--foreground-color);
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
.problem {
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
padding: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.problem:hover {
|
|
||||||
background-color: var(--shadow-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.problem-text {
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.problem .codicon-warning {
|
|
||||||
color: var(--warning-color);
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="icon" type="image/svg+xml" href="<%= require('./icon.svg') %>" />
|
|
||||||
<title>Monaco YAML</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav>
|
|
||||||
<h1>Monaco YAML</h1>
|
|
||||||
<div>
|
|
||||||
<a href="https://npmjs.com/package/monaco-yaml" class="nav-icon">
|
|
||||||
<img
|
|
||||||
alt="npm icon"
|
|
||||||
src="<%= require('@fortawesome/fontawesome-free/svgs/brands/npm.svg') %>"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a href="https://github.com/remcohaszing/monaco-yaml" class="nav-icon">
|
|
||||||
<img
|
|
||||||
alt="GitHub icon"
|
|
||||||
src="<%= require('@fortawesome/fontawesome-free/svgs/brands/github.svg') %>"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<div class="editor-wrapper">
|
|
||||||
<div>
|
|
||||||
<select id="schema-selection">
|
|
||||||
<option value="monaco-yaml.yaml">Monaco YAML example</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div id="breadcrumbs"></div>
|
|
||||||
<div id="editor"></div>
|
|
||||||
<div id="problems"></div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,230 +0,0 @@
|
||||||
import './index.css';
|
|
||||||
|
|
||||||
import { JSONSchemaForSchemaStoreOrgCatalogFiles } from '@schemastore/schema-catalog';
|
|
||||||
import { CancellationToken } from 'monaco-editor/esm/vs/base/common/cancellation';
|
|
||||||
import { getDocumentSymbols } from 'monaco-editor/esm/vs/editor/contrib/documentSymbols/documentSymbols';
|
|
||||||
import {
|
|
||||||
editor,
|
|
||||||
Environment,
|
|
||||||
languages,
|
|
||||||
Position,
|
|
||||||
Range,
|
|
||||||
Uri,
|
|
||||||
} from 'monaco-editor/esm/vs/editor/editor.api';
|
|
||||||
import { SchemasSettings, setDiagnosticsOptions } from 'monaco-yaml';
|
|
||||||
|
|
||||||
// NOTE: This will give you all editor featues. If you would prefer to limit to only the editor
|
|
||||||
// features you want to use, import them each individually. See this example: (https://github.com/microsoft/monaco-editor-samples/blob/main/browser-esm-webpack-small/index.js#L1-L91)
|
|
||||||
import 'monaco-editor';
|
|
||||||
|
|
||||||
import defaultSchemaUri from './schema.json';
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
MonacoEnvironment: Environment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.MonacoEnvironment = {
|
|
||||||
getWorker(moduleId, label) {
|
|
||||||
switch (label) {
|
|
||||||
case 'editorWorkerService':
|
|
||||||
return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker', import.meta.url));
|
|
||||||
case 'yaml':
|
|
||||||
return new Worker(new URL('monaco-yaml/yaml.worker', import.meta.url));
|
|
||||||
default:
|
|
||||||
throw new Error(`Unknown label ${label}`);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultSchema: SchemasSettings = {
|
|
||||||
uri: defaultSchemaUri,
|
|
||||||
fileMatch: ['monaco-yaml.yaml'],
|
|
||||||
};
|
|
||||||
|
|
||||||
setDiagnosticsOptions({
|
|
||||||
schemas: [defaultSchema],
|
|
||||||
});
|
|
||||||
|
|
||||||
const value = `
|
|
||||||
# Property descriptions are displayed when hovering over properties using your cursor
|
|
||||||
property: This property has a JSON schema description
|
|
||||||
|
|
||||||
|
|
||||||
# Titles work too!
|
|
||||||
titledProperty: Titles work too!
|
|
||||||
|
|
||||||
|
|
||||||
# Even markdown descriptions work
|
|
||||||
markdown: hover me to get a markdown based description 😮
|
|
||||||
|
|
||||||
|
|
||||||
# Enums can be autocompleted by placing the cursor after the colon and pressing Ctrl+Space
|
|
||||||
enum:
|
|
||||||
|
|
||||||
|
|
||||||
# Unused anchors will be reported
|
|
||||||
unused anchor: &unused anchor
|
|
||||||
|
|
||||||
|
|
||||||
# Of course numbers are supported!
|
|
||||||
number: 12
|
|
||||||
|
|
||||||
|
|
||||||
# As well as booleans!
|
|
||||||
boolean: true
|
|
||||||
|
|
||||||
|
|
||||||
# And strings
|
|
||||||
string: I am a string
|
|
||||||
|
|
||||||
|
|
||||||
# This property is using the JSON schema recursively
|
|
||||||
reference:
|
|
||||||
boolean: Not a boolean
|
|
||||||
|
|
||||||
|
|
||||||
# Also works in arrays
|
|
||||||
array:
|
|
||||||
- string: 12
|
|
||||||
enum: Mewtwo
|
|
||||||
reference:
|
|
||||||
reference:
|
|
||||||
boolean: true
|
|
||||||
|
|
||||||
|
|
||||||
# JSON referenses can be clicked for navigation
|
|
||||||
pointer:
|
|
||||||
$ref: '#/array'
|
|
||||||
|
|
||||||
|
|
||||||
# This anchor can be referenced
|
|
||||||
anchorRef: &anchor can be clicked as well
|
|
||||||
|
|
||||||
|
|
||||||
# Press control while hovering over the anchor
|
|
||||||
anchorPointer: *anchor
|
|
||||||
|
|
||||||
|
|
||||||
formatting: Formatting is supported too! Under the hood this is powered by Prettier. Just press Ctrl+Shift+I or right click and press Format to format this document.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
`.replace(/:$/m, ': ');
|
|
||||||
|
|
||||||
const ed = editor.create(document.getElementById('editor'), {
|
|
||||||
automaticLayout: true,
|
|
||||||
model: editor.createModel(value, 'yaml', Uri.parse('monaco-yaml.yaml')),
|
|
||||||
theme: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'vs-dark' : 'vs-light',
|
|
||||||
});
|
|
||||||
|
|
||||||
const select = document.getElementById('schema-selection') as HTMLSelectElement;
|
|
||||||
|
|
||||||
fetch('https://www.schemastore.org/api/json/catalog.json').then(async (response) => {
|
|
||||||
if (!response.ok) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const catalog = (await response.json()) as JSONSchemaForSchemaStoreOrgCatalogFiles;
|
|
||||||
const schemas = [defaultSchema];
|
|
||||||
catalog.schemas.sort((a, b) => a.name.localeCompare(b.name));
|
|
||||||
for (const { fileMatch, name, url } of catalog.schemas) {
|
|
||||||
const match =
|
|
||||||
typeof name === 'string' && fileMatch?.find((filename) => /\.ya?ml$/i.test(filename));
|
|
||||||
if (!match) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const option = document.createElement('option');
|
|
||||||
option.value = match;
|
|
||||||
|
|
||||||
option.textContent = name;
|
|
||||||
select.append(option);
|
|
||||||
schemas.push({
|
|
||||||
fileMatch: [match],
|
|
||||||
uri: url,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setDiagnosticsOptions({
|
|
||||||
validate: true,
|
|
||||||
enableSchemaRequest: true,
|
|
||||||
format: true,
|
|
||||||
hover: true,
|
|
||||||
completion: true,
|
|
||||||
schemas,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
select.addEventListener('change', () => {
|
|
||||||
const oldModel = ed.getModel();
|
|
||||||
const newModel = editor.createModel(oldModel.getValue(), 'yaml', Uri.parse(select.value));
|
|
||||||
ed.setModel(newModel);
|
|
||||||
oldModel.dispose();
|
|
||||||
});
|
|
||||||
|
|
||||||
function* iterateSymbols(
|
|
||||||
symbols: languages.DocumentSymbol[],
|
|
||||||
position: Position,
|
|
||||||
): Iterable<languages.DocumentSymbol> {
|
|
||||||
for (const symbol of symbols) {
|
|
||||||
if (Range.containsPosition(symbol.range, position)) {
|
|
||||||
yield symbol;
|
|
||||||
yield* iterateSymbols(symbol.children, position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ed.onDidChangeCursorPosition(async (event) => {
|
|
||||||
const breadcrumbs = document.getElementById('breadcrumbs');
|
|
||||||
const symbols = await getDocumentSymbols(ed.getModel(), false, CancellationToken.None);
|
|
||||||
while (breadcrumbs.lastChild) {
|
|
||||||
breadcrumbs.lastChild.remove();
|
|
||||||
}
|
|
||||||
for (const symbol of iterateSymbols(symbols, event.position)) {
|
|
||||||
const breadcrumb = document.createElement('span');
|
|
||||||
breadcrumb.setAttribute('role', 'button');
|
|
||||||
breadcrumb.classList.add('breadcrumb');
|
|
||||||
breadcrumb.textContent = symbol.name;
|
|
||||||
breadcrumb.title = symbol.detail;
|
|
||||||
if (symbol.kind === languages.SymbolKind.Array) {
|
|
||||||
breadcrumb.classList.add('array');
|
|
||||||
} else if (symbol.kind === languages.SymbolKind.Module) {
|
|
||||||
breadcrumb.classList.add('object');
|
|
||||||
}
|
|
||||||
breadcrumb.addEventListener('click', () => {
|
|
||||||
ed.setPosition({
|
|
||||||
lineNumber: symbol.range.startLineNumber,
|
|
||||||
column: symbol.range.startColumn,
|
|
||||||
});
|
|
||||||
ed.focus();
|
|
||||||
});
|
|
||||||
breadcrumbs.append(breadcrumb);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
editor.onDidChangeMarkers(([resource]) => {
|
|
||||||
const problems = document.getElementById('problems');
|
|
||||||
const markers = editor.getModelMarkers({ resource });
|
|
||||||
while (problems.lastChild) {
|
|
||||||
problems.lastChild.remove();
|
|
||||||
}
|
|
||||||
for (const marker of markers) {
|
|
||||||
const wrapper = document.createElement('div');
|
|
||||||
wrapper.setAttribute('role', 'button');
|
|
||||||
const codicon = document.createElement('div');
|
|
||||||
const text = document.createElement('div');
|
|
||||||
wrapper.classList.add('problem');
|
|
||||||
codicon.classList.add('codicon', 'codicon-warning');
|
|
||||||
text.classList.add('problem-text');
|
|
||||||
text.textContent = marker.message;
|
|
||||||
wrapper.append(codicon, text);
|
|
||||||
wrapper.addEventListener('click', () => {
|
|
||||||
ed.setPosition({ lineNumber: marker.startLineNumber, column: marker.startColumn });
|
|
||||||
ed.focus();
|
|
||||||
});
|
|
||||||
problems.append(wrapper);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"property": {
|
|
||||||
"description": "I have a description"
|
|
||||||
},
|
|
||||||
"titledProperty": {
|
|
||||||
"title": "I have a title",
|
|
||||||
"description": "I also have a description"
|
|
||||||
},
|
|
||||||
"markdown": {
|
|
||||||
"markdownDescription": "Even **markdown** _descriptions_ `are` ~~not~~ supported!"
|
|
||||||
},
|
|
||||||
"enum": {
|
|
||||||
"description": "Pick your starter",
|
|
||||||
"enum": ["Bulbasaur", "Squirtle", "Charmander", "Pikachu"]
|
|
||||||
},
|
|
||||||
"number": {
|
|
||||||
"description": "Numbers work!",
|
|
||||||
"minimum": 42,
|
|
||||||
"maximum": 1337
|
|
||||||
},
|
|
||||||
"boolean": {
|
|
||||||
"description": "Are boolean supported?",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"string": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"reference": {
|
|
||||||
"description": "JSON schemas can be referenced, even recursively",
|
|
||||||
"$ref": "#"
|
|
||||||
},
|
|
||||||
"array": {
|
|
||||||
"description": "It also works in arrays",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
29
examples/demo/src/types.d.ts
vendored
29
examples/demo/src/types.d.ts
vendored
|
|
@ -1,29 +0,0 @@
|
||||||
declare module 'monaco-editor/esm/vs/base/common/cancellation' {
|
|
||||||
export enum CancellationToken {
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'monaco-editor/esm/vs/editor/contrib/documentSymbols/documentSymbols' {
|
|
||||||
import { ITextModel, languages } from 'monaco-editor';
|
|
||||||
import { CancellationToken } from 'monaco-editor/esm/vs/base/common/cancellation';
|
|
||||||
|
|
||||||
export function getDocumentSymbols(
|
|
||||||
model: ITextModel,
|
|
||||||
flat: boolean,
|
|
||||||
token: CancellationToken,
|
|
||||||
): Promise<languages.DocumentSymbol[]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'monaco-editor/esm/vs/editor/editor.worker.js' {
|
|
||||||
import { worker } from 'monaco-editor/esm/vs/editor/editor.api';
|
|
||||||
|
|
||||||
export function initialize(
|
|
||||||
fn: (ctx: worker.IWorkerContext, createData: unknown) => unknown,
|
|
||||||
): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '*.json' {
|
|
||||||
declare const uri: string;
|
|
||||||
export default uri;
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
|
||||||
const HtmlWebPackPlugin = require('html-webpack-plugin');
|
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
output: {
|
|
||||||
filename: '[contenthash].js',
|
|
||||||
},
|
|
||||||
devtool: 'source-map',
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.mjs', '.js', '.ts'],
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
use: [MiniCssExtractPlugin.loader, 'css-loader'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Monaco editor uses .ttf icons.
|
|
||||||
test: /\.(svg|ttf)$/,
|
|
||||||
type: 'asset/resource',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /schema\.json$/,
|
|
||||||
type: 'asset/resource',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.ts$/,
|
|
||||||
loader: 'ts-loader',
|
|
||||||
options: { transpileOnly: true },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
optimization: {
|
|
||||||
minimizer: ['...', new CssMinimizerPlugin()],
|
|
||||||
},
|
|
||||||
plugins: [new HtmlWebPackPlugin(), new MiniCssExtractPlugin({ filename: '[contenthash].css' })],
|
|
||||||
};
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
# Monaco Editor Webpack Loader Plugin Example
|
|
||||||
|
|
||||||
This demo demonstrates how bundle `monaco-editor` and `monaco-yaml` with
|
|
||||||
[monaco-editor-webpack-plugin](https://github.com/microsoft/monaco-editor/tree/main/webpack-plugin).
|
|
||||||
The build output is
|
|
||||||
[esm library](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). Example is
|
|
||||||
based on
|
|
||||||
[link](https://github.com/microsoft/monaco-editor/tree/main/samples/browser-esm-webpack-monaco-plugin).
|
|
||||||
To start it, simply run:
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
- [NodeJS](https://nodejs.org) 16 or higher
|
|
||||||
- [npm](https://github.com/npm/cli) 8.1.2 or higher
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
To run the project locally, clone the repository and set it up:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/remcohaszing/monaco-yaml
|
|
||||||
cd monaco-yaml
|
|
||||||
npm ci
|
|
||||||
npm run prepack
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running
|
|
||||||
|
|
||||||
To start it, simply run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm --workspace monaco-editor-webpack-plugin-example start
|
|
||||||
```
|
|
||||||
|
|
||||||
The demo will open in your browser.
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js';
|
|
||||||
|
|
||||||
export { setDiagnosticsOptions } from 'monaco-yaml';
|
|
||||||
export default monaco;
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Monaco Editor Webpack Plugin Example</title>
|
|
||||||
<style>
|
|
||||||
.editor {
|
|
||||||
width: 800px;
|
|
||||||
height: 600px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="editor"></div>
|
|
||||||
<script src="index.js" type="module"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
const value = `
|
|
||||||
number: 0xfe
|
|
||||||
boolean: true
|
|
||||||
`;
|
|
||||||
|
|
||||||
async function create() {
|
|
||||||
// Dynamic import is possible
|
|
||||||
const { default: monaco } = await import('./main.js');
|
|
||||||
|
|
||||||
// Define schema first
|
|
||||||
monaco.languages.yaml.yamlDefaults.setDiagnosticsOptions({
|
|
||||||
schemas: [
|
|
||||||
{
|
|
||||||
fileMatch: ['*'],
|
|
||||||
uri: 'my-schema.json',
|
|
||||||
schema: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
number: {
|
|
||||||
description: 'number property',
|
|
||||||
type: 'number',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create editor
|
|
||||||
monaco.editor.create(document.querySelector('.editor'), {
|
|
||||||
language: 'yaml',
|
|
||||||
tabSize: 2,
|
|
||||||
value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
create();
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"name": "monaco-editor-webpack-plugin-example",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"private": true,
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"start": "webpack serve --open --mode development",
|
|
||||||
"build": "webpack --mode production"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"css-loader": "^6.0.0",
|
|
||||||
"monaco-editor": "^0.31.0",
|
|
||||||
"monaco-editor-webpack-plugin": "^7.0.0",
|
|
||||||
"monaco-yaml": "file:../..",
|
|
||||||
"style-loader": "^3.0.0",
|
|
||||||
"webpack": "^5.0.0",
|
|
||||||
"webpack-cli": "^4.0.0",
|
|
||||||
"webpack-dev-server": "^4.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
entry: './editor.js',
|
|
||||||
output: {
|
|
||||||
filename: '[name].js',
|
|
||||||
library: {
|
|
||||||
type: 'module',
|
|
||||||
},
|
|
||||||
clean: true,
|
|
||||||
},
|
|
||||||
target: 'es2020',
|
|
||||||
experiments: {
|
|
||||||
outputModule: true,
|
|
||||||
},
|
|
||||||
devtool: 'source-map',
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
use: ['style-loader', 'css-loader'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.ttf$/,
|
|
||||||
type: 'asset',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new MonacoWebpackPlugin({
|
|
||||||
languages: [],
|
|
||||||
customLanguages: [
|
|
||||||
{
|
|
||||||
label: 'yaml',
|
|
||||||
entry: ['monaco-yaml', 'vs/basic-languages/yaml/yaml.contribution'],
|
|
||||||
worker: {
|
|
||||||
id: 'monaco-yaml/yamlWorker',
|
|
||||||
entry: 'monaco-yaml/yaml.worker',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
devServer: {
|
|
||||||
static: {
|
|
||||||
directory: './',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
3
examples/react-webpack-worker-loader/.babelrc
Normal file
3
examples/react-webpack-worker-loader/.babelrc
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"presets": ["@babel/preset-env", "@babel/preset-react"]
|
||||||
|
}
|
||||||
2
examples/react-webpack-worker-loader/.gitignore
vendored
Normal file
2
examples/react-webpack-worker-loader/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
dist/
|
||||||
|
node_modules/
|
||||||
9
examples/react-webpack-worker-loader/README.md
Normal file
9
examples/react-webpack-worker-loader/README.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Demo: React + Weback + Worker Loader + Babel
|
||||||
|
|
||||||
|
To run:
|
||||||
|
```
|
||||||
|
yarn && yarn start
|
||||||
|
```
|
||||||
|
|
||||||
|
The demo will open in your browser. See (index.jsx)[index.jsx#L34-L36] for the schema loaded.
|
||||||
|
|
||||||
10
examples/react-webpack-worker-loader/index.html
Normal file
10
examples/react-webpack-worker-loader/index.html
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>React Example</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="react"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
80
examples/react-webpack-worker-loader/index.jsx
Normal file
80
examples/react-webpack-worker-loader/index.jsx
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import MonacoEditor from 'react-monaco-editor';
|
||||||
|
import 'monaco-yaml/lib/esm/monaco.contribution';
|
||||||
|
import { languages } from 'monaco-editor/esm/vs/editor/editor.api';
|
||||||
|
|
||||||
|
// NOTE: This will give you all editor featues. If you would prefer to limit to only the editor
|
||||||
|
// features you want to use, import them each individually. See this example: (https://github.com/microsoft/monaco-editor-samples/blob/master/browser-esm-webpack-small/index.js#L1-L91)
|
||||||
|
import 'monaco-editor';
|
||||||
|
|
||||||
|
// NOTE: using loader syntax becuase Yaml worker imports editor.worker directly and that
|
||||||
|
// import shouldn't go through loader syntax.
|
||||||
|
import EditorWorker from 'worker-loader!monaco-editor/esm/vs/editor/editor.worker';
|
||||||
|
import YamlWorker from 'worker-loader!monaco-yaml/lib/esm/yaml.worker';
|
||||||
|
|
||||||
|
window.MonacoEnvironment = {
|
||||||
|
getWorker(workerId, label) {
|
||||||
|
if (label === 'yaml') {
|
||||||
|
return new YamlWorker();
|
||||||
|
}
|
||||||
|
return new EditorWorker();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { yaml } = languages || {};
|
||||||
|
|
||||||
|
const Editor = () => {
|
||||||
|
const [value, setValue] = useState('p1: ');
|
||||||
|
useEffect(() => {
|
||||||
|
yaml &&
|
||||||
|
yaml.yamlDefaults.setDiagnosticsOptions({
|
||||||
|
validate: true,
|
||||||
|
enableSchemaRequest: true,
|
||||||
|
hover: true,
|
||||||
|
completion: true,
|
||||||
|
schemas: [
|
||||||
|
{
|
||||||
|
uri: 'http://myserver/foo-schema.json', // id of the first schema
|
||||||
|
fileMatch: ['*'], // associate with our model
|
||||||
|
schema: {
|
||||||
|
id: 'http://myserver/foo-schema.json', // id of the first schema
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
enum: ['v1', 'v2'],
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
$ref: 'http://myserver/bar-schema.json', // reference the second schema
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uri: 'http://myserver/bar-schema.json', // id of the first schema
|
||||||
|
schema: {
|
||||||
|
id: 'http://myserver/bar-schema.json', // id of the first schema
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
q1: {
|
||||||
|
enum: ['x1', 'x2'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MonacoEditor
|
||||||
|
width="800"
|
||||||
|
height="600"
|
||||||
|
language="yaml"
|
||||||
|
value={value}
|
||||||
|
onChange={setValue}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ReactDOM.render(<Editor />, document.getElementById('react'));
|
||||||
31
examples/react-webpack-worker-loader/package.json
Normal file
31
examples/react-webpack-worker-loader/package.json
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "react-webpack-worker-loader-example",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"private": true,
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "webpack-dev-server --open --mode development",
|
||||||
|
"build": "webpack --mode production"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.8.4",
|
||||||
|
"@babel/preset-env": "^7.8.4",
|
||||||
|
"@babel/preset-react": "^7.8.3",
|
||||||
|
"babel-loader": "^8.0.6",
|
||||||
|
"css-loader": "^3.4.2",
|
||||||
|
"file-loader": "^5.1.0",
|
||||||
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
"monaco-editor": "^0.20.0",
|
||||||
|
"monaco-yaml": "file:../..",
|
||||||
|
"react": "^16.12.0",
|
||||||
|
"react-dom": "^16.12.0",
|
||||||
|
"react-monaco-editor": "^0.34.0",
|
||||||
|
"style-loader": "^1.1.3",
|
||||||
|
"webpack": "^4.41.6",
|
||||||
|
"webpack-cli": "^3.3.11",
|
||||||
|
"webpack-dev-server": "^3.10.3",
|
||||||
|
"worker-loader": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
41
examples/react-webpack-worker-loader/webpack.config.js
Normal file
41
examples/react-webpack-worker-loader/webpack.config.js
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
const HtmlWebPackPlugin = require('html-webpack-plugin');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: {
|
||||||
|
main: './index.jsx',
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
globalObject: 'this',
|
||||||
|
filename: '[name].bundle.js',
|
||||||
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.(js|jsx)$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
use: ['style-loader', 'css-loader'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.ttf$/,
|
||||||
|
loader: 'file-loader',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebPackPlugin({
|
||||||
|
template: './index.html',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
node: {
|
||||||
|
fs: 'empty',
|
||||||
|
module: 'empty',
|
||||||
|
},
|
||||||
|
};
|
||||||
5354
examples/react-webpack-worker-loader/yarn.lock
Normal file
5354
examples/react-webpack-worker-loader/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
3
examples/react-webpack/.babelrc
Normal file
3
examples/react-webpack/.babelrc
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"presets": ["@babel/preset-env", "@babel/preset-react"]
|
||||||
|
}
|
||||||
2
examples/react-webpack/.gitignore
vendored
Normal file
2
examples/react-webpack/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
dist/
|
||||||
|
node_modules/
|
||||||
9
examples/react-webpack/README.md
Normal file
9
examples/react-webpack/README.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Demo: React + Weback + Babel
|
||||||
|
|
||||||
|
To run:
|
||||||
|
```
|
||||||
|
yarn && yarn start
|
||||||
|
```
|
||||||
|
|
||||||
|
The demo will open in your browser. See (index.jsx)[index.jsx#L34-L36] for the schema loaded.
|
||||||
|
|
||||||
10
examples/react-webpack/index.html
Normal file
10
examples/react-webpack/index.html
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>React Example</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="react"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
75
examples/react-webpack/index.jsx
Normal file
75
examples/react-webpack/index.jsx
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import MonacoEditor from 'react-monaco-editor';
|
||||||
|
import 'monaco-yaml/lib/esm/monaco.contribution';
|
||||||
|
import { languages } from 'monaco-editor/esm/vs/editor/editor.api';
|
||||||
|
|
||||||
|
// NOTE: This will give you all editor featues. If you would prefer to limit to only the editor
|
||||||
|
// features you want to use, import them each individually. See this example: (https://github.com/microsoft/monaco-editor-samples/blob/master/browser-esm-webpack-small/index.js#L1-L91)
|
||||||
|
import 'monaco-editor';
|
||||||
|
|
||||||
|
window.MonacoEnvironment = {
|
||||||
|
getWorkerUrl(moduleId, label) {
|
||||||
|
if (label === 'yaml') {
|
||||||
|
return './yaml.worker.bundle.js';
|
||||||
|
}
|
||||||
|
return './editor.worker.bundle.js';
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { yaml } = languages || {};
|
||||||
|
|
||||||
|
const Editor = () => {
|
||||||
|
const [value, setValue] = useState('p1: ');
|
||||||
|
useEffect(() => {
|
||||||
|
yaml &&
|
||||||
|
yaml.yamlDefaults.setDiagnosticsOptions({
|
||||||
|
validate: true,
|
||||||
|
enableSchemaRequest: true,
|
||||||
|
hover: true,
|
||||||
|
completion: true,
|
||||||
|
schemas: [
|
||||||
|
{
|
||||||
|
uri: 'http://myserver/foo-schema.json', // id of the first schema
|
||||||
|
fileMatch: ['*'], // associate with our model
|
||||||
|
schema: {
|
||||||
|
id: 'http://myserver/foo-schema.json', // id of the first schema
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
enum: ['v1', 'v2'],
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
$ref: 'http://myserver/bar-schema.json', // reference the second schema
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uri: 'http://myserver/bar-schema.json', // id of the first schema
|
||||||
|
schema: {
|
||||||
|
id: 'http://myserver/bar-schema.json', // id of the first schema
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
q1: {
|
||||||
|
enum: ['x1', 'x2'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MonacoEditor
|
||||||
|
width="800"
|
||||||
|
height="600"
|
||||||
|
language="yaml"
|
||||||
|
value={value}
|
||||||
|
onChange={setValue}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ReactDOM.render(<Editor />, document.getElementById('react'));
|
||||||
30
examples/react-webpack/package.json
Normal file
30
examples/react-webpack/package.json
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"name": "react-webpack-example",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"private": true,
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "webpack-dev-server --open --mode development",
|
||||||
|
"build": "webpack --mode production"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.8.4",
|
||||||
|
"@babel/preset-env": "^7.8.4",
|
||||||
|
"@babel/preset-react": "^7.8.3",
|
||||||
|
"babel-loader": "^8.0.6",
|
||||||
|
"css-loader": "^3.4.2",
|
||||||
|
"file-loader": "^5.1.0",
|
||||||
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
"monaco-editor": "^0.20.0",
|
||||||
|
"monaco-yaml": "file:../..",
|
||||||
|
"react": "^16.12.0",
|
||||||
|
"react-dom": "^16.12.0",
|
||||||
|
"react-monaco-editor": "^0.34.0",
|
||||||
|
"style-loader": "^1.1.3",
|
||||||
|
"webpack": "^4.41.6",
|
||||||
|
"webpack-cli": "^3.3.11",
|
||||||
|
"webpack-dev-server": "^3.10.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
43
examples/react-webpack/webpack.config.js
Normal file
43
examples/react-webpack/webpack.config.js
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
const HtmlWebPackPlugin = require('html-webpack-plugin');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: {
|
||||||
|
main: './index.jsx',
|
||||||
|
'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js',
|
||||||
|
'yaml.worker': 'monaco-yaml/lib/esm/yaml.worker.js',
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
globalObject: 'this',
|
||||||
|
filename: '[name].bundle.js',
|
||||||
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.(js|jsx)$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
use: ['style-loader', 'css-loader'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.ttf$/,
|
||||||
|
loader: 'file-loader',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebPackPlugin({
|
||||||
|
template: './index.html',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
node: {
|
||||||
|
fs: 'empty',
|
||||||
|
module: 'empty',
|
||||||
|
},
|
||||||
|
};
|
||||||
5503
examples/react-webpack/yarn.lock
Normal file
5503
examples/react-webpack/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
162
examples/umd/index.html
Normal file
162
examples/umd/index.html
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
data-name="vs/editor/editor.main"
|
||||||
|
href="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.css"
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h2>Monaco Editor YAML test page</h2>
|
||||||
|
<code id="path"></code>
|
||||||
|
<div
|
||||||
|
id="container"
|
||||||
|
style="width:800px;height:600px;border:1px solid grey"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.x-highlight-range {
|
||||||
|
background-color: lightblue;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Loading basic-languages to get the YAML language definition
|
||||||
|
var paths = {
|
||||||
|
'vs/basic-languages': '../node_modules/monaco-languages/release/dev',
|
||||||
|
'vs/language/yaml': '../lib/dev',
|
||||||
|
vs: '../node_modules/monaco-editor-core/dev/vs',
|
||||||
|
prettier: '../node_modules/prettier',
|
||||||
|
};
|
||||||
|
if (document.location.protocol === 'http:') {
|
||||||
|
// Add support for running local http server
|
||||||
|
let testIndex = document.location.pathname.indexOf('/test/');
|
||||||
|
if (testIndex !== -1) {
|
||||||
|
let prefix = document.location.pathname.substr(0, testIndex);
|
||||||
|
paths['vs/language/yaml'] = prefix + '/lib/dev';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var require = {
|
||||||
|
paths: paths,
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script src="../node_modules/monaco-editor-core/dev/vs/loader.js"></script>
|
||||||
|
<script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.nls.js"></script>
|
||||||
|
<script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
require([
|
||||||
|
'vs/basic-languages/monaco.contribution',
|
||||||
|
'vs/language/yaml/monaco.contribution',
|
||||||
|
'prettier/standalone',
|
||||||
|
'prettier/parser-yaml',
|
||||||
|
], function() {
|
||||||
|
const yaml = `p1: `;
|
||||||
|
const modelUri = monaco.Uri.parse('a://b/foo.json');
|
||||||
|
const editor = monaco.editor.create(
|
||||||
|
document.getElementById('container'),
|
||||||
|
{
|
||||||
|
language: 'yaml',
|
||||||
|
showFoldingControls: 'always',
|
||||||
|
model: monaco.editor.createModel(yaml, 'yaml', modelUri),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
monaco.languages.yaml.yamlDefaults.setDiagnosticsOptions({
|
||||||
|
enableSchemaRequest: true,
|
||||||
|
hover: true,
|
||||||
|
completion: true,
|
||||||
|
validate: true,
|
||||||
|
format: true,
|
||||||
|
schemas: [
|
||||||
|
{
|
||||||
|
uri: 'http://myserver/foo-schema.json', // id of the first schema
|
||||||
|
fileMatch: [modelUri.toString()], // associate with our model
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
enum: ['v1', 'v2'],
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
$ref: 'http://myserver/bar-schema.json', // reference the second schema
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uri: 'http://myserver/bar-schema.json', // id of the first schema
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
q1: {
|
||||||
|
enum: ['x1', 'x2'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
require(['vs/editor/contrib/quickOpen/quickOpen'], async quickOpen => {
|
||||||
|
const NEVER_CANCEL_TOKEN = {
|
||||||
|
isCancellationRequested: false,
|
||||||
|
onCancellationRequested: () => Event.NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
let oldDecorations = [];
|
||||||
|
|
||||||
|
async function _getSymbolForPosition(model, position) {
|
||||||
|
const symbols = await quickOpen.getDocumentSymbols(
|
||||||
|
model,
|
||||||
|
false,
|
||||||
|
NEVER_CANCEL_TOKEN
|
||||||
|
);
|
||||||
|
|
||||||
|
function _recur(symbol) {
|
||||||
|
let target = symbol;
|
||||||
|
if (symbol && symbol.children && symbol.children.length) {
|
||||||
|
target =
|
||||||
|
_recur(
|
||||||
|
symbol.children.find(child =>
|
||||||
|
child.range.containsPosition(position)
|
||||||
|
)
|
||||||
|
) || symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _recur({ children: symbols });
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.onDidChangeCursorSelection(async ({ selection }) => {
|
||||||
|
const model = editor.getModel();
|
||||||
|
const position = selection.getPosition();
|
||||||
|
const symbol = await _getSymbolForPosition(model, position);
|
||||||
|
|
||||||
|
console.log(`${symbol.name}: ${symbol.range}`);
|
||||||
|
if (symbol && symbol.range) {
|
||||||
|
const decoration = {
|
||||||
|
range: symbol.range,
|
||||||
|
options: {
|
||||||
|
isWholeLine: false,
|
||||||
|
className: 'x-highlight-range',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
oldDecorations = editor.deltaDecorations(
|
||||||
|
oldDecorations,
|
||||||
|
decoration ? [decoration] : []
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
# Vite Example
|
|
||||||
|
|
||||||
This minimal example shows how `monaco-yaml` can be used with [Vite](https://vitejs.dev).
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
- [NodeJS](https://nodejs.org) 16 or higher
|
|
||||||
- [npm](https://github.com/npm/cli) 8.1.2 or higher
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
To run the project locally, clone the repository and set it up:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/remcohaszing/monaco-yaml
|
|
||||||
cd monaco-yaml
|
|
||||||
npm ci
|
|
||||||
npm run prepack
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running
|
|
||||||
|
|
||||||
To start it, simply run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm --workspace vite-example start
|
|
||||||
```
|
|
||||||
|
|
||||||
The demo will be available on http://localhost:3000.
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>Monaco YAML</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="editor" style="width: 800px; height: 600px;"></div>
|
|
||||||
<script type="module" src="/index.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
import { editor, Uri } from 'monaco-editor';
|
|
||||||
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
|
||||||
import { setDiagnosticsOptions } from 'monaco-yaml';
|
|
||||||
import YamlWorker from 'monaco-yaml/yaml.worker?worker';
|
|
||||||
|
|
||||||
window.MonacoEnvironment = {
|
|
||||||
getWorker(moduleId, label) {
|
|
||||||
switch (label) {
|
|
||||||
case 'editorWorkerService':
|
|
||||||
return new EditorWorker();
|
|
||||||
case 'yaml':
|
|
||||||
return new YamlWorker();
|
|
||||||
default:
|
|
||||||
throw new Error(`Unknown label ${label}`);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// The uri is used for the schema file match.
|
|
||||||
const modelUri = Uri.parse('a://b/foo.yaml');
|
|
||||||
|
|
||||||
setDiagnosticsOptions({
|
|
||||||
enableSchemaRequest: true,
|
|
||||||
hover: true,
|
|
||||||
completion: true,
|
|
||||||
validate: true,
|
|
||||||
format: true,
|
|
||||||
schemas: [
|
|
||||||
{
|
|
||||||
// Id of the first schema
|
|
||||||
uri: 'http://myserver/foo-schema.json',
|
|
||||||
// Associate with our model
|
|
||||||
fileMatch: [String(modelUri)],
|
|
||||||
schema: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
p1: {
|
|
||||||
enum: ['v1', 'v2'],
|
|
||||||
},
|
|
||||||
p2: {
|
|
||||||
// Reference the second schema
|
|
||||||
$ref: 'http://myserver/bar-schema.json',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Id of the first schema
|
|
||||||
uri: 'http://myserver/bar-schema.json',
|
|
||||||
schema: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
q1: {
|
|
||||||
enum: ['x1', 'x2'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const value = 'p1: \np2: \n';
|
|
||||||
|
|
||||||
editor.create(document.getElementById('editor'), {
|
|
||||||
automaticLayout: true,
|
|
||||||
model: editor.createModel(value, 'yaml', modelUri),
|
|
||||||
});
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
"name": "vite-example",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"start": "vite",
|
|
||||||
"build": "vite build"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"monaco-editor": "^0.31.0",
|
|
||||||
"monaco-yaml": "file:../..",
|
|
||||||
"vite": "^2.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
112
index.d.ts
vendored
112
index.d.ts
vendored
|
|
@ -1,112 +0,0 @@
|
||||||
import { JSONSchema4, JSONSchema6, JSONSchema7 } from 'json-schema';
|
|
||||||
import { IEvent, languages } from 'monaco-editor/esm/vs/editor/editor.api';
|
|
||||||
|
|
||||||
export interface SchemasSettings {
|
|
||||||
/**
|
|
||||||
* A `Uri` file match which will trigger the schema validation. This may be a glob or an exact
|
|
||||||
* path.
|
|
||||||
*
|
|
||||||
* @example '.gitlab-ci.yml'
|
|
||||||
* @example 'file://**\/.github/actions/*.yaml'
|
|
||||||
*/
|
|
||||||
fileMatch: string[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The JSON schema which will be used for validation. If not specified, it will be downloaded from
|
|
||||||
* `uri`.
|
|
||||||
*/
|
|
||||||
schema?: JSONSchema4 | JSONSchema6 | JSONSchema7;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The source URI of the JSON schema. The JSON schema will be downloaded from here if no schema
|
|
||||||
* was supplied. It will also be displayed as the source in hover tooltips.
|
|
||||||
*/
|
|
||||||
uri: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'monaco-editor/esm/vs/editor/editor.api' {
|
|
||||||
namespace languages.yaml {
|
|
||||||
export interface DiagnosticsOptions {
|
|
||||||
/**
|
|
||||||
* If set, enable schema based autocompletion.
|
|
||||||
*
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
readonly completion?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of custom tags.
|
|
||||||
*
|
|
||||||
* @default []
|
|
||||||
*/
|
|
||||||
readonly customTags?: string[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If set, the schema service would load schema content on-demand with 'fetch' if available
|
|
||||||
*
|
|
||||||
* @default false
|
|
||||||
*/
|
|
||||||
readonly enableSchemaRequest?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, formatting using Prettier is enabled. Setting this to `false` does **not** exclude
|
|
||||||
* Prettier from the bundle.
|
|
||||||
*
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
readonly format?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If set, enable hover typs based the JSON schema.
|
|
||||||
*
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
readonly hover?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, a different diffing algorithm is used to generate error messages.
|
|
||||||
*
|
|
||||||
* @default false
|
|
||||||
*/
|
|
||||||
readonly isKubernetes?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of known schemas and/or associations of schemas to file names.
|
|
||||||
*
|
|
||||||
* @default []
|
|
||||||
*/
|
|
||||||
readonly schemas?: SchemasSettings[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If set, the validator will be enabled and perform syntax validation as well as schema
|
|
||||||
* based validation.
|
|
||||||
*
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
readonly validate?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The YAML version to use for parsing.
|
|
||||||
*
|
|
||||||
* @default '1.2'
|
|
||||||
*/
|
|
||||||
readonly yamlVersion?: '1.1' | '1.2';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LanguageServiceDefaults {
|
|
||||||
readonly onDidChange: IEvent<LanguageServiceDefaults>;
|
|
||||||
readonly languageId: string;
|
|
||||||
readonly diagnosticsOptions: DiagnosticsOptions;
|
|
||||||
setDiagnosticsOptions: (options: DiagnosticsOptions) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const yamlDefaults: LanguageServiceDefaults;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure `monaco-yaml` diagnostics options.
|
|
||||||
*
|
|
||||||
* @param options - The options to set.
|
|
||||||
*/
|
|
||||||
export function setDiagnosticsOptions(options?: languages.yaml.DiagnosticsOptions): void;
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
[build]
|
|
||||||
publish = 'examples/demo/dist/'
|
|
||||||
command = 'npm ci && npm run prepack && npm --workspace demo run build'
|
|
||||||
8500
package-lock.json
generated
8500
package-lock.json
generated
File diff suppressed because it is too large
Load diff
121
package.json
121
package.json
|
|
@ -1,71 +1,100 @@
|
||||||
{
|
{
|
||||||
"name": "monaco-yaml",
|
"name": "monaco-yaml",
|
||||||
"version": "4.0.0-alpha.1",
|
"version": "2.5.0",
|
||||||
"description": "YAML plugin for the Monaco Editor",
|
"description": "YAML plugin for the Monaco Editor",
|
||||||
"homepage": "https://monaco-yaml.js.org",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepack": "node build.js",
|
"watch": "tsc -p ./src --watch",
|
||||||
"prepare": "husky install"
|
"compile": "rimraf ./out && yarn compile:umd && yarn compile:esm",
|
||||||
|
"compile:umd": "tsc -p ./src/tsconfig.json",
|
||||||
|
"compile:esm": "tsc -p ./src/tsconfig.esm.json",
|
||||||
|
"bundle": "rimraf ./lib && yarn bundle:umd && yarn bundle:esm && mcopy ./src/monaco.d.ts ./lib/monaco.d.ts",
|
||||||
|
"bundle:umd": "node ./scripts/bundle-umd",
|
||||||
|
"bundle:esm": "node ./scripts/bundle-esm",
|
||||||
|
"build": "yarn compile && yarn bundle",
|
||||||
|
"prepare": "patch-package &&yarn build",
|
||||||
|
"lint": "prettier \"{src,test}/**/*.{json,scss,html,ts}\" --write",
|
||||||
|
"test": "jest --verbose"
|
||||||
|
},
|
||||||
|
"main": "./lib/esm/monaco.contribution.js",
|
||||||
|
"module": "./lib/esm/monaco.contribution.js",
|
||||||
|
"typings": "./lib/monaco.d.ts",
|
||||||
|
"directories": {
|
||||||
|
"lib": "./lib"
|
||||||
},
|
},
|
||||||
"typings": "./index.d.ts",
|
|
||||||
"files": [
|
|
||||||
"index.js",
|
|
||||||
"index.d.ts",
|
|
||||||
"yaml.worker.js"
|
|
||||||
],
|
|
||||||
"workspaces": [
|
|
||||||
"examples/*"
|
|
||||||
],
|
|
||||||
"author": "Kevin Decker <kpdecker@gmail.com> (http://incaseofstairs.com)",
|
"author": "Kevin Decker <kpdecker@gmail.com> (http://incaseofstairs.com)",
|
||||||
"maintainers": [
|
"maintainers": [
|
||||||
"Remco Haszing <remcohaszing@gmail.com> (https://github.com/remcohaszing)"
|
"kpdecker",
|
||||||
|
"pengx17"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/remcohaszing/monaco-yaml"
|
"url": "https://github.com/pengx17/monaco-yaml"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/remcohaszing/monaco-yaml/issues"
|
"url": "https://github.com/pengx17/monaco-yaml/issues"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"prettier": "^1.19.1"
|
||||||
},
|
},
|
||||||
"keywords": [
|
|
||||||
"editor",
|
|
||||||
"frontend",
|
|
||||||
"front-end",
|
|
||||||
"monaco",
|
|
||||||
"monaco-editor",
|
|
||||||
"yaml"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/json-schema": "^7.0.0",
|
"yaml-language-server": "^0.9.0"
|
||||||
"jsonc-parser": "^3.0.0",
|
|
||||||
"path-browserify": "^1.0.0",
|
|
||||||
"prettier": "2.0.5",
|
|
||||||
"vscode-languageserver-textdocument": "^1.0.0",
|
|
||||||
"vscode-languageserver-types": "^3.0.0",
|
|
||||||
"yaml": "2.0.0-10"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"monaco-editor": ">=0.30"
|
"monaco-editor": "^0.20.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
"@types/jest": "^23.3.10",
|
||||||
"esbuild": "^0.14.0",
|
"@types/node": "^10.9.3",
|
||||||
"eslint": "^7.0.0",
|
"husky": "^1.2.1",
|
||||||
"eslint-config-remcohaszing": "^3.0.0",
|
"jest": "^23.6.0",
|
||||||
"husky": "^7.0.0",
|
"lint-staged": "^8.1.0",
|
||||||
"lint-staged": "^12.0.0",
|
"monaco-editor": "^0.20.0",
|
||||||
"monaco-editor": "^0.31.0",
|
"monaco-editor-core": "^0.20.0",
|
||||||
"type-fest": "^2.0.0",
|
"monaco-languages": "^1.10.0",
|
||||||
"typescript": "^4.0.0",
|
"monaco-plugin-helpers": "^1.0.3",
|
||||||
"yaml-language-server": "^1.0.0"
|
"patch-package": "^6.2.2",
|
||||||
|
"prettier": "^1.19.1",
|
||||||
|
"request-light": "^0.2.5",
|
||||||
|
"requirejs": "^2.3.5",
|
||||||
|
"rimraf": "^2.6.2",
|
||||||
|
"ts-jest": "^23.10.5",
|
||||||
|
"typescript": "^3.7.4",
|
||||||
|
"uglify-es": "^3.3.9"
|
||||||
|
},
|
||||||
|
"prettier": {
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"semi": true
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{css,json,md,html,yaml}": [
|
"linters": {
|
||||||
"prettier --write"
|
"*.{json,scss,html,ts,js,jsx}": [
|
||||||
|
"prettier --write",
|
||||||
|
"git add"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"husky": {
|
||||||
|
"hooks": {
|
||||||
|
"pre-commit": "lint-staged"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"globals": {
|
||||||
|
"ts-jest": {
|
||||||
|
"tsConfig": "./test/tsconfig.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"moduleFileExtensions": [
|
||||||
|
"js",
|
||||||
|
"ts"
|
||||||
],
|
],
|
||||||
"*.{js,ts}": [
|
"transform": {
|
||||||
"eslint"
|
"^.+\\.(ts|tsx)$": "ts-jest"
|
||||||
|
},
|
||||||
|
"testMatch": [
|
||||||
|
"**/test/*.test.+(ts|js)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
patches/monaco-plugin-helpers+1.0.2.patch
Normal file
13
patches/monaco-plugin-helpers+1.0.2.patch
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
diff --git a/node_modules/monaco-plugin-helpers/lib/packageESM.js b/node_modules/monaco-plugin-helpers/lib/packageESM.js
|
||||||
|
index 3c333a4..ebec9d2 100644
|
||||||
|
--- a/node_modules/monaco-plugin-helpers/lib/packageESM.js
|
||||||
|
+++ b/node_modules/monaco-plugin-helpers/lib/packageESM.js
|
||||||
|
@@ -79,7 +79,7 @@ function _packageESM(options) {
|
||||||
|
while (queue.length > 0) {
|
||||||
|
var filePath = queue.shift();
|
||||||
|
var fileContents = fs.readFileSync(filePath).toString();
|
||||||
|
- var info = ts.preProcessFile(fileContents);
|
||||||
|
+ var info = ts.preProcessFile(fileContents,true,true);
|
||||||
|
for (var i = info.importedFiles.length - 1; i >= 0; i--) {
|
||||||
|
var importText = info.importedFiles[i].fileName;
|
||||||
|
if (shouldSkipImport(importText)) {
|
||||||
62
scripts/bundle-esm.js
Normal file
62
scripts/bundle-esm.js
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const helpers = require('monaco-plugin-helpers');
|
||||||
|
|
||||||
|
const REPO_ROOT = path.join(__dirname, '../');
|
||||||
|
|
||||||
|
helpers.packageESM({
|
||||||
|
repoRoot: REPO_ROOT,
|
||||||
|
esmSource: 'out/esm',
|
||||||
|
esmDestination: 'lib/esm',
|
||||||
|
entryPoints: ['monaco.contribution.js', 'yamlMode.js', 'yaml.worker.js'],
|
||||||
|
resolveAlias: {
|
||||||
|
'vscode-nls': path.join(REPO_ROOT, 'out/esm/fillers/vscode-nls.js'),
|
||||||
|
'vscode-json-languageservice/lib/umd/services/jsonValidation': path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/vscode-json-languageservice/lib/esm/services/jsonValidation.js'
|
||||||
|
),
|
||||||
|
'vscode-json-languageservice': path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/vscode-json-languageservice/lib/esm/jsonLanguageService.js'
|
||||||
|
),
|
||||||
|
'vscode-json-languageservice/lib/umd/services/jsonHover': path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/vscode-json-languageservice/lib/esm/services/jsonHover.js'
|
||||||
|
),
|
||||||
|
'vscode-json-languageservice/lib/umd/services/jsonDocumentSymbols': path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/vscode-json-languageservice/lib/esm/services/jsonDocumentSymbols.js'
|
||||||
|
),
|
||||||
|
'vscode-json-languageservice/lib/umd/services/jsonSchemaService': path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/vscode-json-languageservice/lib/esm/services/jsonSchemaService.js'
|
||||||
|
),
|
||||||
|
'yaml-language-server/out/server/src/languageservice/yamlLanguageService': path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/yaml-language-server/out/server/src/languageservice/yamlLanguageService.js'
|
||||||
|
),
|
||||||
|
'vscode-json-languageservice/lib/umd/services/jsonDefinition': path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/vscode-json-languageservice/lib/esm/services/jsonDefinition.js'
|
||||||
|
),
|
||||||
|
'vscode-json-languageservice/lib/umd/services/jsonCompletion': path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/vscode-json-languageservice/lib/esm/services/jsonCompletion.js'
|
||||||
|
),
|
||||||
|
buffer: path.join(REPO_ROOT, 'out/esm/fillers/buffer.js'),
|
||||||
|
prettier: path.join(REPO_ROOT, 'out/esm/fillers/prettier.js'),
|
||||||
|
},
|
||||||
|
resolveSkip: ['monaco-editor', 'monaco-editor-core', 'js-yaml', 'prettier'],
|
||||||
|
destinationFolderSimplification: {
|
||||||
|
node_modules: '_deps',
|
||||||
|
'jsonc-parser/lib/esm': 'jsonc-parser',
|
||||||
|
'vscode-languageserver-types/lib/esm': 'vscode-languageserver-types',
|
||||||
|
'vscode-uri/lib/esm': 'vscode-uri',
|
||||||
|
// "vscode-json-languageservice/lib/umd": "vscode-json-languageservice/lib/esm",
|
||||||
|
// "js-yaml/dist": "js-yaml"
|
||||||
|
},
|
||||||
|
});
|
||||||
115
scripts/bundle-umd.js
Normal file
115
scripts/bundle-umd.js
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
const requirejs = require('requirejs');
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
const UglifyES = require('uglify-es');
|
||||||
|
const helpers = require('monaco-plugin-helpers');
|
||||||
|
|
||||||
|
const REPO_ROOT = path.resolve(__dirname, '..');
|
||||||
|
|
||||||
|
const sha1 = helpers.getGitVersion(REPO_ROOT);
|
||||||
|
const semver = require('../package.json').version;
|
||||||
|
const headerVersion = semver + '(' + sha1 + ')';
|
||||||
|
|
||||||
|
const BUNDLED_FILE_HEADER = [
|
||||||
|
'/*!-----------------------------------------------------------------------------',
|
||||||
|
' * Copyright (c) Microsoft Corporation. All rights reserved.',
|
||||||
|
' * monaco-yaml version: ' + headerVersion,
|
||||||
|
' * Released under the MIT license',
|
||||||
|
' * https://github.com/kpdecker/monaco-yaml/blob/master/LICENSE.md',
|
||||||
|
' *-----------------------------------------------------------------------------*/',
|
||||||
|
'',
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
bundleOne('monaco.contribution');
|
||||||
|
bundleOne('yamlMode');
|
||||||
|
bundleOne('yamlWorker');
|
||||||
|
|
||||||
|
function bundleOne(moduleId, exclude) {
|
||||||
|
requirejs.optimize(
|
||||||
|
{
|
||||||
|
baseUrl: 'out/amd/',
|
||||||
|
name: 'vs/language/yaml/' + moduleId,
|
||||||
|
out: 'lib/dev/' + moduleId + '.js',
|
||||||
|
exclude: exclude,
|
||||||
|
paths: {
|
||||||
|
'vs/language/yaml': REPO_ROOT + '/out/amd',
|
||||||
|
'yaml-language-server/out/server/src/languageservice/yamlLanguageService':
|
||||||
|
REPO_ROOT +
|
||||||
|
'/node_modules/yaml-language-server/out/server/src/languageservice/yamlLanguageService',
|
||||||
|
},
|
||||||
|
optimize: 'none',
|
||||||
|
packages: [
|
||||||
|
{
|
||||||
|
name: 'js-yaml',
|
||||||
|
location: path.join(REPO_ROOT, 'node_modules/js-yaml/dist'),
|
||||||
|
main: 'js-yaml',
|
||||||
|
},
|
||||||
|
// The following is required by YAML language service
|
||||||
|
{
|
||||||
|
name: 'vscode-json-languageservice',
|
||||||
|
location: path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/vscode-json-languageservice'
|
||||||
|
),
|
||||||
|
main: 'lib/umd/jsonLanguageService',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'vscode-languageserver-textdocument',
|
||||||
|
location: path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/vscode-languageserver-textdocument'
|
||||||
|
),
|
||||||
|
main: 'lib/umd/main',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'yaml-ast-parser-custom-tags',
|
||||||
|
location: path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/yaml-ast-parser-custom-tags'
|
||||||
|
),
|
||||||
|
main: 'dist/src/index',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'jsonc-parser',
|
||||||
|
location: path.join(REPO_ROOT, 'node_modules/jsonc-parser/lib/umd'),
|
||||||
|
main: 'main',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'vscode-languageserver-types',
|
||||||
|
location: path.join(
|
||||||
|
REPO_ROOT,
|
||||||
|
'node_modules/vscode-languageserver-types/lib/umd'
|
||||||
|
),
|
||||||
|
main: 'main',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'vscode-uri',
|
||||||
|
location: path.join(REPO_ROOT, 'node_modules/vscode-uri/lib/umd'),
|
||||||
|
main: 'index',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'vscode-nls',
|
||||||
|
location: path.join(REPO_ROOT, '/out/amd/fillers'),
|
||||||
|
main: 'vscode-nls',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
const devFilePath = path.join(REPO_ROOT, 'lib/dev/' + moduleId + '.js');
|
||||||
|
const minFilePath = path.join(REPO_ROOT, 'lib/min/' + moduleId + '.js');
|
||||||
|
const fileContents = fs.readFileSync(devFilePath).toString();
|
||||||
|
console.log();
|
||||||
|
console.log(`Minifying ${devFilePath}...`);
|
||||||
|
const result = UglifyES.minify(fileContents, {
|
||||||
|
output: {
|
||||||
|
comments: 'some',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log(`Done.`);
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(path.join(REPO_ROOT, 'lib/min'));
|
||||||
|
} catch (err) {}
|
||||||
|
fs.writeFileSync(minFilePath, BUNDLED_FILE_HEADER + result.code);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export const languageId = 'yaml';
|
|
||||||
1
src/fillers/buffer.ts
Normal file
1
src/fillers/buffer.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export const Buffer = null;
|
||||||
1
src/fillers/os.ts
Normal file
1
src/fillers/os.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export const EOL = '\n';
|
||||||
8
src/fillers/prettier.ts
Normal file
8
src/fillers/prettier.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
const prettier = require('prettier/standalone');
|
||||||
|
const parser = require('prettier/parser-yaml');
|
||||||
|
|
||||||
|
export default {
|
||||||
|
format(text: string, options) {
|
||||||
|
prettier.format(text, Object.assign(options, { plugins: [parser] }));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
/**
|
|
||||||
* This is a stub for `monaco-yaml/lib/esm/schemaSelectionHandlers.js`.
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
||||||
export function JSONSchemaSelection(): void {}
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
export interface Options {
|
export interface Options {
|
||||||
locale?: string;
|
locale?: string;
|
||||||
cacheLanguageResolution?: boolean;
|
cacheLanguageResolution?: boolean;
|
||||||
|
|
@ -6,30 +11,38 @@ export interface LocalizeInfo {
|
||||||
key: string;
|
key: string;
|
||||||
comment: string[];
|
comment: string[];
|
||||||
}
|
}
|
||||||
export type LocalizeFunc = (
|
export interface LocalizeFunc {
|
||||||
info: LocalizeInfo | string,
|
(info: LocalizeInfo, message: string, ...args: any[]): string;
|
||||||
message: string,
|
(key: string, message: string, ...args: any[]): string;
|
||||||
...args: unknown[]
|
}
|
||||||
) => string;
|
|
||||||
export type LoadFunc = (file?: string) => LocalizeFunc;
|
export type LoadFunc = (file?: string) => LocalizeFunc;
|
||||||
|
|
||||||
function format(message: string, args: string[]): string {
|
function format(message: string, args: any[]): string {
|
||||||
return args.length === 0
|
let result: string;
|
||||||
? message
|
|
||||||
: message.replace(/{(\d+)}/g, (match, rest: number[]) => {
|
if (args.length === 0) {
|
||||||
const [index] = rest;
|
result = message;
|
||||||
return typeof args[index] === 'undefined' ? match : args[index];
|
} else {
|
||||||
|
result = message.replace(/\{(\d+)\}/g, (match, rest) => {
|
||||||
|
const index = rest[0];
|
||||||
|
return typeof args[index] !== 'undefined' ? args[index] : match;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function localize(key: LocalizeInfo | string, message: string, ...args: string[]): string {
|
function localize(
|
||||||
|
key: string | LocalizeInfo,
|
||||||
|
message: string,
|
||||||
|
...args: any[]
|
||||||
|
): string {
|
||||||
return format(message, args);
|
return format(message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function loadMessageBundle(): LocalizeFunc {
|
export function loadMessageBundle(file?: string): LocalizeFunc {
|
||||||
return localize;
|
return localize;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function config(): LoadFunc {
|
export function config(opt?: Options | string): LoadFunc {
|
||||||
return loadMessageBundle;
|
return loadMessageBundle;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
78
src/index.ts
78
src/index.ts
|
|
@ -1,78 +0,0 @@
|
||||||
import { Emitter, languages } from 'monaco-editor/esm/vs/editor/editor.api.js';
|
|
||||||
|
|
||||||
import { languageId } from './constants';
|
|
||||||
import { setupMode } from './yamlMode';
|
|
||||||
|
|
||||||
// --- YAML configuration and defaults ---------
|
|
||||||
|
|
||||||
const diagnosticDefault: languages.yaml.DiagnosticsOptions = {
|
|
||||||
completion: true,
|
|
||||||
customTags: [],
|
|
||||||
enableSchemaRequest: false,
|
|
||||||
format: true,
|
|
||||||
isKubernetes: false,
|
|
||||||
hover: true,
|
|
||||||
schemas: [],
|
|
||||||
validate: true,
|
|
||||||
yamlVersion: '1.2',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function createLanguageServiceDefaults(
|
|
||||||
initialDiagnosticsOptions: languages.yaml.DiagnosticsOptions,
|
|
||||||
): languages.yaml.LanguageServiceDefaults {
|
|
||||||
const onDidChange = new Emitter<languages.yaml.LanguageServiceDefaults>();
|
|
||||||
let diagnosticsOptions = initialDiagnosticsOptions;
|
|
||||||
|
|
||||||
const languageServiceDefaults: languages.yaml.LanguageServiceDefaults = {
|
|
||||||
get onDidChange() {
|
|
||||||
return onDidChange.event;
|
|
||||||
},
|
|
||||||
|
|
||||||
get languageId() {
|
|
||||||
return languageId;
|
|
||||||
},
|
|
||||||
|
|
||||||
get diagnosticsOptions() {
|
|
||||||
return diagnosticsOptions;
|
|
||||||
},
|
|
||||||
|
|
||||||
setDiagnosticsOptions(options) {
|
|
||||||
diagnosticsOptions = { ...diagnosticDefault, ...options };
|
|
||||||
onDidChange.fire(languageServiceDefaults);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return languageServiceDefaults;
|
|
||||||
}
|
|
||||||
|
|
||||||
const yamlDefaults = createLanguageServiceDefaults(diagnosticDefault);
|
|
||||||
|
|
||||||
// Export API
|
|
||||||
function createAPI(): typeof languages.yaml {
|
|
||||||
return {
|
|
||||||
yamlDefaults,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
languages.yaml = createAPI();
|
|
||||||
|
|
||||||
// --- Registration to monaco editor ---
|
|
||||||
|
|
||||||
languages.register({
|
|
||||||
id: languageId,
|
|
||||||
extensions: ['.yaml', '.yml'],
|
|
||||||
aliases: ['YAML', 'yaml', 'YML', 'yml'],
|
|
||||||
mimetypes: ['application/x-yaml'],
|
|
||||||
});
|
|
||||||
|
|
||||||
languages.onLanguage('yaml', () => {
|
|
||||||
setupMode(yamlDefaults);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure `monaco-yaml` diagnostics options.
|
|
||||||
*
|
|
||||||
* @param options - The options to set.
|
|
||||||
*/
|
|
||||||
export function setDiagnosticsOptions(options: languages.yaml.DiagnosticsOptions = {}): void {
|
|
||||||
languages.yaml.yamlDefaults.setDiagnosticsOptions(options);
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +1,149 @@
|
||||||
import {
|
/*---------------------------------------------------------------------------------------------
|
||||||
editor,
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
IDisposable,
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
languages,
|
*--------------------------------------------------------------------------------------------*/
|
||||||
MarkerSeverity,
|
'use strict';
|
||||||
MarkerTag,
|
|
||||||
Position,
|
|
||||||
Range,
|
|
||||||
Uri,
|
|
||||||
} from 'monaco-editor/esm/vs/editor/editor.api.js';
|
|
||||||
import * as ls from 'vscode-languageserver-types';
|
|
||||||
import { CustomFormatterOptions } from 'yaml-language-server/lib/esm/languageservice/yamlLanguageService.js';
|
|
||||||
|
|
||||||
import { languageId } from './constants';
|
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
|
||||||
import { YAMLWorker } from './yamlWorker';
|
import { YAMLWorker } from './yamlWorker';
|
||||||
|
|
||||||
export type WorkerAccessor = (...more: Uri[]) => PromiseLike<YAMLWorker>;
|
import * as ls from 'vscode-languageserver-types';
|
||||||
|
|
||||||
|
import Uri = monaco.Uri;
|
||||||
|
import Position = monaco.Position;
|
||||||
|
import Range = monaco.Range;
|
||||||
|
import IRange = monaco.IRange;
|
||||||
|
import Thenable = monaco.Thenable;
|
||||||
|
import CancellationToken = monaco.CancellationToken;
|
||||||
|
import IDisposable = monaco.IDisposable;
|
||||||
|
import { CustomFormatterOptions } from 'yaml-language-server/out/server/src/languageservice/yamlLanguageService';
|
||||||
|
|
||||||
|
export type WorkerAccessor = (...more: Uri[]) => Thenable<YAMLWorker>;
|
||||||
|
|
||||||
// --- diagnostics --- ---
|
// --- diagnostics --- ---
|
||||||
|
|
||||||
function toSeverity(lsSeverity: ls.DiagnosticSeverity): MarkerSeverity {
|
export class DiagnosticsAdapter {
|
||||||
|
private _disposables: IDisposable[] = [];
|
||||||
|
private _listener: { [uri: string]: IDisposable } = Object.create(null);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _languageId: string,
|
||||||
|
private _worker: WorkerAccessor,
|
||||||
|
defaults: LanguageServiceDefaultsImpl
|
||||||
|
) {
|
||||||
|
const onModelAdd = (model: monaco.editor.IModel): void => {
|
||||||
|
const modeId = model.getModeId();
|
||||||
|
if (modeId !== this._languageId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let handle: NodeJS.Timer;
|
||||||
|
this._listener[model.uri.toString()] = model.onDidChangeContent(() => {
|
||||||
|
clearTimeout(handle);
|
||||||
|
handle = setTimeout(() => this._doValidate(model.uri, modeId), 500);
|
||||||
|
});
|
||||||
|
|
||||||
|
this._doValidate(model.uri, modeId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onModelRemoved = (model: monaco.editor.IModel): void => {
|
||||||
|
monaco.editor.setModelMarkers(model, this._languageId, []);
|
||||||
|
const uriStr = model.uri.toString();
|
||||||
|
const listener = this._listener[uriStr];
|
||||||
|
if (listener) {
|
||||||
|
listener.dispose();
|
||||||
|
delete this._listener[uriStr];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this._disposables.push(monaco.editor.onDidCreateModel(onModelAdd));
|
||||||
|
this._disposables.push(
|
||||||
|
monaco.editor.onWillDisposeModel(model => {
|
||||||
|
onModelRemoved(model);
|
||||||
|
this._resetSchema(model.uri);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this._disposables.push(
|
||||||
|
monaco.editor.onDidChangeModelLanguage(event => {
|
||||||
|
onModelRemoved(event.model);
|
||||||
|
onModelAdd(event.model);
|
||||||
|
this._resetSchema(event.model.uri);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
this._disposables.push(
|
||||||
|
defaults.onDidChange(_ => {
|
||||||
|
monaco.editor.getModels().forEach(model => {
|
||||||
|
if (model.getModeId() === this._languageId) {
|
||||||
|
onModelRemoved(model);
|
||||||
|
onModelAdd(model);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
this._disposables.push({
|
||||||
|
dispose: () => {
|
||||||
|
monaco.editor.getModels().forEach(onModelRemoved);
|
||||||
|
for (const key in this._listener) {
|
||||||
|
this._listener[key].dispose();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
monaco.editor.getModels().forEach(onModelAdd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose(): void {
|
||||||
|
this._disposables.forEach(d => d && d.dispose());
|
||||||
|
this._disposables = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private _resetSchema(resource: Uri): void {
|
||||||
|
this._worker().then(worker => {
|
||||||
|
worker.resetSchema(resource.toString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _doValidate(resource: Uri, languageId: string): void {
|
||||||
|
this._worker(resource)
|
||||||
|
.then(worker => {
|
||||||
|
return worker.doValidation(resource.toString()).then(diagnostics => {
|
||||||
|
const markers = diagnostics.map(d => toDiagnostics(resource, d));
|
||||||
|
const model = monaco.editor.getModel(resource);
|
||||||
|
if (model.getModeId() === languageId) {
|
||||||
|
monaco.editor.setModelMarkers(model, languageId, markers);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(undefined, err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toSeverity(lsSeverity: number): monaco.MarkerSeverity {
|
||||||
switch (lsSeverity) {
|
switch (lsSeverity) {
|
||||||
case ls.DiagnosticSeverity.Error:
|
case ls.DiagnosticSeverity.Error:
|
||||||
return MarkerSeverity.Error;
|
return monaco.MarkerSeverity.Error;
|
||||||
case ls.DiagnosticSeverity.Warning:
|
case ls.DiagnosticSeverity.Warning:
|
||||||
return MarkerSeverity.Warning;
|
return monaco.MarkerSeverity.Warning;
|
||||||
case ls.DiagnosticSeverity.Information:
|
case ls.DiagnosticSeverity.Information:
|
||||||
return MarkerSeverity.Info;
|
return monaco.MarkerSeverity.Info;
|
||||||
case ls.DiagnosticSeverity.Hint:
|
case ls.DiagnosticSeverity.Hint:
|
||||||
return MarkerSeverity.Hint;
|
return monaco.MarkerSeverity.Hint;
|
||||||
default:
|
default:
|
||||||
return MarkerSeverity.Info;
|
return monaco.MarkerSeverity.Info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toMarkerDataTag(tag: ls.DiagnosticTag): MarkerTag {
|
function toDiagnostics(
|
||||||
switch (tag) {
|
resource: Uri,
|
||||||
case ls.DiagnosticTag.Deprecated:
|
diag: ls.Diagnostic
|
||||||
return MarkerTag.Deprecated;
|
): monaco.editor.IMarkerData {
|
||||||
case ls.DiagnosticTag.Unnecessary:
|
const code =
|
||||||
return MarkerTag.Unnecessary;
|
typeof diag.code === 'number' ? String(diag.code) : (diag.code as string);
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function toDiagnostics(diag: ls.Diagnostic): editor.IMarkerData {
|
|
||||||
return {
|
return {
|
||||||
severity: toSeverity(diag.severity),
|
severity: toSeverity(diag.severity),
|
||||||
startLineNumber: diag.range.start.line + 1,
|
startLineNumber: diag.range.start.line + 1,
|
||||||
|
|
@ -51,109 +151,48 @@ function toDiagnostics(diag: ls.Diagnostic): editor.IMarkerData {
|
||||||
endLineNumber: diag.range.end.line + 1,
|
endLineNumber: diag.range.end.line + 1,
|
||||||
endColumn: diag.range.end.character + 1,
|
endColumn: diag.range.end.character + 1,
|
||||||
message: diag.message,
|
message: diag.message,
|
||||||
code: String(diag.code),
|
code,
|
||||||
source: diag.source,
|
source: diag.source,
|
||||||
tags: diag.tags?.map(toMarkerDataTag),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createDiagnosticsAdapter(
|
|
||||||
getWorker: WorkerAccessor,
|
|
||||||
defaults: languages.yaml.LanguageServiceDefaults,
|
|
||||||
): void {
|
|
||||||
const listeners = new Map<string, IDisposable>();
|
|
||||||
|
|
||||||
const resetSchema = async (resource: Uri): Promise<void> => {
|
|
||||||
const worker = await getWorker();
|
|
||||||
worker.resetSchema(String(resource));
|
|
||||||
};
|
|
||||||
|
|
||||||
const doValidate = async (resource: Uri): Promise<void> => {
|
|
||||||
const worker = await getWorker(resource);
|
|
||||||
const diagnostics = await worker.doValidation(String(resource));
|
|
||||||
const markers = diagnostics.map(toDiagnostics);
|
|
||||||
const model = editor.getModel(resource);
|
|
||||||
// Return value from getModel can be null if model not found
|
|
||||||
// (e.g. if user navigates away from editor)
|
|
||||||
if (model && model.getLanguageId() === languageId) {
|
|
||||||
editor.setModelMarkers(model, languageId, markers);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onModelAdd = (model: editor.IModel): void => {
|
|
||||||
if (model.getLanguageId() !== languageId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let handle: ReturnType<typeof setTimeout>;
|
|
||||||
listeners.set(
|
|
||||||
String(model.uri),
|
|
||||||
model.onDidChangeContent(() => {
|
|
||||||
clearTimeout(handle);
|
|
||||||
handle = setTimeout(() => doValidate(model.uri), 500);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
doValidate(model.uri);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onModelRemoved = (model: editor.IModel): void => {
|
|
||||||
editor.setModelMarkers(model, languageId, []);
|
|
||||||
const uriStr = String(model.uri);
|
|
||||||
const listener = listeners.get(uriStr);
|
|
||||||
if (listener) {
|
|
||||||
listener.dispose();
|
|
||||||
listeners.delete(uriStr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
editor.onDidCreateModel(onModelAdd);
|
|
||||||
editor.onWillDisposeModel((model) => {
|
|
||||||
onModelRemoved(model);
|
|
||||||
resetSchema(model.uri);
|
|
||||||
});
|
|
||||||
editor.onDidChangeModelLanguage((event) => {
|
|
||||||
onModelRemoved(event.model);
|
|
||||||
onModelAdd(event.model);
|
|
||||||
resetSchema(event.model.uri);
|
|
||||||
});
|
|
||||||
defaults.onDidChange(() => {
|
|
||||||
for (const model of editor.getModels()) {
|
|
||||||
if (model.getLanguageId() === languageId) {
|
|
||||||
onModelRemoved(model);
|
|
||||||
onModelAdd(model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const model of editor.getModels()) {
|
|
||||||
onModelAdd(model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- completion ------
|
// --- completion ------
|
||||||
|
|
||||||
function fromPosition(position: Position): ls.Position {
|
function fromPosition(position: Position): ls.Position {
|
||||||
if (!position) {
|
if (!position) {
|
||||||
return;
|
return void 0;
|
||||||
}
|
}
|
||||||
return { character: position.column - 1, line: position.lineNumber - 1 };
|
return { character: position.column - 1, line: position.lineNumber - 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fromRange(range: IRange): ls.Range {
|
||||||
|
if (!range) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
start: {
|
||||||
|
line: range.startLineNumber - 1,
|
||||||
|
character: range.startColumn - 1,
|
||||||
|
},
|
||||||
|
end: { line: range.endLineNumber - 1, character: range.endColumn - 1 },
|
||||||
|
};
|
||||||
|
}
|
||||||
function toRange(range: ls.Range): Range {
|
function toRange(range: ls.Range): Range {
|
||||||
if (!range) {
|
if (!range) {
|
||||||
return;
|
return void 0;
|
||||||
}
|
}
|
||||||
return new Range(
|
return new Range(
|
||||||
range.start.line + 1,
|
range.start.line + 1,
|
||||||
range.start.character + 1,
|
range.start.character + 1,
|
||||||
range.end.line + 1,
|
range.end.line + 1,
|
||||||
range.end.character + 1,
|
range.end.character + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toCompletionItemKind(kind: ls.CompletionItemKind): languages.CompletionItemKind {
|
function toCompletionItemKind(
|
||||||
const mItemKind = languages.CompletionItemKind;
|
kind: number
|
||||||
|
): monaco.languages.CompletionItemKind {
|
||||||
|
const mItemKind = monaco.languages.CompletionItemKind;
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case ls.CompletionItemKind.Text:
|
case ls.CompletionItemKind.Text:
|
||||||
|
|
@ -192,14 +231,59 @@ function toCompletionItemKind(kind: ls.CompletionItemKind): languages.Completion
|
||||||
return mItemKind.File;
|
return mItemKind.File;
|
||||||
case ls.CompletionItemKind.Reference:
|
case ls.CompletionItemKind.Reference:
|
||||||
return mItemKind.Reference;
|
return mItemKind.Reference;
|
||||||
default:
|
|
||||||
return mItemKind.Property;
|
|
||||||
}
|
}
|
||||||
|
return mItemKind.Property;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toTextEdit(textEdit: ls.TextEdit): editor.ISingleEditOperation {
|
function fromCompletionItemKind(
|
||||||
|
kind: monaco.languages.CompletionItemKind
|
||||||
|
): ls.CompletionItemKind {
|
||||||
|
const mItemKind = monaco.languages.CompletionItemKind;
|
||||||
|
|
||||||
|
switch (kind) {
|
||||||
|
case mItemKind.Text:
|
||||||
|
return ls.CompletionItemKind.Text;
|
||||||
|
case mItemKind.Method:
|
||||||
|
return ls.CompletionItemKind.Method;
|
||||||
|
case mItemKind.Function:
|
||||||
|
return ls.CompletionItemKind.Function;
|
||||||
|
case mItemKind.Constructor:
|
||||||
|
return ls.CompletionItemKind.Constructor;
|
||||||
|
case mItemKind.Field:
|
||||||
|
return ls.CompletionItemKind.Field;
|
||||||
|
case mItemKind.Variable:
|
||||||
|
return ls.CompletionItemKind.Variable;
|
||||||
|
case mItemKind.Class:
|
||||||
|
return ls.CompletionItemKind.Class;
|
||||||
|
case mItemKind.Interface:
|
||||||
|
return ls.CompletionItemKind.Interface;
|
||||||
|
case mItemKind.Module:
|
||||||
|
return ls.CompletionItemKind.Module;
|
||||||
|
case mItemKind.Property:
|
||||||
|
return ls.CompletionItemKind.Property;
|
||||||
|
case mItemKind.Unit:
|
||||||
|
return ls.CompletionItemKind.Unit;
|
||||||
|
case mItemKind.Value:
|
||||||
|
return ls.CompletionItemKind.Value;
|
||||||
|
case mItemKind.Enum:
|
||||||
|
return ls.CompletionItemKind.Enum;
|
||||||
|
case mItemKind.Keyword:
|
||||||
|
return ls.CompletionItemKind.Keyword;
|
||||||
|
case mItemKind.Snippet:
|
||||||
|
return ls.CompletionItemKind.Snippet;
|
||||||
|
case mItemKind.Color:
|
||||||
|
return ls.CompletionItemKind.Color;
|
||||||
|
case mItemKind.File:
|
||||||
|
return ls.CompletionItemKind.File;
|
||||||
|
case mItemKind.Reference:
|
||||||
|
return ls.CompletionItemKind.Reference;
|
||||||
|
}
|
||||||
|
return ls.CompletionItemKind.Property;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toTextEdit(textEdit: ls.TextEdit): monaco.editor.ISingleEditOperation {
|
||||||
if (!textEdit) {
|
if (!textEdit) {
|
||||||
return;
|
return void 0;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
range: toRange(textEdit.range),
|
range: toRange(textEdit.range),
|
||||||
|
|
@ -207,31 +291,34 @@ function toTextEdit(textEdit: ls.TextEdit): editor.ISingleEditOperation {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createCompletionItemProvider(
|
export class CompletionAdapter
|
||||||
getWorker: WorkerAccessor,
|
implements monaco.languages.CompletionItemProvider {
|
||||||
): languages.CompletionItemProvider {
|
constructor(private _worker: WorkerAccessor) {}
|
||||||
return {
|
|
||||||
triggerCharacters: [' ', ':'],
|
|
||||||
|
|
||||||
async provideCompletionItems(model, position) {
|
public get triggerCharacters(): string[] {
|
||||||
|
return [' ', ':'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public provideCompletionItems(
|
||||||
|
model: monaco.editor.IReadOnlyModel,
|
||||||
|
position: Position,
|
||||||
|
context: monaco.languages.CompletionContext,
|
||||||
|
token: CancellationToken
|
||||||
|
): Thenable<monaco.languages.CompletionList> {
|
||||||
|
const wordInfo = model.getWordUntilPosition(position);
|
||||||
const resource = model.uri;
|
const resource = model.uri;
|
||||||
|
|
||||||
const worker = await getWorker(resource);
|
return this._worker(resource)
|
||||||
const info = await worker.doComplete(String(resource), fromPosition(position));
|
.then(worker => {
|
||||||
|
return worker.doComplete(resource.toString(), fromPosition(position));
|
||||||
|
})
|
||||||
|
.then(info => {
|
||||||
if (!info) {
|
if (!info) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const items: monaco.languages.CompletionItem[] = info.items.map(
|
||||||
const wordInfo = model.getWordUntilPosition(position);
|
entry => {
|
||||||
const wordRange = new Range(
|
const item: monaco.languages.CompletionItem = {
|
||||||
position.lineNumber,
|
|
||||||
wordInfo.startColumn,
|
|
||||||
position.lineNumber,
|
|
||||||
wordInfo.endColumn,
|
|
||||||
);
|
|
||||||
|
|
||||||
const items = info.items.map((entry) => {
|
|
||||||
const item: languages.CompletionItem = {
|
|
||||||
label: entry.label,
|
label: entry.label,
|
||||||
insertText: entry.insertText || entry.label,
|
insertText: entry.insertText || entry.label,
|
||||||
sortText: entry.sortText,
|
sortText: entry.sortText,
|
||||||
|
|
@ -239,75 +326,111 @@ export function createCompletionItemProvider(
|
||||||
documentation: entry.documentation,
|
documentation: entry.documentation,
|
||||||
detail: entry.detail,
|
detail: entry.detail,
|
||||||
kind: toCompletionItemKind(entry.kind),
|
kind: toCompletionItemKind(entry.kind),
|
||||||
range: wordRange,
|
range: {
|
||||||
|
startLineNumber: position.lineNumber,
|
||||||
|
endLineNumber: position.lineNumber,
|
||||||
|
...wordInfo,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
if (entry.textEdit) {
|
if (entry.textEdit) {
|
||||||
item.range = toRange(
|
item.range = toRange(entry.textEdit.range);
|
||||||
'range' in entry.textEdit ? entry.textEdit.range : entry.textEdit.replace,
|
|
||||||
);
|
|
||||||
item.insertText = entry.textEdit.newText;
|
item.insertText = entry.textEdit.newText;
|
||||||
}
|
}
|
||||||
if (entry.additionalTextEdits) {
|
if (entry.additionalTextEdits) {
|
||||||
item.additionalTextEdits = entry.additionalTextEdits.map(toTextEdit);
|
item.additionalTextEdits = entry.additionalTextEdits.map(
|
||||||
|
toTextEdit
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (entry.insertTextFormat === ls.InsertTextFormat.Snippet) {
|
if (entry.insertTextFormat === ls.InsertTextFormat.Snippet) {
|
||||||
item.insertTextRules = languages.CompletionItemInsertTextRule.InsertAsSnippet;
|
item.insertTextRules =
|
||||||
|
monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet;
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
incomplete: info.isIncomplete,
|
isIncomplete: info.isIncomplete,
|
||||||
suggestions: items,
|
suggestions: items,
|
||||||
};
|
};
|
||||||
},
|
});
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- definition ------
|
function isMarkupContent(thing: any): thing is ls.MarkupContent {
|
||||||
|
return (
|
||||||
|
thing &&
|
||||||
|
typeof thing === 'object' &&
|
||||||
|
typeof (thing as ls.MarkupContent).kind === 'string'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function createDefinitionProvider(getWorker: WorkerAccessor): languages.DefinitionProvider {
|
function toMarkdownString(
|
||||||
|
entry: ls.MarkupContent | ls.MarkedString
|
||||||
|
): monaco.IMarkdownString {
|
||||||
|
if (typeof entry === 'string') {
|
||||||
return {
|
return {
|
||||||
async provideDefinition(model, position) {
|
value: entry,
|
||||||
const resource = model.uri;
|
|
||||||
|
|
||||||
const worker = await getWorker(resource);
|
|
||||||
const definitions = await worker.doDefinition(String(resource), fromPosition(position));
|
|
||||||
|
|
||||||
return definitions?.map((definition) => ({
|
|
||||||
originSelectionRange: definition.originSelectionRange,
|
|
||||||
range: toRange(definition.targetRange),
|
|
||||||
targetSelectionRange: definition.targetSelectionRange,
|
|
||||||
uri: Uri.parse(definition.targetUri),
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
if (isMarkupContent(entry)) {
|
||||||
|
if (entry.kind === 'plaintext') {
|
||||||
|
return {
|
||||||
|
value: entry.value.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
value: entry.value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { value: '```' + entry.language + '\n' + entry.value + '\n```\n' };
|
||||||
|
}
|
||||||
|
|
||||||
|
function toMarkedStringArray(
|
||||||
|
contents: ls.MarkupContent | ls.MarkedString | ls.MarkedString[]
|
||||||
|
): monaco.IMarkdownString[] {
|
||||||
|
if (!contents) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
if (Array.isArray(contents)) {
|
||||||
|
return contents.map(toMarkdownString);
|
||||||
|
}
|
||||||
|
return [toMarkdownString(contents)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- hover ------
|
// --- hover ------
|
||||||
|
|
||||||
export function createHoverProvider(getWorker: WorkerAccessor): languages.HoverProvider {
|
export class HoverAdapter implements monaco.languages.HoverProvider {
|
||||||
return {
|
constructor(private _worker: WorkerAccessor) {}
|
||||||
async provideHover(model, position) {
|
|
||||||
|
public provideHover(
|
||||||
|
model: monaco.editor.IReadOnlyModel,
|
||||||
|
position: Position,
|
||||||
|
token: CancellationToken
|
||||||
|
): Thenable<monaco.languages.Hover> {
|
||||||
const resource = model.uri;
|
const resource = model.uri;
|
||||||
|
|
||||||
const worker = await getWorker(resource);
|
return this._worker(resource)
|
||||||
const info = await worker.doHover(String(resource), fromPosition(position));
|
.then(worker => {
|
||||||
|
return worker.doHover(resource.toString(), fromPosition(position));
|
||||||
|
})
|
||||||
|
.then(info => {
|
||||||
if (!info) {
|
if (!info) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
range: toRange(info.range),
|
range: toRange(info.range),
|
||||||
contents: [{ value: (info.contents as ls.MarkupContent).value }],
|
contents: toMarkedStringArray(info.contents),
|
||||||
};
|
} as monaco.languages.Hover;
|
||||||
},
|
});
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- document symbols ------
|
// --- document symbols ------
|
||||||
|
|
||||||
function toSymbolKind(kind: ls.SymbolKind): languages.SymbolKind {
|
function toSymbolKind(kind: ls.SymbolKind): monaco.languages.SymbolKind {
|
||||||
const mKind = languages.SymbolKind;
|
const mKind = monaco.languages.SymbolKind;
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case ls.SymbolKind.File:
|
case ls.SymbolKind.File:
|
||||||
|
|
@ -346,43 +469,48 @@ function toSymbolKind(kind: ls.SymbolKind): languages.SymbolKind {
|
||||||
return mKind.Boolean;
|
return mKind.Boolean;
|
||||||
case ls.SymbolKind.Array:
|
case ls.SymbolKind.Array:
|
||||||
return mKind.Array;
|
return mKind.Array;
|
||||||
default:
|
}
|
||||||
return mKind.Function;
|
return mKind.Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DocumentSymbolAdapter
|
||||||
|
implements monaco.languages.DocumentSymbolProvider {
|
||||||
|
constructor(private _worker: WorkerAccessor) {}
|
||||||
|
|
||||||
|
public provideDocumentSymbols(
|
||||||
|
model: monaco.editor.IReadOnlyModel,
|
||||||
|
token: CancellationToken
|
||||||
|
): Thenable<monaco.languages.DocumentSymbol[]> {
|
||||||
|
const resource = model.uri;
|
||||||
|
|
||||||
|
return this._worker(resource)
|
||||||
|
.then(worker => worker.findDocumentSymbols(resource.toString()))
|
||||||
|
.then(items => {
|
||||||
|
if (!items) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return items.map(item => toDocumentSymbol(item));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toDocumentSymbol(item: ls.DocumentSymbol): languages.DocumentSymbol {
|
function toDocumentSymbol(
|
||||||
|
item: ls.DocumentSymbol
|
||||||
|
): monaco.languages.DocumentSymbol {
|
||||||
return {
|
return {
|
||||||
detail: item.detail || '',
|
detail: '',
|
||||||
range: toRange(item.range),
|
range: toRange(item.range),
|
||||||
name: item.name,
|
name: item.name,
|
||||||
kind: toSymbolKind(item.kind),
|
kind: toSymbolKind(item.kind),
|
||||||
selectionRange: toRange(item.selectionRange),
|
selectionRange: toRange(item.selectionRange),
|
||||||
children: item.children.map(toDocumentSymbol),
|
children: item.children.map(child => toDocumentSymbol(child)),
|
||||||
tags: [],
|
tags: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createDocumentSymbolProvider(
|
|
||||||
getWorker: WorkerAccessor,
|
|
||||||
): languages.DocumentSymbolProvider {
|
|
||||||
return {
|
|
||||||
async provideDocumentSymbols(model) {
|
|
||||||
const resource = model.uri;
|
|
||||||
|
|
||||||
const worker = await getWorker(resource);
|
|
||||||
const items = await worker.findDocumentSymbols(String(resource));
|
|
||||||
if (!items) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return items.map(toDocumentSymbol);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function fromFormattingOptions(
|
function fromFormattingOptions(
|
||||||
options: languages.FormattingOptions,
|
options: monaco.languages.FormattingOptions
|
||||||
): CustomFormatterOptions & ls.FormattingOptions {
|
): ls.FormattingOptions & CustomFormatterOptions {
|
||||||
return {
|
return {
|
||||||
tabSize: options.tabSize,
|
tabSize: options.tabSize,
|
||||||
insertSpaces: options.insertSpaces,
|
insertSpaces: options.insertSpaces,
|
||||||
|
|
@ -390,42 +518,115 @@ function fromFormattingOptions(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createDocumentFormattingEditProvider(
|
export class DocumentFormattingEditProvider
|
||||||
getWorker: WorkerAccessor,
|
implements monaco.languages.DocumentFormattingEditProvider {
|
||||||
): languages.DocumentFormattingEditProvider {
|
constructor(private _worker: WorkerAccessor) {}
|
||||||
return {
|
|
||||||
async provideDocumentFormattingEdits(model, options) {
|
public provideDocumentFormattingEdits(
|
||||||
|
model: monaco.editor.IReadOnlyModel,
|
||||||
|
options: monaco.languages.FormattingOptions,
|
||||||
|
token: CancellationToken
|
||||||
|
): Thenable<monaco.editor.ISingleEditOperation[]> {
|
||||||
const resource = model.uri;
|
const resource = model.uri;
|
||||||
|
|
||||||
const worker = await getWorker(resource);
|
return this._worker(resource).then(worker => {
|
||||||
const edits = await worker.format(String(resource), fromFormattingOptions(options));
|
return worker
|
||||||
|
.format(resource.toString(), null, fromFormattingOptions(options))
|
||||||
|
.then(edits => {
|
||||||
if (!edits || edits.length === 0) {
|
if (!edits || edits.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return edits.map(toTextEdit);
|
return edits.map(toTextEdit);
|
||||||
},
|
});
|
||||||
};
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toLink(link: ls.DocumentLink): languages.ILink {
|
export class DocumentRangeFormattingEditProvider
|
||||||
return {
|
implements monaco.languages.DocumentRangeFormattingEditProvider {
|
||||||
range: toRange(link.range),
|
constructor(private _worker: WorkerAccessor) {}
|
||||||
tooltip: link.tooltip,
|
|
||||||
url: link.target,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createLinkProvider(getWorker: WorkerAccessor): languages.LinkProvider {
|
public provideDocumentRangeFormattingEdits(
|
||||||
return {
|
model: monaco.editor.IReadOnlyModel,
|
||||||
async provideLinks(model) {
|
range: Range,
|
||||||
|
options: monaco.languages.FormattingOptions,
|
||||||
|
token: CancellationToken
|
||||||
|
): Thenable<monaco.editor.ISingleEditOperation[]> {
|
||||||
const resource = model.uri;
|
const resource = model.uri;
|
||||||
|
|
||||||
const worker = await getWorker(resource);
|
return this._worker(resource).then(worker => {
|
||||||
const links = await worker.findLinks(String(resource));
|
return worker
|
||||||
|
.format(
|
||||||
return {
|
resource.toString(),
|
||||||
links: links.map(toLink),
|
fromRange(range),
|
||||||
};
|
fromFormattingOptions(options)
|
||||||
},
|
)
|
||||||
};
|
.then(edits => {
|
||||||
|
if (!edits || edits.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return edits.map(toTextEdit);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// export class DocumentColorAdapter
|
||||||
|
// implements monaco.languages.DocumentColorProvider {
|
||||||
|
// constructor(private _worker: WorkerAccessor) {}
|
||||||
|
|
||||||
|
// public provideDocumentColors(
|
||||||
|
// model: monaco.editor.IReadOnlyModel,
|
||||||
|
// token: CancellationToken
|
||||||
|
// ): Thenable<monaco.languages.IColorInformation[]> {
|
||||||
|
// const resource = model.uri;
|
||||||
|
|
||||||
|
// return this._worker(resource)
|
||||||
|
// .then(worker => worker.findDocumentColors(resource.toString()))
|
||||||
|
// .then(infos => {
|
||||||
|
// if (!infos) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// return infos.map(item => ({
|
||||||
|
// color: item.color,
|
||||||
|
// range: toRange(item.range),
|
||||||
|
// }));
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public provideColorPresentations(
|
||||||
|
// model: monaco.editor.IReadOnlyModel,
|
||||||
|
// info: monaco.languages.IColorInformation,
|
||||||
|
// token: CancellationToken
|
||||||
|
// ): Thenable<monaco.languages.IColorPresentation[]> {
|
||||||
|
// const resource = model.uri;
|
||||||
|
|
||||||
|
// return this._worker(resource)
|
||||||
|
// .then(worker =>
|
||||||
|
// worker.getColorPresentations(
|
||||||
|
// resource.toString(),
|
||||||
|
// info.color,
|
||||||
|
// fromRange(info.range)
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// .then(presentations => {
|
||||||
|
// if (!presentations) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// return presentations.map(presentation => {
|
||||||
|
// const item: monaco.languages.IColorPresentation = {
|
||||||
|
// label: presentation.label,
|
||||||
|
// };
|
||||||
|
// if (presentation.textEdit) {
|
||||||
|
// item.textEdit = toTextEdit(presentation.textEdit);
|
||||||
|
// }
|
||||||
|
// if (presentation.additionalTextEdits) {
|
||||||
|
// item.additionalTextEdits = presentation.additionalTextEdits.map(
|
||||||
|
// toTextEdit
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// return item;
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
|
||||||
82
src/monaco.contribution.ts
Normal file
82
src/monaco.contribution.ts
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { setupMode } from './yamlMode';
|
||||||
|
|
||||||
|
import Emitter = monaco.Emitter;
|
||||||
|
import IEvent = monaco.IEvent;
|
||||||
|
|
||||||
|
declare var require: <T>(
|
||||||
|
moduleId: [string],
|
||||||
|
callback: (module: T) => void
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
// --- YAML configuration and defaults ---------
|
||||||
|
|
||||||
|
export class LanguageServiceDefaultsImpl
|
||||||
|
implements monaco.languages.yaml.LanguageServiceDefaults {
|
||||||
|
private _onDidChange = new Emitter<
|
||||||
|
monaco.languages.yaml.LanguageServiceDefaults
|
||||||
|
>();
|
||||||
|
private _diagnosticsOptions: monaco.languages.yaml.DiagnosticsOptions;
|
||||||
|
private _languageId: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
languageId: string,
|
||||||
|
diagnosticsOptions: monaco.languages.yaml.DiagnosticsOptions
|
||||||
|
) {
|
||||||
|
this._languageId = languageId;
|
||||||
|
this.setDiagnosticsOptions(diagnosticsOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
get onDidChange(): IEvent<monaco.languages.yaml.LanguageServiceDefaults> {
|
||||||
|
return this._onDidChange.event;
|
||||||
|
}
|
||||||
|
|
||||||
|
get languageId(): string {
|
||||||
|
return this._languageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
get diagnosticsOptions(): monaco.languages.yaml.DiagnosticsOptions {
|
||||||
|
return this._diagnosticsOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setDiagnosticsOptions(
|
||||||
|
options: monaco.languages.yaml.DiagnosticsOptions
|
||||||
|
): void {
|
||||||
|
this._diagnosticsOptions = options || Object.create(null);
|
||||||
|
this._onDidChange.fire(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const diagnosticDefault: monaco.languages.yaml.DiagnosticsOptions = {
|
||||||
|
validate: true,
|
||||||
|
schemas: [],
|
||||||
|
enableSchemaRequest: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const yamlDefaults = new LanguageServiceDefaultsImpl('yaml', diagnosticDefault);
|
||||||
|
|
||||||
|
// Export API
|
||||||
|
function createAPI(): typeof monaco.languages.yaml {
|
||||||
|
return {
|
||||||
|
yamlDefaults,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
monaco.languages.yaml = createAPI();
|
||||||
|
|
||||||
|
// --- Registration to monaco editor ---
|
||||||
|
|
||||||
|
monaco.languages.register({
|
||||||
|
id: 'yaml',
|
||||||
|
extensions: ['.yaml', '.yml'],
|
||||||
|
aliases: ['YAML', 'yaml', 'YML', 'yml'],
|
||||||
|
mimetypes: ['application/x-yaml'],
|
||||||
|
});
|
||||||
|
|
||||||
|
monaco.languages.onLanguage('yaml', () => {
|
||||||
|
setupMode(yamlDefaults);
|
||||||
|
});
|
||||||
54
src/monaco.d.ts
vendored
Normal file
54
src/monaco.d.ts
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
declare namespace monaco.languages.yaml {
|
||||||
|
export interface DiagnosticsOptions {
|
||||||
|
/**
|
||||||
|
* If set, the validator will be enabled and perform syntax validation as well as schema based validation.
|
||||||
|
*/
|
||||||
|
readonly validate?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of known schemas and/or associations of schemas to file names.
|
||||||
|
*/
|
||||||
|
readonly schemas?: Array<{
|
||||||
|
/**
|
||||||
|
* The URI of the schema, which is also the identifier of the schema.
|
||||||
|
*/
|
||||||
|
readonly uri: string;
|
||||||
|
/**
|
||||||
|
* A list of file names that are associated to the schema. The '*' wildcard can be used. For example '*.schema.json', 'package.json'
|
||||||
|
*/
|
||||||
|
readonly fileMatch?: string[];
|
||||||
|
/**
|
||||||
|
* The schema for the given URI.
|
||||||
|
*/
|
||||||
|
readonly schema?: any;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, the schema service would load schema content on-demand with 'fetch' if available
|
||||||
|
*/
|
||||||
|
readonly enableSchemaRequest?: boolean;
|
||||||
|
/**
|
||||||
|
* If specified, this prefix will be added to all on demand schema requests
|
||||||
|
*/
|
||||||
|
readonly prefix?: string;
|
||||||
|
/**
|
||||||
|
* Whether or not kubernetes yaml is supported
|
||||||
|
*/
|
||||||
|
readonly isKubernetes?: boolean;
|
||||||
|
|
||||||
|
readonly format?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LanguageServiceDefaults {
|
||||||
|
readonly onDidChange: IEvent<LanguageServiceDefaults>;
|
||||||
|
readonly diagnosticsOptions: DiagnosticsOptions;
|
||||||
|
setDiagnosticsOptions(options: DiagnosticsOptions): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const yamlDefaults: LanguageServiceDefaults;
|
||||||
|
}
|
||||||
37
src/requestTypes.ts
Normal file
37
src/requestTypes.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { NotificationType, RequestType } from 'vscode-languageserver';
|
||||||
|
|
||||||
|
export namespace SchemaAssociationNotification {
|
||||||
|
export const type: NotificationType<{}, {}> = new NotificationType(
|
||||||
|
'json/schemaAssociations'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace DynamicCustomSchemaRequestRegistration {
|
||||||
|
export const type: NotificationType<{}, {}> = new NotificationType(
|
||||||
|
'yaml/registerCustomSchemaRequest'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace VSCodeContentRequest {
|
||||||
|
export const type: RequestType<{}, {}, {}, {}> = new RequestType(
|
||||||
|
'vscode/content'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace CustomSchemaContentRequest {
|
||||||
|
export const type: RequestType<{}, {}, {}, {}> = new RequestType(
|
||||||
|
'custom/schema/content'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace CustomSchemaRequest {
|
||||||
|
export const type: RequestType<{}, {}, {}, {}> = new RequestType(
|
||||||
|
'custom/schema/request'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ColorSymbolRequest {
|
||||||
|
export const type: RequestType<{}, {}, {}, {}> = new RequestType(
|
||||||
|
'json/colorSymbols'
|
||||||
|
);
|
||||||
|
}
|
||||||
17
src/tsconfig.esm.json
Normal file
17
src/tsconfig.esm.json
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"outDir": "../out/esm",
|
||||||
|
"target": "es5",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es5",
|
||||||
|
"es2015.collection",
|
||||||
|
"es2015.promise",
|
||||||
|
"es2016",
|
||||||
|
"es2017.string"
|
||||||
|
],
|
||||||
|
"downlevelIteration": true
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/tsconfig.json
Normal file
18
src/tsconfig.json
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "umd",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"outDir": "../out/amd",
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"target": "es5",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es5",
|
||||||
|
"es2015.collection",
|
||||||
|
"es2015.promise",
|
||||||
|
"es2016",
|
||||||
|
"es2017.string"
|
||||||
|
],
|
||||||
|
"downlevelIteration": true
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/typings/refs.d.ts
vendored
Normal file
5
src/typings/refs.d.ts
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
/// <reference path='../../node_modules/monaco-editor-core/monaco.d.ts'/>
|
||||||
|
|
@ -1,67 +1,96 @@
|
||||||
import { editor, languages } from 'monaco-editor/esm/vs/editor/editor.api.js';
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
import { WorkerAccessor } from './languageFeatures';
|
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
|
||||||
import { YAMLWorker } from './yamlWorker';
|
import { YAMLWorker } from './yamlWorker';
|
||||||
|
|
||||||
// 2min
|
import IDisposable = monaco.IDisposable;
|
||||||
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000;
|
import Uri = monaco.Uri;
|
||||||
|
|
||||||
export function createWorkerManager(
|
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min
|
||||||
defaults: languages.yaml.LanguageServiceDefaults,
|
|
||||||
): WorkerAccessor {
|
|
||||||
let worker: editor.MonacoWebWorker<YAMLWorker>;
|
|
||||||
let client: Promise<YAMLWorker>;
|
|
||||||
let lastUsedTime = 0;
|
|
||||||
|
|
||||||
const stopWorker = (): void => {
|
export class WorkerManager {
|
||||||
if (worker) {
|
private _defaults: LanguageServiceDefaultsImpl;
|
||||||
worker.dispose();
|
private _idleCheckInterval: NodeJS.Timer;
|
||||||
worker = undefined;
|
private _lastUsedTime: number;
|
||||||
|
private _configChangeListener: IDisposable;
|
||||||
|
|
||||||
|
private _worker: monaco.editor.MonacoWebWorker<YAMLWorker>;
|
||||||
|
private _client: Promise<YAMLWorker>;
|
||||||
|
|
||||||
|
constructor(defaults: LanguageServiceDefaultsImpl) {
|
||||||
|
this._defaults = defaults;
|
||||||
|
this._worker = null;
|
||||||
|
this._idleCheckInterval = setInterval(() => this._checkIfIdle(), 30 * 1000);
|
||||||
|
this._lastUsedTime = 0;
|
||||||
|
this._configChangeListener = this._defaults.onDidChange(() =>
|
||||||
|
this._stopWorker()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
client = undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
setInterval(() => {
|
public dispose(): void {
|
||||||
if (!worker) {
|
clearInterval(this._idleCheckInterval);
|
||||||
|
this._configChangeListener.dispose();
|
||||||
|
this._stopWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getLanguageServiceWorker(...resources: Uri[]): Promise<YAMLWorker> {
|
||||||
|
let _client: YAMLWorker;
|
||||||
|
return this._getClient()
|
||||||
|
.then(client => {
|
||||||
|
_client = client;
|
||||||
|
})
|
||||||
|
.then(_ => {
|
||||||
|
return this._worker.withSyncedResources(resources);
|
||||||
|
})
|
||||||
|
.then(_ => _client);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _stopWorker(): void {
|
||||||
|
if (this._worker) {
|
||||||
|
this._worker.dispose();
|
||||||
|
this._worker = null;
|
||||||
|
}
|
||||||
|
this._client = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _checkIfIdle(): void {
|
||||||
|
if (!this._worker) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const timePassedSinceLastUsed = Date.now() - lastUsedTime;
|
const timePassedSinceLastUsed = Date.now() - this._lastUsedTime;
|
||||||
if (timePassedSinceLastUsed > STOP_WHEN_IDLE_FOR) {
|
if (timePassedSinceLastUsed > STOP_WHEN_IDLE_FOR) {
|
||||||
stopWorker();
|
this._stopWorker();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 30 * 1000);
|
|
||||||
|
|
||||||
// This is necessary to have updated language options take effect (e.g. schema changes)
|
private _getClient(): Promise<YAMLWorker> {
|
||||||
defaults.onDidChange(() => stopWorker());
|
this._lastUsedTime = Date.now();
|
||||||
|
|
||||||
const getClient = (): Promise<YAMLWorker> => {
|
if (!this._client) {
|
||||||
lastUsedTime = Date.now();
|
this._worker = monaco.editor.createWebWorker<YAMLWorker>({
|
||||||
|
// module that exports the create() method and returns a `YAMLWorker` instance
|
||||||
if (!client) {
|
|
||||||
worker = editor.createWebWorker<YAMLWorker>({
|
|
||||||
// Module that exports the create() method and returns a `YAMLWorker` instance
|
|
||||||
moduleId: 'vs/language/yaml/yamlWorker',
|
moduleId: 'vs/language/yaml/yamlWorker',
|
||||||
|
|
||||||
label: defaults.languageId,
|
label: this._defaults.languageId,
|
||||||
|
|
||||||
// Passed in to the create() method
|
// passed in to the create() method
|
||||||
createData: {
|
createData: {
|
||||||
languageSettings: defaults.diagnosticsOptions,
|
languageSettings: this._defaults.diagnosticsOptions,
|
||||||
enableSchemaRequest: defaults.diagnosticsOptions.enableSchemaRequest,
|
languageId: this._defaults.languageId,
|
||||||
isKubernetes: defaults.diagnosticsOptions.isKubernetes,
|
enableSchemaRequest: this._defaults.diagnosticsOptions
|
||||||
customTags: defaults.diagnosticsOptions.customTags,
|
.enableSchemaRequest,
|
||||||
|
prefix: this._defaults.diagnosticsOptions.prefix,
|
||||||
|
isKubernetes: this._defaults.diagnosticsOptions.isKubernetes,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
client = worker.getProxy();
|
this._client = this._worker.getProxy();
|
||||||
}
|
}
|
||||||
|
|
||||||
return client;
|
return this._client;
|
||||||
};
|
}
|
||||||
|
|
||||||
return async (...resources) => {
|
|
||||||
const client = await getClient();
|
|
||||||
await worker.withSyncedResources(resources);
|
|
||||||
return client;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,15 @@
|
||||||
import { initialize } from 'monaco-editor/esm/vs/editor/editor.worker.js';
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
import { createYAMLWorker, ICreateData } from './yamlWorker';
|
import * as worker from 'monaco-editor/esm/vs/editor/editor.worker';
|
||||||
|
import { YAMLWorker } from './yamlWorker';
|
||||||
|
|
||||||
self.onmessage = () => {
|
self.onmessage = () => {
|
||||||
initialize((ctx, createData: ICreateData) => Object.create(createYAMLWorker(ctx, createData)));
|
// ignore the first message
|
||||||
|
worker.initialize((ctx, createData) => {
|
||||||
|
return new YAMLWorker(ctx, createData);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,73 @@
|
||||||
import { languages } from 'monaco-editor/esm/vs/editor/editor.api.js';
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
import { languageId } from './constants';
|
import * as languageFeatures from './languageFeatures';
|
||||||
import {
|
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
|
||||||
createCompletionItemProvider,
|
import { WorkerManager } from './workerManager';
|
||||||
createDefinitionProvider,
|
import { YAMLWorker } from './yamlWorker';
|
||||||
createDiagnosticsAdapter,
|
|
||||||
createDocumentFormattingEditProvider,
|
|
||||||
createDocumentSymbolProvider,
|
|
||||||
createHoverProvider,
|
|
||||||
createLinkProvider,
|
|
||||||
} from './languageFeatures';
|
|
||||||
import { createWorkerManager } from './workerManager';
|
|
||||||
|
|
||||||
const richEditConfiguration: languages.LanguageConfiguration = {
|
import Uri = monaco.Uri;
|
||||||
|
import IDisposable = monaco.IDisposable;
|
||||||
|
|
||||||
|
export function setupMode(defaults: LanguageServiceDefaultsImpl): void {
|
||||||
|
const disposables: IDisposable[] = [];
|
||||||
|
|
||||||
|
const client = new WorkerManager(defaults);
|
||||||
|
disposables.push(client);
|
||||||
|
|
||||||
|
const worker: languageFeatures.WorkerAccessor = (
|
||||||
|
...uris: Uri[]
|
||||||
|
): Promise<YAMLWorker> => {
|
||||||
|
return client.getLanguageServiceWorker(...uris);
|
||||||
|
};
|
||||||
|
|
||||||
|
const languageId = defaults.languageId;
|
||||||
|
|
||||||
|
disposables.push(
|
||||||
|
monaco.languages.registerCompletionItemProvider(
|
||||||
|
languageId,
|
||||||
|
new languageFeatures.CompletionAdapter(worker)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
disposables.push(
|
||||||
|
monaco.languages.registerHoverProvider(
|
||||||
|
languageId,
|
||||||
|
new languageFeatures.HoverAdapter(worker)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
disposables.push(
|
||||||
|
monaco.languages.registerDocumentSymbolProvider(
|
||||||
|
languageId,
|
||||||
|
new languageFeatures.DocumentSymbolAdapter(worker)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
disposables.push(
|
||||||
|
monaco.languages.registerDocumentFormattingEditProvider(
|
||||||
|
languageId,
|
||||||
|
new languageFeatures.DocumentFormattingEditProvider(worker)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
disposables.push(
|
||||||
|
monaco.languages.registerDocumentRangeFormattingEditProvider(
|
||||||
|
languageId,
|
||||||
|
new languageFeatures.DocumentRangeFormattingEditProvider(worker)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
disposables.push(
|
||||||
|
new languageFeatures.DiagnosticsAdapter(languageId, worker, defaults)
|
||||||
|
);
|
||||||
|
disposables.push(
|
||||||
|
monaco.languages.setLanguageConfiguration(languageId, richEditConfiguration)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Color adapter should be necessary most of the time:
|
||||||
|
// disposables.push(monaco.languages.registerColorProvider(languageId, new languageFeatures.DocumentColorAdapter(worker)));
|
||||||
|
}
|
||||||
|
|
||||||
|
const richEditConfiguration: monaco.languages.LanguageConfiguration = {
|
||||||
comments: {
|
comments: {
|
||||||
lineComment: '#',
|
lineComment: '#',
|
||||||
},
|
},
|
||||||
|
|
@ -39,23 +94,7 @@ const richEditConfiguration: languages.LanguageConfiguration = {
|
||||||
onEnterRules: [
|
onEnterRules: [
|
||||||
{
|
{
|
||||||
beforeText: /:\s*$/,
|
beforeText: /:\s*$/,
|
||||||
action: { indentAction: languages.IndentAction.Indent },
|
action: { indentAction: monaco.languages.IndentAction.Indent },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export function setupMode(defaults: languages.yaml.LanguageServiceDefaults): void {
|
|
||||||
const worker = createWorkerManager(defaults);
|
|
||||||
|
|
||||||
languages.registerCompletionItemProvider(languageId, createCompletionItemProvider(worker));
|
|
||||||
languages.registerHoverProvider(languageId, createHoverProvider(worker));
|
|
||||||
languages.registerDefinitionProvider(languageId, createDefinitionProvider(worker));
|
|
||||||
languages.registerDocumentSymbolProvider(languageId, createDocumentSymbolProvider(worker));
|
|
||||||
languages.registerDocumentFormattingEditProvider(
|
|
||||||
languageId,
|
|
||||||
createDocumentFormattingEditProvider(worker),
|
|
||||||
);
|
|
||||||
languages.registerLinkProvider(languageId, createLinkProvider(worker));
|
|
||||||
createDiagnosticsAdapter(worker, defaults);
|
|
||||||
languages.setLanguageConfiguration(languageId, richEditConfiguration);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,111 +1,127 @@
|
||||||
import { worker } from 'monaco-editor/esm/vs/editor/editor.api.js';
|
/*---------------------------------------------------------------------------------------------
|
||||||
import { Promisable } from 'type-fest';
|
* Copyright (c) Red Hat, Inc. All rights reserved.
|
||||||
import { TextDocument } from 'vscode-languageserver-textdocument';
|
* Copyright (c) Adam Voss. All rights reserved.
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import Thenable = monaco.Thenable;
|
||||||
|
import IWorkerContext = monaco.worker.IWorkerContext;
|
||||||
|
|
||||||
import * as ls from 'vscode-languageserver-types';
|
import * as ls from 'vscode-languageserver-types';
|
||||||
import {
|
import * as yamlService from 'yaml-language-server/out/server/src/languageservice/yamlLanguageService';
|
||||||
CustomFormatterOptions,
|
|
||||||
getLanguageService,
|
|
||||||
LanguageSettings,
|
|
||||||
} from 'yaml-language-server/lib/esm/languageservice/yamlLanguageService.js';
|
|
||||||
|
|
||||||
import { languageId } from './constants';
|
let defaultSchemaRequestService;
|
||||||
|
if (typeof fetch !== 'undefined') {
|
||||||
async function schemaRequestService(uri: string): Promise<string> {
|
defaultSchemaRequestService = function(url) {
|
||||||
const response = await fetch(uri);
|
return fetch(url).then(response => response.text());
|
||||||
if (response.ok) {
|
};
|
||||||
return response.text();
|
|
||||||
}
|
|
||||||
throw new Error(`Schema request failed for ${uri}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface YAMLWorker {
|
export class YAMLWorker {
|
||||||
doValidation: (uri: string) => Promisable<ls.Diagnostic[]>;
|
private _ctx: IWorkerContext;
|
||||||
|
private _languageService: yamlService.LanguageService;
|
||||||
|
private _languageSettings: yamlService.LanguageSettings;
|
||||||
|
private _languageId: string;
|
||||||
|
private _isKubernetes: boolean;
|
||||||
|
|
||||||
doComplete: (uri: string, position: ls.Position) => Promisable<ls.CompletionList>;
|
constructor(ctx: IWorkerContext, createData: ICreateData) {
|
||||||
|
const prefix = createData.prefix || '';
|
||||||
doDefinition: (uri: string, position: ls.Position) => Promisable<ls.LocationLink[]>;
|
const service = (url: string) =>
|
||||||
|
defaultSchemaRequestService(`${prefix}${url}`);
|
||||||
doHover: (uri: string, position: ls.Position) => Promisable<ls.Hover>;
|
this._ctx = ctx;
|
||||||
|
this._languageSettings = createData.languageSettings;
|
||||||
format: (uri: string, options: CustomFormatterOptions) => Promisable<ls.TextEdit[]>;
|
this._languageId = createData.languageId;
|
||||||
|
this._languageService = yamlService.getLanguageService(
|
||||||
resetSchema: (uri: string) => Promisable<boolean>;
|
createData.enableSchemaRequest && service,
|
||||||
|
|
||||||
findDocumentSymbols: (uri: string) => Promisable<ls.DocumentSymbol[]>;
|
|
||||||
|
|
||||||
findLinks: (uri: string) => Promisable<ls.DocumentLink[]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createYAMLWorker(
|
|
||||||
ctx: worker.IWorkerContext,
|
|
||||||
{ enableSchemaRequest, languageSettings }: ICreateData,
|
|
||||||
): YAMLWorker {
|
|
||||||
const languageService = getLanguageService(
|
|
||||||
enableSchemaRequest ? schemaRequestService : null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
null,
|
||||||
|
[]
|
||||||
);
|
);
|
||||||
languageService.configure(languageSettings);
|
this._isKubernetes = createData.isKubernetes || false;
|
||||||
|
this._languageService.configure({
|
||||||
|
...this._languageSettings,
|
||||||
|
hover: true,
|
||||||
|
isKubernetes: this._isKubernetes,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const getTextDocument = (uri: string): TextDocument => {
|
public doValidation(uri: string): Thenable<ls.Diagnostic[]> {
|
||||||
const models = ctx.getMirrorModels();
|
const document = this._getTextDocument(uri);
|
||||||
|
if (document) {
|
||||||
|
return this._languageService.doValidation(document, this._isKubernetes);
|
||||||
|
}
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public doComplete(
|
||||||
|
uri: string,
|
||||||
|
position: ls.Position
|
||||||
|
): Thenable<ls.CompletionList> {
|
||||||
|
const document = this._getTextDocument(uri);
|
||||||
|
return this._languageService.doComplete(
|
||||||
|
document,
|
||||||
|
position,
|
||||||
|
this._isKubernetes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public doResolve(item: ls.CompletionItem): Thenable<ls.CompletionItem> {
|
||||||
|
return this._languageService.doResolve(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public doHover(uri: string, position: ls.Position): Thenable<ls.Hover> {
|
||||||
|
const document = this._getTextDocument(uri);
|
||||||
|
return this._languageService.doHover(document, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public format(
|
||||||
|
uri: string,
|
||||||
|
range: ls.Range,
|
||||||
|
options: yamlService.CustomFormatterOptions
|
||||||
|
): Thenable<ls.TextEdit[]> {
|
||||||
|
const document = this._getTextDocument(uri);
|
||||||
|
const textEdits = this._languageService.doFormat(document, options);
|
||||||
|
return Promise.resolve(textEdits);
|
||||||
|
}
|
||||||
|
|
||||||
|
public resetSchema(uri: string): Thenable<boolean> {
|
||||||
|
return Promise.resolve(this._languageService.resetSchema(uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
public findDocumentSymbols(uri: string): Thenable<ls.DocumentSymbol[]> {
|
||||||
|
const document = this._getTextDocument(uri);
|
||||||
|
const symbols = this._languageService.findDocumentSymbols2(document);
|
||||||
|
return Promise.resolve(symbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getTextDocument(uri: string): ls.TextDocument {
|
||||||
|
const models = this._ctx.getMirrorModels();
|
||||||
for (const model of models) {
|
for (const model of models) {
|
||||||
if (String(model.uri) === uri) {
|
if (model.uri.toString() === uri) {
|
||||||
return TextDocument.create(uri, languageId, model.version, model.getValue());
|
return ls.TextDocument.create(
|
||||||
|
uri,
|
||||||
|
this._languageId,
|
||||||
|
model.version,
|
||||||
|
model.getValue()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
doValidation(uri) {
|
|
||||||
const document = getTextDocument(uri);
|
|
||||||
if (document) {
|
|
||||||
return languageService.doValidation(document, languageSettings.isKubernetes);
|
|
||||||
}
|
}
|
||||||
return [];
|
|
||||||
},
|
|
||||||
|
|
||||||
doComplete(uri, position) {
|
|
||||||
const document = getTextDocument(uri);
|
|
||||||
return languageService.doComplete(document, position, languageSettings.isKubernetes);
|
|
||||||
},
|
|
||||||
|
|
||||||
doDefinition(uri, position) {
|
|
||||||
const document = getTextDocument(uri);
|
|
||||||
return languageService.doDefinition(document, { position, textDocument: { uri } });
|
|
||||||
},
|
|
||||||
|
|
||||||
doHover(uri, position) {
|
|
||||||
const document = getTextDocument(uri);
|
|
||||||
return languageService.doHover(document, position);
|
|
||||||
},
|
|
||||||
|
|
||||||
format(uri, options) {
|
|
||||||
const document = getTextDocument(uri);
|
|
||||||
return languageService.doFormat(document, options);
|
|
||||||
},
|
|
||||||
|
|
||||||
resetSchema(uri) {
|
|
||||||
return languageService.resetSchema(uri);
|
|
||||||
},
|
|
||||||
|
|
||||||
findDocumentSymbols(uri) {
|
|
||||||
const document = getTextDocument(uri);
|
|
||||||
return languageService.findDocumentSymbols2(document, {});
|
|
||||||
},
|
|
||||||
|
|
||||||
findLinks(uri) {
|
|
||||||
const document = getTextDocument(uri);
|
|
||||||
return languageService.findLinks(document);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICreateData {
|
export interface ICreateData {
|
||||||
languageSettings: LanguageSettings;
|
languageId: string;
|
||||||
|
languageSettings: yamlService.LanguageSettings;
|
||||||
enableSchemaRequest: boolean;
|
enableSchemaRequest: boolean;
|
||||||
|
prefix?: string;
|
||||||
isKubernetes?: boolean;
|
isKubernetes?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function create(
|
||||||
|
ctx: IWorkerContext,
|
||||||
|
createData: ICreateData
|
||||||
|
): YAMLWorker {
|
||||||
|
return new YAMLWorker(ctx, createData);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"declaration": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"downlevelIteration": true,
|
|
||||||
"lib": ["dom", "dom.iterable", "es2017"],
|
|
||||||
"module": "esnext",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"noEmit": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"target": "es6",
|
|
||||||
"types": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue