Out With the Old
BIN
.github/wiki-resources/xml-attribute.png
vendored
|
Before Width: | Height: | Size: 643 B |
BIN
.github/wiki-resources/xml-tag.png
vendored
|
Before Width: | Height: | Size: 456 B |
BIN
.github/wiki-resources/xml-text.png
vendored
|
Before Width: | Height: | Size: 143 B |
3
.gitignore
vendored
|
|
@ -1,3 +0,0 @@
|
|||
node_modules
|
||||
src/**/*.js
|
||||
**/*.vsix
|
||||
10
.travis.yml
|
|
@ -1,10 +0,0 @@
|
|||
notifications:
|
||||
email: false
|
||||
|
||||
sudo: false
|
||||
|
||||
install:
|
||||
- npm install
|
||||
|
||||
script:
|
||||
- gulp build
|
||||
15
.vscode/launch.json
vendored
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch Extension",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceRoot}"
|
||||
],
|
||||
"preLaunchTask": "build"
|
||||
}
|
||||
]
|
||||
}
|
||||
11
.vscode/settings.json
vendored
|
|
@ -1,11 +0,0 @@
|
|||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"files.exclude": {
|
||||
"**/.git": true,
|
||||
"**/.DS_Store": true,
|
||||
"**/*.vsix": true,
|
||||
"**/*.js": {"when": "$(basename).ts"}
|
||||
}
|
||||
,
|
||||
"typescript.tsdk": "./node_modules/typescript/lib"
|
||||
}
|
||||
21
.vscode/tasks.json
vendored
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"version": "0.1.0",
|
||||
"command": "gulp",
|
||||
"isShellCommand": true,
|
||||
"args": [
|
||||
"--no-color"
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"taskName": "build",
|
||||
"args": [],
|
||||
"isBuildCommand": true,
|
||||
"isWatching": false,
|
||||
"problemMatcher": [
|
||||
"$lessCompile",
|
||||
"$tsc",
|
||||
"$jshint"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
tsconfig.json
|
||||
CONTRIBUTING.md
|
||||
.gitignore
|
||||
.vscode
|
||||
resources/wiki-images
|
||||
typings
|
||||
**/*.ts
|
||||
**/*.vsix
|
||||
|
|
@ -1 +0,0 @@
|
|||
Detailed release notes are available [here](https://github.com/DotJoshJohnson/vscode-xml/releases).
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
# Contribution Guide
|
||||
Thanks for helping out! This guide provides some guidelines on coding styles and architecture for this extension.
|
||||
Keep in mind that these are guidelines, not rules. Use your best judgement and feel free to make suggestions!
|
||||
|
||||
## Workflow
|
||||
Please use the follow general workflow when making contributions to the code:
|
||||
|
||||
1. Fork the repository.
|
||||
2. Create a feature branch and make your changes.
|
||||
3. Create a pull request to request that your commits be merged to `master`.
|
||||
|
||||
|
||||
## Building the Extension
|
||||
1. Clone the repository locally and run `npm install` from the vscode-xml directory.
|
||||
2. Run the `build` task in VS Code (`CTRL + SHIFT + B`) or start extension debugging (`F5`), which will run the `build` task for you.
|
||||
|
||||
## Style Guide
|
||||
### Quotes
|
||||
Use double quotes for strings whenever possible.
|
||||
|
||||
### Imports
|
||||
As a general rule, always import the `vscode` namespace using the `vsc` alias for consistency.
|
||||
|
||||
### Static Classes
|
||||
When possible, try to use a static class to wrap utility functions so you are importing the class, not just a function.
|
||||
For libraries that do not follow this construct (such as the `xpath` module), *always* import the module using an alias (`import * as xpath from "xpath").
|
||||
|
||||
### Constants
|
||||
Where applicable, try to use constants instead of inline strings and numbers.
|
||||
|
||||
## Implicit Types
|
||||
Moving forward, the compiler is instructed (via tsconfig.json) to throw warnings if any expressions imply an `any` type. In other words, always use type declarations where applicable so it is clear what type is being used.
|
||||
There is an exception to this guideline. If you are using a thrid party library that does not have a *.d.ts file available, you do not need to write one. Just ensure the API is documented (either in this repo or in the library's repo).
|
||||
|
||||
## Folder Structure
|
||||
All TypeScript files should reside under the top `src` folder. Under this, there are several subfolders and top-level files defined below:
|
||||
|
||||
### providers
|
||||
This folder contains any classes that implement provider interfaces from the `vscode` namespace. This folder also contains any code that works directly with the
|
||||
APIs exposed by the `vscode` namespace, such as user interaction or configuration access. Aside for the `vscode` module, no code in this folder should be directly dependent on
|
||||
any external NodeJS modules or libraries.
|
||||
|
||||
### services
|
||||
This folder contains any classes that perform actions/logic required by the providers mentioned above. Services should not be dependent on the `vscode` namespace and *can* be
|
||||
dependent on external Node modules and libraries.
|
||||
|
||||
### utils
|
||||
This folder contains any utility classes/functions.
|
||||
|
||||
### Commands.ts
|
||||
This file acts as an interface to all registered commands in the extension. If a substantial amount of code is required to implement a command, it should be moved to a provider and/or service.
|
||||
|
||||
### Extension.ts
|
||||
Previously named `main.ts`, this is the primary entry point to the extension. Anything that needs done on activation or deactivation of the extension is done here. Both the workspace and global `Memento` instances are exposed from this module, which can be used by providers as needed.
|
||||
21
LICENSE
|
|
@ -1,21 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Josh Johnson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
22
README.md
|
|
@ -1,22 +0,0 @@
|
|||
# XML Tools for Visual Studio Code
|
||||
[](https://gitter.im/vscode-xml/vscode-xml)
|
||||
[](https://travis-ci.org/DotJoshJohnson/vscode-xml)
|
||||
|
||||
## Features
|
||||
* [XML Formatting](https://github.com/DotJoshJohnson/vscode-xml/wiki/xml-formatting)
|
||||
* [XML Tree View](https://github.com/DotJoshJohnson/vscode-xml/wiki/xml-tree-view)
|
||||
* [XPath Evaluation](https://github.com/DotJoshJohnson/vscode-xml/wiki/xpath-evaluation)
|
||||
* [XQuery Linting](https://github.com/DotJoshJohnson/vscode-xml/wiki/xquery-linting)
|
||||
* [XQuery Execution](https://github.com/DotJoshJohnson/vscode-xml/wiki/xquery-script-execution)
|
||||
* [XQuery Code Completion](https://github.com/DotJoshJohnson/vscode-xml/wiki/xquery-code-completion)
|
||||
|
||||
## Release Notes
|
||||
Detailed release notes are available [here](https://github.com/DotJoshJohnson/vscode-xml/releases).
|
||||
|
||||
## Issues
|
||||
Run into a bug? Report it [here](https://github.com/DotJoshJohnson/vscode-xml/issues).
|
||||
|
||||
## Icon Credits
|
||||
Icons used in the XML Tree View are used under the Creative Commons 3.0 BY license.
|
||||
* "Code" icon by Dave Gandy from www.flaticon.com
|
||||
* "At" icon by FreePik from www.flaticon.com
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
var gulp = require("gulp");
|
||||
|
||||
var shell = require("gulp-shell");
|
||||
|
||||
gulp.task("compile-typescript", function () {
|
||||
gulp.src("package.json").pipe(shell("tsc"));
|
||||
});
|
||||
|
||||
gulp.task("build", ["compile-typescript"]);
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"comments": {
|
||||
"lineComment": "//",
|
||||
"blockComment": ["/*", "*/"]
|
||||
},
|
||||
"brackets": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"]
|
||||
]
|
||||
}
|
||||
148
package.json
|
|
@ -1,148 +0,0 @@
|
|||
{
|
||||
"name": "xml",
|
||||
"displayName": "XML Tools",
|
||||
"description": "XML Formatting, XQuery, and XPath Tools for Visual Studio Code",
|
||||
"version": "1.9.2",
|
||||
"publisher": "DotJoshJohnson",
|
||||
"author": {
|
||||
"name": "Josh Johnson",
|
||||
"url": "https://github.com/DotJoshJohnson"
|
||||
},
|
||||
"icon": "resources/xml.png",
|
||||
"galleryBanner": {
|
||||
"color": "#FFFFFF",
|
||||
"theme": "light"
|
||||
},
|
||||
"homepage": "https://github.com/DotJoshJohnson/vscode-xml",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DotJoshJohnson/vscode-xml.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/DotJoshJohnson/vscode-xml/issues"
|
||||
},
|
||||
"engines": {
|
||||
"vscode": "^1.13.0",
|
||||
"node": "^0.12.0"
|
||||
},
|
||||
"categories": [
|
||||
"Languages",
|
||||
"Linters",
|
||||
"Other",
|
||||
"Formatters"
|
||||
],
|
||||
"main": "./src/Extension",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "xmlTools.minifyXml",
|
||||
"title": "XML Tools: Minify XML"
|
||||
},
|
||||
{
|
||||
"command": "xmlTools.evaluateXPath",
|
||||
"title": "XML Tools: Evaluate XPath"
|
||||
},
|
||||
{
|
||||
"command": "xmlTools.executeXQuery",
|
||||
"title": "XML Tools: Execute XQuery"
|
||||
},
|
||||
{
|
||||
"command": "xmlTools.formatAsXml",
|
||||
"title": "XML Tools: Format as XML"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"title": "XML Tools Configuration",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"xmlTools.persistXPathQuery": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Remember the last XPath query used."
|
||||
},
|
||||
"xmlTools.removeCommentsOnMinify": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Remove XML comments when XML is minified."
|
||||
},
|
||||
"xmlTools.splitXmlnsOnFormat": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Put each xmlns attribute on a new line when fromatting XML."
|
||||
},
|
||||
"xmlTools.xqueryExecutionEngine": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The full path to the execution engine executable."
|
||||
},
|
||||
"xmlTools.xqueryExecutionArguments": {
|
||||
"type": "array",
|
||||
"default": ["-xquery", "$(script)", "-in", "$(input)", "-out", "$(input).output.xml"],
|
||||
"description": "Arguments to be passed to the execution engine. '$(script)' and '$(input)' refer to the XQuery script and input XML file, respectively."
|
||||
},
|
||||
"xmlTools.ignoreDefaultNamespace": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Ignores default xmlns attribute when evaluating XPath."
|
||||
}
|
||||
}
|
||||
},
|
||||
"keybindings": [
|
||||
{
|
||||
"key": "ctrl+shift+alt+b",
|
||||
"command": "xmlTools.formatXml"
|
||||
},
|
||||
{
|
||||
"key": "ctrl+shift+alt+x",
|
||||
"command": "xmlTools.evaluateXPath"
|
||||
}
|
||||
],
|
||||
"languages": [
|
||||
{
|
||||
"id": "xquery",
|
||||
"aliases": ["XQuery", "xquery"],
|
||||
"extensions": [".xq",".xql",".xqm",".xqy",".xquery"],
|
||||
"configuration": "./languages/xquery/xquery.json"
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
{
|
||||
"language": "xquery",
|
||||
"scopeName": "source.xquery",
|
||||
"path": "./languages/xquery/xquery.tmLanguage"
|
||||
}
|
||||
],
|
||||
"views": {
|
||||
"explorer": [
|
||||
{
|
||||
"id": "xmlTreeView",
|
||||
"name": "XML Document"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"activationEvents": [
|
||||
"onLanguage:xml",
|
||||
"onLanguage:xsl",
|
||||
"onLanguage:xquery",
|
||||
"onCommand:xmlTools.minifyXml",
|
||||
"onCommand:xmlTools.evaluateXPath",
|
||||
"onCommand:xmlTools.executeXQuery",
|
||||
"onCommand:xmlTools.formatAsXml"
|
||||
],
|
||||
"devDependencies": {
|
||||
"vscode": "^1.1.0",
|
||||
"typescript": "^2.3.4",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-shell": "^0.5.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"xmldom": "^0.1.22",
|
||||
"xpath": "^0.0.9",
|
||||
"xqlint": "^0.2.9"
|
||||
},
|
||||
"scripts": {
|
||||
"vscode:prepublish": "tsc",
|
||||
"postinstall": "node ./node_modules/vscode/bin/install"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 490 490" style="enable-background:new 0 0 490 490;" xml:space="preserve" width="512px" height="512px">
|
||||
<path d="M374.621,429.894c-30.535,14.94-68.393,22.412-113.58,22.412c-42.256,0-80.758-7.175-115.517-21.519 c-34.759-14.35-61.315-36.548-79.682-66.598c-18.367-30.056-27.555-65.878-27.555-107.479c0-39.729,9.188-76.947,27.555-111.675 c18.367-34.716,44.239-61.375,77.61-79.967c33.38-18.592,70.24-27.889,110.609-27.889c35.355,0,67.65,7.39,96.885,22.157 c29.236,14.773,51.219,34.472,65.969,59.086c14.75,24.619,22.12,51.105,22.12,79.464c0,24.277-5.737,47.837-17.203,70.671 c-11.475,22.835-27.036,41.045-46.694,54.629c-14.838,10.357-26.821,15.532-35.97,15.532c-5.005,0-9.267-1.651-12.805-4.966 c-3.538-3.309-5.297-7.256-5.297-11.84c0-2.544,2.581-15.7,7.761-39.474l37.25-170.889h-46.311l-8.797,39.474 c-9.824-15.787-21.553-27.546-35.179-35.272c-13.626-7.725-27.945-11.591-42.949-11.591c-19.657,0-39.93,6.792-60.798,20.377 c-20.869,13.584-38.336,33.916-52.392,60.993c-14.055,27.083-21.084,54.119-21.084,81.115c0,21.901,4.526,42.023,13.587,60.361 c9.051,18.337,20.819,31.922,35.315,40.749c14.486,8.826,29.402,13.243,44.758,13.243c13.968,0,27.897-3.86,41.777-11.592 c13.88-7.72,26.43-17.955,37.642-30.688c1.036,10.357,2.679,17.659,4.917,21.901c3.451,6.625,8.836,11.719,16.167,15.284 c7.331,3.565,16.949,5.35,28.855,5.35c37.25,0,71.57-17.15,102.965-51.448c35.189-38.199,52.773-81.915,52.773-131.16 c0-34.461-8.366-66.383-25.091-95.755c-19.667-34.131-46.527-59.805-80.592-77.041C337.575,8.618,299.161,0,256.387,0 c-55.197,0-102.154,12.223-140.871,36.668C76.79,61.12,46.909,96.352,25.873,142.363C8.621,179.889,0,219.363,0,260.79 c0,37.178,7.243,71.818,21.728,103.903c11.554,25.298,28.718,47.668,51.484,67.113c22.774,19.439,50.319,33.997,82.663,43.676 C188.21,485.161,223.526,490,261.822,490c41.562,0,77.092-5.396,106.582-16.176c29.5-10.785,54.934-25.425,76.32-43.93 c21.387-18.506,36.478-36.675,45.276-54.502h-46.821C427.999,396.784,405.147,414.953,374.621,429.894z M286.913,266.771 c-6.207,17.237-14.193,31.453-23.928,42.662c-9.745,11.203-19.97,19.653-30.663,25.338c-10.693,5.692-20.869,8.531-30.526,8.531 c-14.485,0-27.339-6.45-38.55-19.351c-11.212-12.901-16.813-30.983-16.813-54.247c0-14.605,2.756-30.648,8.279-48.139 c5.513-17.484,12.844-32.345,21.993-44.567c9.139-12.224,18.582-21.097,28.327-26.614c9.745-5.517,20.136-8.276,31.171-8.276 c16.734,0,30.917,6.369,42.559,19.102c11.641,12.733,17.467,30.646,17.467,53.737C296.228,232.264,293.121,249.54,286.913,266.771z" fill="#FFFFFF"/>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
|
|
@ -1,56 +0,0 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 490 490" style="enable-background:new 0 0 490 490;" xml:space="preserve">
|
||||
<path d="M374.621,429.894c-30.535,14.94-68.393,22.412-113.58,22.412c-42.256,0-80.758-7.175-115.517-21.519
|
||||
c-34.759-14.35-61.315-36.548-79.682-66.598c-18.367-30.056-27.555-65.878-27.555-107.479c0-39.729,9.188-76.947,27.555-111.675
|
||||
c18.367-34.716,44.239-61.375,77.61-79.967c33.38-18.592,70.24-27.889,110.609-27.889c35.355,0,67.65,7.39,96.885,22.157
|
||||
c29.236,14.773,51.219,34.472,65.969,59.086c14.75,24.619,22.12,51.105,22.12,79.464c0,24.277-5.737,47.837-17.203,70.671
|
||||
c-11.475,22.835-27.036,41.045-46.694,54.629c-14.838,10.357-26.821,15.532-35.97,15.532c-5.005,0-9.267-1.651-12.805-4.966
|
||||
c-3.538-3.309-5.297-7.256-5.297-11.84c0-2.544,2.581-15.7,7.761-39.474l37.25-170.889h-46.311l-8.797,39.474
|
||||
c-9.824-15.787-21.553-27.546-35.179-35.272c-13.626-7.725-27.945-11.591-42.949-11.591c-19.657,0-39.93,6.792-60.798,20.377
|
||||
c-20.869,13.584-38.336,33.916-52.392,60.993c-14.055,27.083-21.084,54.119-21.084,81.115c0,21.901,4.526,42.023,13.587,60.361
|
||||
c9.051,18.337,20.819,31.922,35.315,40.749c14.486,8.826,29.402,13.243,44.758,13.243c13.968,0,27.897-3.86,41.777-11.592
|
||||
c13.88-7.72,26.43-17.955,37.642-30.688c1.036,10.357,2.679,17.659,4.917,21.901c3.451,6.625,8.836,11.719,16.167,15.284
|
||||
c7.331,3.565,16.949,5.35,28.855,5.35c37.25,0,71.57-17.15,102.965-51.448c35.189-38.199,52.773-81.915,52.773-131.16
|
||||
c0-34.461-8.366-66.383-25.091-95.755c-19.667-34.131-46.527-59.805-80.592-77.041C337.575,8.618,299.161,0,256.387,0
|
||||
c-55.197,0-102.154,12.223-140.871,36.668C76.79,61.12,46.909,96.352,25.873,142.363C8.621,179.889,0,219.363,0,260.79
|
||||
c0,37.178,7.243,71.818,21.728,103.903c11.554,25.298,28.718,47.668,51.484,67.113c22.774,19.439,50.319,33.997,82.663,43.676
|
||||
C188.21,485.161,223.526,490,261.822,490c41.562,0,77.092-5.396,106.582-16.176c29.5-10.785,54.934-25.425,76.32-43.93
|
||||
c21.387-18.506,36.478-36.675,45.276-54.502h-46.821C427.999,396.784,405.147,414.953,374.621,429.894z M286.913,266.771
|
||||
c-6.207,17.237-14.193,31.453-23.928,42.662c-9.745,11.203-19.97,19.653-30.663,25.338c-10.693,5.692-20.869,8.531-30.526,8.531
|
||||
c-14.485,0-27.339-6.45-38.55-19.351c-11.212-12.901-16.813-30.983-16.813-54.247c0-14.605,2.756-30.648,8.279-48.139
|
||||
c5.513-17.484,12.844-32.345,21.993-44.567c9.139-12.224,18.582-21.097,28.327-26.614c9.745-5.517,20.136-8.276,31.171-8.276
|
||||
c16.734,0,30.917,6.369,42.559,19.102c11.641,12.733,17.467,30.646,17.467,53.737C296.228,232.264,293.121,249.54,286.913,266.771z"
|
||||
/>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
|
|
@ -1,42 +0,0 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" width="512px" height="512px" viewBox="0 0 522.468 522.469" style="enable-background:new 0 0 522.468 522.469;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M325.762,70.513l-17.706-4.854c-2.279-0.76-4.524-0.521-6.707,0.715c-2.19,1.237-3.669,3.094-4.429,5.568L190.426,440.53 c-0.76,2.475-0.522,4.809,0.715,6.995c1.237,2.19,3.09,3.665,5.568,4.425l17.701,4.856c2.284,0.766,4.521,0.526,6.71-0.712 c2.19-1.243,3.666-3.094,4.425-5.564L332.042,81.936c0.759-2.474,0.523-4.808-0.716-6.999 C330.088,72.747,328.237,71.272,325.762,70.513z" fill="#FFFFFF"/>
|
||||
<path d="M166.167,142.465c0-2.474-0.953-4.665-2.856-6.567l-14.277-14.276c-1.903-1.903-4.093-2.857-6.567-2.857 s-4.665,0.955-6.567,2.857L2.856,254.666C0.95,256.569,0,258.759,0,261.233c0,2.474,0.953,4.664,2.856,6.566l133.043,133.044 c1.902,1.906,4.089,2.854,6.567,2.854s4.665-0.951,6.567-2.854l14.277-14.268c1.903-1.902,2.856-4.093,2.856-6.57 c0-2.471-0.953-4.661-2.856-6.563L51.107,261.233l112.204-112.201C165.217,147.13,166.167,144.939,166.167,142.465z" fill="#FFFFFF"/>
|
||||
<path d="M519.614,254.663L386.567,121.619c-1.902-1.902-4.093-2.857-6.563-2.857c-2.478,0-4.661,0.955-6.57,2.857l-14.271,14.275 c-1.902,1.903-2.851,4.09-2.851,6.567s0.948,4.665,2.851,6.567l112.206,112.204L359.163,373.442 c-1.902,1.902-2.851,4.093-2.851,6.563c0,2.478,0.948,4.668,2.851,6.57l14.271,14.268c1.909,1.906,4.093,2.854,6.57,2.854 c2.471,0,4.661-0.951,6.563-2.854L519.614,267.8c1.903-1.902,2.854-4.096,2.854-6.57 C522.468,258.755,521.517,256.565,519.614,254.663z" fill="#FFFFFF"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2 KiB |
|
|
@ -1,54 +0,0 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="522.468px" height="522.469px" viewBox="0 0 522.468 522.469" style="enable-background:new 0 0 522.468 522.469;"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M325.762,70.513l-17.706-4.854c-2.279-0.76-4.524-0.521-6.707,0.715c-2.19,1.237-3.669,3.094-4.429,5.568L190.426,440.53
|
||||
c-0.76,2.475-0.522,4.809,0.715,6.995c1.237,2.19,3.09,3.665,5.568,4.425l17.701,4.856c2.284,0.766,4.521,0.526,6.71-0.712
|
||||
c2.19-1.243,3.666-3.094,4.425-5.564L332.042,81.936c0.759-2.474,0.523-4.808-0.716-6.999
|
||||
C330.088,72.747,328.237,71.272,325.762,70.513z"/>
|
||||
<path d="M166.167,142.465c0-2.474-0.953-4.665-2.856-6.567l-14.277-14.276c-1.903-1.903-4.093-2.857-6.567-2.857
|
||||
s-4.665,0.955-6.567,2.857L2.856,254.666C0.95,256.569,0,258.759,0,261.233c0,2.474,0.953,4.664,2.856,6.566l133.043,133.044
|
||||
c1.902,1.906,4.089,2.854,6.567,2.854s4.665-0.951,6.567-2.854l14.277-14.268c1.903-1.902,2.856-4.093,2.856-6.57
|
||||
c0-2.471-0.953-4.661-2.856-6.563L51.107,261.233l112.204-112.201C165.217,147.13,166.167,144.939,166.167,142.465z"/>
|
||||
<path d="M519.614,254.663L386.567,121.619c-1.902-1.902-4.093-2.857-6.563-2.857c-2.478,0-4.661,0.955-6.57,2.857l-14.271,14.275
|
||||
c-1.902,1.903-2.851,4.09-2.851,6.567s0.948,4.665,2.851,6.567l112.206,112.204L359.163,373.442
|
||||
c-1.902,1.902-2.851,4.093-2.851,6.563c0,2.478,0.948,4.668,2.851,6.57l14.271,14.268c1.909,1.906,4.093,2.854,6.57,2.854
|
||||
c2.471,0,4.661-0.951,6.563-2.854L519.614,267.8c1.903-1.902,2.854-4.096,2.854-6.57
|
||||
C522.468,258.755,521.517,256.565,519.614,254.663z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
|
@ -1,69 +0,0 @@
|
|||
import * as vsc from "vscode";
|
||||
import * as ext from "./Extension";
|
||||
import * as xpath from "xpath";
|
||||
import { RangeUtil } from "./utils/RangeUtil";
|
||||
import { XmlFormatter } from "./services/XmlFormatter";
|
||||
import { XPathFeatureProvider } from "./providers/XPath";
|
||||
import { XQueryExecutionProvider } from "./providers/Execution";
|
||||
import { XmlFormattingEditProvider } from "./providers/Formatting";
|
||||
|
||||
const CFG_SECTION: string = "xmlTools";
|
||||
const CFG_REMOVE_COMMENTS: string = "removeCommentsOnMinify";
|
||||
|
||||
export class TextEditorCommands {
|
||||
static minifyXml(editor: vsc.TextEditor, edit: vsc.TextEditorEdit): void {
|
||||
let removeComments: boolean = vsc.workspace.getConfiguration(CFG_SECTION).get<boolean>(CFG_REMOVE_COMMENTS, false);
|
||||
|
||||
let range: vsc.Range = RangeUtil.getRangeForDocument(editor.document);
|
||||
|
||||
let formatter: XmlFormatter = new XmlFormatter();
|
||||
let xml: string = formatter.minify(editor.document.getText());
|
||||
|
||||
edit.replace(range, xml);
|
||||
}
|
||||
|
||||
static evaluateXPath(editor: vsc.TextEditor, edit: vsc.TextEditorEdit): void {
|
||||
XPathFeatureProvider.evaluateXPathAsync(editor, edit);
|
||||
}
|
||||
|
||||
static executeXQuery(editor: vsc.TextEditor, edit: vsc.TextEditorEdit): void {
|
||||
XQueryExecutionProvider.executeXQueryAsync(editor);
|
||||
}
|
||||
|
||||
static formatAsXml(editor: vsc.TextEditor, edit: vsc.TextEditorEdit): void {
|
||||
let edits: vsc.TextEdit[];
|
||||
let formattingEditProvider = new XmlFormattingEditProvider();
|
||||
let formattingOptions: vsc.FormattingOptions = {
|
||||
insertSpaces: (editor.options.insertSpaces as boolean),
|
||||
tabSize: (editor.options.tabSize as number)
|
||||
};
|
||||
|
||||
// if the user has selected text, only format what is selected
|
||||
// otherwise, attempt to format the entire document
|
||||
if (!editor.selection.isEmpty) {
|
||||
edits = formattingEditProvider.provideDocumentRangeFormattingEdits(editor.document, editor.selection, formattingOptions);
|
||||
}
|
||||
|
||||
else {
|
||||
edits = formattingEditProvider.provideDocumentFormattingEdits(editor.document, formattingOptions);
|
||||
}
|
||||
|
||||
if (edits) {
|
||||
for (let i = 0; i < edits.length; i++) {
|
||||
editor.edit(async (editBuilder) => {
|
||||
editBuilder.replace(edits[i].range, edits[i].newText);
|
||||
|
||||
// wiggle the cursor to deselect the formatted XML (is there a non-hacky way to go about this?)
|
||||
await vsc.commands.executeCommand("cursorMove", {
|
||||
to: "left",
|
||||
by: "character"
|
||||
});
|
||||
await vsc.commands.executeCommand("cursorMove", {
|
||||
to: "right",
|
||||
by: "character"
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
import * as vsc from "vscode";
|
||||
import { TextEditorCommands } from "./Commands";
|
||||
import { XmlFormattingEditProvider } from "./providers/Formatting";
|
||||
import { XQueryLintingFeatureProvider } from "./providers/Linting";
|
||||
import { XQueryCompletionItemProvider } from "./providers/Completion";
|
||||
import { XmlTreeViewDataProvider } from "./providers/XmlTreeView";
|
||||
|
||||
export var GlobalState: vsc.Memento;
|
||||
export var WorkspaceState: vsc.Memento;
|
||||
|
||||
const LANG_XML: string = "xml";
|
||||
const LANG_XSL: string = "xsl";
|
||||
const LANG_XQUERY: string = "xquery;"
|
||||
const MEM_QUERY_HISTORY: string = "xpathQueryHistory";
|
||||
|
||||
export function activate(ctx: vsc.ExtensionContext) {
|
||||
console.log("activate extension");
|
||||
// expose global and workspace state to the entire extension
|
||||
GlobalState = ctx.globalState;
|
||||
WorkspaceState = ctx.workspaceState;
|
||||
|
||||
// register palette commands
|
||||
ctx.subscriptions.push(
|
||||
vsc.commands.registerTextEditorCommand("xmlTools.minifyXml", TextEditorCommands.minifyXml),
|
||||
vsc.commands.registerTextEditorCommand("xmlTools.evaluateXPath", TextEditorCommands.evaluateXPath),
|
||||
vsc.commands.registerTextEditorCommand("xmlTools.executeXQuery", TextEditorCommands.executeXQuery),
|
||||
vsc.commands.registerTextEditorCommand("xmlTools.formatAsXml", TextEditorCommands.formatAsXml)
|
||||
);
|
||||
|
||||
// register language feature providers
|
||||
ctx.subscriptions.push(
|
||||
vsc.languages.registerDocumentFormattingEditProvider([LANG_XML, LANG_XSL], new XmlFormattingEditProvider()),
|
||||
vsc.languages.registerDocumentRangeFormattingEditProvider([LANG_XML, LANG_XSL], new XmlFormattingEditProvider()),
|
||||
|
||||
vsc.languages.registerCompletionItemProvider(LANG_XQUERY, new XQueryCompletionItemProvider(), ":", "$")
|
||||
);
|
||||
|
||||
// listen to editor events (for linting)
|
||||
ctx.subscriptions.push(
|
||||
vsc.window.onDidChangeActiveTextEditor(_handleChangeActiveTextEditor),
|
||||
vsc.window.onDidChangeTextEditorSelection(_handleChangeTextEditorSelection)
|
||||
);
|
||||
|
||||
// add views
|
||||
ctx.subscriptions.push(
|
||||
vsc.window.registerTreeDataProvider("xmlTreeView", new XmlTreeViewDataProvider(ctx))
|
||||
);
|
||||
}
|
||||
|
||||
export function deactivate() {
|
||||
// clean up xpath history
|
||||
let memento: vsc.Memento = WorkspaceState || GlobalState;
|
||||
let history = memento.get<any[]>(MEM_QUERY_HISTORY, []);
|
||||
history.splice(0);
|
||||
memento.update(MEM_QUERY_HISTORY, history);
|
||||
}
|
||||
|
||||
function _handleContextChange(editor: vsc.TextEditor): void {
|
||||
if (!editor || !editor.document) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (editor.document.languageId) {
|
||||
case "xquery":
|
||||
XQueryLintingFeatureProvider.provideXQueryDiagnostics(editor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function _handleChangeActiveTextEditor(editor: vsc.TextEditor): void {
|
||||
_handleContextChange(editor);
|
||||
}
|
||||
|
||||
function _handleChangeTextEditorSelection(e: vsc.TextEditorSelectionChangeEvent): void {
|
||||
_handleContextChange(e.textEditor);
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
import * as vsc from "vscode";
|
||||
import { XQueryCompleter, XQueryCompletionItem } from "../services/XQueryCompleter";
|
||||
|
||||
export class XQueryCompletionItemProvider implements vsc.CompletionItemProvider {
|
||||
provideCompletionItems(document: vsc.TextDocument, position: vsc.Position): vsc.CompletionItem[] {
|
||||
let items: vsc.CompletionItem[] = new Array<vsc.CompletionItem>();
|
||||
|
||||
let completer: XQueryCompleter = new XQueryCompleter(document.getText());
|
||||
let completions: XQueryCompletionItem[] = completer.getCompletions(position.line, position.character);
|
||||
|
||||
completions.forEach((completion: XQueryCompletionItem) => {
|
||||
let item: vsc.CompletionItem = new vsc.CompletionItem(completion.name);
|
||||
item.insertText = completion.value;
|
||||
|
||||
switch (completion.meta) {
|
||||
// functions (always qualified with a colon)
|
||||
case "function":
|
||||
item.kind = vsc.CompletionItemKind.Function;
|
||||
|
||||
let funcStart = (completion.value.indexOf(":") + 1);
|
||||
let funcEnd = completion.value.indexOf("(");
|
||||
|
||||
item.insertText = completion.value.substring(funcStart, funcEnd);
|
||||
break;
|
||||
|
||||
// variables and parameters (always qualified with a dollar sign)
|
||||
case "Let binding":
|
||||
case "Local variable":
|
||||
case "Window variable":
|
||||
case "Function parameter":
|
||||
item.kind = vsc.CompletionItemKind.Variable;
|
||||
item.insertText = completion.value.substring(1);
|
||||
break;
|
||||
|
||||
// everything else
|
||||
default: item.kind = vsc.CompletionItemKind.Text;
|
||||
}
|
||||
|
||||
items.push(item);
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
import * as vsc from "vscode";
|
||||
import { ChildProcess } from "../services/ChildProcess";
|
||||
|
||||
const CFG_SECTION: string = "xmlTools";
|
||||
const CFG_XQEXEC: string = "xqueryExecutionEngine";
|
||||
const CFG_XQARGS: string = "xqueryExecutionArguments";
|
||||
|
||||
export class XQueryExecutionProvider {
|
||||
static async executeXQueryAsync(editor: vsc.TextEditor): Promise<void> {
|
||||
// this disposable will be used for creating status bar messages
|
||||
let disposable: vsc.Disposable;
|
||||
|
||||
if (editor.document.languageId !== "xquery") {
|
||||
vsc.window.showErrorMessage("This action can only be performed on an XQuery file.");
|
||||
return;
|
||||
}
|
||||
|
||||
let executable = vsc.workspace.getConfiguration(CFG_SECTION).get<string>(CFG_XQEXEC, null);
|
||||
let args = vsc.workspace.getConfiguration(CFG_SECTION).get<string[]>(CFG_XQARGS, []);
|
||||
|
||||
if (!executable || executable == "") {
|
||||
let action = await vsc.window.showWarningMessage("An XQuery execution engine has not been defined.", "Define Now");
|
||||
|
||||
if (action == "Define Now") {
|
||||
vsc.commands.executeCommand("workbench.action.openGlobalSettings");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let inputFile: vsc.Uri;
|
||||
disposable = vsc.window.setStatusBarMessage("Searching for XML files in folder...");
|
||||
let files: vsc.Uri[] = await vsc.workspace.findFiles("**/*.xml", "", 100);
|
||||
disposable.dispose();
|
||||
|
||||
// user does not have a folder open - prompt for file name
|
||||
if (typeof files === "undefined") {
|
||||
vsc.window.showErrorMessage("You must have a folder opened in VS Code to use this feature.");
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is only one XML file, default it
|
||||
// otherwise, prompt the user to select one from the open folder
|
||||
if (files.length > 1) {
|
||||
let qpItems: any[] = new Array<any>();
|
||||
|
||||
files.forEach((file) => {
|
||||
let filename: string = file.fsPath.replace("\\", "/");
|
||||
|
||||
qpItems.push({ // must implement vscode.QuickPickItem
|
||||
label: filename.substring(filename.lastIndexOf("/") + 1),
|
||||
description: file.fsPath,
|
||||
file: file
|
||||
});
|
||||
});
|
||||
|
||||
let selection = await vsc.window.showQuickPick(qpItems, { placeHolder: "Please select an input file." });
|
||||
|
||||
if (!selection) {
|
||||
return;
|
||||
}
|
||||
|
||||
inputFile = selection.file;
|
||||
}
|
||||
|
||||
else {
|
||||
inputFile = files[0];
|
||||
}
|
||||
|
||||
// prompt for output file name
|
||||
let outputPath: string = null;
|
||||
let outputPathPos: number = -1;
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (i > 0) {
|
||||
if (args[i - 1].search(/out|result/)) {
|
||||
outputPath = args[i];
|
||||
outputPathPos = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (outputPath) {
|
||||
outputPath = await vsc.window.showInputBox({
|
||||
placeHolder: "ex. C:\\TEMP\XQueryOutput\\MyOutputFile.xml",
|
||||
prompt: "Please specify the output file path. Existing file behavior is determined by the execution engine you have specified.",
|
||||
value: outputPath
|
||||
});
|
||||
|
||||
args[outputPathPos] = outputPath;
|
||||
}
|
||||
|
||||
// call out to the execution engine
|
||||
disposable = vsc.window.setStatusBarMessage("Executing XQuery Script...");
|
||||
args = args.map<string>((value: string) => {
|
||||
return value
|
||||
.replace("$(script)", editor.document.uri.fsPath)
|
||||
.replace("$(input)", inputFile.fsPath)
|
||||
.replace("$(project)", vsc.workspace.rootPath);
|
||||
});
|
||||
|
||||
try {
|
||||
await ChildProcess.spawnAsync(executable, args);
|
||||
}
|
||||
|
||||
catch (error) {
|
||||
if (error.message.search(/[Ll]ine:?\s*\d+/gm) > -1) {
|
||||
let match: RegExpExecArray = /[Ll]ine:?\s*\d+/gm.exec(error.message);
|
||||
let line: number = (Number.parseInt(match[0].replace(/([Ll]ine:?\s*)|\s/, "")) - 1);
|
||||
|
||||
let selection: string = await vsc.window.showErrorMessage(error.message, `Go to Line ${line}`);
|
||||
|
||||
if (selection == `Go to Line ${line}`) {
|
||||
editor.revealRange(new vsc.Range(line, 0, line, 0));
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
vsc.window.showErrorMessage(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
finally {
|
||||
disposable.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import * as vsc from "vscode";
|
||||
import { RangeUtil } from "../utils/RangeUtil";
|
||||
import { XmlFormatter, IXmlFormatterOptions } from "../services/XmlFormatter";
|
||||
|
||||
const CFG_SECTION: string = "xmlTools";
|
||||
const CFG_SPLIT_NAMESPACES: string = "splitXmlnsOnFormat";
|
||||
|
||||
export class XmlFormattingEditProvider implements vsc.DocumentFormattingEditProvider, vsc.DocumentRangeFormattingEditProvider {
|
||||
provideDocumentFormattingEdits(document: vsc.TextDocument, options: vsc.FormattingOptions): vsc.TextEdit[] {
|
||||
let range = RangeUtil.getRangeForDocument(document);
|
||||
|
||||
return this._provideFormattingEdits(document, range, options);
|
||||
}
|
||||
|
||||
provideDocumentRangeFormattingEdits(document: vsc.TextDocument, range: vsc.Range, options: vsc.FormattingOptions): vsc.TextEdit[] {
|
||||
return this._provideFormattingEdits(document, range, options);
|
||||
}
|
||||
|
||||
private _provideFormattingEdits(document: vsc.TextDocument, range: vsc.Range, options: vsc.FormattingOptions): vsc.TextEdit[] {
|
||||
let splitNamespaces: boolean = vsc.workspace.getConfiguration(CFG_SECTION).get<boolean>(CFG_SPLIT_NAMESPACES, true);
|
||||
|
||||
let formatterOptions: IXmlFormatterOptions = {
|
||||
preferSpaces: options.insertSpaces,
|
||||
tabSize: options.tabSize,
|
||||
splitNamespaces: splitNamespaces
|
||||
};
|
||||
|
||||
let formatter = new XmlFormatter(formatterOptions);
|
||||
let xml = formatter.format(document.getText(range));
|
||||
|
||||
return [ vsc.TextEdit.replace(range, xml) ];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
import * as vsc from "vscode";
|
||||
import { XQueryLinter, XQueryDiagnostic } from "../services/XQueryLinter";
|
||||
|
||||
export class XQueryLintingFeatureProvider {
|
||||
private static _coreDiagnostics: vsc.DiagnosticCollection;
|
||||
|
||||
static get coreDiagnostics(): vsc.DiagnosticCollection {
|
||||
if (!XQueryLintingFeatureProvider._coreDiagnostics) {
|
||||
XQueryLintingFeatureProvider._coreDiagnostics = vsc.languages.createDiagnosticCollection("XQueryDiagnostics");
|
||||
}
|
||||
|
||||
return XQueryLintingFeatureProvider._coreDiagnostics;
|
||||
}
|
||||
|
||||
static provideXQueryDiagnostics(editor: vsc.TextEditor): void {
|
||||
let diagnostics: vsc.Diagnostic[] = new Array<vsc.Diagnostic>();
|
||||
let xqDiagnostics: XQueryDiagnostic[] = XQueryLinter.lint(editor.document.getText());
|
||||
|
||||
xqDiagnostics.forEach((xqd: XQueryDiagnostic) => {
|
||||
let vSeverity: vsc.DiagnosticSeverity = (xqd.severity == 1) ? vsc.DiagnosticSeverity.Warning : vsc.DiagnosticSeverity.Error;
|
||||
|
||||
let startPos: vsc.Position = new vsc.Position(xqd.startLine, xqd.startColumn);
|
||||
let endPos: vsc.Position = new vsc.Position(xqd.endLine, xqd.endColumn);
|
||||
let range: vsc.Range = new vsc.Range(startPos, endPos);
|
||||
let diagnostic: vsc.Diagnostic = new vsc.Diagnostic(range, xqd.message, vSeverity);
|
||||
|
||||
diagnostics.push(diagnostic);
|
||||
});
|
||||
|
||||
XQueryLintingFeatureProvider.coreDiagnostics.set(editor.document.uri, diagnostics);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
import * as vsc from "vscode";
|
||||
import * as ext from "../Extension";
|
||||
import { XPathEvaluator, EvaluatorResult, EvaluatorResultType } from "../services/XPathEvaluator";
|
||||
|
||||
const CFG_SECTION: string = "xmlTools";
|
||||
const CFG_PERSIST_QUERY: string = "persistXPathQuery";
|
||||
const CFG_IGNORE_DEFAULT_XMLNS: string = "ignoreDefaultNamespace";
|
||||
const MEM_QUERY_HISTORY: string = "xpathQueryHistory";
|
||||
const MEM_QUERY_LAST: string = "xPathQueryLast";
|
||||
const OUTPUT_CHANNEL: string = "XPath Results";
|
||||
|
||||
export class XPathFeatureProvider {
|
||||
static async evaluateXPathAsync(editor: vsc.TextEditor, edit: vsc.TextEditorEdit): Promise<void> {
|
||||
// if there is no workspace, we will track queries in the global Memento
|
||||
let memento: vsc.Memento = ext.WorkspaceState || ext.GlobalState;
|
||||
|
||||
// get the xpath persistence setting
|
||||
let persistQueries: boolean = vsc.workspace.getConfiguration(CFG_SECTION).get<boolean>(CFG_PERSIST_QUERY, true);
|
||||
|
||||
// get the last query if there is one for this document
|
||||
// if not, try pulling the last query ran, regardless of document
|
||||
// NOTE: if the user has focus on the output channel when opening the xquery prompt, the channel is the "active" document
|
||||
let history: HistoricQuery[] = memento.get<HistoricQuery[]>(MEM_QUERY_HISTORY, new Array<HistoricQuery>());
|
||||
let globalLastQuery: string = memento.get<string>(MEM_QUERY_LAST, "");
|
||||
|
||||
let lastQuery: HistoricQuery = history.find((item: HistoricQuery) => {
|
||||
if (item.uri == editor.document.uri.toString()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// set the inital display value and prompt the user
|
||||
let query: string = "";
|
||||
|
||||
if (persistQueries) {
|
||||
if (lastQuery) {
|
||||
query = lastQuery.query;
|
||||
}
|
||||
|
||||
else {
|
||||
query = globalLastQuery;
|
||||
}
|
||||
}
|
||||
|
||||
query = await vsc.window.showInputBox({
|
||||
placeHolder: "XPath Query",
|
||||
prompt: "Please enter an XPath query to evaluate.",
|
||||
value: query
|
||||
});
|
||||
|
||||
// showInputBox() will return undefined if the user dimissed the prompt
|
||||
if (query) {
|
||||
|
||||
let ignoreDefaultNamespace: boolean = vsc.workspace.getConfiguration(CFG_SECTION).get<boolean>(CFG_IGNORE_DEFAULT_XMLNS, true);
|
||||
|
||||
// run the query
|
||||
let xml: string = editor.document.getText();
|
||||
let evalResult: EvaluatorResult;
|
||||
|
||||
try {
|
||||
evalResult = XPathEvaluator.evaluate(query, xml, ignoreDefaultNamespace);
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
vsc.window.showErrorMessage(`Something went wrong while evaluating the XPath: ${error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// show the results to the user
|
||||
let outputChannel: vsc.OutputChannel = vsc.window.createOutputChannel(OUTPUT_CHANNEL);
|
||||
outputChannel.clear();
|
||||
|
||||
outputChannel.appendLine(`XPath Query: ${query}`);
|
||||
outputChannel.append("\n");
|
||||
|
||||
if (evalResult.type === EvaluatorResultType.NODE_COLLECTION) {
|
||||
(evalResult.result as Node[]).forEach((node: XmlNode) => {
|
||||
outputChannel.appendLine(`[Line ${node.lineNumber}] ${node.localName}: ${node.textContent}`);
|
||||
});
|
||||
} else {
|
||||
outputChannel.appendLine(`[Result]: ${evalResult.result}`);
|
||||
}
|
||||
outputChannel.show(vsc.ViewColumn.Three);
|
||||
|
||||
// if persistence is enabled, save the query for later
|
||||
if (persistQueries) {
|
||||
lastQuery = new HistoricQuery(editor.document.uri.toString(), query);
|
||||
|
||||
let affectedIndex: number = -1;
|
||||
history = history.map<HistoricQuery>((item: HistoricQuery, index: number) => {
|
||||
if (item.uri == lastQuery.uri) {
|
||||
item.query = query;
|
||||
affectedIndex = index;
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
if (affectedIndex == -1) {
|
||||
history.push(lastQuery);
|
||||
}
|
||||
|
||||
memento.update(MEM_QUERY_HISTORY, history);
|
||||
memento.update(MEM_QUERY_LAST, query);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class HistoricQuery {
|
||||
constructor(uri: string, query: string) {
|
||||
this.uri = uri;
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
uri: string;
|
||||
query: string;
|
||||
}
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
import * as vsc from "vscode";
|
||||
import * as path from "path";
|
||||
|
||||
let DOMParser = require("xmldom").DOMParser;
|
||||
|
||||
export class XmlTreeViewDataProvider implements vsc.TreeDataProvider<Node> {
|
||||
private _onDidChangeTreeData: vsc.EventEmitter<Node | null> = new vsc.EventEmitter<Node | null>();
|
||||
private _xmlDocument: Document;
|
||||
|
||||
constructor(private _context: vsc.ExtensionContext) {
|
||||
vsc.window.onDidChangeActiveTextEditor((editor) => {
|
||||
this._refreshTree();
|
||||
});
|
||||
|
||||
vsc.workspace.onDidChangeTextDocument((e) => {
|
||||
this._refreshTree();
|
||||
});
|
||||
}
|
||||
|
||||
readonly onDidChangeTreeData: vsc.Event<Node | null> = this._onDidChangeTreeData.event;
|
||||
|
||||
get activeEditor(): vsc.TextEditor | null {
|
||||
return vsc.window.activeTextEditor || null;
|
||||
}
|
||||
|
||||
getChildren(element?: Node): Node[] {
|
||||
if (!this._xmlDocument) {
|
||||
this._refreshTree();
|
||||
}
|
||||
|
||||
if (element) {
|
||||
return [].concat(this._getChildAttributeArray(element), this._getChildElementArray(element));
|
||||
}
|
||||
|
||||
else if (this._xmlDocument) {
|
||||
return [ this._xmlDocument.lastChild ];
|
||||
}
|
||||
|
||||
else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
getTreeItem(element: Node): vsc.TreeItem {
|
||||
let treeItem = new vsc.TreeItem(element.localName);
|
||||
|
||||
if (this._getChildAttributeArray(element).length > 0) {
|
||||
treeItem.collapsibleState = vsc.TreeItemCollapsibleState.Collapsed;
|
||||
}
|
||||
|
||||
if (this._getChildElementArray(element).length > 0) {
|
||||
treeItem.collapsibleState = vsc.TreeItemCollapsibleState.Collapsed;
|
||||
}
|
||||
|
||||
treeItem.command = {
|
||||
command: "revealLine",
|
||||
title: "",
|
||||
arguments: [{
|
||||
lineNumber: (element as any).lineNumber - 1,
|
||||
at: "top"
|
||||
}]
|
||||
};
|
||||
|
||||
treeItem.iconPath = this._getIcon(element);
|
||||
|
||||
return treeItem;
|
||||
}
|
||||
|
||||
private _getChildAttributeArray(node: Node): Node[] {
|
||||
if (!node.attributes) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let array = new Array<Node>();
|
||||
|
||||
for (let i = 0; i < node.attributes.length; i++) {
|
||||
array.push(node.attributes[i]);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
private _getChildElementArray(node: Node): Node[] {
|
||||
if (!node.childNodes) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let array = new Array<Node>();
|
||||
|
||||
for (let i = 0; i < node.childNodes.length; i++) {
|
||||
let child = node.childNodes[i];
|
||||
|
||||
if ((child as any).tagName) {
|
||||
array.push(child);
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
private _getIcon(element: Node): any {
|
||||
let type = "element";
|
||||
|
||||
if (!(element as any).tagName) {
|
||||
type = "attribute";
|
||||
}
|
||||
|
||||
let icon = {
|
||||
dark: this._context.asAbsolutePath(path.join("resources", "icons", `${type}.dark.svg`)),
|
||||
light: this._context.asAbsolutePath(path.join("resources", "icons", `${type}.light.svg`))
|
||||
};
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private _refreshTree(): void {
|
||||
if (!this.activeEditor || this.activeEditor.document.languageId !== "xml") {
|
||||
this._xmlDocument = null;
|
||||
this._onDidChangeTreeData.fire();
|
||||
return;
|
||||
}
|
||||
|
||||
let xml = this.activeEditor.document.getText();
|
||||
this._xmlDocument = new DOMParser().parseFromString(xml, "text/xml");
|
||||
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
let child_process = require("child_process");
|
||||
|
||||
export class ChildProcess {
|
||||
static async spawnAsync(executable: string, args: string[]): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
|
||||
let output: string = "";
|
||||
let handle = child_process.spawn(executable, args);
|
||||
|
||||
handle.stdout.on("data", (data: string) => {
|
||||
output += data;
|
||||
});
|
||||
|
||||
handle.stderr.on("data", (data: string) => {
|
||||
output += data;
|
||||
});
|
||||
|
||||
handle.on("close", (code: string) => {
|
||||
if (code == "0") {
|
||||
resolve();
|
||||
}
|
||||
|
||||
else {
|
||||
reject({ code: code, message: output });
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
import * as xpath from "xpath";
|
||||
|
||||
let DOMParser = require("xmldom").DOMParser;
|
||||
|
||||
export class EvaluatorResult {
|
||||
type: EvaluatorResultType;
|
||||
result: Node[]|number|string|boolean;
|
||||
}
|
||||
|
||||
export class EvaluatorResultType {
|
||||
static SCALAR_TYPE: number = 0;
|
||||
static NODE_COLLECTION: number = 1;
|
||||
}
|
||||
|
||||
export class XPathEvaluator {
|
||||
static evaluate(query: string, xml: string, ignoreDefaultNamespace: boolean): EvaluatorResult {
|
||||
if (ignoreDefaultNamespace) {
|
||||
xml = xml.replace(/xmlns=".+"/g, (match: string) => {
|
||||
return match.replace(/xmlns/g, "xmlns:default");
|
||||
});
|
||||
}
|
||||
|
||||
let nodes: Node[] = new Array<Node>();
|
||||
|
||||
let xdoc: Document = new DOMParser().parseFromString(xml, "text/xml");
|
||||
|
||||
let resolver: xpath.XPathNSResolver = xpath.createNSResolver(xdoc);
|
||||
let result: xpath.XPathResult = xpath.evaluate(
|
||||
query, // xpathExpression
|
||||
xdoc, // contextNode
|
||||
resolver, // namespaceResolver
|
||||
xpath.XPathResult.ANY_TYPE, // resultType
|
||||
null // result
|
||||
)
|
||||
|
||||
let evalResult = new EvaluatorResult();
|
||||
evalResult.type = EvaluatorResultType.SCALAR_TYPE;
|
||||
|
||||
switch(result.resultType) {
|
||||
case xpath.XPathResult.NUMBER_TYPE:
|
||||
evalResult.result = result.numberValue;
|
||||
break;
|
||||
case xpath.XPathResult.STRING_TYPE:
|
||||
evalResult.result = result.stringValue;
|
||||
break;
|
||||
case xpath.XPathResult.BOOLEAN_TYPE:
|
||||
evalResult.result = result.booleanValue;
|
||||
break;
|
||||
case xpath.XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
|
||||
case xpath.XPathResult.ORDERED_NODE_ITERATOR_TYPE:
|
||||
evalResult.result = result.booleanValue;
|
||||
let node: Node;
|
||||
while (node = result.iterateNext()) {
|
||||
nodes.push(node);
|
||||
}
|
||||
evalResult.result = nodes;
|
||||
evalResult.type = EvaluatorResultType.NODE_COLLECTION;
|
||||
break;
|
||||
}
|
||||
|
||||
return evalResult;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
let XQLint = require("xqlint").XQLint;
|
||||
|
||||
export class XQueryCompleter {
|
||||
constructor(script: string) {
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
private _script: string;
|
||||
private _linter: any;
|
||||
|
||||
get script(): string {
|
||||
return this._script;
|
||||
}
|
||||
|
||||
set script(value: string) {
|
||||
this._script = value;
|
||||
this._linter = new XQLint(this._script);
|
||||
}
|
||||
|
||||
getCompletions(line: number, column: number): XQueryCompletionItem[] {
|
||||
let items: XQueryCompletionItem[] = new Array<XQueryCompletionItem>();
|
||||
|
||||
this._linter.getCompletions({line: line, col: column}).forEach((completion: any) => {
|
||||
items.push(new XQueryCompletionItem(completion.name, completion.value, completion.meta));
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
export class XQueryCompletionItem {
|
||||
constructor(name: string, value: string, meta: string) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.meta = meta;
|
||||
}
|
||||
|
||||
name: string;
|
||||
value: string;
|
||||
meta: string;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
let XQLint = require("xqlint").XQLint;
|
||||
|
||||
export class XQueryLinter {
|
||||
static SEVERITY_WARNING: number = 1;
|
||||
static SEVERITY_ERROR: number = 2;
|
||||
|
||||
static lint(text: string): XQueryDiagnostic[] {
|
||||
let linter = new XQLint(text);
|
||||
let diagnostics: XQueryDiagnostic[] = new Array<XQueryDiagnostic>();
|
||||
|
||||
linter.getErrors().forEach((error: any) => {
|
||||
diagnostics.push(new XQueryDiagnostic(XQueryLinter.SEVERITY_ERROR, error.message, error.pos.sl, error.pos.sc, error.pos.el, error.pos.ec));
|
||||
});
|
||||
|
||||
linter.getWarnings().forEach((warning: any) => {
|
||||
diagnostics.push(new XQueryDiagnostic(XQueryLinter.SEVERITY_WARNING, warning.message, warning.pos.sl, warning.pos.sc, warning.pos.el, warning.pos.ec));
|
||||
});
|
||||
|
||||
return diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
export class XQueryDiagnostic {
|
||||
constructor(severity: number, message: string, startLine: number, startColumn: number, endLine: number, endColumn: number) {
|
||||
this.severity = severity;
|
||||
this.message = message;
|
||||
this.startLine = startLine;
|
||||
this.startColumn = startColumn;
|
||||
this.endLine = endLine;
|
||||
this.endColumn = endColumn;
|
||||
}
|
||||
|
||||
severity: number;
|
||||
message: string;
|
||||
startLine: number;
|
||||
startColumn: number;
|
||||
endLine: number;
|
||||
endColumn: number;
|
||||
}
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
// Based on pretty-data (https://github.com/vkiryukhin/pretty-data)
|
||||
export class XmlFormatter {
|
||||
constructor(options?: IXmlFormatterOptions) {
|
||||
options = options || {};
|
||||
|
||||
if (typeof options.preferSpaces === "undefined") {
|
||||
options.preferSpaces = false;
|
||||
}
|
||||
|
||||
if (typeof options.splitNamespaces === "undefined") {
|
||||
options.splitNamespaces = true;
|
||||
}
|
||||
|
||||
options.tabSize = options.tabSize || 4;
|
||||
options.newLine = options.newLine || "\n";
|
||||
|
||||
this.newLine = options.newLine || "\n";
|
||||
this.indentPattern = (options.preferSpaces) ? " ".repeat(options.tabSize) : "\t";
|
||||
this.splitNamespaces = options.splitNamespaces;
|
||||
}
|
||||
|
||||
newLine: string;
|
||||
indentPattern: string;
|
||||
splitNamespaces: boolean;
|
||||
|
||||
format(xml: string): string {
|
||||
xml = this.minify(xml, false);
|
||||
xml = xml.replace(/</g, "~::~<");
|
||||
|
||||
if (this.splitNamespaces) {
|
||||
xml = xml
|
||||
.replace(/xmlns\:/g, "~::~xmlns:")
|
||||
.replace(/xmlns\=/g, "~::~xmlns=");
|
||||
}
|
||||
|
||||
let parts: string[] = xml.split("~::~");
|
||||
console.log(parts);
|
||||
let inComment: boolean = false;
|
||||
let level: number = 0;
|
||||
let output: string = "";
|
||||
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
// <!
|
||||
if (parts[i].search(/<!/) > -1) {
|
||||
output += this._getIndent(level, parts[i]);
|
||||
inComment = true;
|
||||
|
||||
// end <!
|
||||
if (parts[i].search(/-->/) > -1 || parts[i].search(/\]>/) > -1 || parts[i].search(/!DOCTYPE/) > -1) {
|
||||
inComment = false;
|
||||
}
|
||||
}
|
||||
|
||||
// end <!
|
||||
else if (parts[i].search(/-->/) > -1 || parts[i].search(/\]>/) > -1) {
|
||||
output += parts[i];
|
||||
inComment = false;
|
||||
}
|
||||
|
||||
// <elm></elm>
|
||||
else if (/^<(\w|:)/.test(parts[i - 1]) && /^<\/(\w|:)/.test(parts[i])
|
||||
&& /^<[\w:\-\.\,\/]+/.exec(parts[i - 1])[0] == /^<\/[\w:\-\.\,]+/.exec(parts[i])[0].replace("/", "")) {
|
||||
|
||||
output += parts[i];
|
||||
if (!inComment) level--;
|
||||
}
|
||||
|
||||
// <elm>
|
||||
else if (parts[i].search(/<(\w|:)/) > -1 && parts[i].search(/<\//) == -1 && parts[i].search(/\/>/) == -1) {
|
||||
output = (!inComment) ? output += this._getIndent(level++, parts[i]) : output += parts[i];
|
||||
}
|
||||
|
||||
// <elm>...</elm>
|
||||
else if (parts[i].search(/<(\w|:)/) > -1 && parts[i].search(/<\//) > -1) {
|
||||
output = (!inComment) ? output += this._getIndent(level, parts[i]) : output += parts[i];
|
||||
}
|
||||
|
||||
// </elm>
|
||||
else if (parts[i].search(/<\//) > -1) {
|
||||
output = (!inComment) ? output += this._getIndent(--level, parts[i]) : output += parts[i];
|
||||
}
|
||||
|
||||
// <elm />
|
||||
else if (parts[i].search(/\/>/) > -1 && (!this.splitNamespaces || parts[i].search(/xmlns(:|=)/) == -1)) {
|
||||
output = (!inComment) ? output += this._getIndent(level, parts[i]) : output += parts[i];
|
||||
}
|
||||
|
||||
// xmlns />
|
||||
else if (parts[i].search(/\/>/) > -1 && parts[i].search(/xmlns(:|=)/) > -1 && this.splitNamespaces) {
|
||||
output = (!inComment) ? output += this._getIndent(level--, parts[i]) : output += parts[i];
|
||||
}
|
||||
|
||||
// <?xml ... ?>
|
||||
else if (parts[i].search(/<\?/) > -1) {
|
||||
output += this._getIndent(level, parts[i]);
|
||||
}
|
||||
|
||||
// xmlns
|
||||
else if (this.splitNamespaces && (parts[i].search(/xmlns\:/) > -1 || parts[i].search(/xmlns\=/) > -1)) {
|
||||
output += this._getIndent(level, parts[i]);
|
||||
}
|
||||
|
||||
else {
|
||||
output += parts[i];
|
||||
}
|
||||
}
|
||||
|
||||
// remove leading newline
|
||||
if (output[0] == this.newLine) {
|
||||
output = output.slice(1);
|
||||
}
|
||||
|
||||
else if (output.substring(0, 1) == this.newLine) {
|
||||
output = output.slice(2);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
minify(xml: string, removeComments?: boolean): string {
|
||||
if (typeof removeComments === "undefined") {
|
||||
removeComments = false;
|
||||
}
|
||||
|
||||
xml = this._stripLineBreaks(xml); // all line breaks outside of CDATA elements
|
||||
xml = (removeComments) ? xml.replace(/\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/g, "") : xml;
|
||||
xml = xml.replace(/>\s{0,}</g, "><"); // insignificant whitespace between tags
|
||||
xml = xml.replace(/"\s+(?=[^\s]+=)/g, "\" "); // spaces between attributes
|
||||
xml = xml.replace(/"\s+(?=>)/g, "\""); // spaces between the last attribute and tag close (>)
|
||||
xml = xml.replace(/"\s+(?=\/>)/g, "\" "); // spaces between the last attribute and tag close (/>)
|
||||
xml = xml.replace(/[^ <>="]\s+[^ <>="]+=/g, (match: string) => { // spaces between the node name and the first attribute
|
||||
return match.replace(/\s+/g, " ");
|
||||
});
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
private _getIndent(level: number, trailingValue?: string): string {
|
||||
trailingValue = trailingValue || "";
|
||||
|
||||
return `${this.newLine}${this.indentPattern.repeat(level)}${trailingValue}`;
|
||||
}
|
||||
|
||||
private _stripLineBreaks(xml: string): string {
|
||||
let output: string = "";
|
||||
let inTag: boolean = false;
|
||||
let inTagName: boolean = false;
|
||||
let inCdata: boolean = false;
|
||||
let inAttribute: boolean = false;
|
||||
|
||||
for (let i = 0; i < xml.length; i++) {
|
||||
let char: string = xml.charAt(i);
|
||||
let prev: string = xml.charAt(i - 1);
|
||||
let next: string = xml.charAt(i + 1);
|
||||
|
||||
if (char == "!" && (xml.substr(i, 8) == "![CDATA[" || xml.substr(i, 3) == "!--")) {
|
||||
inCdata = true;
|
||||
}
|
||||
|
||||
else if (char == "]" && (xml.substr(i, 3) == "]]>")) {
|
||||
inCdata = false;
|
||||
}
|
||||
|
||||
else if (char == "-" && (xml.substr(i, 3) == "-->")) {
|
||||
inCdata = false;
|
||||
}
|
||||
|
||||
else if (char.search(/[\r\n]/g) > -1 && !inCdata) {
|
||||
if (/\r/.test(char) && /\S|\r|\n/.test(prev) && /\S|\r|\n/.test(xml.charAt(i + this.newLine.length))) {
|
||||
output += char;
|
||||
}
|
||||
|
||||
else if (/\n/.test(char) && /\S|\r|\n/.test(xml.charAt(i - this.newLine.length)) && /\S|\r|\n/.test(next)) {
|
||||
output += char;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
output += char;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IXmlFormatterOptions {
|
||||
preferSpaces?: boolean;
|
||||
tabSize?: number;
|
||||
newLine?: string;
|
||||
splitNamespaces?: boolean;
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
import * as vsc from "vscode";
|
||||
|
||||
export class RangeUtil {
|
||||
static getRangeForDocument(document: vsc.TextDocument): vsc.Range {
|
||||
let lastLineIndex = (document.lineCount - 1);
|
||||
let range = new vsc.Range(new vsc.Position(0, 0), new vsc.Position(lastLineIndex, Number.MAX_VALUE));
|
||||
|
||||
range = document.validateRange(range);
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"removeComments": true,
|
||||
"target": "es6"
|
||||
},
|
||||
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
2088
typings/node/node.d.ts
vendored
3
typings/thenable/thenable.d.ts
vendored
|
|
@ -1,3 +0,0 @@
|
|||
declare class Thenable<T> extends Promise<T> {
|
||||
// shim for vscode's Thenable<T>
|
||||
}
|
||||
4
typings/xmldom/xmldom.d.ts
vendored
|
|
@ -1,4 +0,0 @@
|
|||
declare class XmlNode extends Node {
|
||||
lineNumber: number;
|
||||
columnNumber: number;
|
||||
}
|
||||
197
typings/xpath/xpath.d.ts
vendored
|
|
@ -1,197 +0,0 @@
|
|||
// Type definitions for xpath v0.0.7
|
||||
// Project: https://github.com/goto100/xpath
|
||||
// Definitions by: Andrew Bradley <https://github.com/cspotcode/>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
// Some documentation prose is copied from the XPath documentation at https://developer.mozilla.org.
|
||||
|
||||
declare module 'xpath' {
|
||||
|
||||
// select1 can return any of: `Node`, `boolean`, `string`, `number`.
|
||||
// select and selectWithResolver can return any of the above return types or `Array<Node>`.
|
||||
// For this reason, their return types are `any`.
|
||||
|
||||
interface SelectFn {
|
||||
/**
|
||||
* Evaluate an XPath expression against a DOM node. Returns the result as one of the following:
|
||||
* * Array<Node>
|
||||
* * Node
|
||||
* * boolean
|
||||
* * number
|
||||
* * string
|
||||
* @param xpathText
|
||||
* @param contextNode
|
||||
* @param single If true and the evaluation result is one or more Nodes, will return only the first Node instead of an Array<Node>
|
||||
*/
|
||||
(xpathText: string, contextNode: Node, single?: boolean): any;
|
||||
}
|
||||
|
||||
var select: SelectFn;
|
||||
|
||||
/**
|
||||
* Evaluate an xpath expression against a DOM node, returning the first result only.
|
||||
* Equivalent to `select(xpathText, contextNode, true)`
|
||||
* @param xpathText
|
||||
* @param contextNode
|
||||
*/
|
||||
function select1(xpathText: string, contextNode: Node): any;
|
||||
|
||||
/**
|
||||
* Evaluate an XPath expression against a DOM node using a given namespace resolver. Returns the result as one of the following:
|
||||
* * Array<Node>
|
||||
* * Node
|
||||
* * boolean
|
||||
* * number
|
||||
* * string
|
||||
* @param xpathText
|
||||
* @param contextNode
|
||||
* @param resolver
|
||||
* @param single If true and the evaluation result is one or more Nodes, will return only the first Node instead of an Array<Node>
|
||||
*/
|
||||
function selectWithResolver(xpathText: string, contextNode: Node, resolver: XPathNSResolver, single?: boolean): any;
|
||||
|
||||
/**
|
||||
* Evaluate an xpath expression against a DOM.
|
||||
* @param xpathText xpath expression as a string.
|
||||
* @param contextNode xpath expression is evaluated relative to this DOM node.
|
||||
* @param resolver XML namespace resolver
|
||||
* @param resultType
|
||||
* @param result If non-null, xpath *may* reuse this XPathResult object instead of creating a new one. However, it is not required to do so.
|
||||
* @return XPathResult object containing the result of the expression.
|
||||
*/
|
||||
function evaluate(xpathText: string, contextNode: Node, resolver: XPathNSResolver, resultType: number, result?: XPathResult): XPathResult;
|
||||
|
||||
/**
|
||||
* Creates a `select` function that uses the given namespace prefix to URI mappings when evaluating queries.
|
||||
* @param namespaceMappings an object mapping namespace prefixes to namespace URIs. Each key is a prefix; each value is a URI.
|
||||
* @return a function with the same signature as `xpath.select`
|
||||
*/
|
||||
function useNamespaces(namespaceMappings: NamespaceMap): typeof select;
|
||||
interface NamespaceMap {
|
||||
[namespacePrefix: string]: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an XPath expression into an XPathExpression which can be (repeatedly) evaluated against a DOM.
|
||||
* @param xpathText XPath expression as a string
|
||||
* @param namespaceURLMapper Namespace resolver
|
||||
* @return compiled expression
|
||||
*/
|
||||
function createExpression(xpathText: string, namespaceURLMapper: XPathNSResolver): XPathExpression;
|
||||
|
||||
/**
|
||||
* Create an XPathNSResolver that resolves based on the information available in the context of a DOM node.
|
||||
* @param node
|
||||
*/
|
||||
function createNSResolver(node: Node): XPathNSResolver;
|
||||
|
||||
/**
|
||||
* Result of evaluating an XPathExpression.
|
||||
*/
|
||||
class XPathResult {
|
||||
/**
|
||||
* A result set containing whatever type naturally results from evaluation of the expression. Note that if the result is a node-set then UNORDERED_NODE_ITERATOR_TYPE is always the resulting type.
|
||||
*/
|
||||
static ANY_TYPE: number;
|
||||
/**
|
||||
* A result containing a single number. This is useful for example, in an XPath expression using the count() function.
|
||||
*/
|
||||
static NUMBER_TYPE: number;
|
||||
/**
|
||||
* A result containing a single string.
|
||||
*/
|
||||
static STRING_TYPE: number;
|
||||
/**
|
||||
* A result containing a single boolean value. This is useful for example, in an XPath expression using the not() function.
|
||||
*/
|
||||
static BOOLEAN_TYPE: number;
|
||||
/**
|
||||
* A result node-set containing all the nodes matching the expression. The nodes may not necessarily be in the same order that they appear in the document.
|
||||
*/
|
||||
static UNORDERED_NODE_ITERATOR_TYPE: number;
|
||||
/**
|
||||
* A result node-set containing all the nodes matching the expression. The nodes in the result set are in the same order that they appear in the document.
|
||||
*/
|
||||
static ORDERED_NODE_ITERATOR_TYPE: number;
|
||||
/**
|
||||
* A result node-set containing snapshots of all the nodes matching the expression. The nodes may not necessarily be in the same order that they appear in the document.
|
||||
*/
|
||||
static UNORDERED_NODE_SNAPSHOT_TYPE: number;
|
||||
/**
|
||||
* A result node-set containing snapshots of all the nodes matching the expression. The nodes in the result set are in the same order that they appear in the document.
|
||||
*/
|
||||
static ORDERED_NODE_SNAPSHOT_TYPE: number;
|
||||
/**
|
||||
* A result node-set containing any single node that matches the expression. The node is not necessarily the first node in the document that matches the expression.
|
||||
*/
|
||||
static ANY_UNORDERED_NODE_TYPE: number;
|
||||
/**
|
||||
* A result node-set containing the first node in the document that matches the expression.
|
||||
*/
|
||||
static FIRST_ORDERED_NODE_TYPE: number;
|
||||
|
||||
/**
|
||||
* Type of this result. It is one of the enumerated result types.
|
||||
*/
|
||||
resultType: number;
|
||||
|
||||
/**
|
||||
* Returns the next node in this result, if this result is one of the _ITERATOR_ result types.
|
||||
*/
|
||||
iterateNext(): Node;
|
||||
|
||||
/**
|
||||
* returns the result node for a given index, if this result is one of the _SNAPSHOT_ result types.
|
||||
* @param index
|
||||
*/
|
||||
snapshotItem(index: number): Node;
|
||||
|
||||
/**
|
||||
* Number of nodes in this result, if this result is one of the _SNAPSHOT_ result types.
|
||||
*/
|
||||
snapshotLength: number;
|
||||
|
||||
/**
|
||||
* Value of this result, if it is a BOOLEAN_TYPE result.
|
||||
*/
|
||||
booleanValue: boolean;
|
||||
/**
|
||||
* Value of this result, if it is a NUMBER_TYPE result.
|
||||
*/
|
||||
numberValue: number;
|
||||
/**
|
||||
* Value of this result, if it is a STRING_TYPE result.
|
||||
*/
|
||||
stringValue: string;
|
||||
|
||||
/**
|
||||
* Value of this result, if it is a FIRST_ORDERED_NODE_TYPE result.
|
||||
*/
|
||||
singleNodeValue: Node;
|
||||
}
|
||||
|
||||
/**
|
||||
* A compiled XPath expression, ready to be (repeatedly) evaluated against a DOM node.
|
||||
*/
|
||||
interface XPathExpression {
|
||||
/**
|
||||
* evaluate this expression against a DOM node.
|
||||
* @param contextNode
|
||||
* @param resultType
|
||||
* @param result
|
||||
*/
|
||||
evaluate(contextNode: Node, resultType: number, result?: XPathResult): XPathResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object that can resolve XML namespace prefixes to namespace URIs.
|
||||
*/
|
||||
interface XPathNSResolver {
|
||||
/**
|
||||
* Given an XML namespace prefix, returns the corresponding XML namespace URI.
|
||||
* @param prefix XML namespace prefix
|
||||
* @return XML namespace URI
|
||||
*/
|
||||
lookupNamespaceURI(prefix: string): string;
|
||||
}
|
||||
}
|
||||