mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-13 17:22:15 -05:00
XML Formatter (#6182)
* add xml formatter extenstion * remove unused imports
This commit is contained in:
@@ -46,7 +46,6 @@ expressly granted herein, whether by implication, estoppel or otherwise.
|
||||
node-fetch: https://github.com/bitinn/node-fetch
|
||||
node-pty: https://github.com/Tyriar/node-pty
|
||||
nsfw: https://github.com/Axosoft/nsfw
|
||||
pretty-data: https://github.com/vkiryukhin/pretty-data
|
||||
primeng: https://github.com/primefaces/primeng
|
||||
process-nextick-args: https://github.com/calvinmetcalf/process-nextick-args
|
||||
pty.js: https://github.com/chjj/pty.js
|
||||
@@ -1420,16 +1419,6 @@ SOFTWARE.
|
||||
=========================================
|
||||
END OF nsfw NOTICES AND INFORMATION
|
||||
|
||||
%% pretty-data NOTICES AND INFORMATION BEGIN HERE
|
||||
=========================================
|
||||
License: Dual licensed under the MIT and GPL licenses:
|
||||
|
||||
http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
http://www.gnu.org/licenses/gpl.html
|
||||
=========================================
|
||||
END OF pretty-data NOTICES AND INFORMATION
|
||||
|
||||
%% primeng NOTICES AND INFORMATION BEGIN HERE
|
||||
=========================================
|
||||
The MIT License (MIT)
|
||||
|
||||
10
extensions/xml-language-features/.vscodeignore
Normal file
10
extensions/xml-language-features/.vscodeignore
Normal file
@@ -0,0 +1,10 @@
|
||||
test/**
|
||||
src/**
|
||||
tsconfig.json
|
||||
out/test/**
|
||||
out/**
|
||||
extension.webpack.config.js
|
||||
cgmanifest.json
|
||||
yarn.lock
|
||||
preview-src/**
|
||||
webpack.config.js
|
||||
20
extensions/xml-language-features/extension.webpack.config.js
Normal file
20
extensions/xml-language-features/extension.webpack.config.js
Normal file
@@ -0,0 +1,20 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
//@ts-check
|
||||
|
||||
'use strict';
|
||||
|
||||
const withDefaults = require('../shared.webpack.config');
|
||||
|
||||
module.exports = withDefaults({
|
||||
context: __dirname,
|
||||
resolve: {
|
||||
mainFields: ['module', 'main']
|
||||
},
|
||||
entry: {
|
||||
extension: './src/extension.ts',
|
||||
}
|
||||
});
|
||||
27
extensions/xml-language-features/package.json
Normal file
27
extensions/xml-language-features/package.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "xml-language-features",
|
||||
"displayName": "%displayName%",
|
||||
"description": "%description%",
|
||||
"version": "1.0.0",
|
||||
"publisher": "microsoft",
|
||||
"engines": {
|
||||
"vscode": "^1.20.0"
|
||||
},
|
||||
"main": "./out/extension",
|
||||
"categories": [
|
||||
"Programming Languages"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onLanguage:xml"
|
||||
],
|
||||
"scripts": {
|
||||
"compile": "gulp compile-extension:markdown-language-features && npm run build-preview",
|
||||
"watch": "npm run build-preview && gulp watch-extension:markdown-language-features",
|
||||
"vscode:prepublish": "npm run build-ext && npm run build-preview",
|
||||
"build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown-language-features ./tsconfig.json",
|
||||
"build-preview": "webpack --mode development"
|
||||
},
|
||||
"dependencies": {
|
||||
"tsxml": "^0.1.0"
|
||||
}
|
||||
}
|
||||
4
extensions/xml-language-features/package.nls.json
Normal file
4
extensions/xml-language-features/package.nls.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"displayName": "XML Language Features",
|
||||
"description": "Provides rich language support for XML."
|
||||
}
|
||||
18
extensions/xml-language-features/src/extension.ts
Normal file
18
extensions/xml-language-features/src/extension.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as xml from 'tsxml';
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
context.subscriptions.push(vscode.languages.registerDocumentFormattingEditProvider({ language: 'xml' }, {
|
||||
provideDocumentFormattingEdits: document => format(document)
|
||||
}));
|
||||
}
|
||||
|
||||
function format(document: vscode.TextDocument): vscode.ProviderResult<vscode.TextEdit[]> {
|
||||
const range = new vscode.Range(0, 0, document.lineCount, document.lineAt(document.lineCount - 1).range.end.character);
|
||||
return xml.Compiler.formatXmlString(document.getText()).then(formatted => [new vscode.TextEdit(range, formatted)]);
|
||||
}
|
||||
@@ -3,9 +3,5 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'pretty-data' {
|
||||
export interface PrettyData {
|
||||
xml(input: string): string;
|
||||
}
|
||||
export var pd: PrettyData;
|
||||
}
|
||||
/// <reference path='../../../../src/vs/vscode.d.ts'/>
|
||||
/// <reference path='../../../../src/vs/vscode.proposed.d.ts'/>
|
||||
13
extensions/xml-language-features/tsconfig.json
Normal file
13
extensions/xml-language-features/tsconfig.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "../shared.tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out",
|
||||
"experimentalDecorators": true,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
]
|
||||
}
|
||||
8
extensions/xml-language-features/yarn.lock
Normal file
8
extensions/xml-language-features/yarn.lock
Normal file
@@ -0,0 +1,8 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
tsxml@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tsxml/-/tsxml-0.1.0.tgz#d73f14a0d844af51edc0b98bdb52634a41b9b0d4"
|
||||
integrity sha1-1z8UoNhEr1HtwLmL21JjSkG5sNQ=
|
||||
@@ -60,7 +60,6 @@
|
||||
"native-watchdog": "1.0.0",
|
||||
"ng2-charts": "^1.6.0",
|
||||
"node-pty": "0.9.0-beta9",
|
||||
"pretty-data": "^0.40.0",
|
||||
"reflect-metadata": "^0.1.8",
|
||||
"rxjs": "5.4.0",
|
||||
"sanitize-html": "^1.19.1",
|
||||
|
||||
1
src/bootstrap-window.js
vendored
1
src/bootstrap-window.js
vendored
@@ -115,7 +115,6 @@ exports.load = function (modulePaths, resultCallback, options) {
|
||||
'@angular/router',
|
||||
'angular2-grid',
|
||||
'ansi_up',
|
||||
'pretty-data',
|
||||
'html-query-plan',
|
||||
'ng2-charts',
|
||||
'rxjs/Observable',
|
||||
|
||||
@@ -11,16 +11,12 @@ import { SaveResultsRequestParams } from 'azdata';
|
||||
import { IQueryManagementService } from 'sql/platform/query/common/queryManagement';
|
||||
import { ISaveRequest, SaveFormat } from 'sql/workbench/parts/grid/common/interfaces';
|
||||
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWindowsService, IWindowService, FileFilter } from 'vs/platform/windows/common/windows';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as pretty from 'pretty-data';
|
||||
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
@@ -38,13 +34,11 @@ let prevSavePath: string;
|
||||
*/
|
||||
export class ResultSerializer {
|
||||
public static tempFileCount: number = 1;
|
||||
private static MAX_FILENAMES = 100;
|
||||
|
||||
private _uri: string;
|
||||
private _filePath: string;
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IOutputService private _outputService: IOutputService,
|
||||
@IQueryManagementService private _queryManagementService: IQueryManagementService,
|
||||
@IConfigurationService private _workspaceConfigurationService: IConfigurationService,
|
||||
@@ -52,7 +46,6 @@ export class ResultSerializer {
|
||||
@IWorkspaceContextService private _contextService: IWorkspaceContextService,
|
||||
@IWindowsService private _windowsService: IWindowsService,
|
||||
@IWindowService private _windowService: IWindowService,
|
||||
@IUntitledEditorService private _untitledEditorService: IUntitledEditorService,
|
||||
@INotificationService private _notificationService: INotificationService
|
||||
) { }
|
||||
|
||||
@@ -72,59 +65,6 @@ export class ResultSerializer {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a xml/json link - Opens the content in a new editor pane
|
||||
*/
|
||||
public openLink(content: string, columnName: string, linkType: string): void {
|
||||
let fileMode: string = undefined;
|
||||
let fileUri = this.getUntitledFileUri(columnName);
|
||||
|
||||
if (linkType === SaveFormat.XML) {
|
||||
fileMode = SaveFormat.XML;
|
||||
try {
|
||||
content = pretty.pd.xml(content);
|
||||
} catch (e) {
|
||||
// If Xml fails to parse, fall back on original Xml content
|
||||
}
|
||||
} else if (linkType === SaveFormat.JSON) {
|
||||
let jsonContent: string = undefined;
|
||||
fileMode = SaveFormat.JSON;
|
||||
try {
|
||||
jsonContent = JSON.parse(content);
|
||||
} catch (e) {
|
||||
// If Json fails to parse, fall back on original Json content
|
||||
}
|
||||
if (jsonContent) {
|
||||
// If Json content was valid and parsed, pretty print content to a string
|
||||
content = JSON.stringify(jsonContent, undefined, 4);
|
||||
}
|
||||
}
|
||||
|
||||
this.openUntitledFile(fileMode, content, fileUri);
|
||||
}
|
||||
|
||||
private getUntitledFileUri(columnName: string): URI {
|
||||
let fileName = columnName;
|
||||
|
||||
let uri: URI = URI.from({ scheme: Schemas.untitled, path: fileName });
|
||||
|
||||
// If the current filename is taken, try another up to a max number
|
||||
if (this._untitledEditorService.exists(uri)) {
|
||||
let i = 1;
|
||||
while (i < ResultSerializer.MAX_FILENAMES
|
||||
&& this._untitledEditorService.exists(uri)) {
|
||||
fileName = [columnName, i.toString()].join('-');
|
||||
uri = URI.from({ scheme: Schemas.untitled, path: fileName });
|
||||
i++;
|
||||
}
|
||||
if (this._untitledEditorService.exists(uri)) {
|
||||
// If this fails, return undefined and let the system figure out the right name
|
||||
uri = undefined;
|
||||
}
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
private ensureOutputChannelExists(): void {
|
||||
Registry.as<IOutputChannelRegistry>(OutputExtensions.OutputChannels)
|
||||
.registerChannel({
|
||||
@@ -387,23 +327,4 @@ export class ResultSerializer {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the saved file in a new vscode editor pane
|
||||
*/
|
||||
private openUntitledFile(fileMode: string, contents: string, fileUri: URI = undefined): void {
|
||||
const input = this._untitledEditorService.createOrGet(fileUri, fileMode, contents);
|
||||
|
||||
this._editorService.openEditor(input, { pinned: true })
|
||||
.then(
|
||||
(success) => {
|
||||
},
|
||||
(error: any) => {
|
||||
this._notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
message: error
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,16 +145,6 @@ export class DataService {
|
||||
serializer.saveResults(this._uri, saveRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* send request to open content in new editor
|
||||
* @param content The content to be opened
|
||||
* @param columnName The column name of the content
|
||||
*/
|
||||
openLink(content: string, columnName: string, linkType: string): void {
|
||||
let serializer = this._instantiationService.createInstance(ResultSerializer);
|
||||
serializer.openLink(content, columnName, linkType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a copy request
|
||||
* @param selection The selection range to copy
|
||||
|
||||
@@ -16,7 +16,6 @@ import { IGridInfo, IGridDataSet, SaveFormat } from 'sql/workbench/parts/grid/co
|
||||
import * as Utils from 'sql/platform/connection/common/utils';
|
||||
import { DataService } from 'sql/workbench/parts/grid/services/dataService';
|
||||
import * as actions from 'sql/workbench/parts/grid/views/gridActions';
|
||||
import * as Services from 'sql/base/browser/ui/table/formatters';
|
||||
import * as GridContentEvents from 'sql/workbench/parts/grid/common/gridContentEvents';
|
||||
import { ResultsVisibleContext, ResultsGridFocussedContext, ResultsMessagesFocussedContext, QueryEditorVisibleContext } from 'sql/workbench/parts/query/common/queryContext';
|
||||
import { IQueryEditorService } from 'sql/workbench/services/queryEditor/common/queryEditorService';
|
||||
@@ -487,65 +486,6 @@ export abstract class GridParentComponent {
|
||||
sel.addRange(range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add handler for clicking on xml link
|
||||
*/
|
||||
xmlLinkHandler = (cellRef: string, row: number, dataContext: JSON, colDef: any) => {
|
||||
const self = this;
|
||||
|
||||
let value = self.getCellValueString(dataContext, colDef);
|
||||
if (value.startsWith('<ShowPlanXML') && colDef.name !== 'XML Showplan') {
|
||||
self.handleQueryPlanLink(cellRef, value);
|
||||
} else {
|
||||
self.handleLink(cellRef, row, dataContext, colDef, 'xml');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add handler for clicking on json link
|
||||
*/
|
||||
jsonLinkHandler = (cellRef: string, row: number, dataContext: JSON, colDef: any) => {
|
||||
const self = this;
|
||||
self.handleLink(cellRef, row, dataContext, colDef, 'json');
|
||||
}
|
||||
|
||||
private handleQueryPlanLink(cellRef: string, value: string): void {
|
||||
const self = this;
|
||||
jQuery(cellRef).children('.xmlLink').click(function (): void {
|
||||
self.queryEditorService.newQueryPlanEditor(value);
|
||||
});
|
||||
}
|
||||
|
||||
private handleLink(cellRef: string, row: number, dataContext: JSON, colDef: any, linkType: string): void {
|
||||
const self = this;
|
||||
let value = self.getCellValueString(dataContext, colDef);
|
||||
jQuery(cellRef).children('.xmlLink').click(function (): void {
|
||||
self.dataService.openLink(value, colDef.name, linkType);
|
||||
});
|
||||
}
|
||||
|
||||
private getCellValueString(dataContext: JSON, colDef: any): string {
|
||||
let returnVal = '';
|
||||
let value = dataContext[colDef.field];
|
||||
if (Services.DBCellValue.isDBCellValue(value)) {
|
||||
returnVal = value.displayValue;
|
||||
} else if (typeof value === 'string') {
|
||||
returnVal = value;
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return asyncPostRender handler based on type
|
||||
*/
|
||||
public linkHandler(type: string): Function {
|
||||
if (type === 'xml') {
|
||||
return this.xmlLinkHandler;
|
||||
} else { // default to JSON handler
|
||||
return this.jsonLinkHandler;
|
||||
}
|
||||
}
|
||||
|
||||
keyEvent(e: KeyboardEvent): void {
|
||||
if (this.tryHandleKeyEvent(new StandardKeyboardEvent(e))) {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as pretty from 'pretty-data';
|
||||
|
||||
import { attachTableStyler } from 'sql/platform/theme/common/styler';
|
||||
import QueryRunner from 'sql/platform/query/common/queryRunner';
|
||||
import { VirtualizedCollection, AsyncDataProvider } from 'sql/base/browser/ui/table/asyncDataView';
|
||||
@@ -41,6 +39,8 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { formatDocumentWithSelectedProvider, FormattingMode } from 'vs/editor/contrib/format/format';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
const ROW_HEIGHT = 29;
|
||||
const HEADER_HEIGHT = 26;
|
||||
@@ -605,30 +605,14 @@ class GridTable<T> extends Disposable implements IView {
|
||||
let column = this.resultSet.columnInfo[event.cell.cell - 1];
|
||||
// handle if a showplan link was clicked
|
||||
if (column && (column.isXml || column.isJson)) {
|
||||
this.runner.getQueryRows(event.cell.row, 1, this.resultSet.batchId, this.resultSet.id).then(d => {
|
||||
this.runner.getQueryRows(event.cell.row, 1, this.resultSet.batchId, this.resultSet.id).then(async d => {
|
||||
let value = d.resultSubset.rows[0][event.cell.cell - 1];
|
||||
let content = value.displayValue;
|
||||
if (column.isXml) {
|
||||
try {
|
||||
content = pretty.pd.xml(content);
|
||||
} catch (e) {
|
||||
// If Xml fails to parse, fall back on original Xml content
|
||||
}
|
||||
} else {
|
||||
let jsonContent: string = undefined;
|
||||
try {
|
||||
jsonContent = JSON.parse(content);
|
||||
} catch (e) {
|
||||
// If Json fails to parse, fall back on original Json content
|
||||
}
|
||||
if (jsonContent) {
|
||||
// If Json content was valid and parsed, pretty print content to a string
|
||||
content = JSON.stringify(jsonContent, undefined, 4);
|
||||
}
|
||||
}
|
||||
|
||||
let input = this.untitledEditorService.createOrGet(undefined, column.isXml ? 'xml' : 'json', content);
|
||||
this.editorService.openEditor(input);
|
||||
const input = this.untitledEditorService.createOrGet(undefined, column.isXml ? 'xml' : 'json', content);
|
||||
const model = await input.resolve();
|
||||
await this.instantiationService.invokeFunction(formatDocumentWithSelectedProvider, model.textEditorModel, FormattingMode.Explicit, CancellationToken.None);
|
||||
return this.editorService.openEditor(input);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7091,11 +7091,6 @@ pretty-bytes@^1.0.2:
|
||||
get-stdin "^4.0.1"
|
||||
meow "^3.1.0"
|
||||
|
||||
pretty-data@^0.40.0:
|
||||
version "0.40.0"
|
||||
resolved "https://registry.yarnpkg.com/pretty-data/-/pretty-data-0.40.0.tgz#572aa8ea23467467ab94b6b5266a6fd9c8fddd72"
|
||||
integrity sha1-Vyqo6iNGdGerlLa1Jmpv2cj93XI=
|
||||
|
||||
pretty-hrtime@^1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
|
||||
|
||||
Reference in New Issue
Block a user