diff --git a/package.json b/package.json index 49bf409..678d966 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,11 @@ "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." } } }, diff --git a/src/Extension.ts b/src/Extension.ts index 622e72b..6bcdbe9 100644 --- a/src/Extension.ts +++ b/src/Extension.ts @@ -2,7 +2,7 @@ import * as vsc from 'vscode'; import { TextEditorCommands } from './Commands'; -import { XmlDocumentFormattingEditProvider, XmlRangeFormattingEditProvider } from './providers/Formatting'; +import { XmlFormattingEditProvider } from './providers/Formatting'; export var GlobalState: vsc.Memento; export var WorkspaceState: vsc.Memento; @@ -24,8 +24,8 @@ export function activate(ctx: vsc.ExtensionContext) { // register language feature providers ctx.subscriptions.push( - vsc.languages.registerDocumentFormattingEditProvider(LANG_XML, new XmlDocumentFormattingEditProvider()), - vsc.languages.registerDocumentRangeFormattingEditProvider(LANG_XML, new XmlRangeFormattingEditProvider()) + vsc.languages.registerDocumentFormattingEditProvider(LANG_XML, new XmlFormattingEditProvider()), + vsc.languages.registerDocumentRangeFormattingEditProvider(LANG_XML, new XmlFormattingEditProvider()) ); } diff --git a/src/providers/Formatting.ts b/src/providers/Formatting.ts index 61766b3..494308a 100644 --- a/src/providers/Formatting.ts +++ b/src/providers/Formatting.ts @@ -2,21 +2,32 @@ import * as vsc from 'vscode'; import { RangeUtil } from '../utils/RangeUtil'; -import { XmlFormatter } from '../services/XmlFormatter'; +import { XmlFormatter, IXmlFormatterOptions } from '../services/XmlFormatter'; -export class XmlDocumentFormattingEditProvider implements vsc.DocumentFormattingEditProvider { +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); - let formatter = new XmlFormatter(options.insertSpaces, options.tabSize); - let xml = formatter.format(document.getText()); - return [ vsc.TextEdit.replace(range, xml) ]; + return this._provideFormattingEdits(document, range, options); } -} - -export class XmlRangeFormattingEditProvider implements vsc.DocumentRangeFormattingEditProvider { + provideDocumentRangeFormattingEdits(document: vsc.TextDocument, range: vsc.Range, options: vsc.FormattingOptions): vsc.TextEdit[] { - let formatter = new XmlFormatter(options.insertSpaces, options.tabSize); + 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(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()); return [ vsc.TextEdit.replace(range, xml) ]; diff --git a/src/services/XmlFormatter.ts b/src/services/XmlFormatter.ts index 821c8ae..2aed3c1 100644 --- a/src/services/XmlFormatter.ts +++ b/src/services/XmlFormatter.ts @@ -2,29 +2,40 @@ // Based on pretty-data (https://github.com/vkiryukhin/pretty-data) export class XmlFormatter { - constructor(preferSpaces?: boolean, tabSize?: number, newLine?: string) { - if (typeof preferSpaces === 'undefined') { - preferSpaces = false; + constructor(options?: IXmlFormatterOptions) { + options = options || {}; + + if (typeof options.preferSpaces === 'undefined') { + options.preferSpaces = false; } - tabSize = tabSize || 4; - newLine = newLine || '\n'; + if (typeof options.splitNamespaces === 'undefined') { + options.splitNamespaces = true; + } - this.newLine = newLine || '\n'; - this.indentPattern = (preferSpaces) ? ' '.repeat(tabSize) : '\t'; + 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(/