From e6ca8f597fc80c9d4f15ab9540eecdde8f9dedc5 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Sat, 25 Jul 2020 22:17:47 -0400 Subject: [PATCH 1/9] Add Tests for Issue #294 --- src/test/extension.test.ts | 4 ++++ src/test/test-data/issue-294.formatted.xml | 7 +++++++ src/test/test-data/issue-294.unformatted.xml | 7 +++++++ 3 files changed, 18 insertions(+) create mode 100644 src/test/test-data/issue-294.formatted.xml create mode 100644 src/test/test-data/issue-294.unformatted.xml diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index dc4e04d..c2e20dd 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -107,6 +107,10 @@ describe("V2XmlFormatter", () => { it("should not add trailing whitespace", () => { testFormatter(xmlFormatter, options, "issue-288"); }); + + it("should handle mixed content on the same line as another element", () => { + testFormatter(xmlFormatter, options, "issue-294"); + }); }); describe("#minifyXml(xml, options)", () => { diff --git a/src/test/test-data/issue-294.formatted.xml b/src/test/test-data/issue-294.formatted.xml new file mode 100644 index 0000000..0d46e60 --- /dev/null +++ b/src/test/test-data/issue-294.formatted.xml @@ -0,0 +1,7 @@ + + +
+ ThisCausesBug + +
+
\ No newline at end of file diff --git a/src/test/test-data/issue-294.unformatted.xml b/src/test/test-data/issue-294.unformatted.xml new file mode 100644 index 0000000..2fdc9de --- /dev/null +++ b/src/test/test-data/issue-294.unformatted.xml @@ -0,0 +1,7 @@ + + +
+ ThisCausesBug + +
+
\ No newline at end of file From e9ba54d3b841cf474f26659503ebe0ecfe047eb2 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Sat, 25 Jul 2020 22:26:22 -0400 Subject: [PATCH 2/9] Add "Get Current XPath" to Editor Context Menu closes #284 --- package.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index ca89fab..c927a94 100644 --- a/package.json +++ b/package.json @@ -245,6 +245,11 @@ "command": "xmlTools.minifyXml", "group": "1_modification@100", "when": "editorLangId == 'xml'" + }, + { + "command": "xmlTools.getCurrentXPath", + "group": "z_commands", + "when": "editorLangId == 'xml'" } ] }, @@ -280,4 +285,4 @@ "xpath": "0.0.27", "xqlint": "^0.4.1" } -} +} \ No newline at end of file From 68b18c87023918d04a64d3ddd1d41cd8747e6be4 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Sat, 25 Jul 2020 22:37:56 -0400 Subject: [PATCH 3/9] Set "xqueryExecutionEngine" Scope to "Machine" closes #280 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c927a94..6e839a2 100644 --- a/package.json +++ b/package.json @@ -159,7 +159,7 @@ "type": "string", "default": "", "description": "The full path to the executable to run when executing XQuery scripts.", - "scope": "window" + "scope": "machine" }, "xmlTools.xqueryExecutionInputLimit": { "type": "integer", From 428bf450a1559966b16490bfc66d806f6c2ba99b Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Wed, 25 Nov 2020 16:13:57 -0500 Subject: [PATCH 4/9] Bump v2.6.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6e839a2..8822f2b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "xml", "displayName": "XML Tools", "description": "XML Formatting, XQuery, and XPath Tools for Visual Studio Code", - "version": "2.5.1", + "version": "2.6.0", "preview": false, "publisher": "DotJoshJohnson", "author": { From 276e16b245a7c7cc6014185d08fa6b70ba8710a4 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Wed, 25 Nov 2020 16:26:08 -0500 Subject: [PATCH 5/9] Correct Test for Issue 294 closes #294 --- src/test/extension.test.ts | 2 +- src/test/test-data/issue-294.formatted.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index c2e20dd..be01e22 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -108,7 +108,7 @@ describe("V2XmlFormatter", () => { testFormatter(xmlFormatter, options, "issue-288"); }); - it("should handle mixed content on the same line as another element", () => { + it("should handle mixed content on the same line as another element without error", () => { testFormatter(xmlFormatter, options, "issue-294"); }); }); diff --git a/src/test/test-data/issue-294.formatted.xml b/src/test/test-data/issue-294.formatted.xml index 0d46e60..df31b2b 100644 --- a/src/test/test-data/issue-294.formatted.xml +++ b/src/test/test-data/issue-294.formatted.xml @@ -1,7 +1,7 @@
- ThisCausesBug - -
+ ThisCausesBug + +
\ No newline at end of file From ab082e3e0ec8f9e3cd4ae111f18c37bb65bb16d4 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Wed, 25 Nov 2020 16:46:31 -0500 Subject: [PATCH 6/9] Add Minify XML (Selection) Command closes #302 --- package.json | 9 +++++++++ src/constants.ts | 1 + src/extension.ts | 7 ++++--- src/formatting/commands/index.ts | 1 + src/formatting/commands/minifyXmlSelection.ts | 19 +++++++++++++++++++ 5 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 src/formatting/commands/minifyXmlSelection.ts diff --git a/package.json b/package.json index 8822f2b..a43c3d6 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,10 @@ { "command": "xmlTools.minifyXml", "title": "XML Tools: Minify XML" + }, + { + "command": "xmlTools.minifyXmlSelection", + "title": "XML Tools: Minify XML (Selection)" } ], "configuration": { @@ -246,6 +250,11 @@ "group": "1_modification@100", "when": "editorLangId == 'xml'" }, + { + "command": "xmlTools.minifyXmlSelection", + "group": "1_modification@100", + "when": "editorLangId == 'xml' && editorHasSelection" + }, { "command": "xmlTools.getCurrentXPath", "group": "z_commands", diff --git a/src/constants.ts b/src/constants.ts index 07d969e..81ebbd0 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -6,6 +6,7 @@ export namespace commands { export const textToXml = "xmlTools.textToXml"; export const getCurrentXPath = "xmlTools.getCurrentXPath"; export const minifyXml = "xmlTools.minifyXml"; + export const minifyXmlSelection = "xmlTools.minifyXmlSelection"; } export namespace contextKeys { diff --git a/src/extension.ts b/src/extension.ts index 17b41b2..e91b4c5 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,12 +1,12 @@ import { commands, languages, window, workspace, ExtensionContext, Memento, TextEditor, TextEditorSelectionChangeEvent, TextEditorSelectionChangeKind, DiagnosticCollection - } from "vscode"; +} from "vscode"; import { createDocumentSelector, ExtensionState, Configuration } from "./common"; import { XQueryCompletionItemProvider } from "./completion"; import { XmlFormatterFactory, XmlFormattingEditProvider } from "./formatting"; -import { formatAsXml, minifyXml, xmlToText, textToXml } from "./formatting/commands"; +import { formatAsXml, minifyXml, xmlToText, textToXml, minifyXmlSelection } from "./formatting/commands"; import { XQueryLinter } from "./linting"; import { XmlTreeDataProvider } from "./tree-view"; import { evaluateXPath, getCurrentXPath } from "./xpath/commands"; @@ -35,6 +35,7 @@ export function activate(context: ExtensionContext) { commands.registerTextEditorCommand(constants.commands.xmlToText, xmlToText), commands.registerTextEditorCommand(constants.commands.textToXml, textToXml), commands.registerTextEditorCommand(constants.commands.minifyXml, minifyXml), + commands.registerTextEditorCommand(constants.commands.minifyXmlSelection, minifyXmlSelection), languages.registerDocumentFormattingEditProvider(xmlXsdDocSelector, xmlFormattingEditProvider), languages.registerDocumentRangeFormattingEditProvider(xmlXsdDocSelector, xmlFormattingEditProvider) ); @@ -91,7 +92,7 @@ function _handleContextChange(editor: TextEditor): void { switch (editor.document.languageId) { case constants.languageIds.xquery: - diagnosticCollectionXQuery.set(editor.document.uri, new XQueryLinter().lint(editor.document.getText())); + diagnosticCollectionXQuery.set(editor.document.uri, new XQueryLinter().lint(editor.document.getText())); break; } } diff --git a/src/formatting/commands/index.ts b/src/formatting/commands/index.ts index 3dc6ea2..35a228e 100644 --- a/src/formatting/commands/index.ts +++ b/src/formatting/commands/index.ts @@ -2,3 +2,4 @@ export * from "./formatAsXml"; export * from "./minifyXml"; export * from "./xmlToText"; export * from "./textToXml"; +export * from "./minifyXmlSelection"; diff --git a/src/formatting/commands/minifyXmlSelection.ts b/src/formatting/commands/minifyXmlSelection.ts new file mode 100644 index 0000000..b63762d --- /dev/null +++ b/src/formatting/commands/minifyXmlSelection.ts @@ -0,0 +1,19 @@ +import { workspace } from "vscode"; +import { Range, TextEditor, TextEditorEdit } from "vscode"; + +import { XmlFormatterFactory } from "../xml-formatter"; +import { XmlFormattingOptionsFactory } from "../xml-formatting-options"; + +export function minifyXmlSelection(editor: TextEditor, edit: TextEditorEdit): void { + const xmlFormatter = XmlFormatterFactory.getXmlFormatter(); + const xmlFormattingOptions = XmlFormattingOptionsFactory.getXmlFormattingOptions({ + insertSpaces: editor.options.insertSpaces, + tabSize: editor.options.tabSize + }, editor.document); + + editor.selections.reverse().forEach(selection => { + const range = new Range(selection.start, selection.end); + + edit.replace(range, xmlFormatter.minifyXml(editor.document.getText(range), xmlFormattingOptions)); + }); +} From 4dab0b5d4e5e187deeb3e0dcd7bccd155a6964dc Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Wed, 25 Nov 2020 22:11:16 -0500 Subject: [PATCH 7/9] Add preserveSpacesBetweenAttributes Setting --- package.json | 6 ++++++ src/common/configuration.ts | 6 +++++- src/formatting/xml-formatting-options.ts | 5 +++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index a43c3d6..b491c20 100644 --- a/package.json +++ b/package.json @@ -176,6 +176,12 @@ "default": "**/*.xml", "description": "The pattern used to search for input XML files when executing XQuery scripts.", "scope": "window" + }, + "xmlTools.preserveSpacesBetweenAttributes": { + "type": "boolean", + "default": false, + "description": "Preserves any spaces between attributes during formatting.", + "scope": "resource" } } }, diff --git a/src/common/configuration.ts b/src/common/configuration.ts index b1461d0..2d6dffc 100644 --- a/src/common/configuration.ts +++ b/src/common/configuration.ts @@ -59,11 +59,15 @@ export class Configuration { return this._getForResource("splitXmlnsOnFormat", resource); } + static preserveSpacesBetweenAttributes(resource: Uri): boolean { + return this._getForResource("preserveSpacesBetweenAttributes", resource); + } + private static _getForResource(section: string, resource: Uri): T { return workspace.getConfiguration(ExtensionTopLevelSection, resource).get(section); } - private static _getForWindow(section: string): T { + private static _getForWindow(section: string): T { return workspace.getConfiguration(ExtensionTopLevelSection).get(section); } } diff --git a/src/formatting/xml-formatting-options.ts b/src/formatting/xml-formatting-options.ts index 7c5185a..bbfb0d9 100644 --- a/src/formatting/xml-formatting-options.ts +++ b/src/formatting/xml-formatting-options.ts @@ -1,7 +1,6 @@ import { EndOfLine, FormattingOptions, TextDocument } from "vscode"; import { Configuration } from "../common"; -import * as constants from "../constants"; export interface XmlFormattingOptions { editorOptions: FormattingOptions; @@ -11,6 +10,7 @@ export interface XmlFormattingOptions { splitAttributesOnFormat: boolean; splitXmlnsOnFormat: boolean; initialIndentLevel?: number; + preserveSpacesBetweenAttributes: boolean; } export class XmlFormattingOptionsFactory { @@ -22,7 +22,8 @@ export class XmlFormattingOptionsFactory { removeCommentsOnMinify: Configuration.removeCommentsOnMinify(document.uri), splitAttributesOnFormat: Configuration.splitAttributesOnFormat(document.uri), splitXmlnsOnFormat: Configuration.splitXmlnsOnFormat(document.uri), - initialIndentLevel: 0 + initialIndentLevel: 0, + preserveSpacesBetweenAttributes: Configuration.preserveSpacesBetweenAttributes(document.uri) }; } } From c36509902e19fee11b2e4e514ca2a01a140ade90 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Wed, 25 Nov 2020 22:21:42 -0500 Subject: [PATCH 8/9] Implement Attribute Space Preservation --- src/formatting/formatters/v2-xml-formatter.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/formatting/formatters/v2-xml-formatter.ts b/src/formatting/formatters/v2-xml-formatter.ts index 281f631..55a6bcd 100644 --- a/src/formatting/formatters/v2-xml-formatter.ts +++ b/src/formatting/formatters/v2-xml-formatter.ts @@ -17,12 +17,18 @@ export class V2XmlFormatter implements XmlFormatter { }); // do some light minification to get rid of insignificant whitespace - xml = xml.replace(/"\s+(?=[^\s]+=)/g, "\" "); // spaces between attributes + if (!options.preserveSpacesBetweenAttributes) { + 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, " "); - }); + + if (!options.preserveSpacesBetweenAttributes) { + xml = xml.replace(/(?!="]\s+[^ <>="]+=(?![^<]*?\]\]>)/g, (match: string) => { // spaces between the node name and the first attribute + return match.replace(/\s+/g, " "); + }); + } // the coast is clear - we can drop those "<" brackets back in xml = this._unsanitizeCommentsAndCDATA(xml); From db108a9db603cad2528d15bf28b6f42a2ab671ae Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Wed, 25 Nov 2020 22:25:21 -0500 Subject: [PATCH 9/9] Add Test --- src/test/extension.test.ts | 14 ++++++++++++-- src/test/test-data/issue-308.formatted.xml | 11 +++++++++++ src/test/test-data/issue-308.unformatted.xml | 11 +++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 src/test/test-data/issue-308.formatted.xml create mode 100644 src/test/test-data/issue-308.unformatted.xml diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index be01e22..8ab4884 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -21,7 +21,8 @@ describe("V2XmlFormatter", () => { newLine: "\r\n", removeCommentsOnMinify: false, splitAttributesOnFormat: false, - splitXmlnsOnFormat: true + splitXmlnsOnFormat: true, + preserveSpacesBetweenAttributes: false }; it("should handle basic XML", () => { @@ -111,6 +112,14 @@ describe("V2XmlFormatter", () => { it("should handle mixed content on the same line as another element without error", () => { testFormatter(xmlFormatter, options, "issue-294"); }); + + it("should optionally preserve whitespace between attributes", () => { + options.preserveSpacesBetweenAttributes = true; + + testFormatter(xmlFormatter, options, "issue-308"); + + options.preserveSpacesBetweenAttributes = false; + }); }); describe("#minifyXml(xml, options)", () => { @@ -124,7 +133,8 @@ describe("V2XmlFormatter", () => { newLine: "\r\n", removeCommentsOnMinify: false, splitAttributesOnFormat: false, - splitXmlnsOnFormat: true + splitXmlnsOnFormat: true, + preserveSpacesBetweenAttributes: false }; it("should preserve whitespace on minify if xml:space is set to 'preserve-whitespace'", () => { diff --git a/src/test/test-data/issue-308.formatted.xml b/src/test/test-data/issue-308.formatted.xml new file mode 100644 index 0000000..1764642 --- /dev/null +++ b/src/test/test-data/issue-308.formatted.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/test-data/issue-308.unformatted.xml b/src/test/test-data/issue-308.unformatted.xml new file mode 100644 index 0000000..1764642 --- /dev/null +++ b/src/test/test-data/issue-308.unformatted.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file