├── .editorconfig
├── .github
└── workflows
│ ├── ci.yaml
│ ├── native-image.yaml
│ └── release.yml
├── .gitignore
├── .vscode-test.mjs
├── .vscode
├── extensions.json
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── DCO
├── Jenkinsfile
├── LICENSE
├── NativeImage.jenkins
├── README.md
├── USAGE_DATA.md
├── docs
├── BindingWithGrammar.md
├── CodeLens.md
├── Commands.md
├── Extensions.md
├── Features.md
├── Features
│ ├── DTDFeatures.md
│ ├── RelaxNGFeatures.md
│ ├── XIncludeFeatures.md
│ ├── XMLCatalogFeatures.md
│ ├── XMLColorsFeatures.md
│ ├── XMLFeatures.md
│ ├── XMLFilePathSupport.md
│ ├── XMLReferencesFeatures.md
│ └── XSDFeatures.md
├── Folding.md
├── Formatting.md
├── Preferences.md
├── Proxy.md
├── README.md
├── Refactor.md
├── Symbols.md
├── Troubleshooting.md
├── Validation.md
└── images
│ ├── BindingWithGrammar
│ ├── BindToGrammarCodeAction.png
│ ├── BindToGrammarCodeActionDropdown.png
│ ├── BindToGrammarCodeLens.png
│ ├── BindToGrammarCommand.png
│ ├── BindingWizardDemo.gif
│ ├── BindingWizardDropdown.png
│ ├── BindingWizardFileExplorer.png
│ ├── GenerateDTDFromXML.gif
│ ├── GenerateRelaxNGFromXML.gif
│ └── GenerateXSDFromXML.gif
│ ├── CodeLens
│ ├── DTDElementCodeLens.gif
│ ├── XSDElementCodeLens.gif
│ └── XSDTypeCodeLens.gif
│ ├── Commands
│ └── XMLCommands.png
│ ├── Extensions
│ ├── DebugAttachRemote.png
│ ├── DebugConfigurations.png
│ ├── DebugLemMinXExtensionInEclipse.png
│ ├── DebugLemMinXExtensionInVSCode.png
│ ├── DebugMultiRootSetup.png
│ ├── DebugVSCodeXML.png
│ ├── DebugVSCodeXMLSingleRoot.png
│ ├── EclipseRunDebugConfigurations.png
│ ├── EclipseWithLemMinXExtensionOpen.png
│ ├── HitABreakpointVSCode.png
│ ├── InstallVSCodeExtensionForLemMinXExtension.png
│ ├── LaunchVSCodeExtensionForLemMinXExtension.png
│ ├── NewDebugConfiguration.png
│ ├── PackageVSCodeExtensionForLemMinXExtension.png
│ ├── ProjectWindowAndDebugWindow.png
│ ├── ProjectWindowAndDebugWindowSingleRoot.png
│ ├── TerminalInstallVSCodeExtensionForLemMinXExtension.png
│ └── VSCodeExtensionForLemMinXExtension.png
│ ├── Features
│ ├── AttributeCompletionXML.gif
│ ├── AutoCloseTagEndXML.gif
│ ├── AutoCloseTagEndXSD.gif
│ ├── AutoCloseTagSlashXML.gif
│ ├── AutoCloseTagSlashXSD.gif
│ ├── CodeLensBind.png
│ ├── CodeLensCatalogRegistration.gif
│ ├── CodeLensDTD.gif
│ ├── CodeLensReferencesDTD.gif
│ ├── CodeLensReferencesXSD.gif
│ ├── CodeLensXSD.gif
│ ├── CompletionBasedOnDTD.gif
│ ├── CompletionBasedOnXSD.gif
│ ├── FoldingSetTrueXML.gif
│ ├── FoldingXML.gif
│ ├── FormatXML.gif
│ ├── GenerateXMLSchemaSnippet.gif
│ ├── GenerateXMLSnippet.gif
│ ├── HighlightCorrespondingXML.gif
│ ├── HighlightOccurrenceXSD.gif
│ ├── HoverBasedOnDTD.gif
│ ├── HoverBasedOnXSD.gif
│ ├── JumpToClosingTagXML.gif
│ ├── JumpToClosingTagXSD.gif
│ ├── JumpToElementDeclarationDTD.gif
│ ├── JumpToOpeningTagXML.gif
│ ├── JumpToOpeningTagXSD.gif
│ ├── JumpToTypeDefinitionXSD.gif
│ ├── JumpToXSDDefFromXML.gif
│ ├── LinkedEditingXML.gif
│ ├── RenameTagXML.gif
│ ├── RenameTagXSD.gif
│ ├── RenameTypeReferenceXSD.gif
│ ├── SelectionRange.gif
│ ├── SymbolOutlineXML.gif
│ ├── TypeAutocompleteXSD.gif
│ ├── ValidateXSDSameName.gif
│ ├── ValidateXSDType.gif
│ ├── ValidationDTD.gif
│ ├── ValidationXML.gif
│ ├── XIncludeDocumentLink.gif
│ ├── XIncludeValidation.png
│ ├── XMLColorsFeatures.png
│ ├── XMLFilePathsInAttrFeatures.png
│ ├── XMLFilePathsInTextFeatures.png
│ ├── XMLReferencesWithDocbook.gif
│ ├── XMLReferencesWithTEI.gif
│ └── XMLReferencesWithWebXML.gif
│ ├── Preferences
│ └── HoverDocumentationQuickDemo.gif
│ ├── Refactor
│ ├── SurroundWithCDATA.gif
│ ├── SurroundWithComments.gif
│ └── SurroundWithTags.gif
│ ├── RelaxNG
│ ├── GoToTypeDefinitionMenu.png
│ ├── GoToTypeDefinitionResult.png
│ ├── RNGDefineSupport.gif
│ ├── RNGHrefSupport.gif
│ ├── RelaxNGCompactSyntaxOverview.png
│ ├── RelaxNGCompletionAndDocumentation.png
│ ├── RelaxNGHoverAndDocumentation.png
│ ├── RelaxNGSnippetsSupport.gif
│ ├── RelaxNGSupport.gif
│ ├── RelaxNGValidation.png
│ ├── RelaxNGXMLSyntaxOverview.png
│ └── XMLValidatedWithRelaxNG.png
│ ├── Symbols
│ ├── ShowReferencedGrammars.png
│ ├── SymbolsBeansWithIdAttrFilter.png
│ ├── SymbolsBuildWithInlineAttrFilter.png
│ ├── SymbolsPOMWithTextFilter.png
│ └── SymbolsPOMWithoutFilter.png
│ ├── Validation
│ ├── DoctypeError1.png
│ ├── DoctypeError2.png
│ ├── ExternalEntityResolvingDemonstration.gif
│ ├── GenerateXSD.gif
│ ├── XMLGrammarError.png
│ ├── XMLSyntaxError.png
│ └── XMLSyntaxErrorCodeAction.gif
│ ├── pre-release.png
│ └── vscode-xml-maven.gif
├── eslint.config.mjs
├── gulpfile.js
├── icons
└── icon128.png
├── images
├── DebugAttachRemote.png
├── DebugMenuCallStack.png
├── DownloadBinaryArtifacts.png
├── DownloadBinaryChecks.png
└── LaunchExtension.png
├── package-lock.json
├── package.json
├── rnc.language-configuration.json
├── schemas
└── package.schema.json
├── src
├── api
│ ├── xmlExtensionApi.ts
│ └── xmlExtensionApiImplementation.ts
├── client
│ ├── clientErrorHandler.ts
│ ├── indentation.ts
│ ├── languageParticipants.ts
│ ├── tagClosing.ts
│ └── xmlClient.ts
├── commands
│ ├── clientCommandConstants.ts
│ ├── lspCommandConstants.ts
│ ├── registerCommands.ts
│ └── serverCommandConstants.ts
├── extension.ts
├── lsp-commands.ts
├── markdownPreviewProvider.ts
├── plugin.ts
├── server
│ ├── binary
│ │ ├── binaryHashManager.ts
│ │ └── binaryServerStarter.ts
│ ├── java
│ │ ├── javaServerStarter.ts
│ │ └── jvmArguments.ts
│ ├── requirements.ts
│ └── serverStarter.ts
├── settings
│ ├── externalXmlSettings.ts
│ ├── proxySettings.ts
│ ├── settings.ts
│ └── variableSubstitution.ts
├── telemetry.ts
├── test
│ └── smoke.test.ts
└── utils
│ └── fileUtils.ts
├── syntaxes
├── dtd.tmLanguage.json
└── rnc.tmLanguage.json
├── test-workspace
└── .vscode
│ └── settings.json
├── tsconfig.json
├── webpack.config.js
└── webview-resources
├── document.css
├── highlight.css
└── markdown.css
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | charset = utf-8
4 | trim_trailing_whitespace = true
5 | insert_final_newline = false
6 |
7 | [*.{ts,js,json,md}]
8 | indent_style = space
9 | indent_size = 2
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: Continuous Integration
2 | on: [ push, pull_request ]
3 | jobs:
4 |
5 | lint:
6 | runs-on: ubuntu-latest
7 | steps:
8 | - uses: actions/checkout@v2
9 | - name: Install dependencies
10 | run: npm i --also=dev
11 | - name: Run TypeScript compiler (under webpack)
12 | run: npm run compile
13 | - name: Run ESLint
14 | run: npm run eslint
15 |
16 | build-test-native-image:
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: actions/checkout@v4
20 | with:
21 | repository: 'eclipse/lemminx'
22 | - uses: graalvm/setup-graalvm@557ffcf459751b4d92319ee255bf3bec9b73964c #v1.2.5
23 | with:
24 | distribution: graalvm-community
25 | java-version: 17
26 | - run: ./mvnw -B package -Dnative -DskipTests -Dgraalvm.static=-H:+StaticExecutableWithDynamicLibC -Dcbi.jarsigner.skip=true
27 | - run: mv org.eclipse.lemminx/target/lemminx-* lemminx-linux
28 | - uses: actions/upload-artifact@v4
29 | with:
30 | name: lemminx-linux
31 | path: lemminx-linux
32 | if-no-files-found: error
33 |
34 | smoke-test:
35 | runs-on: ubuntu-latest
36 | needs: build-test-native-image
37 | steps:
38 | - uses: actions/checkout@v4
39 | - uses: actions/download-artifact@v4
40 | with:
41 | name: lemminx-linux
42 | path: server
43 | - name: Make lemminx binary executable
44 | run: chmod u+x ./server/lemminx-linux
45 | - name: Make lemminx binary trusted
46 | run: sha256sum ./server/lemminx-linux > ./server/lemminx-linux.sha256
47 | - name: Install dependencies
48 | run: npm i --also=dev
49 | - name: Run smoke test suite
50 | run: xvfb-run npm test
51 | - name: Delete lemminx binary
52 | if: always()
53 | uses: geekyeggo/delete-artifact@e46cfb9575865f907c2beb2e4170b5f4c7d77c52
54 | with:
55 | name: lemminx-linux
56 |
--------------------------------------------------------------------------------
/.github/workflows/native-image.yaml:
--------------------------------------------------------------------------------
1 | name: native-image
2 | on:
3 | workflow_call:
4 | inputs:
5 | publishPreRelease:
6 | description: 'Publish a pre-release ?'
7 | required: true
8 | type: string
9 | default: 'true'
10 | jobs:
11 | setup-xml-version:
12 | runs-on: ubuntu-latest
13 | outputs:
14 | xml-server-version: ${{ steps.setup-xml-version.outputs.XML_SERVER_VERSION }}
15 | steps:
16 | - name: Check Out VS Code XML
17 | uses: actions/checkout@v4
18 | - id: setup-xml-version
19 | run: echo "XML_SERVER_VERSION=$(cat package.json | jq -r .xmlServer.version)" >> $GITHUB_OUTPUT
20 | build-binary-unix:
21 | runs-on: ${{ matrix.os }}
22 | needs: setup-xml-version
23 | env:
24 | GRAALVM_DISTRO: graalvm-community
25 | GRAALVM_JAVA: 17
26 | strategy:
27 | fail-fast: true
28 | matrix:
29 | label: [osx-x86_64, osx-aarch_64, linux]
30 | include:
31 | - label: osx-x86_64
32 | os: macos-13
33 | - label: osx-aarch_64
34 | os: macos-latest
35 | - label: linux
36 | os: ubuntu-22.04
37 | prop: -Dgraalvm.static=-H:+StaticExecutableWithDynamicLibC
38 | steps:
39 | - uses: actions/checkout@v4
40 | with:
41 | repository: 'eclipse/lemminx'
42 | ref: ${{ inputs.publishPreRelease == 'true' && 'main' || needs.setup-xml-version.outputs.xml-server-version }}
43 | - name: Cache Maven dependencies
44 | uses: actions/cache@v4
45 | with:
46 | path: |
47 | ~/.m2/repository
48 | ~/.m2/wrapper
49 | !~/.m2/repository/org/eclipse/lemminx
50 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
51 | restore-keys: |
52 | ${{ runner.os }}-maven-
53 | - name: Cache GraalVM
54 | uses: actions/cache@v4
55 | with:
56 | path: |
57 | /opt/hostedtoolcache/${{env.GRAALVM_DISTRO}}-jdk-*
58 | ~/hostedtoolcache/${{env.GRAALVM_DISTRO}}-jdk-*
59 | key: ${{ runner.os }}-${{env.GRAALVM_DISTRO}}-jdk-${{ env.GRAALVM_JAVA }}
60 | restore-keys: |
61 | ${{ runner.os }}-${{env.GRAALVM_DISTRO}}-jdk-
62 | - uses: graalvm/setup-graalvm@557ffcf459751b4d92319ee255bf3bec9b73964c #v1.2.5
63 | with:
64 | distribution: ${{env.GRAALVM_DISTRO}}
65 | java-version: ${{env.GRAALVM_JAVA}}
66 | - run: ./mvnw -B package -Dnative -DskipTests ${{ matrix.prop }} -Dcbi.jarsigner.skip=true
67 | - run: mv org.eclipse.lemminx/target/lemminx-* lemminx-${{ matrix.label }}
68 | - uses: actions/upload-artifact@v4
69 | with:
70 | name: lemminx-${{ matrix.label }}
71 | path: lemminx-${{ matrix.label }}
72 | if-no-files-found: error
73 | build-binary-windows:
74 | runs-on: windows-latest
75 | needs: setup-xml-version
76 | env:
77 | GRAALVM_DISTRO: graalvm-community
78 | GRAALVM_JAVA: 17
79 | steps:
80 | - name: Check out LemMinX
81 | uses: actions/checkout@v4
82 | with:
83 | repository: 'eclipse/lemminx'
84 | ref: ${{ inputs.publishPreRelease == 'true' && 'main' || needs.setup-xml-version.outputs.xml-server-version }}
85 | - name: Cache Maven dependencies
86 | uses: actions/cache@v4
87 | with:
88 | path: |
89 | ~/.m2/repository
90 | ~/.m2/wrapper
91 | !~/.m2/repository/org/eclipse/lemminx
92 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
93 | restore-keys: |
94 | ${{ runner.os }}-maven-
95 | - name: Cache GraalVM
96 | uses: actions/cache@v4
97 | with:
98 | path: |
99 | C:\hostedtoolcache\windows\${{env.GRAALVM_DISTRO}}-*
100 | key: ${{ runner.os }}-${{env.GRAALVM_DISTRO}}-jdk-${{ env.GRAALVM_JAVA }}
101 | restore-keys: |
102 | ${{ runner.os }}-${{env.GRAALVM_DISTRO}}-jdk-
103 | - uses: ilammy/msvc-dev-cmd@7315a94840631165970262a99c72cfb48a65d25d #v1.12.0
104 | - uses: graalvm/setup-graalvm@557ffcf459751b4d92319ee255bf3bec9b73964c #v1.2.5
105 | with:
106 | distribution: ${{env.GRAALVM_DISTRO}}
107 | java-version: ${{env.GRAALVM_JAVA}}
108 | - run: .\mvnw.cmd -B package -Dnative -DskipTests -D "cbi.jarsigner.skip=true"
109 | - run: mv org.eclipse.lemminx\target\lemminx-*.exe lemminx-win32.exe
110 | - uses: actions/upload-artifact@v4
111 | with:
112 | name: lemminx-win32
113 | path: lemminx-win32.exe
114 | if-no-files-found: error
115 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/out
2 | *.vsix
3 | server/**
4 | node_modules/
5 | dist/
6 | .gradle/
7 | .idea/
8 | .vscode-test/
9 | .DS_Store
--------------------------------------------------------------------------------
/.vscode-test.mjs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2025 Red Hat, Inc. and others.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v2.0
5 | * which accompanies this distribution, and is available at
6 | * https://www.eclipse.org/legal/epl-v20.html
7 | *
8 | * Contributors:
9 | * Red Hat Inc. - initial API and implementation
10 | */
11 | import { defineConfig } from '@vscode/test-cli';
12 |
13 | export default defineConfig({
14 | files: 'out/src/test/**/*.test.js',
15 | workspaceFolder: 'test-workspace'
16 | });
17 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "dbaeumer.vscode-eslint",
4 | "EditorConfig.EditorConfig",
5 | "amodio.tsl-problem-matcher"
6 | ]
7 | }
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | {
3 | "version": "0.2.0",
4 | "configurations": [
5 | {
6 | "name": "Launch Extension",
7 | "type": "extensionHost",
8 | "request": "launch",
9 | "runtimeExecutable": "${execPath}",
10 | "args": [
11 | "--extensionDevelopmentPath=${workspaceRoot}"
12 | ],
13 | "sourceMaps": true,
14 | "outFiles": [
15 | "${workspaceRoot}/dist/**/*.js"
16 | ],
17 | "preLaunchTask": "npm: watch",
18 | "env": {
19 | "VSCODE_REDHAT_TELEMETRY_DEBUG": "true",
20 | "LEMMINX_DEBUG": "1"
21 | }
22 | },
23 | {
24 | "name": "Launch Extension & Wait for remote debugger",
25 | "type": "extensionHost",
26 | "request": "launch",
27 | "runtimeExecutable": "${execPath}",
28 | "args": [
29 | "--extensionDevelopmentPath=${workspaceRoot}"
30 | ],
31 | "sourceMaps": true,
32 | "outFiles": [
33 | "${workspaceRoot}/dist/**/*.js"
34 | ],
35 | "preLaunchTask": "npm: watch",
36 | "env": {
37 | "SUSPEND_SERVER": "true",
38 | "VSCODE_REDHAT_TELEMETRY_DEBUG": "true",
39 | "LEMMINX_DEBUG": "1"
40 | }
41 | }
42 | ]
43 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false // set this to true to hide the "out" folder with the compiled JS files
5 | },
6 | "search.exclude": {
7 | "out": true // set this to false to include "out" folder in search results
8 | },
9 | "typescript.tsdk": "./node_modules/typescript/lib",
10 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "problemMatcher": [
10 | "$eslint-stylish",
11 | "$ts-webpack-watch"
12 | ],
13 | "isBackground": true,
14 | "presentation": {
15 | "reveal": "never"
16 | },
17 | "group": {
18 | "kind": "build",
19 | "isDefault": true
20 | }
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | node_modules
3 | src/
4 | tsconfig.json
5 | .eslintrc.json
6 | .eslintignore
7 | webpack.config.js
8 | gulpfile.js
9 | .editorconfig
10 | CONTRIBUTING.md
11 | Jenkinsfile
12 | *.jenkins
13 | images/
14 | !docs/images
15 | .tool-versions
16 | .github/
17 | .gitignore
18 | test-workspace
19 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | Contributions are essential for keeping this extension great. We try to keep it as easy as possible to contribute changes and we are open to suggestions for making it even easier. There are only a few guidelines that we need contributors to follow.
4 |
5 | ## Development
6 |
7 | ### Installation Prerequisites:
8 |
9 | * latest [Visual Studio Code](https://code.visualstudio.com/)
10 | * [Node.js](https://nodejs.org/) v4.0.0 or higher
11 | * [JDK 11+](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
12 | * [Maven](https://maven.apache.org/)
13 |
14 | ### Steps
15 | 1. Fork and clone this repository
16 |
17 | 2. Fork and clone the [LemMinX - XML Language Server ](https://github.com/eclipse/lemminx)
18 |
19 | * **Note:** The directory format has to match the following:
20 |
21 | ```
22 | YOUR_FOLDER/
23 | ├──── lemminx/
24 | │
25 | ├──── vscode-xml/
26 | ```
27 |
28 | 3. `cd lemminx/`
29 |
30 | 4. Install the maven dependencies Mac/Linux:
31 | ```bash
32 | $ ./mvnw verify
33 | ```
34 | or for Windows:
35 | ```bash
36 | $ mvnw.cmd verify
37 | ```
38 |
39 |
40 | 5. `cd vscode-xml/`
41 |
42 | 6. Install the dependencies:
43 | ```bash
44 | $ npm install
45 | ```
46 |
47 | 7. In `vscode-xml/`, build the server by running:
48 |
49 | ```bash
50 | $ npm run build-server
51 | ```
52 |
53 | 8. To run the extension, open the Debugging tab in VSCode.
54 | 9. Select and run 'Launch Extension (vscode-xml)' at the top left:
55 |
56 | 
57 |
58 | ### Debugging Language Server
59 |
60 | After completing the prerequisite steps above, and after launching the **Extension Development Host** for `vscode-xml`, you can also debug the language `server/lemminx` and can be used as follows:
61 |
62 | #### On VSCode
63 |
64 | 1. Ensure that the most recent changes of `lemminx` have been built before launching the **Extension Development Host** (as per Step 7 in [Steps](#Steps)), and that the **Extension Development Host** is running.
65 |
66 | 2. Open `lemminx` in VSCode. This should display the "Debug (Attach) - Remote" option in the "Debugging" tab.
67 |
68 | 3. To run the debugger, open the "Debugging" tab in VSCode.
69 |
70 | 4. Select and run "Debug (Attach) - Remote" at the top left:
71 |
72 | 
73 |
74 | This will make the `lemminx` debugger attach to the **Extension Development Host** instance.
75 |
76 | To confirm that the debugger has properly attached, the "Call Stack" dropdown in the "Debugging" tab should be populated as follows:
77 |
78 | 
79 |
80 | Now that the `lemminx` debugger is properly attached, any language server interactions can be debugged and breakpoints in `lemminx` will be tracked.
81 |
82 | ## Binary server development
83 |
84 | ### Testing a binary version of LemMinX
85 |
86 | 1. Copy the binary version of LemMinX to:
87 |
88 | | OS | Location (relative to root of repository) |
89 | | --- | --- |
90 | | Linux | `./server/lemminx-linux` |
91 | | macOS | `./server/lemminx-darwin-x86_64` |
92 | | Windows | `.\server\lemminx-win32.exe` |
93 |
94 | Alternatively, you can set the `xml.server.binary.path` preference to specify the path of the binary to run.
95 |
96 | 2. Make sure that you set `xml.server.preferBinary` to `true`,
97 | disable any [LemMinX extensions](./docs/Extensions.md)
98 | by commenting out `xml.extension.jars` in your `settings.json`,
99 | and uninstall or disable any VS Code extensions that provide extra LemMinX features.
100 |
101 | 3. Launch vscode-xml in development mode, and double check that the binary server is running by checking the server logging (Output > XML Support)
102 |
103 | ### Downloading the GitHub Actions binary for your PR
104 |
105 | 1. Open the GitHub page for your PR.
106 |
107 | 2. Click on "Checks":
108 |
109 | 
110 |
111 | 3. Click "Artifacts", then select the binary for your operating system:
112 |
113 | 
114 |
115 | ### Building a binary with GraalVM locally
116 |
117 | If you submit a LemMinX PR, GitHub Actions will generate a binary for your PR that you can use for testing.
118 | If you need to generate a LemMinX binary locally for whatever reason, follow these steps:
119 |
120 | 1. Download and set up [GraalVM and its dependencies](https://www.graalvm.org/docs/getting-started/)
121 | * The latest version should work
122 | 2. Make sure that the environment variable `JAVA_HOME` points to the GraalVM installation.
123 | 3. Run `./mvnw clean package -DskipTests -Dnative` from the root of the LemMinX repository
124 | * This will use a lot of memory (> 4 GB) and take a while
125 | 4. The binary is generated in `./org.eclipse.lemminx/target`
126 |
127 | ### Certificate of Origin
128 |
129 | By contributing to this project you agree to the Developer Certificate of
130 | Origin (DCO). This document was created by the Linux Kernel community and is a
131 | simple statement that you, as a contributor, have the legal right to make the
132 | contribution. See the [DCO](DCO) file for details.
133 |
--------------------------------------------------------------------------------
/DCO:
--------------------------------------------------------------------------------
1 | Developer Certificate of Origin
2 | Version 1.1
3 |
4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
5 | 1 Letterman Drive
6 | Suite D4700
7 | San Francisco, CA, 94129
8 |
9 | Everyone is permitted to copy and distribute verbatim copies of this
10 | license document, but changing it is not allowed.
11 |
12 |
13 | Developer's Certificate of Origin 1.1
14 |
15 | By making a contribution to this project, I certify that:
16 |
17 | (a) The contribution was created in whole or in part by me and I
18 | have the right to submit it under the open source license
19 | indicated in the file; or
20 |
21 | (b) The contribution is based upon previous work that, to the best
22 | of my knowledge, is covered under an appropriate open source
23 | license and I have the right under that license to submit that
24 | work with modifications, whether created in whole or in part
25 | by me, under the same open source license (unless I am
26 | permitted to submit under a different license), as indicated
27 | in the file; or
28 |
29 | (c) The contribution was provided directly to me by some other
30 | person who certified (a), (b) or (c) and I have not modified
31 | it.
32 |
33 | (d) I understand and agree that this project and the contribution
34 | are public and that a record of the contribution (including all
35 | personal information I submit with it, including my sign-off) is
36 | maintained indefinitely and may be redistributed consistent with
37 | this project or the open source license(s) involved.
38 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env groovy
2 |
3 | def installBuildRequirements(){
4 | def nodeHome = tool 'nodejs-14.19.1'
5 | env.PATH="${env.PATH}:${nodeHome}/bin"
6 | sh "npm install -g typescript"
7 | sh 'npm install -g --force "@vscode/vsce"'
8 | }
9 |
10 | def buildVscodeExtension(){
11 | sh "npm install"
12 | sh "npm run vscode:prepublish"
13 | }
14 |
15 | def buildLemMinXBinary() {
16 | sh "curl -Lo NativeImage.jenkins https://raw.githubusercontent.com/${params.FORK}/vscode-xml/${params.BRANCH}/NativeImage.jenkins"
17 | load "NativeImage.jenkins"
18 | }
19 |
20 | node('rhel8'){
21 | sh "curl -Lo package.json https://raw.githubusercontent.com/${params.FORK}/vscode-xml/${params.BRANCH}/package.json"
22 | def packageJson = readJSON file: 'package.json'
23 | def serverVersion = packageJson?.xmlServer?.version
24 | def files = []
25 | if (serverVersion && publishToMarketPlace.equals('true')) {
26 | stage 'Download XML LS'
27 | def serverUrl = "https://repo.eclipse.org/content/repositories/lemminx-releases/org/eclipse/lemminx/org.eclipse.lemminx/${serverVersion}/org.eclipse.lemminx-${serverVersion}-uber.jar"
28 | sh "curl -Lo org.eclipse.lemminx-${serverVersion}-uber.jar ${serverUrl}"
29 | files = findFiles(glob: 'org.eclipse.lemminx*-uber.jar')
30 | }
31 |
32 | buildLemMinXBinary()
33 |
34 | if (!files[0]) {
35 | stage 'Build XML LS'
36 | git url: 'https://github.com/eclipse/lemminx.git', branch: 'main'
37 | sh "./mvnw clean verify -B -U -e -P!jboss-maven-repos,!redhat-ga-repository,!redhat-ea-repository"
38 | sh "mv org.eclipse.lemminx/target/org.eclipse.lemminx*-uber.jar ."
39 | files = findFiles(glob: 'org.eclipse.lemminx*-uber.jar')
40 | }
41 | stash name: 'server_distro', includes :files[0].path
42 | }
43 |
44 | node('rhel8'){
45 | stage 'Checkout vscode-xml code'
46 | deleteDir()
47 | def gitUrl = "${GIT_REPO}"
48 |
49 | git url: gitUrl?:'https://github.com/redhat-developer/vscode-xml.git', branch: params.BRANCH?: 'main'
50 |
51 | stage 'set the link to download the binary server'
52 | def packageJson = readJSON file: 'package.json'
53 | def binaryUploadFolder = 'latest'
54 | def downloadLocation = 'https://github.com/redhat-developer/vscode-xml'
55 | if (publishToMarketPlace.equals('true')) {
56 | sh "sed -i -e 's|${downloadLocation}/releases/download/latest|${downloadLocation}/releases/download/${packageJson.version}|g' package.json"
57 | }
58 |
59 | stage 'install vscode-xml build requirements'
60 | installBuildRequirements()
61 |
62 | stage 'Build vscode-xml'
63 | buildVscodeExtension()
64 | unstash 'server_distro'
65 | def files = findFiles(glob: '**/org.eclipse.lemminx*-uber.jar')
66 | sh "mkdir ./server"
67 | sh "mv ${files[0].path} ./server"
68 |
69 | env.publishPreReleaseFlag = ""
70 | if(publishPreRelease.equals('true')){
71 | stage "Prepare for pre-release"
72 | sh "npx gulp prepare_pre_release"
73 | packageJson = readJSON file: 'package.json'
74 | env.publishPreReleaseFlag = "--pre-release"
75 | }
76 |
77 | stage "Package vscode-xml"
78 | sh "mkdir ../staging"
79 | unstash 'binaries'
80 | unstash 'checksums'
81 | sh "mv lemminx-* ../staging"
82 | def platformToTarget = [ "linux-x64" : "linux", "win32-x64" : "win32", "darwin-x64" : "osx-x86_64", "darwin-arm64" : "osx-x86_64"]
83 | for(entry in platformToTarget){
84 | def target = entry.key
85 | def platform = entry.value
86 | sh "unzip -d ./server ../staging/lemminx-${platform}.zip"
87 | sh "cp ../staging/lemminx-${platform}.sha256 ./server"
88 | sh "vsce package ${env.publishPreReleaseFlag} --target ${target} -o vscode-xml-${target}-${packageJson.version}-${env.BUILD_NUMBER}.vsix"
89 | sh "rm ./server/lemminx-*"
90 | }
91 | // This vsix only gets published to OpenVSX (if option is set)
92 | // server folder still needed to publish generic vsix below
93 | sh "cp ../staging/lemminx-*.sha256 ./server"
94 | sh "vsce package -o vscode-xml-${packageJson.version}-${env.BUILD_NUMBER}.vsix"
95 |
96 | //stage 'Test vscode-xml for staging'
97 | //wrap([$class: 'Xvnc']) {
98 | // sh "npm test --silent"
99 | //}
100 |
101 | stage 'Archive artifacts'
102 | archiveArtifacts artifacts: '*.vsix'
103 | stash name:'vsix', includes:'*.vsix'
104 | }
105 |
106 | node('rhel8'){
107 | sh 'npm install -g --force "@vscode/vsce"'
108 | sh 'npm install -g "ovsx"'
109 | if(publishToMarketPlace.equals('true') || publishToOVSX.equals('true') || publishPreRelease.equals('true')){
110 |
111 | if (publishToMarketPlace.equals('true') || publishToOVSX.equals('true')) {
112 | timeout(time:2, unit:'DAYS') {
113 | input message:'Approve deployment?', submitter: 'fbricon,rgrunber,azerr,davthomp'
114 | }
115 | }
116 |
117 | stage "Publish to Marketplaces"
118 | unstash 'vsix'
119 | def vsix = findFiles(glob: '**.vsix')
120 | def platformVsixes = findFiles(glob: '**.vsix', excludes: vsix[0].path)
121 |
122 | // VS Code Marketplace
123 | if (publishToMarketPlace.equals('true') || publishPreRelease.equals('true')) {
124 | withCredentials([[$class: 'StringBinding', credentialsId: 'vscode_java_marketplace', variable: 'TOKEN']]) {
125 | for(platformVsix in platformVsixes){
126 | sh 'vsce publish -p ${TOKEN}' + " --packagePath ${platformVsix.path}"
127 | }
128 | // Cannot combine packagePath & target, so re-generate (generic) package and publish
129 | sh 'vsce publish -p ${TOKEN}' + " ${env.publishPreReleaseFlag}"
130 | }
131 | }
132 |
133 | // Open-VSX Marketplace
134 | if (publishToOVSX.equals('true') || publishPreRelease.equals('true')) {
135 | withCredentials([[$class: 'StringBinding', credentialsId: 'open-vsx-access-token', variable: 'OVSX_TOKEN']]) {
136 | for(platformVsix in platformVsixes){
137 | sh 'ovsx publish -p ${OVSX_TOKEN}' + " --packagePath ${platformVsix.path}"
138 | }
139 |
140 | sh 'ovsx publish -p ${OVSX_TOKEN}' + " ${env.publishPreReleaseFlag}"
141 | }
142 | }
143 |
144 | }// if any publishing
145 | }
146 |
--------------------------------------------------------------------------------
/NativeImage.jenkins:
--------------------------------------------------------------------------------
1 | // Parameters that need to be declared for this pipeline:
2 | // * GRAALVM_VERSION: The version of GraalVM to download in the Windows an macOS builds
3 | // * publishToMarketPlace: Upload to the "stable" folder if true, upload to the "snapshots" folder if false
4 | // * UPLOAD_LOCATION: The base location where the artifacts (binaries and sha256 hashes) will be uploaded
5 | // * FORK: The fork of vscode-xml that is being built for
6 | // * BRANCH: The branch of vscode-xml that is being built for
7 | pipeline {
8 | agent none
9 | stages {
10 | stage("native-image") {
11 | parallel {
12 | // Assumes GraalVM is set up on the rhel8 agent, and the environment variable "GRAALVM_PATH" points to its location
13 | stage("Linux native-image") {
14 | agent {
15 | label "rhel8"
16 | }
17 | steps {
18 | sh "rm -f lemminx-linux"
19 | sh "rm -rf lemminx"
20 | script {
21 | if (publishToMarketPlace.equals('true')) {
22 | sh "curl -Lo package.json https://raw.githubusercontent.com/${params.FORK}/vscode-xml/${params.BRANCH}/package.json"
23 | def packageJson = readJSON file: 'package.json'
24 | def lemminxVersion = packageJson?.xmlServer?.version
25 | sh "git clone -b ${lemminxVersion} https://github.com/eclipse/lemminx.git"
26 | } else {
27 | sh "git clone https://github.com/eclipse/lemminx.git"
28 | }
29 | }
30 | sh "cd lemminx && JAVA_HOME=\$GRAALVM_PATH ./mvnw clean package -B -Dnative -DskipTests -Dgraalvm.static='-H:+StaticExecutableWithDynamicLibC' && cd .."
31 | sh "rm lemminx/org.eclipse.lemminx/target/*.build_artifacts.txt"
32 | sh "cp lemminx/org.eclipse.lemminx/target/lemminx-linux* lemminx-linux"
33 | stash name: 'lemminx-linux', includes: 'lemminx-linux'
34 | }
35 | }
36 | stage("Windows native-image") {
37 | agent {
38 | label "win10"
39 | }
40 | steps {
41 | powershell """
42 | if (Test-Path lemminx-win32.exe) { Remove-Item lemminx-win32.exe }
43 | Remove-Item -Recurse -Force lemminx
44 | """
45 | script {
46 | if (publishToMarketPlace.equals('true')) {
47 | powershell """
48 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
49 | Invoke-WebRequest https://raw.githubusercontent.com/${params.FORK}/vscode-xml/${params.BRANCH}/package.json -OutFile package.json
50 | """
51 | def packageJson = readJSON file: 'package.json'
52 | def lemminxVersion = packageJson?.xmlServer?.version
53 | powershell """
54 | git clone -b ${lemminxVersion} git@github.com:eclipse/lemminx.git
55 | """
56 | } else {
57 | powershell """
58 | git clone git@github.com:eclipse/lemminx.git
59 | """
60 | }
61 | }
62 | powershell """
63 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
64 | if (-not (Test-Path graalvm-windows-${params.GRAALVM_VERSION}.zip)) {
65 | Invoke-WebRequest https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-${params.GRAALVM_VERSION}/graalvm-ce-java17-windows-amd64-${params.GRAALVM_VERSION}.zip -OutFile graalvm-windows-${params.GRAALVM_VERSION}.zip
66 | Expand-Archive graalvm-windows-${params.GRAALVM_VERSION}.zip
67 | .\\graalvm-windows-${params.GRAALVM_VERSION}\\graalvm-ce-java17-${params.GRAALVM_VERSION}\\bin\\gu install native-image
68 | }
69 | """
70 | bat """
71 | pushd .
72 | setlocal
73 | set JAVA_HOME=%cd%\\graalvm-windows-${params.GRAALVM_VERSION}\\graalvm-ce-java17-${params.GRAALVM_VERSION}
74 | call \"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat\"
75 | popd
76 | cd lemminx
77 | .\\mvnw.cmd clean package -B -Dnative -DskipTests
78 | endlocal
79 | cd ..
80 | """
81 | powershell "mv lemminx\\org.eclipse.lemminx\\target\\lemminx-windows*.exe lemminx-win32.exe"
82 | stash name: 'lemminx-win32.exe', includes: 'lemminx-win32.exe'
83 | }
84 | }
85 | stage("macOS native-image") {
86 | agent {
87 | label "mac"
88 | }
89 | steps {
90 | sh "rm -f lemminx-osx-x86_64.zip lemminx-osx-x86_64.sha256"
91 | sh "rm -rf lemminx"
92 | script {
93 | if (publishToMarketPlace.equals('true')) {
94 | sh "curl -Lo package.json https://raw.githubusercontent.com/${params.FORK}/vscode-xml/${params.BRANCH}/package.json"
95 | def packageJson = readJSON file: 'package.json'
96 | def lemminxVersion = packageJson?.xmlServer?.version
97 | sh "git clone -b ${lemminxVersion} https://github.com/eclipse/lemminx.git"
98 | } else {
99 | sh "git clone https://github.com/eclipse/lemminx.git"
100 | }
101 | }
102 | sh """
103 | if [ ! -f graalvm-darwin-${params.GRAALVM_VERSION}.tar.gz ]; then
104 | curl https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-${params.GRAALVM_VERSION}/graalvm-ce-java17-darwin-amd64-${params.GRAALVM_VERSION}.tar.gz -L --output graalvm-darwin-${params.GRAALVM_VERSION}.tar.gz
105 | tar -xzf graalvm-darwin-${params.GRAALVM_VERSION}.tar.gz
106 | ./graalvm-ce-java17-${params.GRAALVM_VERSION}/Contents/Home/bin/gu install native-image
107 | fi
108 | """
109 | sh "cd lemminx && JAVA_HOME=`pwd`/../graalvm-ce-java17-${params.GRAALVM_VERSION}/Contents/Home ./mvnw clean package -B -Dnative -DskipTests && cd .."
110 | sh "rm lemminx/org.eclipse.lemminx/target/*.build_artifacts.txt"
111 | sh "cp lemminx/org.eclipse.lemminx/target/lemminx-osx-x86_64* lemminx-osx-x86_64"
112 |
113 | stash name: 'lemminx-osx-x86_64', includes: 'lemminx-osx-x86_64'
114 | }
115 | }
116 | }
117 | }
118 | stage ("Zip and upload") {
119 | agent {
120 | label "rhel8"
121 | }
122 | steps {
123 | unstash name: 'lemminx-linux'
124 | unstash name: 'lemminx-win32.exe'
125 | unstash name: 'lemminx-osx-x86_64'
126 |
127 | sh "zip lemminx-linux.zip lemminx-linux"
128 | sh "zip lemminx-win32.zip lemminx-win32.exe"
129 | sh "zip lemminx-osx-x86_64.zip lemminx-osx-x86_64"
130 |
131 | // get the sha256 hash of the binaries
132 | sh "sha256sum lemminx-linux > lemminx-linux.sha256"
133 | sh "sha256sum lemminx-win32.exe > lemminx-win32.sha256"
134 | sh "sha256sum lemminx-osx-x86_64 > lemminx-osx-x86_64.sha256"
135 | stash name: 'checksums', includes: 'lemminx-*.sha256'
136 | stash name: 'binaries', includes: 'lemminx-*.zip'
137 | }
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/USAGE_DATA.md:
--------------------------------------------------------------------------------
1 | # Data collection
2 |
3 | vscode-xml has opt-in telemetry collection, provided by [vscode-redhat-telemetry](https://github.com/redhat-developer/vscode-redhat-telemetry).
4 |
5 | ## What's included in the vscode-xml telemetry data
6 |
7 | * JVM information:
8 | * Whether LemMinX is being run with Java or as a GraalVM native image (binary)
9 | * The name of the vm (`java.vm.name`)
10 | * The name of the runtime (`java.runtime.name`)
11 | * The version of the JVM (`java.version`)
12 | * The free, total, and max VM memory
13 | * LemMinX Version information:
14 | * The server version number
15 | * Does NOT include the `JAVA_HOME` environment variable for privacy reasons
16 | * The value of the `xml.server.preferBinary` setting
17 | * A telemetry event is sent every time the binary server download succeeds, fails, or is stopped by the user
18 | * If the download fails, the associated error is attached to the telemetry event
19 | * A telemetry event is sent every time you click the "Open Proxy Configuration Documentation" link that is provided when the language server binary download fails due to a proxy related issue.
20 | * A telemetry event is sent every time you click the "Download Java" link that appears when you have [LemMinX extensions](./docs/Extensions.md) installed but don't have Java installed.
21 | * A telemetry event is sent every time the Java XML language server crashes due to an Out Of Memory Error, which also contains the maximum heap space for the JVM (-Xmx) that you've set.
22 | * A telemetry event is sent every time you click on the link to the documentation that appears after the Java XML language server crashes due to an Out Of Memory Error.
23 | * Text Document Information
24 | * When a document is opened :
25 | * The file extension (eg. `xml`, `xsd`, `dtd`, `rng`)
26 | * The associated grammar types (eg. `none`, `doctype`, `xml-model`, `xsi:schemaLocation`, `xsi:noNamespaceSchemaLocation`)
27 | * The grammar identifiers for an XML document (eg. `http://maven.apache.org/xsd/maven-4.0.0.xsd`)
28 | * The resolver used to resolve the grammar identifier (eg. `catalog`, `file association`, `embedded catalog.xsd`, `embedded xml.xsd`, `embedded xslt.xsd`, `relaxng.rng`)
29 |
30 | ## What's included in the general telemetry data
31 |
32 | Please see the
33 | [vscode-redhat-telemetry data collection information](https://github.com/redhat-developer/vscode-redhat-telemetry/blob/HEAD/USAGE_DATA.md#usage-data-being-collected-by-red-hat-extensions)
34 | for information on what data it collects.
35 |
36 | ## How to opt in or out
37 |
38 | Use the `redhat.telemetry.enabled` setting in order to enable or disable telemetry collection.
39 | Note that this extension abides by Visual Studio Code's telemetry level: if `telemetry.telemetryLevel` is set to off, then no telemetry events will be sent to Red Hat, even if `redhat.telemetry.enabled` is set to true. If `telemetry.telemetryLevel` is set to `error` or `crash`, only events containing an error or errors property will be sent to Red Hat.
40 |
--------------------------------------------------------------------------------
/docs/BindingWithGrammar.md:
--------------------------------------------------------------------------------
1 | # Binding with Grammar
2 |
3 | [vscode-xml](https://github.com/redhat-developer/vscode-xml) provides support for automatic XML schema/grammar binding through generation and/or using an existing `.xsd/.dtd` file.
4 |
5 | 
6 |
7 | [Validation with XSD grammar](Validation.md#validation-with-xsd-grammar) and [Validation with DTD grammar](Validation.md#validation-with-dtd-grammar) provide more information on manual binding of an XML document.
8 |
9 | In the following sections, we would like to bind the XML document `foo.xml`:
10 | ```xml
11 |
12 |
13 |
14 | ```
15 | with an associated grammar file.
16 |
17 | ## Binding with Existing Grammar
18 |
19 | Consider an XSD document, `foo.xsd` (in the same directory as `foo.xml`), defined as follows :
20 | ```xsd
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | ```
32 | and a DTD document, `foo.dtd` (in the same directory as `foo.xml`), defined as follows:
33 | ```dtd
34 |
35 |
36 | ```
37 |
38 | Either file can be bound using the [XML Binding Wizard](#the-xml-binding-wizard), which can be triggered by [Command](#command), [CodeLens](#codelens) or [Quick Fix](#quick-fix).
39 |
40 | ### The XML Binding Wizard
41 |
42 | After opening the binding wizard using one of the methods mentioned above, a dropdown with the following 2 options will appear at the Command Palette:
43 |
44 | 
45 |
46 | 1. Standard (xsi, DOCTYPE)
47 |
48 | If the selected file is an XSD file, this option will bind the grammar file by adding the `xmlns:xsi` (with the value as "http://www.w3.org/2001/XMLSchema-instance") and `xsi:noNamespaceSchemaLocation` (with the value as the path to the grammar file) attributes to the root tag:
49 | ```xml
50 |
52 |
53 |
54 | ```
55 |
56 | If the XSD file contains a `targetNamespace` attribute, with an `elementFormDefault` attribute with value "qualified" in the `xs:schema` tag, as follows:
57 | ```xsd
58 |
59 | ```
60 | then the XML document will have the `targetNamespace` set as a `xmlns` attribute and an additional attribute for `xsi:schemaLocation`:
61 | ```xml
62 |
65 |
66 |
67 | ```
68 |
69 | If the selected file is a DTD file, this option will bind the grammar file by adding a ` SYSTEM "">` tag at the beginning of the document:
70 | ```xml
71 |
72 |
73 |
74 |
75 | ```
76 |
77 | 2. XML Model association
78 |
79 | This option will bind the grammar file by adding the `xml-model` tag at the beginning of the document, with an `href` value as the path to the grammar file:
80 | ```xml
81 |
82 |
83 |
84 |
85 | ```
86 | The same applies when selecting `foo.dtd`.
87 |
88 | After selecting an option, you can select the desired grammar file using your file explorer:
89 |
90 | 
91 |
92 | ### Command
93 |
94 | The command "XML: Bind to grammar/schema file" can be executed from the VSCode command palette, as well as be bound to a shortcut.
95 |
96 | 
97 |
98 | If the current XML document is not bound using an existing grammar/schema, the command will have the user select a existing `.xsd/.dtd` grammar file to bind to the XML document.
99 |
100 | Otherwise, an error will be thrown on the client if the XML document already has a bound grammar/schema.
101 |
102 | ### CodeLens
103 |
104 | When [CodeLenses](./Preferences.md#code-lens) are enabled, an unbound XML document will display a CodeLens above the root element as follows:
105 |
106 | 
107 |
108 | ### Quick Fix
109 |
110 | For any unbound XML document, a Quick Fix suggestion will appear beside the root element.
111 |
112 | 
113 |
114 | With the cursor on the first opening tag, use `Ctrl + .`, `Quick Fix...` or the lightbulb that appears and select the "Bind to existing grammar/schema"
115 |
116 | 
117 |
118 | ## Binding with New Grammar
119 |
120 | Consider the case where the directory only contains `foo.xml` (i.e. there does not exist an appropriate `.xsd/.dtd` file to bind).
121 |
122 | A file can be generated using a [Quick Fix](#quick-fix-1).
123 |
124 | ### Quick Fix
125 |
126 | #### Generate XSD from XML
127 |
128 | When an unbound XML file is open, an XML Schema/XSD file can be generated from the opening tag in the XML file.
129 |
130 | With the cursor on the first opening tag, use `Ctrl + .` or `Quick Fix...` or the lightbulb that appears and select "Generate foo.xsd and bind with *" to create the file in the the same directory.
131 |
132 | 
133 |
134 | #### Generate DTD from XML
135 |
136 | When an unbound XML file is open, a Document Type Definition/DTD file can be generated from the opening tag in the XML file.
137 |
138 | With the cursor on the first opening tag, use `Ctrl + .` or `Quick Fix...` or the lightbulb that appears and select "Generate foo.dtd and bind with *" to create the file in the the same directory.
139 |
140 | 
141 |
142 | #### Generate RELAX NG from XML
143 |
144 | When an unbound XML file is open, a RELAX NG schema can be generated from the opening tag in the XML file.
145 |
146 | With the cursor on the first opening tag, use `Ctrl + .` or `Quick Fix...` or the lightbulb that appears and select "Generate foo.rng and bind with RelaxNG" to create the file in the the same directory.
147 |
148 | 
149 |
--------------------------------------------------------------------------------
/docs/CodeLens.md:
--------------------------------------------------------------------------------
1 |
2 | ## Code Lens
3 |
4 | ### XML Features
5 |
6 | CodeLens provides grammar binding for unbound XML documents, appearing above the root element, which will trigger the [XML Binding Wizard](BindingWithGrammar.md#the-xml-binding-wizard).
7 |
8 | 
9 |
10 | ### DTD features
11 |
12 | Code lens is provided in `.dtd` files to show where elements defined in the DTD are referenced.
13 | For instance, in the following code:
14 |
15 | ```xml
16 |
17 |
18 |
19 |
20 |
21 | ```
22 |
23 | There will be a code lens entry after the first line that points from the
24 | definition of the element `to` to where it is used in the definition of the
25 | element `letter`.
26 |
27 | Here is a demonstration of the above Code Lens:
28 |
29 | 
30 |
31 | ### XSD Features
32 |
33 | Code lens is also provided in `.xsd` files. It shows where top level types
34 | and elements are referenced. For instance, in the following code:
35 |
36 | ```xml
37 |
38 |
42 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | ```
52 |
53 | There will be a code lens above the line where the `yell` type is defined
54 | that points to where it is referenced when defining the `root-element` element.
55 |
56 | Here is a demonstration of the above Code Lens:
57 |
58 | 
59 |
60 | Here is a demonstration of the code lens for `xs:element`:
61 |
62 | 
63 |
--------------------------------------------------------------------------------
/docs/Commands.md:
--------------------------------------------------------------------------------
1 | # Commands
2 |
3 | [vscode-xml](https://github.com/redhat-developer/vscode-xml) provides several vscode commands which are available with `Ctrl+Shift+P`.
4 |
5 | 
6 |
7 | ## Bind to grammar/schema file
8 |
9 | This command triggers the [XML Binding Wizard](BindingWithGrammar.md#the-xml-binding-wizard) for the current file.
10 |
11 | Details on the command are described [here](BindingWithGrammar.md#command).
12 |
13 | ## Open XML Documentation
14 |
15 | This command opens the `XML Documentation`.
16 |
17 | ## Revalidate current XML file
18 |
19 | This command re-triggers the [XML Validation](Validation.md#xml-validation) for the current file.
20 |
21 | When the [Server Cache Path](Preferences.md#server-cache-path) is activated, the command removes the referenced XSD, DTD grammar from the local cache.
22 |
23 | ## Revalidate all open XML files
24 |
25 | This command re-triggers the [XML Validation](Validation.md#xml-validation) for the all opened XML files.
26 |
27 | When the [Server Cache Path](Preferences.md#server-cache-path) is activated, the command clears the remote grammar cache and revalidates all opened files.
28 |
29 | ## Restart XML Language Server
30 |
31 | This command restarts the XML language server.
32 |
--------------------------------------------------------------------------------
/docs/Features.md:
--------------------------------------------------------------------------------
1 | # Features
2 |
3 | [vscode-xml](https://github.com/redhat-developer/vscode-xml) has a number of notable features available for XML, XSD and DTD support.
4 |
5 | - [XML features](Features/XMLFeatures.md#xml-features)
6 | - [XSD features](Features/XSDFeatures.md#xsd-features)
7 | - [DTD features](Features/DTDFeatures.md#dtd-features)
8 | - [RelaxNG features](Features/RelaxNGFeatures.md#relaxng-features)
9 | - [XInclude features](Features/XIncludeFeatures.md#xinclude-features)
10 | - [XML Catalog features](Features/XMLCatalogFeatures.md#xml-catalog-features)
11 | - [XML References features](Features/XMLReferencesFeatures.md#xml-references-features)
12 | - [XML Colors features](Features/XMLColorsFeatures.md#xml-colors-features)
--------------------------------------------------------------------------------
/docs/Features/DTDFeatures.md:
--------------------------------------------------------------------------------
1 | # DTD Features
2 |
3 | ## CodeLens Support
4 |
5 | CodeLens is supported for `.dtd` files, which can show where an element declaration is referenced.
6 |
7 | 
8 |
9 | This feature also supports listing and highlighting the number of references to an element declaration and the line(s) referenced on.
10 |
11 | 
12 |
13 | ### Read more
14 |
15 | See [CodeLens](../CodeLens.md#code-lens) for more details.
16 |
17 | ## Category Accessibility
18 |
19 | After defining an `!ELEMENT` tag in the `.dtd` file, there are features available for categories.
20 |
21 | ### Jump to element declaration
22 |
23 | For an `!ELEMENT` tag that contains a category/element-content attribute, there is support for navigating to its definition element.
24 |
25 | 
26 |
27 | ## Syntax Validation
28 |
29 | DTD syntax validation is enabled for any `.dtd` file.
30 |
31 | 
32 |
--------------------------------------------------------------------------------
/docs/Features/RelaxNGFeatures.md:
--------------------------------------------------------------------------------
1 | # RelaxNG features
2 |
3 | [vscode-xml](https://github.com/redhat-developer/vscode-xml) provides validation, completion, hover in XML file based on [RelaxNG schemas](https://relaxng.org/) since `0.22.0`:
4 |
5 | 
6 |
7 | It supports both:
8 |
9 | * [RelaxNG XML syntax (*.rng files)](https://relaxng.org/tutorial-20011203.html).
10 | * [RelaxNG Compact syntax (*.rnc files)](https://relaxng.org/compact-tutorial-20030326.html).
11 |
12 | 
13 |
14 | You can associate your XML file with `RelaxNG grammar` (`file` or `URL`) using :
15 |
16 | * an `xml-model` processing instruction
17 |
18 | ```xml
19 |
20 |
21 | ...
22 |
23 | ```
24 |
25 | * an `XML catalog` using the same method as [XSD](Validation.md#XML-catalog-with-XSD)
26 | * a `file association` using the same method as [XSD](Validation.md#XML-file-association-with-xsd)
27 |
28 | ## RelaxNG grammar
29 |
30 | [vscode-xml](https://github.com/redhat-developer/vscode-xml) provides support for `RelaxNG grammars`:
31 |
32 | * for [RelaxNG XML syntax (*.rng files)](https://relaxng.org/tutorial-20011203.html), it provides the same support as XSD/DTD grammars (completion, hover, validation, etc).
33 |
34 | 
35 |
36 | * for [RelaxNG Compact syntax (*.rnc files)](https://relaxng.org/compact-tutorial-20030326.html) it provides only syntax coloration.
37 |
38 | 
39 |
40 | ### RelaxNG grammar XML Syntax
41 |
42 | [vscode-xml](https://github.com/redhat-developer/vscode-xml) provides support for reference between `define/@name` and `ref/@name` with codelens, definition, completion, highlighting, references, rename:
43 |
44 | 
45 |
46 | It also provides support for `include/@href` and `externalRef/@href` attributes to navigate easily to the referenced `rng` grammar file:
47 |
48 | 
49 |
50 | # Validation
51 |
52 | XML validation based on RelaxNG (rng, rnc) is supported:
53 |
54 | 
55 |
56 | # Completion
57 |
58 | XML completion based on RelaxNG (rng, rnc) is supported. The completion for rng can show the documentation:
59 |
60 | 
61 |
62 | # Hover
63 |
64 | Hover based on RelaxNG rng can show the documentation:
65 |
66 | 
67 |
68 | # Go to Type Definition
69 |
70 | From the XML document you can go to the type definition to navigate to the element/attribute declaration for both `rnc` and `rng`.
71 |
72 | To do this, select an XML element/attribute and use the contextual menu `Go to Type Definition`:
73 |
74 | 
75 |
76 | When you click on this menu item, VS Code will open the `rng` or `rnc` grammar file and place the cursor on the proper `element/attribute` declaration:
77 |
78 | 
79 |
80 | # How to start?
81 |
82 | ## Using snippets
83 |
84 | You can use snippets to quickly create:
85 |
86 | * an XML file associated with a RelaxNG grammar
87 | * a RelaxNG XML file
88 |
89 | Here's a demo:
90 |
91 | 
92 |
93 | ## Creating XML, rng, rnc files
94 |
95 | You can create a RelaxNG grammar that uses the XML syntax by making a file with the extension `.rng`.
96 | For instance, here is a file `addressBook.rng` that defines a RelaxNG grammar:
97 |
98 | ```xml
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | ```
120 |
121 | You can create a RelaxNG grammar that uses the [compact syntax](https://relaxng.org/compact-tutorial-20030326.html) by making a file with the extension `.rnc`.
122 | For instance, here is a file `addressBook.rnc` that defines the same RelaxNG grammar as `addressBook.rng`:
123 |
124 | ```rnc
125 | element addressBook {
126 | element card {
127 | element name { text },
128 | element email { text }
129 | }*
130 | }
131 | ```
132 |
133 | The following file, `addressBook.xml`, references `addressBook.rng` using the `xml-model` processing instruction.
134 | [vscode-xml](https://github.com/redhat-developer/vscode-xml) will provide the features based on the grammar shown in [the demo at the beginning of this page](#relaxng-features) when you open `addressBook.xml`.
135 |
136 | ```xml
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 | ```
145 |
146 | # Generate RELAX NG from XML
147 |
148 | When an unbound XML file is open, a RELAX NG schema can be generated from the opening tag in the XML file.
149 |
150 | See: [Generate RELAX NG from XML](../BindingWithGrammar.md#generate-relax-ng-from-xml).
151 |
--------------------------------------------------------------------------------
/docs/Features/XIncludeFeatures.md:
--------------------------------------------------------------------------------
1 | # XInclude Features
2 |
3 | ## Validation
4 |
5 | XML validation with [XInclude](https://www.w3.org/TR/xinclude/) is supported, which can be enabled / disabled with the `xml.validation.xInclude.enabled` setting.
6 |
7 | 
8 |
9 | ## Document Link
10 |
11 | Document link is supported with `href` attribute.
12 |
13 | 
14 |
--------------------------------------------------------------------------------
/docs/Features/XMLCatalogFeatures.md:
--------------------------------------------------------------------------------
1 | # XML Catalog Features
2 |
3 | ## Validation
4 |
5 | XML Catalog is supported with both DTD and XSD. Please see here for more information on the usage of [XML Catalog With DTD](../Validation.md#xml-catalog-with-dtd) and [XML Catalog With XSD](../Validation.md#xml-catalog-with-xsd).
6 |
7 | ## Code Lens
8 |
9 | CodeLens is supported for XML catalogs, which shows whether the catalog is registered or not.
10 | It also provides the ability to register or unregister the catalog in settings.json.
11 |
12 | 
13 |
--------------------------------------------------------------------------------
/docs/Features/XMLColorsFeatures.md:
--------------------------------------------------------------------------------
1 | # XML Colors Features
2 |
3 | XML colors support provides the capability to mark a DOM node (attribute or text) as color with the `xml.colors` settings by using XPath expression :
4 |
5 | * `color/text()` defines the text node of the `color` element.
6 | * `item/@color` defines the `color` attribute node of the `item` element.
7 |
8 | ## Define Color in Text Content with `color/text()`
9 |
10 | Given this [android color](https://developer.android.com/guide/topics/resources/more-resources#Color) XML file sample:
11 |
12 | ```xml
13 |
14 |
15 | #f00
16 | rgb(222,82,0.82)
17 | #0cffffff
18 |
19 | ```
20 |
21 | In this sample, text of `color` tag element `#f00` declare a color with hexadecimal. [vscode-xml](https://github.com/redhat-developer/vscode-xml) provides a color support with the `xml.colors` settings. For [android color](https://developer.android.com/guide/topics/resources/more-resources#Color) case, you can declare this settings:
22 |
23 | ```json
24 | "xml.colors": [
25 | {
26 | "pattern": "**/res/values/colors.xml",
27 | "expressions": [
28 | {
29 | "xpath": "resources/color/text()"
30 | },
31 | {
32 | "xpath": "resources/drawable/text()"
33 | }
34 | ]
35 | }
36 | ]
37 | ```
38 |
39 | After saving this setting, you will get color support for the text node of `color` tag element in the `colors.xml` file:
40 |
41 | 
42 |
43 | ## Define Color in Attribute with `item/@color`
44 |
45 | Attribute values may also be marked as color by using the proper XPath.
46 |
47 | Given this `colors.xml` XML file:
48 |
49 | ```xml
50 |
51 |
52 |
53 |
54 |
55 | ```
56 |
57 | You can declare this settings:
58 |
59 | ```json
60 | "xml.colors": [
61 | {
62 | "pattern": "**/colors.xml",
63 | "expressions": [
64 | {
65 | "xpath": "item/@color"
66 | }
67 | ]
68 | }
69 | ]
70 | ```
--------------------------------------------------------------------------------
/docs/Features/XMLFeatures.md:
--------------------------------------------------------------------------------
1 | # XML Features
2 |
3 | [vscode-xml](https://github.com/redhat-developer/vscode-xml) provides a number of notable features, with demos below.
4 |
5 | ## Formatting
6 |
7 | To format an XML document, you can use the formatting shortcut `Ctrl + Shift + K`.
8 |
9 | 
10 |
11 | For more information on formatting capabilities, see [Formatting](../Formatting.md#formatting).
12 |
13 | ## Folding
14 |
15 | XML tag folding is supported:
16 |
17 | To collapse and expand a tag, press the arrow.
18 |
19 | 
20 |
21 | For more information on folding capabilities, see [Folding](../Folding.md#folding).
22 |
23 | ## XML Tag Auto Close
24 |
25 | XML tag `auto-close` is supported:
26 |
27 | Using `/` in an opening tag will auto close the tag.
28 |
29 | 
30 |
31 | ## Auto Rename Tag
32 |
33 | Linked editing is supported, allowing for simultaneous changes an opening and closing tag pair.
34 |
35 | To enable this feature, the setting `editor.linkedEditing` must be set to `true` in your `settings.json`.
36 |
37 | 
38 |
39 | ## Jump to Start/End Tag
40 |
41 | For quick navigation, you can use `Ctrl + Click` on a closing tag to jump to the corresponding opening tag.
42 |
43 | 
44 |
45 | The same applies to jumping from an opening tag to the respective closing tag.
46 |
47 | 
48 |
49 | ## Rename Tag
50 |
51 | To rename a single tag and its corresponding opening/closing, highlight the tag and press `F2` or use the dropdown to select `Rename Symbol`.
52 |
53 | 
54 |
55 | ## Tag Name Highlighting
56 |
57 | When placing the cursor on an XML tag, the corresponding opening/closing tag will be highlighted.
58 |
59 | 
60 |
61 | ## Symbols from Outline and Breadcrumbs
62 |
63 | The `OUTLINE` dropdown under `EXPLORER` details the XML tags in the document and their children. The `Breadcrumbs` bar also shows the hierarchy of the tag that the cursor is on. Both features permit jumping to the tag(s) displayed.
64 |
65 | 
66 |
67 | ## Snippet Generation
68 |
69 | When starting a new XML document, `Ctrl` + `Space` lists different snippet options to set up the document.
70 |
71 | 
72 |
73 | There are also a number of keywords that will be recognized as snippets and autocompleted. For example, typing `schema` will list schema related snippet options.
74 |
75 | 
76 |
77 | ## Completion Support
78 |
79 | ### Basic completion
80 |
81 | If an XML file is not associated to a bound grammar file, you can utilize XML completion which uses existing XML tag elements.
82 |
83 | ### Attribute value completion
84 |
85 | For an XML tag attribute, there is autocompletion support for the attribute value. For example, for path completion, type `.` or `/`.
86 |
87 | 
88 |
89 | ### Completion based on grammar
90 |
91 | #### Completion based on XSD
92 |
93 | When an XML file is associated with an XSD file, there is support for completion based on the tags, attribute names and values defined in the XML Schema/XSD file.
94 |
95 | 
96 |
97 | #### Completion based on DTD
98 |
99 | When XML file is associated with a DTD file, completion based on tags, attributes name and value defined in the DTD file are supported.
100 |
101 | 
102 |
103 | ## Jump to Grammar Definition
104 |
105 | If an XML file is associated with an XSD file, there is support for jumping from the XML tag to the schema definition.
106 |
107 | 
108 |
109 | ## Hover Support
110 |
111 | ### Hover based on grammar
112 |
113 | #### Hover based on XSD
114 |
115 | When XML file is associated with an XSD file, hover documentation based on tags, attributes name and value defined in the XML Schema/XSD file are supported.
116 |
117 | 
118 |
119 | #### Hover based on DTD
120 |
121 | When XML file is associated with a DTD file, hover documentation based on tags, attributes name and value defined in the DTD file are supported.
122 |
123 | 
124 |
125 | ## Validation Support
126 |
127 | ### Syntax validation
128 |
129 | LemMinX will show syntax errors in your XML documentation, and will provide quick fixes to resolve these errors.
130 |
131 | 
132 |
133 | There is also validation based on grammar when an XSD or DTD file is associated with the XML document.
134 |
135 | ### Read more
136 |
137 | See [XML Validation](../Validation.md#xml-validation) for more details.
138 |
139 | ## Binding Grammar to an XML Document
140 |
141 | For any XML document, should you need to bind a grammar or schema with the file, you can do so by either using an existing grammar file, or by generating one using the built-in schema generator.
142 |
143 | See [Binding with Existing Grammar](../BindingWithGrammar.md#binding-with-existing-grammar) for info on binding to an existing schema.
144 |
145 | See [Binding with New Grammar](../BindingWithGrammar.md#binding-with-new-grammar) for info on grammar generation.
146 |
147 | ## Selection Range
148 |
149 | You can use `Alt + Shift + Right Arrow` to expand your selection range according to the structure of the XML document.
150 |
151 | For instance, if you expand the selection range in an element with text content, it will first select all the text content, then the element.
152 |
153 | This also works for other portions of an XML document, such as attributes and the DTD subset.
154 |
155 | 
156 |
157 | ## CodeLens
158 |
159 | CodeLens is supported for `.xml` files for a number of different features.
160 |
161 | ### CodeLens 'Bind to grammar/schema...'
162 |
163 | If the current XML document is not bound to an existing grammar/schema, a CodeLens will appear above the root element, which will trigger the [XML Binding Wizard](../BindingWithGrammar.md#the-xml-binding-wizard).
164 |
165 | 
166 |
167 | For more information on CodeLens capabilities, see [CodeLens](../CodeLens.md#code-lens).
168 |
169 | ## Custom Feature Implementation
170 |
171 | You can implement your own feature with a [Java extension](../Extensions.md).
172 |
--------------------------------------------------------------------------------
/docs/Features/XMLFilePathSupport.md:
--------------------------------------------------------------------------------
1 | # XML File Paths Features
2 |
3 | XML file path support provides the capability to mark a DOM node (attribute or text) as file path with the `xml.filePathSupport.mappings` setting, by using XPath expression :
4 |
5 | * `path/text()` defines the text node of the `path` element.
6 | * `item/@path` defines the `path` attribute node of the `item` element.
7 |
8 | Once the DOM node is designated as a file path, you will enjoy the benefits of file completion.
9 |
10 | * Files completion.
11 |
12 | ## Define File path in Text Content with `path/text()`
13 |
14 | Given this XML file `items.xml` sample:
15 |
16 | ```xml
17 |
18 |
19 | path/to/file.xml
20 |
21 | ```
22 |
23 | In this example:
24 |
25 | The text within the `path` tag element `path/to/file.xml` represents a file path. The [vscode-xml](https://github.com/redhat-developer/vscode-xml) extension offers file path support through the `xml.filePathSupport.mappings` settings. You can configure this setting as follows:
26 |
27 | ```json
28 | "xml.filePathSupport.mappings": [
29 | {
30 | "pattern": "**/items.xml",
31 | "expressions": [
32 | {
33 | "xpath": "items/path/text()"
34 | }
35 | ]
36 | }
37 | ]
38 | ```
39 |
40 | After saving this setting, you will get file path completion support for the text node of `path` tag element:
41 |
42 | 
43 |
44 | ## Define File path in Attribute with `item/@path`
45 |
46 | Attribute values may also be marked as file path by using the proper XPath.
47 |
48 | Given this `items.xml` XML file:
49 |
50 | ```xml
51 |
52 |
53 |
54 |
55 |
56 | ```
57 |
58 | You can declare this settings:
59 |
60 | ```json
61 | "xml.filePathSupport.mappings": [
62 | {
63 | "pattern": "**/items.xml",
64 | "expressions": [
65 | {
66 | "xpath": "item/@path"
67 | }
68 | ]
69 | }
70 | ]
71 | ```
72 |
73 | After saving this setting, you will get file path completion support for the text node of `path` attribute:
74 |
75 | 
76 |
77 | ## Filter the file path completion result
78 |
79 | Given this `images.xml` file:
80 |
81 | ```xml
82 |
83 |
84 |
85 | ```
86 |
87 | If you need to restrict file path completion on `image/@src` files with the `.png`, `.gif` or `.jpg` extensions, you can use the `filter` property, with this settings:
88 |
89 | ```json
90 | "xml.filePathSupport.mappings": [
91 | {
92 | "pattern": "**/images.xml",
93 | "expressions": [
94 | {
95 | "xpath": "image/@src",
96 | "filter": [".png", ".gif", ".jpg"]
97 | }
98 | ]
99 | }
100 | ]
101 | ```
102 |
103 | ## Separator to declare multiple file paths.
104 |
105 | Given this `paths.xml` file:
106 |
107 | ```xml
108 |
109 |
110 |
111 | ```
112 |
113 | If you want to handle file path completion for `item/@paths` by declaring several file paths separated by `;`, you can use the `separator` property with these settings:
114 |
115 | ```json
116 | "xml.filePathSupport.mappings": [
117 | {
118 | "pattern": "**/paths.xml",
119 | "expressions": [
120 | {
121 | "xpath": "item/@paths",
122 | "separator": ";"
123 | }
124 | ]
125 | }
126 | ]
127 | ```
128 |
--------------------------------------------------------------------------------
/docs/Features/XMLReferencesFeatures.md:
--------------------------------------------------------------------------------
1 | # XML References Features
2 |
3 | XML References support provides the capability to reference a DOM node (attribute or text) to an another DOM node (attribute or text) with the `xml.references` settings by using XPath expression :
4 |
5 | * `foo/@attr` defines the `attr` attribute node of the `foo` element.
6 | * `foo/text()` defines the text node of the `foo` element.
7 |
8 | Once you have declared those reference, you will benefit with completion, definition, highlight, validation, rename, find references, and show references count with codelens:
9 |
10 | 
11 |
12 | ## Attribute node references (foo/@attr)
13 |
14 | Given this [docbook](https://docbook.org/) XML file sample:
15 |
16 | ```xml
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | ```
31 |
32 | At first, please note that [resolve external entities](https://github.com/redhat-developer/vscode-xml/blob/main/docs/Validation.md#resolve-external-entities) must be enabled for this DTD to work.
33 |
34 | In this sample, `linkend` attribute in `` references the `chapter-1` declared in ``. [vscode-xml](https://github.com/redhat-developer/vscode-xml) provides a completion, definition, highlighting support to support this kind of references easily with the `xml.references` settings. For docbook case, you can declare this settings:
35 |
36 | ```json
37 | "xml.references": [
38 | {
39 | "pattern": "**/*.xml",
40 | "expressions": [
41 | {
42 | "from": "xref/@linkend",
43 | "to": "@id"
44 | }
45 | ]
46 | }
47 | ]
48 | ```
49 |
50 | After saving this setting, you will get completion, go to definition, and highlighting for `xref` in the docbook file:
51 |
52 | 
53 |
54 | The `xml.references` settings is an array of objects with the following properties:
55 |
56 | * `pattern`: matches the files that reference declared with `expressions` applies to. See [glob syntax](https://docs.oracle.com/javase/tutorial/essential/io/fileOps.html#glob) for more information about the pattern syntax.
57 | * `prefix (optional)`: the prefix to use (ex : '#') for from for all the declared reference expressions.
58 | * `multiple (optional)`: true if the from attribute, text can declare several from references and false otherwise for all the declared reference expressions.
59 | * `expressions`: array of reference expression:
60 | * `prefix (optional)`: the prefix to use (ex : '#') for from.
61 | * `multiple (optional)`: true if the from attribute, text can declare several from references and false otherwise.
62 | * `from`: the from reference DOM node (attribute, text) declared with XPath (ex: `foo/@attr`, `foo/text()`).
63 | * `to`: the to reference DOM node (attribute, text) declared with XPath (ex: `foo/@attr`, `foo/text()`).
64 |
65 | ### prefix
66 |
67 | Given this [TEI](https://tei-c.org/) XML file sample:
68 |
69 | ```xml
70 |
71 |
72 |
73 |
74 |
75 |
76 | Title
77 |
78 |
79 |
Publication information
80 |
81 |
82 |
Information about the source
83 |
84 |
85 |
86 |
87 |
88 |
Some text here.
89 |
90 |
91 |
92 |
93 | ```
94 |
95 | In this sample, `corresp` attribute in `` references the `body-id` (without `#`) declared in ``. It means that the `corresp` attribute value (with `#`) reference `@xml:id` attribute (without `#`). To support that, you can configure settings by using `prefix`:
96 |
97 | ```json
98 | "xml.references": [
99 | {
100 | "pattern": "**/*.xml",
101 | "prefix": "#",
102 | "expressions": [
103 | {
104 | "from": "@resp",
105 | "to": "persName/@xml:id"
106 | },
107 | {
108 | "from": "@corresp",
109 | "to": "@xml:id"
110 | }
111 | ]
112 | }
113 | ]
114 | ```
115 | ## Multiple target
116 |
117 | If the `origin` attribute (which matches the `from` reference path) declares multiple targets (which matches the `to` reference path), you can use `multiple`
118 |
119 | Given this XML file where `target` attribute defines several targets separated with whitespace (#body-id #p-id):
120 |
121 | ```xml
122 |
123 |
Some text here.
124 |
125 |
126 | ```
127 |
128 | In this sample, `target` attribute in `` references the `body-id` and `p-id` (without `#`) declared in `` and `
`. It means that the `target` attribute value (with `#`) reference `@xml:id` attribute (without `#`). To support that, you can configure settings by using `multiple`:
129 |
130 | ```json
131 | "xml.references": [
132 | {
133 | "pattern": "**/*.xml",
134 | "prefix": "#",
135 | "multiple": true,
136 | "expressions": [
137 | {
138 | "from": "link/@target",
139 | "to": "@xml:id"
140 | }
141 | ]
142 | }
143 | ]
144 | ```
145 |
146 | ## Text node references (foo/text())
147 |
148 | Given this *web.xml* sample:
149 |
150 | ```xml
151 |
155 |
156 | comingsoon
157 | mysite.server.ComingSoonServlet
158 |
159 |
160 | comingsoon
161 | /*
162 |
163 |
164 | ```
165 |
166 | In this sample, `servlet-mapping/servlet-name` text in `comingsoon` references the `comingsoon` declared in ``servlet/servlet-name` text. To support that, you can configure settings like this:
167 |
168 | ```json
169 | "xml.references": [
170 | {
171 | "pattern": "**/web.xml",
172 | "expressions": [
173 | {
174 | "from": "servlet-mapping/servlet-name/text()",
175 | "to": "servlet/servlet-name/text()"
176 | }
177 | ]
178 | }
179 | ]
180 | ```
181 |
182 | 
183 |
184 | ### Limitation
185 |
186 | XML references have some limitation:
187 |
188 | * *references works only for a given XML file*: it is not possible to reference some DOM nodes coming from another XML files. However if the file uses include (like xi:include) the reference will only work in the file which has the include statement, and not in the file being included.
189 |
190 | If you need those support, please [create an issue](https://github.com/redhat-developer/vscode-xml/issues)
--------------------------------------------------------------------------------
/docs/Features/XSDFeatures.md:
--------------------------------------------------------------------------------
1 | # XSD Features
2 |
3 | ## CodeLens Support
4 |
5 | CodeLens is supported for `.xsd` files, which can show where a type is referenced.
6 |
7 | 
8 |
9 | This feature also supports listing the number of references to a type and the line(s) referenced on.
10 |
11 | 
12 |
13 | ### Read more
14 |
15 | See [CodeLens](../CodeLens.md#code-lens) for more details.
16 |
17 | ## XSD Tag Support
18 |
19 | After defining a `Type` or `element` tag in the `.xsd` file, there are a number of features supported in relation to types/elements.
20 |
21 | ### Type completion
22 |
23 | There is autocompletion support for assigning these types to element tags.
24 |
25 | 
26 |
27 | ### Jump to type definition
28 |
29 | For an `element` tag that is assigned a type, there is support for navigating to its definition from any type assignment.
30 |
31 | 
32 |
33 | ### Highlight type instances
34 |
35 | After defining a `Type` or `element`, selecting the `name` attribute will highlight all occurrences.
36 |
37 | 
38 |
39 | ### Change all type occurrences
40 |
41 | To rename a `Type` definition and its associated `element` `type` attribute values, highlight the `name` attribute of the `Type` and press `F2` or use the dropdown to select `Rename Symbol`.
42 |
43 | 
44 |
45 | ## Syntax Validation
46 |
47 | XSD syntax validation is enabled for any `.xsd` file.
48 |
49 | ### Validate element name with same type
50 |
51 | Validation of `.xsd` files enforces all `element` tags that share a type to have different names.
52 |
53 | 
54 |
55 | ### Validate type definition exists
56 |
57 | Validation of `.xsd` files enforces all `element` tags to be assigned a type that has already been defined.
58 |
59 | 
60 |
--------------------------------------------------------------------------------
/docs/Folding.md:
--------------------------------------------------------------------------------
1 | ## Folding
2 |
3 | ### xml.foldings.includeClosingTagInFold
4 |
5 | When folding, the closing tag will remain unfolded by default.
6 |
7 | 
8 |
9 | To change this to minimize the closing tag within the fold, set folding.includeClosingTagInFold to `true`.
10 |
11 | 
12 |
--------------------------------------------------------------------------------
/docs/Proxy.md:
--------------------------------------------------------------------------------
1 | # Proxy
2 |
3 | This page explains how to get vscode-xml to work through a proxy.
4 |
5 | ## Prerequisites
6 |
7 | You need to make sure that you can access any online XML schemas that you want to work with through the proxy.
8 | Also, if are using open-vsx.org instead of Visual Studio Marketplace for extensions
9 | and you want to use the binary language server,
10 | then you will need to make sure that your proxy allows connections to GitHub,
11 | since the binary language server is downloaded from GitHub when using open-vsx.org [for the time being](https://github.com/redhat-developer/vscode-xml/issues/739).
12 |
13 | ## Setting up the proxy in VS Code
14 |
15 | VS Code provides a setting called `http.proxySupport`.
16 | If you set it to `override`, VS Code will attempt to rewrite the requests from extensions to go through the proxy that is configured for VS Code.
17 | However, this method sometimes does not work correctly.
18 |
19 | The tested way to get vscode-xml to use your proxy is to set the following settings:
20 | * `http.proxy`:
21 | The address at which the proxy can be accessed.
22 | As an example, use `"http://localhost:3128"` for a proxy running on your machine on port 3128.
23 | vscode-xml (as well as VS Code) assumes that the same proxy address is used for the HTTP and HTTPS requests.
24 | * `http.proxyAuthorization`:
25 | The authorization header to use for the proxy requests.
26 | This is only needed when the proxy requires authorization.
27 | This follows the form `"[type] [credientials]"`,
28 | where `type` is the authorization type that the proxy uses,
29 | and `credentials` are your credentials for accessing the proxy.
30 | The format of the `credentials` is different for each authorization type.
31 | For instance, `"Basic dXNlcm5hbWU6cGFzc3dvcmQ="` is the authorization header
32 | for a proxy that uses Basic authorization,
33 | where your username is `username` and your password is `password`.
34 | The credentials, `"dXNlcm5hbWU6cGFzc3dvcmQ="`, is `username:password` encoded in base64,
35 | which is the format that is expected for Basic authorization.
36 | Please refer to [this MDN link](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) for more information about authorization headers.
37 |
38 | Once these settings are set,
39 | vscode-xml will forward any requests that it makes through the proxy,
40 | such as the binary server download request
41 | and requests from the language server to download schema.
42 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # XML Documentation
2 |
3 | Welcome to the [vscode-xml](https://github.com/redhat-developer/vscode-xml) documentation.
4 |
5 | ## User Guide
6 |
7 | * [XML Validation](Validation.md#xml-validation): How to validate XML with a grammar (XSD/DTD/RelaxNG)?
8 | * [Preferences](Preferences.md#preferences): More info on available [vscode-xml](https://github.com/redhat-developer/vscode-xml) preferences.
9 | * [Formatting](Formatting.md#formatting): More info on the available formatting preferences.
10 | * [XML Commands](Commands.md#commands): More info on the available XML vscode commands.
11 | * [Symbols](Symbols.md#symbols): More info on the available settings for the document symbols (outline).
12 | * [Troubleshooting](Troubleshooting.md#troubleshooting): Info on troubleshooting and fixes to issues.
13 | * [Features](Features.md#features): Notable info and demos on features available to use.
14 | * [Proxy](Proxy.md#proxy): Instructions for setting up vscode-xml to work behind a proxy.
15 | * [Binding With Grammar](BindingWithGrammar.md#binding-with-grammar): Extension feature to bind an XML document to a grammar/schema file.
16 |
17 | ## Developer Guide
18 |
19 | * [Extensions](Extensions.md#extensions): How to extend vscode-xml settings and XML features (completion, validation, hover, etc)?
--------------------------------------------------------------------------------
/docs/Refactor.md:
--------------------------------------------------------------------------------
1 | # Refactor
2 |
3 | ## Surround with Tags (Wrap)
4 |
5 | This refactor command gives the capability to select an XML content and surround it with a given tag. To execute this command you can:
6 |
7 | * use command palette (`Ctrl+P`) and type `Surround`
8 |
9 | 
10 |
11 | * use contextual menu
12 |
13 | If you prefer using keyboard to process `Surround with Tags (Wrap)`,you need to associate this command with a keybinding. See [Keyboard Shortcuts editor](https://code.visualstudio.com/docs/getstarted/keybindings#_keyboard-shortcuts-editor) for more informations.
14 |
15 | ## Surround with Comments
16 |
17 | Similar to `Surround with Tags (Wrap)`, you can comment out the selected XML content:
18 |
19 | 
20 |
21 | ## Surround with CDATA
22 |
23 | Similar to `Surround with Tags (Wrap)`, you can surround the selected XML content with CDATA:
24 |
25 | 
--------------------------------------------------------------------------------
/docs/Troubleshooting.md:
--------------------------------------------------------------------------------
1 | # Troubleshooting
2 |
3 | ## Issues
4 |
5 | Please create [vscode-xml issues](https://github.com/redhat-developer/vscode-xml/issues) for any problem.
6 |
7 | ### No support on xml file.
8 |
9 | Sometimes an old instance of the XML Language Server is still running.
10 |
11 | You can check if the server is not working in VSCode by going to:
12 | 1) Turning on `xml.trace.server` in the VSCode preferences
13 | 2) `View -> Output -> XML Support` (drop down menu top right)
14 | If it is not working it will indicate the server has Shutdown.
15 |
16 | You can kill the process by:
17 |
18 | 1) Run `jps` command in terminal
19 | 2) Check if multiple instances of `org.eclipse.lemminx-uber.jar` or `XMLServerLauncher`
20 | 3) According to your OS:
21 |
22 | * on Windows OS: run `taskkill /F /PID ...` all instances
23 | * on other OS: run `kill -9 ...` all instances
24 |
25 | ### The Language Server Crashes Due to an Out Of Memory Error
26 |
27 | If you are working with large XML files or referencing large schema files,
28 | this may lead to the language server running out of memory.
29 | The Java language server is more likely to run out memory than the binary language server.
30 | [Switching to the binary language server](Preferences.md#server-binary-mode)
31 | (via the `xml.server.preferBinary` setting)
32 | or increasing the memory available to the Java language server could resolve this issue.
33 |
34 | If you get an Out of Memory Error, but aren't working with large XML files,
35 | then there may be a memory leak in the language server.
36 | Please [file a issue](https://github.com/redhat-developer/vscode-xml/issues) with a description of what you were doing if this is the case.
37 |
38 | #### How to increase the amount of memory available to the Java Language Server
39 |
40 | 1. Go to settings
41 | 2. Navigate to the setting `xml.server.vmargs`
42 | 3. Add `-Xmx512m` to the setting string. This allows the language server to use at most 512 megabytes of memory.
43 | 4. If the problem persists, you can increase the `512m` to `1G` or higher
44 |
--------------------------------------------------------------------------------
/docs/images/BindingWithGrammar/BindToGrammarCodeAction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/BindingWithGrammar/BindToGrammarCodeAction.png
--------------------------------------------------------------------------------
/docs/images/BindingWithGrammar/BindToGrammarCodeActionDropdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/BindingWithGrammar/BindToGrammarCodeActionDropdown.png
--------------------------------------------------------------------------------
/docs/images/BindingWithGrammar/BindToGrammarCodeLens.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/BindingWithGrammar/BindToGrammarCodeLens.png
--------------------------------------------------------------------------------
/docs/images/BindingWithGrammar/BindToGrammarCommand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/BindingWithGrammar/BindToGrammarCommand.png
--------------------------------------------------------------------------------
/docs/images/BindingWithGrammar/BindingWizardDemo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/BindingWithGrammar/BindingWizardDemo.gif
--------------------------------------------------------------------------------
/docs/images/BindingWithGrammar/BindingWizardDropdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/BindingWithGrammar/BindingWizardDropdown.png
--------------------------------------------------------------------------------
/docs/images/BindingWithGrammar/BindingWizardFileExplorer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/BindingWithGrammar/BindingWizardFileExplorer.png
--------------------------------------------------------------------------------
/docs/images/BindingWithGrammar/GenerateDTDFromXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/BindingWithGrammar/GenerateDTDFromXML.gif
--------------------------------------------------------------------------------
/docs/images/BindingWithGrammar/GenerateRelaxNGFromXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/BindingWithGrammar/GenerateRelaxNGFromXML.gif
--------------------------------------------------------------------------------
/docs/images/BindingWithGrammar/GenerateXSDFromXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/BindingWithGrammar/GenerateXSDFromXML.gif
--------------------------------------------------------------------------------
/docs/images/CodeLens/DTDElementCodeLens.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/CodeLens/DTDElementCodeLens.gif
--------------------------------------------------------------------------------
/docs/images/CodeLens/XSDElementCodeLens.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/CodeLens/XSDElementCodeLens.gif
--------------------------------------------------------------------------------
/docs/images/CodeLens/XSDTypeCodeLens.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/CodeLens/XSDTypeCodeLens.gif
--------------------------------------------------------------------------------
/docs/images/Commands/XMLCommands.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Commands/XMLCommands.png
--------------------------------------------------------------------------------
/docs/images/Extensions/DebugAttachRemote.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/DebugAttachRemote.png
--------------------------------------------------------------------------------
/docs/images/Extensions/DebugConfigurations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/DebugConfigurations.png
--------------------------------------------------------------------------------
/docs/images/Extensions/DebugLemMinXExtensionInEclipse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/DebugLemMinXExtensionInEclipse.png
--------------------------------------------------------------------------------
/docs/images/Extensions/DebugLemMinXExtensionInVSCode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/DebugLemMinXExtensionInVSCode.png
--------------------------------------------------------------------------------
/docs/images/Extensions/DebugMultiRootSetup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/DebugMultiRootSetup.png
--------------------------------------------------------------------------------
/docs/images/Extensions/DebugVSCodeXML.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/DebugVSCodeXML.png
--------------------------------------------------------------------------------
/docs/images/Extensions/DebugVSCodeXMLSingleRoot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/DebugVSCodeXMLSingleRoot.png
--------------------------------------------------------------------------------
/docs/images/Extensions/EclipseRunDebugConfigurations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/EclipseRunDebugConfigurations.png
--------------------------------------------------------------------------------
/docs/images/Extensions/EclipseWithLemMinXExtensionOpen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/EclipseWithLemMinXExtensionOpen.png
--------------------------------------------------------------------------------
/docs/images/Extensions/HitABreakpointVSCode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/HitABreakpointVSCode.png
--------------------------------------------------------------------------------
/docs/images/Extensions/InstallVSCodeExtensionForLemMinXExtension.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/InstallVSCodeExtensionForLemMinXExtension.png
--------------------------------------------------------------------------------
/docs/images/Extensions/LaunchVSCodeExtensionForLemMinXExtension.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/LaunchVSCodeExtensionForLemMinXExtension.png
--------------------------------------------------------------------------------
/docs/images/Extensions/NewDebugConfiguration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/NewDebugConfiguration.png
--------------------------------------------------------------------------------
/docs/images/Extensions/PackageVSCodeExtensionForLemMinXExtension.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/PackageVSCodeExtensionForLemMinXExtension.png
--------------------------------------------------------------------------------
/docs/images/Extensions/ProjectWindowAndDebugWindow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/ProjectWindowAndDebugWindow.png
--------------------------------------------------------------------------------
/docs/images/Extensions/ProjectWindowAndDebugWindowSingleRoot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/ProjectWindowAndDebugWindowSingleRoot.png
--------------------------------------------------------------------------------
/docs/images/Extensions/TerminalInstallVSCodeExtensionForLemMinXExtension.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/TerminalInstallVSCodeExtensionForLemMinXExtension.png
--------------------------------------------------------------------------------
/docs/images/Extensions/VSCodeExtensionForLemMinXExtension.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Extensions/VSCodeExtensionForLemMinXExtension.png
--------------------------------------------------------------------------------
/docs/images/Features/AttributeCompletionXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/AttributeCompletionXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/AutoCloseTagEndXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/AutoCloseTagEndXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/AutoCloseTagEndXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/AutoCloseTagEndXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/AutoCloseTagSlashXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/AutoCloseTagSlashXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/AutoCloseTagSlashXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/AutoCloseTagSlashXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/CodeLensBind.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/CodeLensBind.png
--------------------------------------------------------------------------------
/docs/images/Features/CodeLensCatalogRegistration.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/CodeLensCatalogRegistration.gif
--------------------------------------------------------------------------------
/docs/images/Features/CodeLensDTD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/CodeLensDTD.gif
--------------------------------------------------------------------------------
/docs/images/Features/CodeLensReferencesDTD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/CodeLensReferencesDTD.gif
--------------------------------------------------------------------------------
/docs/images/Features/CodeLensReferencesXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/CodeLensReferencesXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/CodeLensXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/CodeLensXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/CompletionBasedOnDTD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/CompletionBasedOnDTD.gif
--------------------------------------------------------------------------------
/docs/images/Features/CompletionBasedOnXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/CompletionBasedOnXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/FoldingSetTrueXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/FoldingSetTrueXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/FoldingXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/FoldingXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/FormatXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/FormatXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/GenerateXMLSchemaSnippet.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/GenerateXMLSchemaSnippet.gif
--------------------------------------------------------------------------------
/docs/images/Features/GenerateXMLSnippet.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/GenerateXMLSnippet.gif
--------------------------------------------------------------------------------
/docs/images/Features/HighlightCorrespondingXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/HighlightCorrespondingXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/HighlightOccurrenceXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/HighlightOccurrenceXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/HoverBasedOnDTD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/HoverBasedOnDTD.gif
--------------------------------------------------------------------------------
/docs/images/Features/HoverBasedOnXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/HoverBasedOnXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/JumpToClosingTagXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/JumpToClosingTagXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/JumpToClosingTagXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/JumpToClosingTagXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/JumpToElementDeclarationDTD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/JumpToElementDeclarationDTD.gif
--------------------------------------------------------------------------------
/docs/images/Features/JumpToOpeningTagXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/JumpToOpeningTagXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/JumpToOpeningTagXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/JumpToOpeningTagXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/JumpToTypeDefinitionXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/JumpToTypeDefinitionXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/JumpToXSDDefFromXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/JumpToXSDDefFromXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/LinkedEditingXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/LinkedEditingXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/RenameTagXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/RenameTagXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/RenameTagXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/RenameTagXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/RenameTypeReferenceXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/RenameTypeReferenceXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/SelectionRange.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/SelectionRange.gif
--------------------------------------------------------------------------------
/docs/images/Features/SymbolOutlineXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/SymbolOutlineXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/TypeAutocompleteXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/TypeAutocompleteXSD.gif
--------------------------------------------------------------------------------
/docs/images/Features/ValidateXSDSameName.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/ValidateXSDSameName.gif
--------------------------------------------------------------------------------
/docs/images/Features/ValidateXSDType.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/ValidateXSDType.gif
--------------------------------------------------------------------------------
/docs/images/Features/ValidationDTD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/ValidationDTD.gif
--------------------------------------------------------------------------------
/docs/images/Features/ValidationXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/ValidationXML.gif
--------------------------------------------------------------------------------
/docs/images/Features/XIncludeDocumentLink.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/XIncludeDocumentLink.gif
--------------------------------------------------------------------------------
/docs/images/Features/XIncludeValidation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/XIncludeValidation.png
--------------------------------------------------------------------------------
/docs/images/Features/XMLColorsFeatures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/XMLColorsFeatures.png
--------------------------------------------------------------------------------
/docs/images/Features/XMLFilePathsInAttrFeatures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/XMLFilePathsInAttrFeatures.png
--------------------------------------------------------------------------------
/docs/images/Features/XMLFilePathsInTextFeatures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/XMLFilePathsInTextFeatures.png
--------------------------------------------------------------------------------
/docs/images/Features/XMLReferencesWithDocbook.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/XMLReferencesWithDocbook.gif
--------------------------------------------------------------------------------
/docs/images/Features/XMLReferencesWithTEI.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/XMLReferencesWithTEI.gif
--------------------------------------------------------------------------------
/docs/images/Features/XMLReferencesWithWebXML.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Features/XMLReferencesWithWebXML.gif
--------------------------------------------------------------------------------
/docs/images/Preferences/HoverDocumentationQuickDemo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Preferences/HoverDocumentationQuickDemo.gif
--------------------------------------------------------------------------------
/docs/images/Refactor/SurroundWithCDATA.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Refactor/SurroundWithCDATA.gif
--------------------------------------------------------------------------------
/docs/images/Refactor/SurroundWithComments.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Refactor/SurroundWithComments.gif
--------------------------------------------------------------------------------
/docs/images/Refactor/SurroundWithTags.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Refactor/SurroundWithTags.gif
--------------------------------------------------------------------------------
/docs/images/RelaxNG/GoToTypeDefinitionMenu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/GoToTypeDefinitionMenu.png
--------------------------------------------------------------------------------
/docs/images/RelaxNG/GoToTypeDefinitionResult.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/GoToTypeDefinitionResult.png
--------------------------------------------------------------------------------
/docs/images/RelaxNG/RNGDefineSupport.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/RNGDefineSupport.gif
--------------------------------------------------------------------------------
/docs/images/RelaxNG/RNGHrefSupport.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/RNGHrefSupport.gif
--------------------------------------------------------------------------------
/docs/images/RelaxNG/RelaxNGCompactSyntaxOverview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/RelaxNGCompactSyntaxOverview.png
--------------------------------------------------------------------------------
/docs/images/RelaxNG/RelaxNGCompletionAndDocumentation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/RelaxNGCompletionAndDocumentation.png
--------------------------------------------------------------------------------
/docs/images/RelaxNG/RelaxNGHoverAndDocumentation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/RelaxNGHoverAndDocumentation.png
--------------------------------------------------------------------------------
/docs/images/RelaxNG/RelaxNGSnippetsSupport.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/RelaxNGSnippetsSupport.gif
--------------------------------------------------------------------------------
/docs/images/RelaxNG/RelaxNGSupport.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/RelaxNGSupport.gif
--------------------------------------------------------------------------------
/docs/images/RelaxNG/RelaxNGValidation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/RelaxNGValidation.png
--------------------------------------------------------------------------------
/docs/images/RelaxNG/RelaxNGXMLSyntaxOverview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/RelaxNGXMLSyntaxOverview.png
--------------------------------------------------------------------------------
/docs/images/RelaxNG/XMLValidatedWithRelaxNG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/RelaxNG/XMLValidatedWithRelaxNG.png
--------------------------------------------------------------------------------
/docs/images/Symbols/ShowReferencedGrammars.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Symbols/ShowReferencedGrammars.png
--------------------------------------------------------------------------------
/docs/images/Symbols/SymbolsBeansWithIdAttrFilter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Symbols/SymbolsBeansWithIdAttrFilter.png
--------------------------------------------------------------------------------
/docs/images/Symbols/SymbolsBuildWithInlineAttrFilter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Symbols/SymbolsBuildWithInlineAttrFilter.png
--------------------------------------------------------------------------------
/docs/images/Symbols/SymbolsPOMWithTextFilter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Symbols/SymbolsPOMWithTextFilter.png
--------------------------------------------------------------------------------
/docs/images/Symbols/SymbolsPOMWithoutFilter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Symbols/SymbolsPOMWithoutFilter.png
--------------------------------------------------------------------------------
/docs/images/Validation/DoctypeError1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Validation/DoctypeError1.png
--------------------------------------------------------------------------------
/docs/images/Validation/DoctypeError2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Validation/DoctypeError2.png
--------------------------------------------------------------------------------
/docs/images/Validation/ExternalEntityResolvingDemonstration.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Validation/ExternalEntityResolvingDemonstration.gif
--------------------------------------------------------------------------------
/docs/images/Validation/GenerateXSD.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Validation/GenerateXSD.gif
--------------------------------------------------------------------------------
/docs/images/Validation/XMLGrammarError.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Validation/XMLGrammarError.png
--------------------------------------------------------------------------------
/docs/images/Validation/XMLSyntaxError.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Validation/XMLSyntaxError.png
--------------------------------------------------------------------------------
/docs/images/Validation/XMLSyntaxErrorCodeAction.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/Validation/XMLSyntaxErrorCodeAction.gif
--------------------------------------------------------------------------------
/docs/images/pre-release.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/pre-release.png
--------------------------------------------------------------------------------
/docs/images/vscode-xml-maven.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/images/vscode-xml-maven.gif
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 |
3 | import eslint from '@eslint/js';
4 | import tseslint from 'typescript-eslint';
5 | import globals from "globals";
6 |
7 | export default tseslint.config(
8 | eslint.configs.recommended,
9 | tseslint.configs.recommended,
10 | {
11 | ignores: [
12 | "node_modules/**",
13 | "dist/**",
14 | "server/**",
15 | "out/**",
16 | ],
17 | },
18 | {
19 | files: [ "src/**/*" ],
20 | rules: {
21 | "@typescript-eslint/no-unused-vars": [
22 | "warn",
23 | {
24 | "argsIgnorePattern": "^_",
25 | "caughtErrorsIgnorePattern": "^_"
26 | }
27 | ],
28 | "@typescript-eslint/no-explicit-any": "warn",
29 | }
30 | }, {
31 | files: [
32 | "gulpfile.js",
33 | "webpack.config.js"
34 | ],
35 | languageOptions: {
36 | sourceType: "commonjs",
37 | globals: globals.node
38 | },
39 | rules: {
40 | "@typescript-eslint/no-var-requires": "off",
41 | "@typescript-eslint/no-require-imports": "off"
42 | }
43 | }
44 | );
45 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const gulp = require('gulp');
3 | const cp = require('child_process');
4 | const fse = require('fs-extra');
5 | const glob = require('glob');
6 |
7 | const server_dir = '../lemminx';
8 |
9 | gulp.task('build_server', function (done) {
10 | cp.execSync(mvnw() + " clean verify -DskipTests", { cwd: server_dir, stdio: [0, 1, 2] });
11 | gulp.src(server_dir + '/org.eclipse.lemminx/target/org.eclipse.lemminx-uber.jar', { encoding: false })
12 | .pipe(gulp.dest('./server'));
13 | done();
14 | });
15 |
16 | gulp.task('build_server_with_binary', function (done) {
17 | cp.execSync(mvnw() + " clean verify -DskipTests -Dnative", { cwd: server_dir, stdio: [0, 1, 2] });
18 | gulp.src([server_dir + '/org.eclipse.lemminx/target/org.eclipse.lemminx-uber.jar', server_dir + '/org.eclipse.lemminx/target/lemminx-*'], { encoding: false })
19 | .pipe(gulp.dest('./server'))
20 | .on('end', function () {
21 | glob.Glob('./server/lemminx-*.txt', (_er, txtfiles) => {
22 | fse.removeSync(txtfiles[0]);
23 | glob.Glob('./server/lemminx-*-*', (_err, binfiles) => {
24 | fse.moveSync(binfiles[0], './server/lemminx-' + (isWin() ? 'win32.exe' : (isMac() ? 'osx-x86_64' : 'linux')), { overwrite: true });
25 | });
26 | });
27 | });
28 | done();
29 | });
30 |
31 | gulp.task('prepare_pre_release', function (done) {
32 | const json = JSON.parse(fse.readFileSync("./package.json").toString());
33 | const stableVersion = json.version.match(/(\d+)\.(\d+)\.(\d+)/);
34 | const major = stableVersion[1];
35 | const minor = stableVersion[2];
36 | const date = new Date();
37 | const month = date.getMonth() + 1;
38 | const day = date.getDate();
39 | const hours = date.getHours();
40 | const patch = `${date.getFullYear()}${prependZero(month)}${prependZero(day)}${prependZero(hours)}`;
41 | const insiderPackageJson = Object.assign(json, {
42 | version: `${major}.${minor}.${patch}`,
43 | });
44 | fse.writeFileSync("./package.json", JSON.stringify(insiderPackageJson, null, 2));
45 | done();
46 | });
47 |
48 | function isWin() {
49 | return /^win/.test(process.platform);
50 | }
51 |
52 | function isMac() {
53 | return /^darwin/.test(process.platform);
54 | }
55 |
56 | function mvnw() {
57 | return isWin() ? "mvnw.cmd" : server_dir + "/mvnw";
58 | }
59 |
60 | function prependZero(number) {
61 | if (number > 99) {
62 | throw "Unexpected value to prepend with zero";
63 | }
64 | return `${number < 10 ? "0" : ""}${number}`;
65 | }
66 |
--------------------------------------------------------------------------------
/icons/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/icons/icon128.png
--------------------------------------------------------------------------------
/images/DebugAttachRemote.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/images/DebugAttachRemote.png
--------------------------------------------------------------------------------
/images/DebugMenuCallStack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/images/DebugMenuCallStack.png
--------------------------------------------------------------------------------
/images/DownloadBinaryArtifacts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/images/DownloadBinaryArtifacts.png
--------------------------------------------------------------------------------
/images/DownloadBinaryChecks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/images/DownloadBinaryChecks.png
--------------------------------------------------------------------------------
/images/LaunchExtension.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-xml/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/images/LaunchExtension.png
--------------------------------------------------------------------------------
/rnc.language-configuration.json:
--------------------------------------------------------------------------------
1 | // Copy of https://github.com/RussGlover/relaxNgCompactSyntaxHighlighter/blob/master/language-configuration.json
2 | {
3 | "comments": {
4 | "lineComment": "#"
5 | },
6 | // symbols used as brackets
7 | "brackets": [
8 | ["{", "}"],
9 | ["[", "]"],
10 | ["(", ")"]
11 | ],
12 | // symbols that are auto closed when typing
13 | "autoClosingPairs": [
14 | ["{", "}"],
15 | ["[", "]"],
16 | ["(", ")"],
17 | ["\"", "\""],
18 | ["'", "'"]
19 | ],
20 | // symbols that that can be used to surround a selection
21 | "surroundingPairs": [
22 | ["{", "}"],
23 | ["[", "]"],
24 | ["(", ")"],
25 | ["\"", "\""],
26 | ["'", "'"]
27 | ]
28 | }
--------------------------------------------------------------------------------
/schemas/package.schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/draft-04/schema#",
3 | "title": "XML Language server contributions to package.json",
4 | "type": "object",
5 | "properties": {
6 | "contributes": {
7 | "type": "object",
8 | "properties": {
9 | "xml.javaExtensions": {
10 | "type": "array",
11 | "markdownDescription": "XML language server extensions",
12 | "items": {
13 | "type": "string",
14 | "description": "Relative path to a XML language server extension JAR file"
15 | }
16 | },
17 | "xmlLanguageParticipants": {
18 | "type": "array",
19 | "description": "A list of languages that participate with the XML language server.",
20 | "items": {
21 | "type": "object",
22 | "properties": {
23 | "languageId": {
24 | "type": "string",
25 | "description": "The id of the language that participates with XML language server."
26 | }
27 | }
28 | }
29 | }
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/api/xmlExtensionApi.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Interface for APIs exposed from the extension.
3 | *
4 | * @remarks
5 | * A sample code to use these APIs are as following:
6 | * const ext = await vscode.extensions.getExtension('redhat.vscode-xml').activate();
7 | * ext.addXMLCatalogs(...);
8 | * ext.removeXMLCatalogs(...);
9 | * ext.addXMLFileAssociations(...);
10 | * ext.removeXMLFileAssociations(...);
11 | */
12 | export interface XMLExtensionApi {
13 | /**
14 | * Adds XML Catalogs in addition to the catalogs defined in the settings.json file.
15 | *
16 | * @remarks
17 | * An example is to call this API:
18 | * ```ts
19 | * addXMLCatalogs(['path/to/catalog.xml', 'path/to/anotherCatalog.xml'])
20 | * ```
21 | * @param catalogs - A list of path to XML catalogs
22 | * @returns None
23 | */
24 | addXMLCatalogs(catalogs: string[]): void;
25 | /**
26 | * Removes XML Catalogs from the extension.
27 | *
28 | * @remarks
29 | * An example is to call this API:
30 | * ```ts
31 | * removeXMLCatalogs(['path/to/catalog.xml', 'path/to/anotherCatalog.xml'])
32 | * ```
33 | * @param catalogs - A list of path to XML catalogs
34 | * @returns None
35 | */
36 | removeXMLCatalogs(catalogs: string[]): void;
37 | /**
38 | * Adds XML File Associations in addition to the catalogs defined in the settings.json file.
39 | *
40 | * @remarks
41 | * An example is to call this API:
42 | * ```ts
43 | * addXMLFileAssociations([{
44 | * "systemId": "path/to/file.xsd",
45 | * "pattern": "file1.xml"
46 | * },{
47 | * "systemId": "http://www.w3.org/2001/XMLSchema.xsd",
48 | * "pattern": "file2.xml"
49 | * }])
50 | * ```
51 | * @param fileAssociations - A list of file association
52 | * @returns None
53 | */
54 | addXMLFileAssociations(fileAssociations: XMLFileAssociation[]): void;
55 | /**
56 | * Removes XML File Associations from the extension.
57 | *
58 | * @remarks
59 | * An example is to call this API:
60 | * ```ts
61 | * removeXMLFileAssociations([{
62 | * "systemId": "path/to/file.xsd",
63 | * "pattern": "file1.xml"
64 | * },{
65 | * "systemId": "http://www.w3.org/2001/XMLSchema.xsd",
66 | * "pattern": "file2.xml"
67 | * }])
68 | * ```
69 | * @param fileAssociations - A list of file association
70 | * @returns None
71 | */
72 | removeXMLFileAssociations(fileAssociations: XMLFileAssociation[]): void;
73 |
74 | }
75 |
76 | /**
77 | * Interface for the FileAssociation shape.
78 | * @param systemId - The path to a valid XSD.
79 | * @param pattern - The file pattern associated with the XSD.
80 | *
81 | * @returns None
82 | */
83 | export interface XMLFileAssociation {
84 | systemId: string,
85 | pattern: string;
86 | }
--------------------------------------------------------------------------------
/src/api/xmlExtensionApiImplementation.ts:
--------------------------------------------------------------------------------
1 | import { DidChangeConfigurationNotification } from "vscode-languageclient";
2 | import { LanguageClient } from "vscode-languageclient/node";
3 | import { RequirementsData } from "../server/requirements";
4 | import { ExternalXmlSettings } from "../settings/externalXmlSettings";
5 | import { getXMLSettings, onConfigurationChange } from "../settings/settings";
6 | import { XMLExtensionApi, XMLFileAssociation } from "./xmlExtensionApi";
7 |
8 | /**
9 | * Returns the implementation of the vscode-xml extension API
10 | *
11 | * @param languageClient
12 | * @param logfile
13 | * @param externalXmlSettings
14 | * @param requirementsData
15 | * @return the implementation of the vscode-xml extension API
16 | */
17 | export function getXmlExtensionApiImplementation(languageClient: LanguageClient, logfile: string, externalXmlSettings: ExternalXmlSettings, requirementsData: RequirementsData): XMLExtensionApi {
18 | return {
19 | // add API set catalogs to internal memory
20 | addXMLCatalogs: (catalogs: string[]) => {
21 | const externalXmlCatalogs = externalXmlSettings.xmlCatalogs;
22 | catalogs.forEach(element => {
23 | if (!externalXmlCatalogs.includes(element)) {
24 | externalXmlCatalogs.push(element);
25 | }
26 | });
27 | languageClient.sendNotification(DidChangeConfigurationNotification.type, { settings: getXMLSettings(requirementsData.java_home, logfile, externalXmlSettings) });
28 | onConfigurationChange();
29 | },
30 | // remove API set catalogs to internal memory
31 | removeXMLCatalogs: (catalogs: string[]) => {
32 | catalogs.forEach(element => {
33 | const externalXmlCatalogs = externalXmlSettings.xmlCatalogs;
34 | if (externalXmlCatalogs.includes(element)) {
35 | const itemIndex = externalXmlCatalogs.indexOf(element);
36 | externalXmlCatalogs.splice(itemIndex, 1);
37 | }
38 | });
39 | languageClient.sendNotification(DidChangeConfigurationNotification.type, { settings: getXMLSettings(requirementsData.java_home, logfile, externalXmlSettings) });
40 | onConfigurationChange();
41 | },
42 | // add API set fileAssociations to internal memory
43 | addXMLFileAssociations: (fileAssociations: XMLFileAssociation[]) => {
44 | const externalfileAssociations = externalXmlSettings.xmlFileAssociations;
45 | fileAssociations.forEach(element => {
46 | if (!externalfileAssociations.some(fileAssociation => fileAssociation.pattern === element.pattern)) {
47 | externalfileAssociations.push(element);
48 | }
49 | });
50 | languageClient.sendNotification(DidChangeConfigurationNotification.type, { settings: getXMLSettings(requirementsData.java_home, logfile, externalXmlSettings) });
51 | onConfigurationChange();
52 | },
53 | // remove API set fileAssociations to internal memory
54 | removeXMLFileAssociations: (fileAssociations: XMLFileAssociation[]) => {
55 | const externalfileAssociations = externalXmlSettings.xmlFileAssociations;
56 | fileAssociations.forEach(element => {
57 | const itemIndex = externalfileAssociations.findIndex(fileAssociation => fileAssociation.pattern === element.pattern) //returns -1 if item not found
58 | if (itemIndex > -1) {
59 | externalfileAssociations.splice(itemIndex, 1);
60 | }
61 | });
62 | languageClient.sendNotification(DidChangeConfigurationNotification.type, { settings: getXMLSettings(requirementsData.java_home, logfile, externalXmlSettings) });
63 | onConfigurationChange();
64 | }
65 | } as XMLExtensionApi;
66 | }
67 |
--------------------------------------------------------------------------------
/src/client/clientErrorHandler.ts:
--------------------------------------------------------------------------------
1 | import * as fs from "fs-extra";
2 | import { commands, ConfigurationTarget, ExtensionContext, window, workspace } from "vscode";
3 | import { CloseAction, CloseHandlerResult, ErrorAction, ErrorHandler, ErrorHandlerResult, Message } from "vscode-languageclient";
4 | import * as ClientCommandConstants from "../commands/clientCommandConstants";
5 | import { HEAP_DUMP_LOCATION } from "../server/java/jvmArguments";
6 | import * as Telemetry from "../telemetry";
7 | import * as glob from "glob";
8 | import { totalmem } from "os";
9 |
10 | /**
11 | * An error handler that restarts the language server,
12 | * unless it has been restarted 5 times in the last 10 minutes,
13 | * or if it crashed due to an Out Of Memory Error
14 | *
15 | * Adapted from [vscode-java](https://github.com/redhat-developer/vscode-java)
16 | */
17 | export class ClientErrorHandler implements ErrorHandler {
18 |
19 | private restarts: number[];
20 | private name: string;
21 | private context: ExtensionContext;
22 | private heapDumpFolder: string;
23 |
24 | constructor(name: string, context: ExtensionContext) {
25 | this.name = name;
26 | this.restarts = [];
27 | this.context = context;
28 | this.heapDumpFolder = getHeapDumpFolderFromSettings() || context.globalStorageUri.fsPath;
29 | }
30 |
31 | error(_error: Error, _message: Message, _count: number): ErrorHandlerResult {
32 | return {
33 | action: ErrorAction.Continue
34 | };
35 | }
36 |
37 | closed(): CloseHandlerResult {
38 | return {
39 | action: this.doClosed()
40 | }
41 | }
42 |
43 | doClosed(): CloseAction {
44 | this.restarts.push(Date.now());
45 | const heapProfileGlob = new glob.GlobSync(`${this.heapDumpFolder}/java_*.hprof`);
46 | if (heapProfileGlob.found.length) {
47 | // Only clean heap dumps that are generated in the default location.
48 | // The default location is the extension global storage
49 | // This means that if users change the folder where the heap dumps are placed,
50 | // then they will be able to read the heap dumps,
51 | // since they aren't immediately deleted.
52 | cleanUpHeapDumps(this.context);
53 | Telemetry.sendTelemetry(Telemetry.JAVA_OOM_EVT, { 'jvm.xmx': getXmxFromSettings() });
54 | showOOMMessage();
55 | return CloseAction.DoNotRestart;
56 | }
57 | if (this.restarts.length < 5) {
58 | return CloseAction.Restart;
59 | } else {
60 | const diff = this.restarts[this.restarts.length - 1] - this.restarts[0];
61 | if (diff <= 10 * 60 * 1000) {
62 | window.showErrorMessage(`The ${this.name} language server crashed 5 times in the last 10 minutes. The server will not be restarted.`);
63 | return CloseAction.DoNotRestart;
64 | }
65 | this.restarts.shift();
66 | return CloseAction.Restart;
67 | }
68 | }
69 |
70 | }
71 |
72 | /**
73 | * Deletes all the heap dumps generated by Out Of Memory errors
74 | *
75 | * @returns when the heap dumps have been deleted
76 | */
77 | export async function cleanUpHeapDumps(context: ExtensionContext): Promise {
78 | const heapProfileGlob = new glob.GlobSync(`${context.globalStorageUri.fsPath}/java_*.hprof`);
79 | for (const heapProfile of heapProfileGlob.found) {
80 | await fs.remove(heapProfile);
81 | }
82 | }
83 |
84 | /**
85 | * Shows a message about the server crashing due to an out of memory issue
86 | */
87 | async function showOOMMessage(): Promise {
88 | const DOCS = 'More info...';
89 | const DOUBLE = 'Double allocated memory';
90 | const result = await window.showErrorMessage('The XML Language Server crashed due to an Out Of Memory Error, and will not be restarted. ', //
91 | DOUBLE, DOCS);
92 | if (result === DOCS) {
93 | Telemetry.sendTelemetry(Telemetry.OPEN_OOM_DOCS_EVT);
94 | await commands.executeCommand(ClientCommandConstants.OPEN_DOCS,
95 | {
96 | page: 'Troubleshooting',
97 | section: 'the-language-server-crashes-due-to-an-out-of-memory-error'
98 | }
99 | );
100 | } else if (result === DOUBLE) {
101 | doubleAllocatedMemory();
102 | }
103 | }
104 |
105 | const HEAP_DUMP_FOLDER_EXTRACTOR = new RegExp(`${HEAP_DUMP_LOCATION}(?:'([^']+)'|"([^"]+)"|([^\\s]+))`);
106 | const MAX_HEAP_SIZE_EXTRACTOR = new RegExp(`-Xmx([0-9]+)[kKmMgG]`);
107 |
108 | /**
109 | * Returns the heap dump folder defined in the user's preferences, or undefined if the user does not set the heap dump folder
110 | *
111 | * @returns the heap dump folder defined in the user's preferences, or undefined if the user does not set the heap dump folder
112 | */
113 | function getHeapDumpFolderFromSettings(): string {
114 | const jvmArgs: string = workspace.getConfiguration('xml.server').get('vmargs');
115 | const results = HEAP_DUMP_FOLDER_EXTRACTOR.exec(jvmArgs);
116 | if (!results || !results[0]) {
117 | return undefined;
118 | }
119 | return results[1] || results[2] || results[3];
120 | }
121 |
122 | const XMX_EXTRACTOR = /-Xmx([^\s]+)/;
123 |
124 | /**
125 | * Returns the value that the user set for Xmx, or DEFAULT if the user didn't set Xmx
126 | *
127 | * @returns the value that the user set for Xmx, or DEFAULT if the user didn't set Xmx
128 | */
129 | function getXmxFromSettings(): string {
130 | const vmargs: string = workspace.getConfiguration('xml.server').get('vmargs', null);
131 | if (vmargs != null) {
132 | const extractOfVmargs: RegExpExecArray = XMX_EXTRACTOR.exec(vmargs);
133 | if (extractOfVmargs.length && extractOfVmargs[1]) {
134 | return extractOfVmargs[1];
135 | }
136 | }
137 | return 'DEFAULT';
138 | }
139 |
140 | /**
141 | * Double the memory allocated to lemminx in the vmargs parameter
142 | */
143 | async function doubleAllocatedMemory() {
144 | let vmargs: string = workspace.getConfiguration('xml.server').get('vmargs', null);
145 | const results = MAX_HEAP_SIZE_EXTRACTOR.exec(vmargs);
146 | if (results && results[0]) {
147 | const maxMemArg: string = results[0];
148 | const maxMemValue = Number(results[1]);
149 | const newMaxMemArg: string = maxMemArg.replace(maxMemValue.toString(), (maxMemValue * 2).toString());
150 | vmargs = vmargs.replace(maxMemArg, newMaxMemArg);
151 | await workspace.getConfiguration().update("xml.server.vmargs", vmargs, ConfigurationTarget.Global);
152 | } else {
153 | // by default, many JVM take 1/4 of the physical memory as -Xmx
154 | // in the case it crashes, set -Xmx to half of total physical memory, in megabytes
155 | vmargs = `-Xmx ${Math.trunc(totalmem()/2/1000000)}m ${vmargs}`;
156 | await workspace.getConfiguration().update("xml.server.vmargs", vmargs, ConfigurationTarget.Global);
157 | }
158 | }
--------------------------------------------------------------------------------
/src/client/indentation.ts:
--------------------------------------------------------------------------------
1 | import { IndentAction, LanguageConfiguration } from "vscode";
2 |
3 | export function getIndentationRules(): LanguageConfiguration {
4 | return {
5 |
6 | // indentationRules referenced from:
7 | // https://github.com/microsoft/vscode/blob/d00558037359acceea329e718036c19625f91a1a/extensions/html-language-features/client/src/htmlMain.ts#L114-L115
8 | indentationRules: {
9 | increaseIndentPattern: /<(?!\?|[^>]*\/>)([-_.A-Za-z0-9]+)(?=\s|>)\b[^>]*>(?!.*<\/\1>)|)|\{[^}"']*$/,
10 | decreaseIndentPattern: /^\s*(<\/[-_.A-Za-z0-9]+\b[^>]*>|-->|\})/
11 | },
12 | onEnterRules: [
13 | {
14 | beforeText: /<(?:[_:\w][_:\w\-.\d]*)(?:(?:[^'"/>]|"[^"]*"|'[^']*')*?(?!\/)>)[^<]*$/i,
15 | afterText: /^<\/(?:[_:\w][_:\w-.\d]*)\s*>/i,
16 | action: { indentAction: IndentAction.IndentOutdent }
17 | },
18 | {
19 | beforeText: /<(?:\w[\w\d]*)(?:(?:[^'"/>]|"[^"]*"|'[^']*')*?(?!\/)>)[^<]*$/i,
20 | action: { indentAction: IndentAction.Indent }
21 | }
22 | ]
23 | };
24 | }
--------------------------------------------------------------------------------
/src/client/languageParticipants.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Copyright (c) Microsoft Corporation. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | *--------------------------------------------------------------------------------------------*/
5 |
6 | import { Event, EventEmitter, extensions } from 'vscode';
7 | import { DocumentFilter, DocumentSelector } from 'vscode-languageclient';
8 |
9 | const SCHEMES: string[] = [
10 | 'untitled',
11 | 'file',
12 | 'ftp',
13 | 'http',
14 | 'https',
15 | 'ssh',
16 | 'streamfile',
17 | ];
18 |
19 | /**
20 | * XML language participant contribution.
21 | */
22 | interface LanguageParticipantContribution {
23 | /**
24 | * The id of the language which participates with the XML language server.
25 | */
26 | languageId: string;
27 | }
28 |
29 | export interface LanguageParticipants {
30 | readonly onDidChange: Event;
31 | readonly documentSelector: DocumentSelector;
32 | hasLanguage(languageId: string): boolean;
33 | dispose(): void;
34 | }
35 |
36 | export function getLanguageParticipants(): LanguageParticipants {
37 | const onDidChangeEmmiter = new EventEmitter();
38 | let languages = new Set();
39 |
40 | function update() {
41 | const oldLanguages = languages;
42 |
43 | languages = new Set();
44 | languages.add('xml');
45 | languages.add('xsl');
46 | languages.add('dtd');
47 | languages.add('svg');
48 |
49 | for (const extension of extensions.all /*extensions.allAcrossExtensionHosts*/) {
50 | const xmlLanguageParticipants = extension.packageJSON?.contributes?.xmlLanguageParticipants as LanguageParticipantContribution[];
51 | if (Array.isArray(xmlLanguageParticipants)) {
52 | for (const xmlLanguageParticipant of xmlLanguageParticipants) {
53 | const languageId = xmlLanguageParticipant.languageId;
54 | if (typeof languageId === 'string') {
55 | languages.add(languageId);
56 | }
57 | }
58 | }
59 | }
60 | return !isEqualSet(languages, oldLanguages);
61 | }
62 | update();
63 |
64 | const changeListener = extensions.onDidChange(_ => {
65 | if (update()) {
66 | onDidChangeEmmiter.fire();
67 | }
68 | });
69 |
70 | return {
71 | onDidChange: onDidChangeEmmiter.event,
72 | get documentSelector() {
73 | return SCHEMES.flatMap(scheme => {
74 | return Array.from(languages).map(language => {
75 | return {
76 | language,
77 | scheme
78 | } as DocumentFilter;
79 | });
80 | });
81 | },
82 | hasLanguage(languageId: string) { return languages.has(languageId); },
83 | dispose: () => changeListener.dispose()
84 | };
85 | }
86 |
87 | function isEqualSet(s1: Set, s2: Set) {
88 | if (s1.size !== s2.size) {
89 | return false;
90 | }
91 | for (const e of s1) {
92 | if (!s2.has(e)) {
93 | return false;
94 | }
95 | }
96 | return true;
97 | }
98 |
--------------------------------------------------------------------------------
/src/client/tagClosing.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Copyright (c) Microsoft Corporation. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | *
5 | * Retrieved from: https://github.com/Microsoft/vscode/blob/f707828426bd87e88c17d2da34f2ceed0019d8bd/extensions/html-language-features/client/src/tagClosing.ts
6 | *--------------------------------------------------------------------------------------------*/
7 | 'use strict';
8 |
9 | import { window, workspace, Disposable, TextDocumentContentChangeEvent, TextDocument, Position, SnippetString, Range } from 'vscode';
10 |
11 | export interface AutoCloseResult {
12 | snippet: string,
13 | range?: Range
14 | }
15 |
16 | export function activateTagClosing(tagProvider: (document: TextDocument, position: Position) => Thenable, supportedLanguages: { [id: string]: boolean }, configName: string): Disposable {
17 |
18 | const disposables: Disposable[] = [];
19 | workspace.onDidChangeTextDocument(event => onDidChangeTextDocument(event.document, event.contentChanges), null, disposables);
20 |
21 | let isEnabled = false;
22 | updateEnabledState();
23 | window.onDidChangeActiveTextEditor(updateEnabledState, null, disposables);
24 |
25 | let timeout: NodeJS.Timeout | undefined = undefined;
26 |
27 | function updateEnabledState() {
28 | isEnabled = false;
29 | const editor = window.activeTextEditor;
30 | if (!editor) {
31 | return;
32 | }
33 | const document = editor.document;
34 | if (!supportedLanguages[document.languageId]) {
35 | return;
36 | }
37 | if (!workspace.getConfiguration(undefined, document.uri).get(configName)) {
38 | return;
39 | }
40 | isEnabled = true;
41 | }
42 |
43 | function onDidChangeTextDocument(document: TextDocument, changes: ReadonlyArray) {
44 | if (!isEnabled) {
45 | return;
46 | }
47 | const activeDocument = window.activeTextEditor && window.activeTextEditor.document;
48 | if (document !== activeDocument || changes.length === 0) {
49 | return;
50 | }
51 | if (typeof timeout !== 'undefined') {
52 | clearTimeout(timeout);
53 | }
54 | const lastChange = changes[changes.length - 1];
55 | const lastCharacter = lastChange.text[lastChange.text.length - 1];
56 | if (lastChange.rangeLength > 0 || lastCharacter !== '>' && lastCharacter !== '/') {
57 | return;
58 | }
59 | const rangeStart = lastChange.range.start;
60 | const version = document.version;
61 | timeout = setTimeout(() => {
62 | const position = new Position(rangeStart.line, rangeStart.character + lastChange.text.length);
63 | tagProvider(document, position).then(result => {
64 | const text = result?.snippet;
65 | if (text && isEnabled) {
66 | const activeEditor = window.activeTextEditor;
67 | if (activeEditor) {
68 | const activeDocument = activeEditor.document;
69 | if (document === activeDocument && activeDocument.version === version) {
70 | const selections = activeEditor.selections;
71 | if (selections.length > 1 && selections.some(s => s.active.isEqual(position))) {
72 | // multiple cusror case
73 | activeEditor.insertSnippet(new SnippetString(text), selections.map(s => s.active));
74 | } else {
75 | // no multiple cursor we use the range coming from le LSP closeTag request to support 'xml.completion.autoCloseRemovesContent' setting
76 | activeEditor.insertSnippet(new SnippetString(text), getReplaceLocation(result.range, position));
77 | }
78 | }
79 | }
80 | }
81 | }, (_reason: any) => {
82 | console.log('xml/closeTag request has been cancelled');
83 | });
84 | timeout = void 0;
85 | }, 100);
86 | }
87 | return Disposable.from(...disposables);
88 | }
89 |
90 | function getReplaceLocation(range: Range, position: Position): Range | Position {
91 | if (range != null) {
92 | // re-create Range
93 | let line = range.start.line;
94 | let character = range.start.character;
95 | const startPosition = new Position(line, character);
96 | line = range.end.line;
97 | character = range.end.character;
98 | const endPosition = new Position(line, character);
99 | return new Range(startPosition, endPosition);
100 | }
101 | return position;
102 | }
--------------------------------------------------------------------------------
/src/commands/clientCommandConstants.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * VScode client commands.
3 | */
4 |
5 | /**
6 | * Show XML references
7 | */
8 | export const SHOW_REFERENCES = 'xml.show.references';
9 |
10 | /**
11 | * Show editor references
12 | */
13 | export const EDITOR_SHOW_REFERENCES = 'editor.action.showReferences';
14 |
15 | /**
16 | * Reload VS Code window
17 | */
18 | export const RELOAD_WINDOW = 'workbench.action.reloadWindow';
19 |
20 | /**
21 | * Open settings command
22 | *
23 | * A `settingId: string` parameter can be optionally provided
24 | */
25 | export const OPEN_SETTINGS = 'xml.open.settings';
26 |
27 | /**
28 | * Open settings command
29 | *
30 | * A `settingId: string` parameter can be optionally provided
31 | */
32 | export const OPEN_URI = 'xml.open.uri';
33 |
34 | /**
35 | * Render markdown string to html string
36 | */
37 | export const MARKDOWN_API_RENDER = 'markdown.api.render';
38 |
39 | export const OPEN_DOCS = 'xml.open.docs';
40 |
41 | /**
42 | * Commands to revalidate files with an LSP command on the XML Language Server
43 | */
44 | export const VALIDATE_CURRENT_FILE = 'xml.validation.current.file';
45 |
46 | export const VALIDATE_ALL_FILES = 'xml.validation.all.files';
47 |
48 | export const OPEN_DOCS_HOME = 'xml.open.docs.home';
49 |
50 | /**
51 | * VSCode client commands to open the binding wizard to bind a XML to a grammar/schema.
52 | */
53 | export const OPEN_BINDING_WIZARD = 'xml.open.binding.wizard';
54 |
55 | /**
56 | * VSCode client command to open the grammar/schema binding wizard from command menu.
57 | */
58 | export const COMMAND_PALETTE_BINDING_WIZARD = 'xml.command.bind.grammar';
59 |
60 | /**
61 | * Client command to execute an XML command on XML Language Server side.
62 | */
63 | export const EXECUTE_WORKSPACE_COMMAND = 'xml.workspace.executeCommand';
64 |
65 | /**
66 | * Command to restart connection to language server.
67 | */
68 | export const RESTART_LANGUAGE_SERVER = 'xml.restart.language.server';
69 |
70 | /**
71 | * Command to wrap element.
72 | */
73 | export const REFACTOR_SURROUND_WITH_TAGS = 'xml.refactor.surround.with.tags';
74 |
75 | export const REFACTOR_SURROUND_WITH_COMMENTS = 'xml.refactor.surround.with.comments';
76 |
77 | export const REFACTOR_SURROUND_WITH_CDATA = 'xml.refactor.surround.with.cdata';
--------------------------------------------------------------------------------
/src/commands/lspCommandConstants.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * LSP Command Constants.
3 | */
4 |
5 | /**
6 | * Command to register/unregister catalog.
7 | */
8 | export const UPDATE_CONFIGURATION = 'xml.update.configuration'
9 |
--------------------------------------------------------------------------------
/src/commands/serverCommandConstants.ts:
--------------------------------------------------------------------------------
1 | import * as ClientCommandConstants from "./clientCommandConstants";
2 |
3 | /**
4 | * XML Language Server commands.
5 | */
6 |
7 | /**
8 | * Auto close tags
9 | */
10 | export const AUTO_CLOSE_TAGS = 'xml.completion.autoCloseTags';
11 |
12 | /**
13 | * Commands to revalidate files with an LSP command on the XML Language Server
14 | */
15 | export const VALIDATE_CURRENT_FILE = ClientCommandConstants.VALIDATE_CURRENT_FILE;
16 |
17 | export const VALIDATE_ALL_FILES = ClientCommandConstants.VALIDATE_ALL_FILES;
18 |
19 | /**
20 | * Command to associate a grammar in a XML document
21 | */
22 | export const ASSOCIATE_GRAMMAR_INSERT = "xml.associate.grammar.insert";
23 |
24 | /**
25 | * Command to check if the current XML document is bound to a grammar
26 | */
27 | export const CHECK_BOUND_GRAMMAR = "xml.check.bound.grammar";
28 |
29 | /**
30 | * Command to check if a given file pattern matches any file on the workspace
31 | */
32 | export const CHECK_FILE_PATTERN = "xml.check.file.pattern";
33 |
34 | /**
35 | * Command to surround with tags, comments, cdata
36 | */
37 | export const REFACTOR_SURROUND_WITH = "xml.refactor.surround.with";
--------------------------------------------------------------------------------
/src/extension.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Red Hat, Inc. and others.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v2.0
5 | * which accompanies this distribution, and is available at
6 | * https://www.eclipse.org/legal/epl-v20.html
7 | *
8 | * Contributors:
9 | * Red Hat Inc. - initial API and implementation
10 | * Microsoft Corporation - Auto Closing Tags
11 | */
12 |
13 | import * as fs from 'fs-extra';
14 | import { ConfigurationTarget, ExtensionContext, Uri, commands, extensions, languages, window, workspace } from "vscode";
15 | import { Executable, LanguageClient } from 'vscode-languageclient/node';
16 | import { XMLExtensionApi } from './api/xmlExtensionApi';
17 | import { getXmlExtensionApiImplementation } from './api/xmlExtensionApiImplementation';
18 | import { cleanUpHeapDumps } from './client/clientErrorHandler';
19 | import { getIndentationRules } from './client/indentation';
20 | import { XML_SUPPORTED_LANGUAGE_IDS, startLanguageClient } from './client/xmlClient';
21 | import { registerClientOnlyCommands } from './commands/registerCommands';
22 | import { collectXmlJavaExtensions } from './plugin';
23 | import * as requirements from './server/requirements';
24 | import { prepareExecutable } from './server/serverStarter';
25 | import { ExternalXmlSettings } from "./settings/externalXmlSettings";
26 | import { getXMLConfiguration } from './settings/settings';
27 | import * as Telemetry from './telemetry';
28 |
29 | let languageClient: LanguageClient;
30 |
31 | export async function activate(context: ExtensionContext): Promise {
32 |
33 | await Telemetry.startTelemetry(context);
34 |
35 | registerClientOnlyCommands(context);
36 |
37 | // Update indentation rules for all language which are XML.
38 | XML_SUPPORTED_LANGUAGE_IDS.forEach((languageId: string) => {
39 | languages.setLanguageConfiguration(languageId, getIndentationRules());
40 | });
41 |
42 | // Register in the context 'xml.supportedLanguageIds' to use it in command when condition in package.json
43 | commands.executeCommand('setContext', 'xml.supportedLanguageIds', XML_SUPPORTED_LANGUAGE_IDS);
44 |
45 | let requirementsData: requirements.RequirementsData;
46 | try {
47 | requirementsData = await requirements.resolveRequirements(context);
48 | } catch (error) {
49 | if (!workspace.getConfiguration('xml').get('server.preferBinary') && error.message !== requirements.NO_JAVA_FOUND) {
50 | const USE_BINARY = 'Always use binary server';
51 | void window.showWarningMessage(error.message + ' The binary server will be used instead. Please consider downloading and installing a recent Java runtime, or configuring vscode-xml to always use the binary server.', USE_BINARY, error.label) //
52 | .then(button => {
53 | if (button === error.label) {
54 | commands.executeCommand('vscode.open', error.openUrl);
55 | } else if (button === USE_BINARY) {
56 | workspace.getConfiguration('xml').update('server.preferBinary', true, ConfigurationTarget.Global);
57 | }
58 | });
59 | }
60 | requirementsData = {} as requirements.RequirementsData;
61 | }
62 |
63 | const storageUri = context.storageUri ?? context.globalStorageUri;
64 | const logfile = Uri.joinPath(storageUri, 'lemminx.log').fsPath;
65 | await fs.ensureDir(context.globalStorageUri.fsPath);
66 | await cleanUpHeapDumps(context);
67 |
68 | const externalXmlSettings: ExternalXmlSettings = new ExternalXmlSettings();
69 |
70 | const serverOptions: Executable = await prepareExecutable(
71 | requirementsData, collectXmlJavaExtensions(extensions.all, getXMLConfiguration().get("extension.jars", [])), context);
72 |
73 | languageClient = await startLanguageClient(context, serverOptions, logfile, externalXmlSettings, requirementsData);
74 |
75 | return getXmlExtensionApiImplementation(languageClient, logfile, externalXmlSettings, requirementsData);
76 | }
77 |
78 | export async function deactivate(): Promise {
79 | if (languageClient) {
80 | await languageClient.stop();
81 | languageClient = undefined;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/lsp-commands.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2022 Red Hat, Inc. and others.
3 |
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 |
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import { commands, ConfigurationTarget, Disposable, workspace, window } from 'vscode';
18 | import { getDirectoryPath, getRelativePath, getWorkspaceUri } from './utils/fileUtils';
19 | import * as CommandKind from './commands/lspCommandConstants';
20 |
21 | /**
22 | * Registers the `CommandKind.UPDATE_CONFIGURATION` command
23 | */
24 | export function registerConfigurationUpdateCommand(): Disposable {
25 | return commands.registerCommand(CommandKind.UPDATE_CONFIGURATION, resolveConfigurationItemEdit);
26 | }
27 |
28 | function resolveConfigurationItemEdit(configurationItemEdit: ConfigurationItemEdit) {
29 | if (configurationItemEdit.valueKind == ConfigurationItemValueKind.file) {
30 | configurationItemEdit.value = resolveFilePath(configurationItemEdit.value);
31 | }
32 | switch (configurationItemEdit.editType) {
33 | case ConfigurationItemEditType.Add:
34 | addToPreferenceArray(configurationItemEdit.section, configurationItemEdit.value);
35 | break;
36 | case ConfigurationItemEditType.Delete: {
37 | removeFromPreferenceArray(configurationItemEdit.section, configurationItemEdit.value);
38 | }
39 | }
40 | }
41 |
42 | function resolveFilePath(filePath: any): any {
43 | const currentWorkspaceUri = getWorkspaceUri(window.activeTextEditor.document).toString();
44 | return getDirectoryPath(filePath).includes(currentWorkspaceUri) ? getRelativePath(currentWorkspaceUri, filePath) : filePath;
45 |
46 | }
47 |
48 | function addToPreferenceArray(key: string, value: T): void {
49 | const configArray: T[] = workspace.getConfiguration().get(key, []);
50 | if (configArray.includes(value)) {
51 | return;
52 | }
53 | configArray.push(value);
54 | workspace.getConfiguration().update(key, configArray, ConfigurationTarget.Workspace);
55 | }
56 |
57 | function removeFromPreferenceArray(key: string, value: T): void {
58 | const configArray: T[] = workspace.getConfiguration().get(key, []);
59 | if (!configArray.includes(value)) {
60 | return;
61 | }
62 | const resultPref = configArray.filter(i => i != value);
63 | workspace.getConfiguration().update(key, resultPref, ConfigurationTarget.Workspace);
64 | }
65 |
66 | interface ConfigurationItemEdit {
67 | section: string;
68 | value: any;
69 | editType: ConfigurationItemEditType;
70 | valueKind: ConfigurationItemValueKind;
71 | }
72 |
73 | enum ConfigurationItemEditType {
74 | Add = 0,
75 | Delete = 1
76 | }
77 |
78 | enum ConfigurationItemValueKind {
79 | file = 0
80 | }
--------------------------------------------------------------------------------
/src/markdownPreviewProvider.ts:
--------------------------------------------------------------------------------
1 | import { Disposable, WebviewPanel, window, ViewColumn, commands, Uri, Webview, ExtensionContext, env } from "vscode";
2 | import * as fse from 'fs-extra';
3 | import * as path from 'path';
4 | import * as ClientCommandConstants from "./commands/clientCommandConstants";
5 |
6 | class MarkdownPreviewProvider implements Disposable {
7 | private panel: WebviewPanel | undefined;
8 | // a cache maps document path to rendered html
9 | private documentCache: Map = new Map();
10 | private disposables: Disposable[] = [];
11 |
12 | public async show(markdownFilePath: string, title: string, section: string, context: ExtensionContext): Promise {
13 | if (!this.panel) {
14 | this.panel = window.createWebviewPanel('xml.markdownPreview', title, ViewColumn.Active, {
15 | localResourceRoots: [
16 | Uri.file(path.join(context.extensionPath, 'webview-resources')),
17 | Uri.file(path.dirname(markdownFilePath)),
18 | ],
19 | retainContextWhenHidden: true,
20 | enableFindWidget: true,
21 | enableScripts: true,
22 | enableCommandUris: true
23 | });
24 | }
25 |
26 | this.disposables.push(this.panel.onDidDispose(() => {
27 | this.panel = undefined;
28 | }));
29 |
30 | this.panel.iconPath = Uri.file(path.join(context.extensionPath, 'icons', 'icon128.png'));
31 | this.panel.webview.html = await this.getHtmlContent(this.panel.webview, markdownFilePath, section, context);
32 | this.panel.title = title;
33 | this.panel.reveal(this.panel.viewColumn);
34 | }
35 |
36 | public dispose(): void {
37 | if (this.panel) {
38 | this.panel.dispose();
39 | }
40 | for (const disposable of this.disposables) {
41 | disposable.dispose();
42 | }
43 | }
44 |
45 | protected async getHtmlContent(webview: Webview, markdownFilePath: string, section: string, context: ExtensionContext): Promise {
46 | const nonce: string = this.getNonce();
47 | const styles: string = this.getStyles(webview, context);
48 | let body: string | undefined = this.documentCache.get(markdownFilePath);
49 | if (!body) {
50 | let markdownString: string = await fse.readFile(markdownFilePath, 'utf8');
51 | markdownString = markdownString.replace(/__VSCODE_ENV_APPNAME_PLACEHOLDER__/, env.appName);
52 | // HACK: This will not replace cross-page links if they don't have a section
53 | // i.e. [here](OtherPage#section) gets replaced, but [here](OtherPage) doesn't
54 | // Captures markdown links like this: [$1]($2#$3)
55 | // where $1, $2, $3 are non empty strings that are then passed to the replace function
56 | markdownString = markdownString.replace(/\[([^\]]+)\]\(([^#)]+)#([^)]*)\)/g,
57 | (_match: string, linkText: string, page: string, section: string) => {
58 | const linkedPageAbsPath = path.join(path.dirname(markdownFilePath), page);
59 | // __dirname resolves to the `dist` folder
60 | const linkedPageRelativePath = path.relative(path.join(__dirname, '..', 'docs'), linkedPageAbsPath);
61 | return `${linkText}`
62 | });
63 | body = await commands.executeCommand(ClientCommandConstants.MARKDOWN_API_RENDER, markdownString);
64 | this.documentCache.set(markdownFilePath, body);
65 | }
66 | return `
67 |
68 |
69 |
70 |
71 |
72 |
73 | ${styles}
74 |
75 |
76 |
77 | ${body}
78 |
83 |
95 |
96 |
97 | `;
98 | }
99 |
100 | protected getStyles(webview: Webview, context: ExtensionContext): string {
101 | const styles: Uri[] = [
102 | Uri.file(path.join(context.extensionPath, 'webview-resources', 'highlight.css')),
103 | Uri.file(path.join(context.extensionPath, 'webview-resources', 'markdown.css')),
104 | Uri.file(path.join(context.extensionPath, 'webview-resources', 'document.css')),
105 | ];
106 | return styles.map((styleUri: Uri) => ``).join('\n');
107 | }
108 |
109 | private getNonce(): string {
110 | let text = "";
111 | const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
112 | for (let i = 0; i < 32; i++) {
113 | text += possible.charAt(Math.floor(Math.random() * possible.length));
114 | }
115 | return text;
116 | }
117 | }
118 |
119 | export const markdownPreviewProvider: MarkdownPreviewProvider = new MarkdownPreviewProvider();
--------------------------------------------------------------------------------
/src/plugin.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import * as vscode from 'vscode';
4 | import * as path from 'path';
5 | import * as ClientCommandConstants from './commands/clientCommandConstants';
6 | import * as glob from 'glob';
7 |
8 | let existingExtensions: Array;
9 |
10 | export function collectXmlJavaExtensions(extensions: readonly vscode.Extension[], jars: string[]): string[] {
11 | const result = [];
12 | if (extensions && extensions.length) {
13 | for (const extension of extensions) {
14 | const contributesSection = extension.packageJSON['contributes'];
15 | if (contributesSection) {
16 | const xmlJavaExtensions = contributesSection['xml.javaExtensions'];
17 | if (Array.isArray(xmlJavaExtensions) && xmlJavaExtensions.length) {
18 | for (const xmLJavaExtensionPath of xmlJavaExtensions) {
19 | result.push(...glob.sync(path.resolve(extension.extensionPath, xmLJavaExtensionPath)));
20 | }
21 | }
22 | }
23 | }
24 | }
25 | for (const extension of jars) {
26 | result.push(...glob.sync(extension));
27 | }
28 | // Make a copy of extensions:
29 | existingExtensions = result.slice();
30 | return result;
31 | }
32 |
33 | export function onExtensionChange(extensions: readonly vscode.Extension[], jars: string[]) {
34 | if (!existingExtensions) {
35 | return;
36 | }
37 | const oldExtensions = new Set(existingExtensions.slice());
38 | const newExtensions = collectXmlJavaExtensions(extensions, jars);
39 | let hasChanged = ( oldExtensions.size !== newExtensions.length);
40 | if (!hasChanged) {
41 | for (const newExtension of newExtensions) {
42 | if (!oldExtensions.has(newExtension)) {
43 | hasChanged = true;
44 | break;
45 | }
46 | }
47 | }
48 |
49 | if (hasChanged) {
50 | const msg = `Extensions to the XML Language Server changed, reloading ${vscode.env.appName} is required for the changes to take effect.`;
51 | const action = 'Reload';
52 | const restartId = ClientCommandConstants.RELOAD_WINDOW;
53 | vscode.window.showWarningMessage(msg, action).then((selection) => {
54 | if (action === selection) {
55 | vscode.commands.executeCommand(restartId);
56 | }
57 | });
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/server/binary/binaryHashManager.ts:
--------------------------------------------------------------------------------
1 | import { ConfigurationTarget, workspace } from "vscode";
2 |
3 | const TRUSTED_HASHES_SETTING_ID = 'xml.server.binary.trustedHashes';
4 |
5 | /**
6 | * Returns the list of user trusted binary hashes
7 | *
8 | * @returns the list of user trusted binary hashes
9 | */
10 | export function getTrustedHashes(): string[] {
11 | const trustedHashesValue = workspace.getConfiguration().inspect(TRUSTED_HASHES_SETTING_ID).globalValue;
12 | if (!Array.isArray(trustedHashesValue)) {
13 | return [];
14 | }
15 | return trustedHashesValue as string[];
16 | }
17 |
18 |
19 | /**
20 | * Add a new hash to the list of trusted binary hashes
21 | *
22 | * @param hash The hash to add to the list of trusted binary hashes
23 | */
24 | export function addTrustedHash(hash: string): void {
25 | const trustedHashes = getTrustedHashes();
26 | trustedHashes.push(hash);
27 | workspace.getConfiguration().update(TRUSTED_HASHES_SETTING_ID, trustedHashes, ConfigurationTarget.Global);
28 | }
--------------------------------------------------------------------------------
/src/server/java/javaServerStarter.ts:
--------------------------------------------------------------------------------
1 | import * as os from 'os';
2 | import * as path from 'path';
3 | import { ExtensionContext, window, workspace } from 'vscode';
4 | import { Executable } from 'vscode-languageclient/node';
5 | import { getProxySettings, getProxySettingsAsJVMArgs, jvmArgsContainsProxySettings, ProxySettings } from '../../settings/proxySettings';
6 | import { getJavaagentFlag, getKey, getXMLConfiguration, IS_WORKSPACE_VMARGS_XML_ALLOWED, xmlServerVmargs } from '../../settings/settings';
7 | import { RequirementsData } from '../requirements';
8 | import { HEAP_DUMP_LOCATION, CRASH_ON_OOM, HEAP_DUMP } from './jvmArguments';
9 | import * as glob from 'glob';
10 |
11 | // eslint-disable-next-line no-var
12 | declare var v8debug;
13 |
14 | export const DEBUG = (typeof v8debug === 'object') || startedInDebugMode();
15 |
16 | export async function prepareJavaExecutable(
17 | context: ExtensionContext,
18 | requirements: RequirementsData,
19 | xmlJavaExtensions: string[]
20 | ): Promise {
21 |
22 | return {
23 | command: path.resolve(requirements.java_home + '/bin/java'),
24 | args: prepareParams(requirements, xmlJavaExtensions, context)
25 | } as Executable;
26 | }
27 |
28 | function prepareParams(requirements: RequirementsData, xmlJavaExtensions: string[], context: ExtensionContext): string[] {
29 | const params: string[] = [];
30 | if (DEBUG) {
31 | if (process.env['SUSPEND_SERVER'] === 'true') {
32 | params.push('-agentlib:jdwp=transport=dt_socket,server=y,address=1054');
33 | } else {
34 | params.push('-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1054,quiet=y');
35 | }
36 | }
37 | let vmargsCheck = workspace.getConfiguration().inspect(xmlServerVmargs).workspaceValue;
38 | if (vmargsCheck !== undefined) {
39 | const agentFlag = getJavaagentFlag(vmargsCheck);
40 | if (agentFlag !== null) {
41 | const keyVmargs = getKey(IS_WORKSPACE_VMARGS_XML_ALLOWED, context.storagePath, vmargsCheck);
42 | const key = context.globalState.get(keyVmargs);
43 | if (key !== true) {
44 | vmargsCheck = workspace.getConfiguration().inspect(xmlServerVmargs).globalValue;
45 | }
46 | }
47 | } else {
48 | vmargsCheck = getXMLConfiguration().get('server.vmargs');
49 | }
50 | let vmargs: string;
51 | if (vmargsCheck !== undefined) {
52 | vmargs = vmargsCheck + '';
53 | } else {
54 | vmargs = '';
55 | }
56 |
57 | const proxySettings: ProxySettings = getProxySettings();
58 | if (proxySettings && !jvmArgsContainsProxySettings(vmargs)) {
59 | vmargs += getProxySettingsAsJVMArgs(proxySettings);
60 | }
61 |
62 | if (os.platform() == 'win32') {
63 | const watchParentProcess = '-DwatchParentProcess=';
64 | if (vmargs.indexOf(watchParentProcess) < 0) {
65 | params.push(watchParentProcess + 'false');
66 | }
67 | }
68 | if (vmargs.indexOf(CRASH_ON_OOM) < 0) {
69 | params.push(CRASH_ON_OOM);
70 | }
71 | if (vmargs.indexOf(HEAP_DUMP) < 0) {
72 | params.push(HEAP_DUMP);
73 | }
74 | if (vmargs.indexOf(HEAP_DUMP_LOCATION) < 0) {
75 | params.push(`${HEAP_DUMP_LOCATION}${context.globalStorageUri.fsPath}`);
76 | } else {
77 | window.showWarningMessage('Heap dump location has been modified. '
78 | + 'vscode-xml won\'t delete the heap dumps. '
79 | + 'vscode-xml\'s Out Of Memory detection won\'t work properly, '
80 | + 'unless you manually delete the heap dumps after each Out Of Memory crash.');
81 | }
82 |
83 | // "OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify
84 | // were deprecated in JDK 13 and will likely be removed in a future release."
85 | // so only add -noverify for older versions
86 | if (params.indexOf('-noverify') < 0 && params.indexOf('-Xverify:none') < 0 && requirements.java_version < 13) {
87 | params.push('-noverify');
88 | }
89 | parseVMargs(params, vmargs);
90 | const server_home: string = path.resolve(__dirname, '../server');
91 | const launchersFound: Array = glob.sync('**/org.eclipse.lemminx*-uber.jar', { cwd: server_home });
92 | if (launchersFound.length) {
93 | let xmlJavaExtensionsClasspath = '';
94 | if (xmlJavaExtensions.length > 0) {
95 | const pathSeparator = os.platform() == 'win32' ? ';' : ':';
96 | xmlJavaExtensionsClasspath = pathSeparator + xmlJavaExtensions.join(pathSeparator);
97 | }
98 | params.push('-cp'); params.push(path.resolve(server_home, launchersFound[0]) + xmlJavaExtensionsClasspath);
99 | params.push('org.eclipse.lemminx.XMLServerLauncher');
100 | } else {
101 | return null;
102 | }
103 | return params;
104 | }
105 |
106 | function startedInDebugMode(): boolean {
107 | const args = (process as any).execArgv as string[];
108 | return hasDebugFlag(args);
109 | }
110 |
111 | function hasDebugFlag(args: string[]): boolean {
112 | if (args) {
113 | // See https://nodejs.org/en/docs/guides/debugging-getting-started/
114 | return args.some(arg => /^--inspect/.test(arg) || /^--debug/.test(arg));
115 | }
116 | return false;
117 | }
118 |
119 | //exported for tests
120 | export function parseVMargs(params: any[], vmargsLine: string) {
121 | if (!vmargsLine) {
122 | return;
123 | }
124 | const vmargs = vmargsLine.match(/(?:[^\s"]+|"[^"]*")+/g);
125 | if (vmargs === null) {
126 | return;
127 | }
128 | vmargs.forEach(arg => {
129 | //remove all standalone double quotes
130 | arg = arg.replace(/(\\)?"/g, function ($0, $1) { return ($1 ? $0 : ''); });
131 | //unescape all escaped double quotes
132 | arg = arg.replace(/(\\)"/g, '"');
133 | if (params.indexOf(arg) < 0) {
134 | params.push(arg);
135 | }
136 | });
137 | }
138 |
--------------------------------------------------------------------------------
/src/server/java/jvmArguments.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021 Red Hat, Inc. and others.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v2.0
5 | * which accompanies this distribution, and is available at
6 | * https://www.eclipse.org/legal/epl-v20.html
7 | *
8 | * Contributors:
9 | * Red Hat Inc. - initial API and implementation
10 | */
11 |
12 | /**
13 | * Argument that tells the program where to generate the heap dump that is created when an OutOfMemoryError is raised and `HEAP_DUMP` has been passed
14 | */
15 | export const HEAP_DUMP_LOCATION = '-XX:HeapDumpPath=';
16 |
17 | /**
18 | * Argument that tells the program to crash when an OutOfMemoryError is raised
19 | */
20 | export const CRASH_ON_OOM = '-XX:+ExitOnOutOfMemoryError';
21 |
22 | /**
23 | * Argument that tells the program to generate a heap dump file when an OutOfMemoryError is raised
24 | */
25 | export const HEAP_DUMP = '-XX:+HeapDumpOnOutOfMemoryError';
26 |
--------------------------------------------------------------------------------
/src/server/serverStarter.ts:
--------------------------------------------------------------------------------
1 | import { commands, ConfigurationTarget, ExtensionContext, window } from "vscode";
2 | import { Executable } from "vscode-languageclient/node";
3 | import { getXMLConfiguration } from "../settings/settings";
4 | import * as Telemetry from "../telemetry";
5 | import { ABORTED_ERROR, prepareBinaryExecutable } from "./binary/binaryServerStarter";
6 | import { prepareJavaExecutable } from "./java/javaServerStarter";
7 | import { getOpenJDKDownloadLink, RequirementsData } from "./requirements";
8 |
9 | /**
10 | * Returns the executable to use to launch LemMinX (the XML Language Server)
11 | *
12 | * @param requirements the java information, or an empty object if there is no java
13 | * @param xmlJavaExtensions a list of all the java extension jars
14 | * @param context the extensions context
15 | * @throws if neither the binary nor the java version of the extension can be launched
16 | * @returns the executable to launch LemMinX with (the XML language server)
17 | */
18 | export async function prepareExecutable(
19 | requirements: RequirementsData,
20 | xmlJavaExtensions: string[],
21 | context: ExtensionContext): Promise {
22 |
23 | const hasJava: boolean = requirements.java_home !== undefined;
24 | const hasExtensions: boolean = xmlJavaExtensions.length !== 0;
25 | const preferBinary: boolean = getXMLConfiguration().get("server.preferBinary", false);
26 | const silenceExtensionWarning: boolean = getXMLConfiguration().get("server.silenceExtensionWarning", false);
27 |
28 | const useBinary: boolean = (!hasJava) || (preferBinary && !hasExtensions);
29 |
30 | if (hasExtensions && !hasJava && !silenceExtensionWarning) {
31 | const DOWNLOAD_JAVA = 'Get Java';
32 | const CONFIGURE_JAVA = 'More Info';
33 | const DISABLE_WARNING = 'Disable Warning';
34 | window.showInformationMessage('Extensions to the XML language server were detected, but no Java was found. '
35 | + 'In order to use these extensions, please install and configure a Java runtime (Java 11 or more recent).',
36 | DOWNLOAD_JAVA, CONFIGURE_JAVA, DISABLE_WARNING)
37 | .then((selection: string) => {
38 | if (selection === DOWNLOAD_JAVA) {
39 | Telemetry.sendTelemetry(Telemetry.OPEN_JAVA_DOWNLOAD_LINK_EVT).then(() => {
40 | commands.executeCommand('vscode.open', getOpenJDKDownloadLink());
41 | });
42 | } else if (selection === CONFIGURE_JAVA) {
43 | commands.executeCommand('xml.open.docs', { page: 'Preferences.md', section: 'java-home' });
44 | } else if (selection === DISABLE_WARNING) {
45 | getXMLConfiguration().update('server.silenceExtensionWarning', true, ConfigurationTarget.Global);
46 | }
47 | });
48 | }
49 |
50 | if (useBinary) {
51 | return prepareBinaryExecutable(context)
52 | .catch((e) => {
53 | const javaServerMessage = hasJava ? 'Falling back to the Java server.' : 'Cannot start XML language server, since Java is missing.';
54 | if (e === ABORTED_ERROR) {
55 | window.showWarningMessage(`${e.message}. ${javaServerMessage}`);
56 | } else {
57 | window.showErrorMessage(`${e}. ${javaServerMessage}`);
58 | }
59 | if (!hasJava) {
60 | throw new Error("Failed to launch binary XML language server and no Java is installed");
61 | }
62 | return prepareJavaExecutable(context, requirements, xmlJavaExtensions);
63 | });
64 | }
65 | return prepareJavaExecutable(context, requirements, xmlJavaExtensions);
66 | }
67 |
--------------------------------------------------------------------------------
/src/settings/externalXmlSettings.ts:
--------------------------------------------------------------------------------
1 | import { XMLFileAssociation } from "../api/xmlExtensionApi";
2 |
3 | /**
4 | * Represents vscode-xml settings that other vscode extensions can contribute to
5 | */
6 | export class ExternalXmlSettings {
7 |
8 | private _xmlCatalogs: string[]
9 | private _xmlFileAssociations: XMLFileAssociation[]
10 |
11 | constructor() {
12 | this._xmlCatalogs = [];
13 | this._xmlFileAssociations = [];
14 | }
15 |
16 | get xmlCatalogs(): string[] {
17 | return this._xmlCatalogs;
18 | }
19 |
20 | get xmlFileAssociations(): any[] {
21 | return this._xmlFileAssociations;
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/src/settings/proxySettings.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021 Red Hat, Inc. and others.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v2.0
5 | * which accompanies this distribution, and is available at
6 | * https://www.eclipse.org/legal/epl-v20.html
7 | *
8 | * Contributors:
9 | * Red Hat Inc. - initial API and implementation
10 | */
11 | import { workspace } from 'vscode';
12 |
13 | /**
14 | * Represents the information needed to communicate through a proxy
15 | */
16 | export class ProxySettings {
17 |
18 | private _host: string;
19 | private _port: string;
20 | private _auth?: ProxyAuthorization;
21 |
22 | constructor(host: string, port: string, auth?: ProxyAuthorization) {
23 | this._host = host;
24 | this._port = port;
25 | this._auth = auth;
26 | }
27 |
28 | get host(): string {
29 | return this._host;
30 | }
31 |
32 | get port(): string {
33 | return this._port;
34 | }
35 |
36 | get auth(): ProxyAuthorization {
37 | return this._auth;
38 | }
39 |
40 | }
41 |
42 | /**
43 | * Represents the information needed to authenticate with the proxy
44 | */
45 | export class ProxyAuthorization {
46 |
47 | private _username: string;
48 | private _password: string;
49 |
50 | constructor(username: string, password: string) {
51 | this._username = username;
52 | this._password = password;
53 | }
54 |
55 | get username(): string {
56 | return this._username
57 | }
58 |
59 | get password(): string {
60 | return this._password;
61 | }
62 |
63 | }
64 |
65 |
66 | /**
67 | * Returns the proxy settings that are declared in the VS Code settings, or null if no proxy is configured
68 | *
69 | * @throws if the proxy settings aren't in the expected format
70 | * @returns the proxy settings that are declared in the VS Code settings, or null if no proxy is configured
71 | */
72 | export function getProxySettings(): ProxySettings {
73 | const proxyAddress = getProxyAddress();
74 | if (!proxyAddress) {
75 | return null;
76 | }
77 | const regexResult = HOST_AND_PORT_EXTRACTOR.exec(proxyAddress);
78 | if (!regexResult || !regexResult[1]) {
79 | return null;
80 | }
81 | const host: string = regexResult[1];
82 | const port: string = regexResult[2] ? regexResult[2] : "80";
83 |
84 | const proxyAuthorizationString = getProxyAuthorization();
85 | if (!proxyAuthorizationString) {
86 | return new ProxySettings(host, port);
87 | }
88 | if (proxyAuthorizationString.indexOf(' ') === -1) {
89 | throw new Error('A space is expected in the Authorization header between the authorization method and encoded username/password');
90 | }
91 |
92 | const encodedUserAndPass = proxyAuthorizationString.split(' ').pop();
93 | const decodedUserAndPass: string = Buffer.from(encodedUserAndPass, 'base64').toString('utf8');
94 | if (decodedUserAndPass.indexOf(':') === -1) {
95 | throw new Error('Authorization header is not in the expected format');
96 | }
97 | const [uriEncodedUsername, uriEncodedPassword] = decodedUserAndPass.split(':');
98 | const proxyAuthorization = new ProxyAuthorization(decodeURIComponent(uriEncodedUsername), decodeURIComponent(uriEncodedPassword));
99 | return new ProxySettings(host, port, proxyAuthorization);
100 | }
101 |
102 | /**
103 | * Returns the proxy settings as arguments for the JVM
104 | *
105 | * eg. -Dhttp.proxyHost= -Dhttp.proxyPort= -Dhttp.proxyUser= -Dhttp.proxyPassword=
106 | *
107 | * @param proxySettings the proxy settings to convert into JVM args
108 | */
109 | export function getProxySettingsAsJVMArgs(proxySettings: ProxySettings): string {
110 | // Java doesn't recognize localhost in the proxy settings
111 | const adaptedHostName = 'localhost'.startsWith(proxySettings.host) ? '127.0.0.1' : proxySettings.host;
112 | let proxyJVMArgs: string = ` -Dhttp.proxyHost=${adaptedHostName} -Dhttp.proxyPort=${proxySettings.port}`
113 | + ` -Dhttps.proxyHost=${adaptedHostName} -Dhttps.proxyPort=${proxySettings.port} `;
114 | if (proxySettings.auth) {
115 | proxyJVMArgs += ` -Dhttp.proxyUser=${proxySettings.auth.username} -Dhttp.proxyPassword=${proxySettings.auth.password}`
116 | + ` -Dhttps.proxyUser=${proxySettings.auth.username} -Dhttps.proxyPassword=${proxySettings.auth.password} `;
117 | }
118 | return proxyJVMArgs;
119 | }
120 |
121 | /**
122 | * Returns the proxy settings as environment variables for LemMinX
123 | *
124 | * @param proxySettings the proxy settings to convert into environment variables
125 | * @returns the proxy settings as environment variables for LemMinX
126 | */
127 | export function getProxySettingsAsEnvironmentVariables(proxySettings: ProxySettings): Record {
128 | // process.env inherits from Object, so it's okay to do so here as well
129 | const proxyEnv: Record = {};
130 |
131 | proxyEnv['HTTP_PROXY_HOST'] = proxySettings.host;
132 | proxyEnv['HTTP_PROXY_PORT'] = proxySettings.port;
133 |
134 | if (proxySettings.auth) {
135 | proxyEnv['HTTP_PROXY_USERNAME'] = proxySettings.auth.username;
136 | proxyEnv['HTTP_PROXY_PASSWORD'] = proxySettings.auth.password;
137 | }
138 |
139 | return proxyEnv;
140 | }
141 |
142 | /**
143 | * Checks if the given JVM arguments contain any proxy configuration
144 | *
145 | * @param jvmArgs the arguments being passed to the JVM
146 | */
147 | export function jvmArgsContainsProxySettings(jvmArgs: string): boolean {
148 | return (
149 | [JVM_PROXY_HOST, JVM_PROXY_PORT, JVM_PROXY_USER, JVM_PROXY_PASS] //
150 | .map(prop => jvmArgs.indexOf(`-D${prop}`) !== -1)
151 | .reduce((a, b, _index, _array) => a || b, false)
152 | );
153 | }
154 |
155 | const HOST_AND_PORT_EXTRACTOR = /(?:https?:\/\/)?([^:/]+)(?::([0-9]+))?/;
156 |
157 | const JVM_PROXY_HOST = 'http.proxyHost';
158 | const JVM_PROXY_PORT = 'http.proxyPort';
159 | const JVM_PROXY_USER = 'http.proxyUser';
160 | const JVM_PROXY_PASS = 'http.proxyPassword';
161 |
162 | /**
163 | * Returns the address of the proxy
164 | *
165 | * @returns the address of the proxy
166 | */
167 | function getProxyAddress(): string {
168 | const fromSettings = workspace.getConfiguration('http').get('proxy', undefined);
169 | if (fromSettings) {
170 | return fromSettings;
171 | }
172 | // VS Code allows you to set up the proxy using the environment variables http_proxy and https_proxy
173 | // Use this as fallback if the `"http.proxy"` setting isn't set
174 | return process.env['http_proxy'];
175 | }
176 |
177 | /**
178 | * Returns the Proxy-Authorization to use to access the proxy
179 | *
180 | * @returns The Proxy-Authorization to use to access the proxy
181 | */
182 | function getProxyAuthorization(): string {
183 | return workspace.getConfiguration('http').get('proxyAuthorization', undefined);
184 | }
--------------------------------------------------------------------------------
/src/settings/variableSubstitution.ts:
--------------------------------------------------------------------------------
1 | import * as path from "path";
2 | import { window } from "vscode";
3 | import { getFilePath, getWorkspaceUri } from "../utils/fileUtils";
4 | import { XMLFileAssociation } from "../api/xmlExtensionApi";
5 |
6 | /**
7 | * Represents a variable that refers to a value that can be resolved
8 | */
9 | class VariableSubstitution {
10 |
11 | private varName: string;
12 | private varKind: VariableSubstitutionKind;
13 | private getValue: (currentFileUri: string, currentWorkspaceUri: string) => string;
14 | private replaceRegExp: RegExp | undefined;
15 |
16 | /**
17 | *
18 | * @param name the name of this variable
19 | * @param kind the kind of this variable
20 | * @param getValue a function that resolves the value of the variable
21 | */
22 | constructor(name: string, kind: VariableSubstitutionKind, getValue: (currentFileUri: string, currentWorkspaceUri: string) => string) {
23 | this.varName = name;
24 | this.varKind = kind;
25 | this.getValue = getValue;
26 | }
27 |
28 | public get name(): string {
29 | return this.varName;
30 | }
31 |
32 | public get kind(): VariableSubstitutionKind {
33 | return this.varKind;
34 | }
35 |
36 | /**
37 | * Returns the string with the references to this variable replaced with the value, or the original string if the value cannot be resolved
38 | *
39 | * @param original the string to substitute variable value
40 | * @param currentFileUri the uri of the currently focused file, as a string
41 | * @param currentWorkspaceUri the uri of the root of the currently open workspace, as a string
42 | * @returns the string with the references to this variable replaced with the value, or the original string if the value cannot be resolved
43 | */
44 | public substituteString(original: string, currentFileUri: string, currentWorkspaceUri: string): string {
45 | const value: string = this.getValue(currentFileUri, currentWorkspaceUri);
46 | return value ? original.replace(this.getReplaceRegExp(), value) : original;
47 | }
48 |
49 | /**
50 | * Returns a regex that matches all references to the variable
51 | *
52 | * Lazily initialized
53 | *
54 | * @returns a regex that matches all references to the variable
55 | */
56 | public getReplaceRegExp(): RegExp {
57 | if (!this.replaceRegExp) {
58 | this.replaceRegExp = new RegExp('\\$\\{' + `${this.name}` + '\\}', 'g');
59 | }
60 | return this.replaceRegExp;
61 | }
62 | }
63 |
64 | enum VariableSubstitutionKind {
65 | Workspace,
66 | File
67 | }
68 |
69 | // A list of all variable substitutions. To add a new variable substitution, add an entry to this list
70 | const VARIABLE_SUBSTITUTIONS: VariableSubstitution[] = [
71 | new VariableSubstitution(
72 | "workspaceFolder",
73 | VariableSubstitutionKind.Workspace,
74 | (currentFileUri: string, currentWorkspaceUri: string): string => {
75 | return currentWorkspaceUri;
76 | }
77 | ),
78 | new VariableSubstitution(
79 | "fileDirname",
80 | VariableSubstitutionKind.File,
81 | (currentFileUri: string, _currentWorkspaceUri: string): string => {
82 | return path.dirname(currentFileUri);
83 | }
84 | ),
85 | new VariableSubstitution(
86 | "fileBasenameNoExtension",
87 | VariableSubstitutionKind.File,
88 | (currentFileUri: string, _currentWorkspaceUri: string): string => {
89 | return path.basename(currentFileUri, path.extname(currentFileUri));
90 | }
91 | )
92 | ];
93 |
94 | /**
95 | * Returns the file associations with as many variable references resolved as possible
96 | *
97 | * @param associations the file associations to resolve the variable references in
98 | * @returns the file associations with as many variable references resolved as possible
99 | */
100 | export function getVariableSubstitutedAssociations(associations: XMLFileAssociation[]): XMLFileAssociation[] {
101 |
102 | // Collect properties needed to resolve variables
103 | const currentFile = (window.activeTextEditor && window.activeTextEditor.document && window.activeTextEditor.document.languageId === 'xml') ? window.activeTextEditor.document : undefined;
104 | const currentFileUri = getFilePath(currentFile);
105 | const currentWorkspaceUri = getWorkspaceUri(currentFile);
106 |
107 | // Remove variables that can't be resolved
108 | let variablesToSubstitute = VARIABLE_SUBSTITUTIONS;
109 | if (!currentWorkspaceUri) {
110 | variablesToSubstitute = variablesToSubstitute.filter(variable => { return variable.kind !== VariableSubstitutionKind.Workspace });
111 | }
112 | if (!currentFileUri) {
113 | variablesToSubstitute = variablesToSubstitute.filter(variable => { return variable.kind !== VariableSubstitutionKind.File });
114 | }
115 |
116 | /**
117 | * Returns the string with the values for all the variables that can be resolved substituted in the string
118 | *
119 | * @param val the value to substitute the variables into
120 | * @return the string with the values for all the variables that can be resolved substituted in the string
121 | */
122 | const subVars = (val: string): string => {
123 | let newVal = val;
124 | for (const settingVariable of variablesToSubstitute) {
125 | newVal = settingVariable.substituteString(newVal, currentFileUri, currentWorkspaceUri?.toString());
126 | }
127 | return newVal;
128 | }
129 |
130 | return associations.map((association: XMLFileAssociation) => {
131 | return {
132 | pattern: subVars(association.pattern),
133 | systemId: subVars(association.systemId)
134 | };
135 | });
136 | }
137 |
138 | /**
139 | * Returns true if any of the file associations contain references to variables that refer to current file, and false otherwise
140 | *
141 | * @param associations A list of file associations to check
142 | * @returns true if any of the file associations contain references to variables that refer to current file, and false otherwise
143 | */
144 | export function containsVariableReferenceToCurrentFile(associations: XMLFileAssociation[]): boolean {
145 | const fileVariables: VariableSubstitution[] = VARIABLE_SUBSTITUTIONS.filter(variable => variable.kind === VariableSubstitutionKind.File);
146 | for (const association of associations) {
147 | for (const variable of fileVariables) {
148 | if (variable.getReplaceRegExp().test(association.pattern) || variable.getReplaceRegExp().test(association.systemId)) {
149 | return true;
150 | }
151 | }
152 | }
153 | return false;
154 | }
155 |
--------------------------------------------------------------------------------
/src/telemetry.ts:
--------------------------------------------------------------------------------
1 | import { getRedHatService, TelemetryService } from "@redhat-developer/vscode-redhat-telemetry";
2 | import { ExtensionContext } from "vscode";
3 | import { getXMLConfiguration } from "./settings/settings";
4 |
5 | /**
6 | * Wrap vscode-redhat-telemetry to suit vscode-xml
7 | */
8 |
9 | export const OPEN_JAVA_DOWNLOAD_LINK_EVT = "xml.open.java.download.link";
10 | export const OPEN_PROXY_CONFIG_DOCS_EVT = "xml.open.proxy.config.docs.link";
11 | export const OPEN_OOM_DOCS_EVT = "xml.open.oom.docs.link";
12 | export const SETTINGS_EVT = "xml.settings";
13 | export const BINARY_DOWNLOAD_EVT = "xml.binary.download";
14 | export const JAVA_OOM_EVT = "xml.java.oom";
15 | export const STARTUP_EVT = "startup";
16 | export const SERVER_INITIALIZED_EVT = "server.initialized";
17 |
18 | export const BINARY_DOWNLOAD_STATUS_PROP = "status";
19 |
20 | export const BINARY_DOWNLOAD_SUCCEEDED = "succeeded";
21 | export const BINARY_DOWNLOAD_FAILED = "failed";
22 | export const BINARY_DOWNLOAD_ABORTED = "aborted";
23 |
24 | let _telemetryManager: TelemetryService = null;
25 | let serverInitializedReceived = false;
26 |
27 | /**
28 | * Starts the telemetry service
29 | *
30 | * @returns when the telemetry service has been started
31 | * @throws Error if the telemetry service has already been started
32 | */
33 | export async function startTelemetry(context: ExtensionContext): Promise {
34 | if (_telemetryManager) {
35 | throw new Error("The telemetry service for vscode-xml has already been started")
36 | }
37 | const redhatService = await getRedHatService(context);
38 | _telemetryManager = await redhatService.getTelemetryService();
39 | setTimeout(sendEmptyStartUp, 15000);
40 | return;
41 | }
42 |
43 | function sendEmptyStartUp() {
44 | if (!serverInitializedReceived) {
45 | return sendTelemetry(STARTUP_EVT, {
46 | "xml.settings.preferBinary": (getXMLConfiguration()['server']['preferBinary'] as boolean)
47 | });
48 | }
49 | }
50 |
51 | /**
52 | * Send a telemetry event with the given name and data
53 | *
54 | * @param eventName the name of the telemetry event
55 | * @param data the telemetry data
56 | * @throws Error if the telemetry service has not been started yet
57 | */
58 | export async function sendTelemetry(eventName: string, data?: any): Promise {
59 | if (!_telemetryManager) {
60 | throw new Error("The telemetry service for vscode-xml has not been started yet");
61 | }
62 | if (eventName === STARTUP_EVT) {
63 | serverInitializedReceived = true;
64 | }
65 | return _telemetryManager.send({
66 | name: eventName,
67 | properties: data
68 | });
69 | }
70 |
--------------------------------------------------------------------------------
/src/test/smoke.test.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2025 Red Hat, Inc. and others.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v2.0
5 | * which accompanies this distribution, and is available at
6 | * https://www.eclipse.org/legal/epl-v20.html
7 | *
8 | * Contributors:
9 | * Red Hat Inc. - initial API and implementation
10 | */
11 | import * as assert from 'assert';
12 | import * as vscode from 'vscode';
13 | import * as fs from 'fs/promises';
14 | import { tmpdir } from 'os';
15 | import * as path from 'path';
16 |
17 | suite('Smoke tests', function () {
18 |
19 | this.timeout(10_000);
20 |
21 | // diagnostics take some time to appear; the language server must be started and respond to file open event
22 | const DIAGNOSTICS_DELAY = 4_000;
23 |
24 | const SCHEMA = `
25 |
27 |
28 |
29 |
30 |
31 | Size Type documentation
32 |
33 |
34 |
35 |
36 |
37 | Small documentation
38 |
39 |
40 |
41 |
42 | Medium documentation
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | `;
72 |
73 | const SCHEMA_INSTANCE = `
74 |
75 | purple
76 | `;
77 |
78 | const SCHEMA_FILENAME = "dressSize.xsd";
79 | const SCHEMA_INSTANCE_NAME = "references-schema.xml";
80 |
81 | let tempDir: string;
82 | let schemaPath: string;
83 | let schemaInstancePath: string;
84 |
85 | this.beforeAll(async function () {
86 | tempDir = tmpdir();
87 | schemaPath = path.join(tempDir, SCHEMA_FILENAME);
88 | schemaInstancePath = path.join(tempDir, SCHEMA_INSTANCE_NAME);
89 | await fs.appendFile(schemaPath, SCHEMA);
90 | await fs.appendFile(schemaInstancePath, SCHEMA_INSTANCE);
91 | });
92 |
93 | this.afterAll(async function () {
94 | await fs.rm(schemaPath);
95 | await fs.rm(schemaInstancePath);
96 | });
97 |
98 | test("instance has right diagnostics", async function () {
99 | const textDocument = await vscode.workspace.openTextDocument(schemaInstancePath);
100 | await vscode.window.showTextDocument(textDocument);
101 | await new Promise(resolve => setTimeout(resolve, DIAGNOSTICS_DELAY));
102 | const diagnostics = vscode.languages.getDiagnostics(vscode.Uri.file(schemaInstancePath));
103 |
104 | assert.strictEqual(diagnostics.length, 2);
105 | assert.strictEqual(diagnostics[0].message, "cvc-datatype-valid.1.2.3: 'purple' is not a valid value of union type 'SizeType'.", );
106 | assert.strictEqual(diagnostics[1].message, "cvc-type.3.1.3: The value 'purple' of element 'dresssize' is not valid.");
107 | });
108 | });
109 |
--------------------------------------------------------------------------------
/src/utils/fileUtils.ts:
--------------------------------------------------------------------------------
1 | import * as path from "path";
2 | import { TextDocument, Uri, workspace, WorkspaceFolder } from "vscode";
3 |
4 | /**
5 | * Return the current workspace uri from root
6 | *
7 | * @param document the opened TextDocument
8 | * @returns the path from root of the current workspace
9 | */
10 | export function getWorkspaceUri(document: TextDocument): Uri | undefined {
11 | const currentWorkspace: WorkspaceFolder = (document && document.uri) ? workspace.getWorkspaceFolder(document.uri) : undefined;
12 | return ((currentWorkspace && currentWorkspace.uri) || (workspace.workspaceFolders && workspace.workspaceFolders.length > 0 && workspace.workspaceFolders[0].uri));
13 | }
14 |
15 | /**
16 | * Return the uri of the current file
17 | *
18 | * @param document the opened TextDocument
19 | * @returns the uri of the current file
20 | */
21 | export function getFilePath(document: TextDocument): string {
22 | return (document && document.uri) ? document.uri.fsPath : undefined;
23 | }
24 |
25 | /**
26 | * Uses path to return a basename from a uri
27 | *
28 | * @param filePath the uri of the file
29 | * @return the filename
30 | */
31 | export function getFileName(filePath: string): string {
32 | return path.basename(filePath);
33 | }
34 |
35 | /**
36 | * Return the relative file path between a start and destination uri
37 | *
38 | * @param startPath the absolute path of the beginning directory
39 | * @param destinationPath the absolute path of destination file
40 | * @returns the path to the destination relative to the start
41 | */
42 | export function getRelativePath(startPath: string, destinationPath: string): string {
43 | return path.relative(path.normalize(startPath), path.normalize(destinationPath)).replace(/\\/g, '/');
44 | }
45 |
46 | /**
47 | * Uses path to return the directory name from a uri
48 | *
49 | * @param filePath the uri of the file
50 | * @return the directory path
51 | */
52 | export function getDirectoryPath(filePath: string): string {
53 | return path.dirname(filePath);
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/syntaxes/dtd.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "DTD",
3 | "scopeName": "text.xml.dtd",
4 | "fileTypes": [
5 | "dtd"
6 | ],
7 | "patterns": [
8 | {
9 | "begin": "()",
19 | "name": "meta.tag.type.dtd",
20 | "patterns": [
21 | {
22 | "match": "\\s+(CDATA|IDREFS|IDREF|ID|NMTOKENS|NMTOKEN|ENTITY|ENTITIES|NOTATION|SYSTEM|NDATA)",
23 | "name": "keyword.other.data-type.dtd"
24 | },
25 | {
26 | "match": "(#[A-Z]+)|(ANY)|(EMPTY)",
27 | "name": "constant.language.dtd"
28 | },
29 | {
30 | "begin": "'|\"",
31 | "end": "'|\"",
32 | "name": "string.quoted.double.dtd"
33 | },
34 | {
35 | "begin": "(%[a-zA-Z][a-zA-Z0-9_-])",
36 | "end": ";",
37 | "name": "variable.language.dtd"
38 | }
39 | ]
40 | },
41 | {
42 | "begin": "()",
44 | "name": "comment.block.dtd"
45 | }
46 | ]
47 | }
--------------------------------------------------------------------------------
/syntaxes/rnc.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "fileTypes": ["rnc"],
3 | "foldingStartMarker": "\\{\\s*$",
4 | "foldingStopMarker": "^\\s*\\}",
5 | "name": "RelaxNG Compact",
6 | "patterns": [
7 | {
8 | "match": "\\bgrammar\\b",
9 | "name": "keyword.other.grammar.rnc"
10 | },
11 | {
12 | "match": "\\bstart\\b",
13 | "name": "keyword.other.start.rnc"
14 | },
15 | {
16 | "match": "\\b(text|empty|xsd\\:(int|integer|double|date(Time)?|time|string|decimal))\\b",
17 | "name": "storage.type.rnc"
18 | },
19 | {
20 | "captures":
21 | {
22 | "1":
23 | {
24 | "name": "keyword.other.attribute.rnc"
25 | },
26 | "2":
27 | {
28 | "name": "entity.other.attribute.rnc"
29 | }
30 | },
31 | "match": "\\b(attribute)\\s+([a-zA-Z][-a-zA-Z_0-9]*)\\s*\\{",
32 | "name": "meta.declaration.attribute.rnc"
33 | },
34 | {
35 | "captures":
36 | {
37 | "1":
38 | {
39 | "name": "keyword.other.element.rnc"
40 | },
41 | "2":
42 | {
43 | "name": "entity.other.element.rnc"
44 | }
45 | },
46 | "match": "\\b(element)\\s+([a-zA-Z][-a-zA-Z_0-9]*)\\s*\\{",
47 | "name": "meta.declaration.element.rnc"
48 | },
49 | {
50 | "match": "#.*$",
51 | "name": "comment.hash.rnc"
52 | },
53 | {
54 | "begin": "\"",
55 | "end": "\"",
56 | "name": "string.quoted.double.rnc",
57 | "patterns": [
58 | {
59 | "match": "\\\\.",
60 | "name": "constant.character.escape.rnc"
61 | }]
62 | },
63 | {
64 | "begin": "'",
65 | "end": "'",
66 | "name": "string.quoted.single.rnc",
67 | "patterns": [
68 | {
69 | "match": "\\\\.",
70 | "name": "constant.character.escape.rnc"
71 | }]
72 | },
73 | {
74 | "captures":
75 | {
76 | "1":
77 | {
78 | "name": "entity.other.grammar_production.rnc"
79 | }
80 | },
81 | "match": "\\b([a-zA-Z][a-zA-Z_0-9]*)\\s*=",
82 | "name": "meta.grammar_production.rnc"
83 | }],
84 | "scopeName": "source.rnc",
85 | "uuid": "85F32571-780F-4AAC-BA70-C2229E0B1BDA"
86 | }
--------------------------------------------------------------------------------
/test-workspace/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "xml.server.preferBinary": true
3 | }
4 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es6",
5 | "outDir": "out",
6 | "alwaysStrict": true,
7 | "lib": [
8 | "dom",
9 | "es2019"
10 | ],
11 | "sourceMap": true,
12 | "rootDir": ".",
13 | "plugins": [
14 | {
15 | "name": "eslint"
16 | }
17 | ]
18 | },
19 | "exclude": [
20 | "node_modules",
21 | ".vscode-test"
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | //@ts-check
5 |
6 | 'use strict';
7 |
8 | const path = require('path');
9 | const ESLintPlugin = require('eslint-webpack-plugin');
10 |
11 | /**@type {import('webpack').Configuration}*/
12 | const config = {
13 | target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
14 | node: {
15 | __dirname: false,
16 | __filename: false
17 | },
18 | entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
19 | output: {
20 | // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
21 | path: path.resolve(__dirname, 'dist'),
22 | filename: 'extension.js',
23 | libraryTarget: 'commonjs2',
24 | devtoolModuleFilenameTemplate: '../[resource-path]'
25 | },
26 | devtool: 'source-map',
27 | externals: {
28 | vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
29 | },
30 | resolve: {
31 | // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
32 | extensions: ['.ts', '.js']
33 | },
34 | module: {
35 | rules: [
36 | {
37 | test: /\.ts$/,
38 | exclude: /node_modules/,
39 | use: [
40 | {
41 | loader: 'ts-loader'
42 | }
43 | ]
44 | }
45 | ]
46 | },
47 | infrastructureLogging: {
48 | level: 'log'
49 | },
50 | plugins: [
51 | new ESLintPlugin({
52 | configType: "flat",
53 | extensions: [
54 | ".ts",
55 | ".js"
56 | ]
57 | }),
58 | ]
59 | };
60 | module.exports = config;
61 |
--------------------------------------------------------------------------------
/webview-resources/document.css:
--------------------------------------------------------------------------------
1 | .btn {
2 | border: 0;
3 | color: var(--vscode-button-foreground);
4 | background-color: var(--vscode-button-background);
5 | }
6 |
7 | .btn svg {
8 | fill: var(--vscode-button-foreground);
9 | }
10 |
11 | .btn:hover {
12 | background-color: var(--vscode-button-hoverBackground);
13 | }
14 |
15 | .floating-bottom-right {
16 | position: fixed;
17 | bottom: 1rem;
18 | right: 1rem;
19 | }
--------------------------------------------------------------------------------
/webview-resources/highlight.css:
--------------------------------------------------------------------------------
1 | /*
2 | https://raw.githubusercontent.com/isagalaev/highlight.js/master/src/styles/vs2015.css
3 | */
4 | /*
5 | * Visual Studio 2015 dark style
6 | * Author: Nicolas LLOBERA
7 | */
8 |
9 |
10 | .hljs-keyword,
11 | .hljs-literal,
12 | .hljs-symbol,
13 | .hljs-name {
14 | color: #569CD6;
15 | }
16 | .hljs-link {
17 | color: #569CD6;
18 | text-decoration: underline;
19 | }
20 |
21 | .hljs-built_in,
22 | .hljs-type {
23 | color: #4EC9B0;
24 | }
25 |
26 | .hljs-number,
27 | .hljs-class {
28 | color: #B8D7A3;
29 | }
30 |
31 | .hljs-string,
32 | .hljs-meta-string {
33 | color: #D69D85;
34 | }
35 |
36 | .hljs-regexp,
37 | .hljs-template-tag {
38 | color: #9A5334;
39 | }
40 |
41 | .hljs-subst,
42 | .hljs-function,
43 | .hljs-title,
44 | .hljs-params,
45 | .hljs-formula {
46 | color: #DCDCDC;
47 | }
48 |
49 | .hljs-comment,
50 | .hljs-quote {
51 | color: #57A64A;
52 | font-style: italic;
53 | }
54 |
55 | .hljs-doctag {
56 | color: #608B4E;
57 | }
58 |
59 | .hljs-meta,
60 | .hljs-meta-keyword,
61 | .hljs-tag {
62 | color: #9B9B9B;
63 | }
64 |
65 | .hljs-variable,
66 | .hljs-template-variable {
67 | color: #BD63C5;
68 | }
69 |
70 | .hljs-attr,
71 | .hljs-attribute,
72 | .hljs-builtin-name {
73 | color: #9CDCFE;
74 | }
75 |
76 | .hljs-section {
77 | color: gold;
78 | }
79 |
80 | .hljs-emphasis {
81 | font-style: italic;
82 | }
83 |
84 | .hljs-strong {
85 | font-weight: bold;
86 | }
87 |
88 | /*.hljs-code {
89 | font-family:'Monospace';
90 | }*/
91 |
92 | .hljs-bullet,
93 | .hljs-selector-tag,
94 | .hljs-selector-id,
95 | .hljs-selector-class,
96 | .hljs-selector-attr,
97 | .hljs-selector-pseudo {
98 | color: #D7BA7D;
99 | }
100 |
101 | .hljs-addition {
102 | background-color: var(--vscode-diffEditor-insertedTextBackground, rgba(155, 185, 85, 0.2));
103 | color: rgb(155, 185, 85);
104 | display: inline-block;
105 | width: 100%;
106 | }
107 |
108 | .hljs-deletion {
109 | background: var(--vscode-diffEditor-removedTextBackground, rgba(255, 0, 0, 0.2));
110 | color: rgb(255, 0, 0);
111 | display: inline-block;
112 | width: 100%;
113 | }
114 |
115 |
116 | /*
117 | From https://raw.githubusercontent.com/isagalaev/highlight.js/master/src/styles/vs.css
118 | */
119 | /*
120 |
121 | Visual Studio-like style based on original C# coloring by Jason Diamond
122 |
123 | */
124 |
125 | .vscode-light .hljs-function,
126 | .vscode-light .hljs-params,
127 | .vscode-light .hljs-number,
128 | .vscode-light .hljs-class {
129 | color: inherit;
130 | }
131 |
132 | .vscode-light .hljs-comment,
133 | .vscode-light .hljs-quote,
134 | .vscode-light .hljs-number,
135 | .vscode-light .hljs-class,
136 | .vscode-light .hljs-variable {
137 | color: #008000;
138 | }
139 |
140 | .vscode-light .hljs-keyword,
141 | .vscode-light .hljs-selector-tag,
142 | .vscode-light .hljs-name,
143 | .vscode-light .hljs-tag {
144 | color: #00f;
145 | }
146 |
147 | .vscode-light .hljs-built_in,
148 | .vscode-light .hljs-builtin-name {
149 | color: #007acc;
150 | }
151 |
152 | .vscode-light .hljs-string,
153 | .vscode-light .hljs-section,
154 | .vscode-light .hljs-attribute,
155 | .vscode-light .hljs-literal,
156 | .vscode-light .hljs-template-tag,
157 | .vscode-light .hljs-template-variable,
158 | .vscode-light .hljs-type {
159 | color: #a31515;
160 | }
161 |
162 | .vscode-light .hljs-selector-attr,
163 | .vscode-light .hljs-selector-pseudo,
164 | .vscode-light .hljs-meta,
165 | .vscode-light .hljs-meta-keyword {
166 | color: #2b91af;
167 | }
168 |
169 | .vscode-light .hljs-title,
170 | .vscode-light .hljs-doctag {
171 | color: #808080;
172 | }
173 |
174 | .vscode-light .hljs-attr {
175 | color: #f00;
176 | }
177 |
178 | .vscode-light .hljs-symbol,
179 | .vscode-light .hljs-bullet,
180 | .vscode-light .hljs-link {
181 | color: #00b0e8;
182 | }
183 |
184 |
185 | .vscode-light .hljs-emphasis {
186 | font-style: italic;
187 | }
188 |
189 | .vscode-light .hljs-strong {
190 | font-weight: bold;
191 | }
--------------------------------------------------------------------------------
/webview-resources/markdown.css:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Copyright (c) Microsoft Corporation. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | *--------------------------------------------------------------------------------------------*/
5 | /*https://raw.githubusercontent.com/microsoft/vscode/master/extensions/markdown-language-features/media/markdown.css*/
6 |
7 | html, body {
8 | font-family: var(--vscode-markdown-font-family, -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif);
9 | font-size: var(--vscode-markdown-font-size, 14px);
10 | padding: 0 26px;
11 | line-height: var(--vscode-markdown-line-height, 22px);
12 | word-wrap: break-word;
13 | }
14 |
15 | #code-csp-warning {
16 | position: fixed;
17 | top: 0;
18 | right: 0;
19 | color: white;
20 | margin: 16px;
21 | text-align: center;
22 | font-size: 12px;
23 | font-family: sans-serif;
24 | background-color:#444444;
25 | cursor: pointer;
26 | padding: 6px;
27 | box-shadow: 1px 1px 1px rgba(0,0,0,.25);
28 | }
29 |
30 | #code-csp-warning:hover {
31 | text-decoration: none;
32 | background-color:#007acc;
33 | box-shadow: 2px 2px 2px rgba(0,0,0,.25);
34 | }
35 |
36 | body.scrollBeyondLastLine {
37 | margin-bottom: calc(100vh - 22px);
38 | }
39 |
40 | body.showEditorSelection .code-line {
41 | position: relative;
42 | }
43 |
44 | body.showEditorSelection .code-active-line:before,
45 | body.showEditorSelection .code-line:hover:before {
46 | content: "";
47 | display: block;
48 | position: absolute;
49 | top: 0;
50 | left: -12px;
51 | height: 100%;
52 | }
53 |
54 | body.showEditorSelection li.code-active-line:before,
55 | body.showEditorSelection li.code-line:hover:before {
56 | left: -30px;
57 | }
58 |
59 | .vscode-light.showEditorSelection .code-active-line:before {
60 | border-left: 3px solid rgba(0, 0, 0, 0.15);
61 | }
62 |
63 | .vscode-light.showEditorSelection .code-line:hover:before {
64 | border-left: 3px solid rgba(0, 0, 0, 0.40);
65 | }
66 |
67 | .vscode-light.showEditorSelection .code-line .code-line:hover:before {
68 | border-left: none;
69 | }
70 |
71 | .vscode-dark.showEditorSelection .code-active-line:before {
72 | border-left: 3px solid rgba(255, 255, 255, 0.4);
73 | }
74 |
75 | .vscode-dark.showEditorSelection .code-line:hover:before {
76 | border-left: 3px solid rgba(255, 255, 255, 0.60);
77 | }
78 |
79 | .vscode-dark.showEditorSelection .code-line .code-line:hover:before {
80 | border-left: none;
81 | }
82 |
83 | .vscode-high-contrast.showEditorSelection .code-active-line:before {
84 | border-left: 3px solid rgba(255, 160, 0, 0.7);
85 | }
86 |
87 | .vscode-high-contrast.showEditorSelection .code-line:hover:before {
88 | border-left: 3px solid rgba(255, 160, 0, 1);
89 | }
90 |
91 | .vscode-high-contrast.showEditorSelection .code-line .code-line:hover:before {
92 | border-left: none;
93 | }
94 |
95 | img {
96 | max-width: 100%;
97 | max-height: 100%;
98 | }
99 |
100 | a {
101 | text-decoration: none;
102 | }
103 |
104 | a:hover {
105 | text-decoration: underline;
106 | }
107 |
108 | a:focus,
109 | input:focus,
110 | select:focus,
111 | textarea:focus {
112 | outline: 1px solid -webkit-focus-ring-color;
113 | outline-offset: -1px;
114 | }
115 |
116 | hr {
117 | border: 0;
118 | height: 2px;
119 | border-bottom: 2px solid;
120 | }
121 |
122 | h1 {
123 | padding-bottom: 0.3em;
124 | line-height: 1.2;
125 | border-bottom-width: 1px;
126 | border-bottom-style: solid;
127 | }
128 |
129 | h1, h2, h3 {
130 | font-weight: normal;
131 | }
132 |
133 | table {
134 | border-collapse: collapse;
135 | }
136 |
137 | table > thead > tr > th {
138 | text-align: left;
139 | border-bottom: 1px solid;
140 | }
141 |
142 | table > thead > tr > th,
143 | table > thead > tr > td,
144 | table > tbody > tr > th,
145 | table > tbody > tr > td {
146 | padding: 5px 10px;
147 | }
148 |
149 | table > tbody > tr + tr > td {
150 | border-top: 1px solid;
151 | }
152 |
153 | blockquote {
154 | margin: 0 7px 0 5px;
155 | padding: 0 16px 0 10px;
156 | border-left-width: 5px;
157 | border-left-style: solid;
158 | }
159 |
160 | code {
161 | font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
162 | font-size: 1em;
163 | line-height: 1.357em;
164 | }
165 |
166 | body.wordWrap pre {
167 | white-space: pre-wrap;
168 | }
169 |
170 | pre:not(.hljs),
171 | pre.hljs code > div {
172 | padding: 16px;
173 | border-radius: 3px;
174 | overflow: auto;
175 | }
176 |
177 | pre code {
178 | color: var(--vscode-editor-foreground);
179 | tab-size: 4;
180 | }
181 |
182 | /** Theming */
183 |
184 | .vscode-light pre {
185 | background-color: rgba(220, 220, 220, 0.4);
186 | }
187 |
188 | .vscode-dark pre {
189 | background-color: rgba(10, 10, 10, 0.4);
190 | }
191 |
192 | .vscode-high-contrast pre {
193 | background-color: rgb(0, 0, 0);
194 | }
195 |
196 | .vscode-high-contrast h1 {
197 | border-color: rgb(0, 0, 0);
198 | }
199 |
200 | .vscode-light table > thead > tr > th {
201 | border-color: rgba(0, 0, 0, 0.69);
202 | }
203 |
204 | .vscode-dark table > thead > tr > th {
205 | border-color: rgba(255, 255, 255, 0.69);
206 | }
207 |
208 | .vscode-light h1,
209 | .vscode-light hr,
210 | .vscode-light table > tbody > tr + tr > td {
211 | border-color: rgba(0, 0, 0, 0.18);
212 | }
213 |
214 | .vscode-dark h1,
215 | .vscode-dark hr,
216 | .vscode-dark table > tbody > tr + tr > td {
217 | border-color: rgba(255, 255, 255, 0.18);
218 | }
--------------------------------------------------------------------------------