forked from external/vscode-xml
		
	Add XML FormattingEditProviders
This commit is contained in:
		
							parent
							
								
									cf5331466b
								
							
						
					
					
						commit
						3d9879c853
					
				
					 2 changed files with 129 additions and 16 deletions
				
			
		| 
						 | 
				
			
			@ -1,22 +1,132 @@
 | 
			
		|||
'use strict';
 | 
			
		||||
 | 
			
		||||
import { TextEditor, TextEditorEdit } from 'vscode';
 | 
			
		||||
import {
 | 
			
		||||
Range,
 | 
			
		||||
TextEdit,
 | 
			
		||||
TextEditor,
 | 
			
		||||
TextDocument,
 | 
			
		||||
TextEditorEdit,
 | 
			
		||||
CancellationToken,
 | 
			
		||||
FormattingOptions,
 | 
			
		||||
DocumentFormattingEditProvider,
 | 
			
		||||
DocumentRangeFormattingEditProvider
 | 
			
		||||
} from 'vscode';
 | 
			
		||||
 | 
			
		||||
import { getRangeForDocument } from '../utils/RangeUtils';
 | 
			
		||||
 | 
			
		||||
let pd = require('pretty-data').pd;
 | 
			
		||||
 | 
			
		||||
export function formatXml(editor: TextEditor, edit: TextEditorEdit): void {
 | 
			
		||||
	let current = editor.document.getText();
 | 
			
		||||
	let pretty = pd.xml(current);
 | 
			
		||||
	let range = getRangeForDocument(editor.document);
 | 
			
		||||
 | 
			
		||||
	edit.replace(range, pretty);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function linearizeXml(editor: TextEditor, edit: TextEditorEdit): void {
 | 
			
		||||
	let current = editor.document.getText();
 | 
			
		||||
	let linear = pd.xmlmin(current);
 | 
			
		||||
	let range = getRangeForDocument(editor.document);
 | 
			
		||||
 | 
			
		||||
	edit.replace(range, linear);
 | 
			
		||||
	edit.replace(range, _linearizeXml(current));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class XmlDocumentFormattingProvider implements DocumentFormattingEditProvider {
 | 
			
		||||
	provideDocumentFormattingEdits(document: TextDocument, options: FormattingOptions, token: CancellationToken): TextEdit[] {
 | 
			
		||||
		let current = document.getText();
 | 
			
		||||
		let range = getRangeForDocument(document);
 | 
			
		||||
 | 
			
		||||
		return [TextEdit.replace(range, _formatXml(current, options))];
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class XmlRangeFormattingProvider implements DocumentRangeFormattingEditProvider {
 | 
			
		||||
	provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): TextEdit[] {
 | 
			
		||||
		let current = document.getText(range);
 | 
			
		||||
 | 
			
		||||
		return [TextEdit.replace(range, _formatXml(current, options))];
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _strRepeat(source: string, count: number): string {
 | 
			
		||||
	let output = '';
 | 
			
		||||
	
 | 
			
		||||
	for (let i = 0; i < count; i++) {
 | 
			
		||||
		output += source;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _linearizeXml(xml: string): string {
 | 
			
		||||
	return xml.replace(/>\s{0,}</g, '><');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _formatXml(xml: string, options: FormattingOptions): string {
 | 
			
		||||
	/* This code was taken from https://github.com/vkiryukhin/pretty-data/blob/master/pretty-data.js
 | 
			
		||||
	 * and refactored to fit our needs for this extension. pretty-data is dual-licensed (MIT/GPL).
 | 
			
		||||
	 */
 | 
			
		||||
	
 | 
			
		||||
	let parts = _linearizeXml(xml)
 | 
			
		||||
		.replace(/</g,"~::~<")
 | 
			
		||||
		.replace(/xmlns\:/g,"~::~xmlns:")
 | 
			
		||||
		.replace(/xmlns\=/g,"~::~xmlns=")
 | 
			
		||||
		.split('~::~');
 | 
			
		||||
	
 | 
			
		||||
	let tab = _strRepeat(' ', options.tabSize);
 | 
			
		||||
	let deep = 0;
 | 
			
		||||
	let output = '';
 | 
			
		||||
	let formatted = false;
 | 
			
		||||
	
 | 
			
		||||
	for (let i = 0; i < parts.length; i++) {
 | 
			
		||||
		
 | 
			
		||||
		// start comment, CDATA, or DOCTYPE
 | 
			
		||||
		if (parts[i].search(/<!/) > -1) {
 | 
			
		||||
			output += _strRepeat(tab, deep) + parts[i];
 | 
			
		||||
			formatted = true;
 | 
			
		||||
			
 | 
			
		||||
			// end comment, CDATA, or DOCTYPE
 | 
			
		||||
			if (parts[i].search(/-->/) > -1 || parts[i].search(/\]>/) > -1 || parts[i].search(/!DOCTYPE/) > -1) {
 | 
			
		||||
				formatted = false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		// end comment or CDATA
 | 
			
		||||
		else if (parts[i].search(/-->/) > -1 || parts[i].search(/\]>/) > -1) {
 | 
			
		||||
			output += parts[i];
 | 
			
		||||
			formatted = false;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		// <elm></elm>
 | 
			
		||||
		else if (/^<\w/.exec(parts[i - 1]) && /^<\/\w/.exec(parts[i]) && (/^<[\w:\-\.\,]+/.exec(parts[i - 1])[0] == /^<\/[\w:\-\.\,]+/.exec(parts[i])[0].replace('/','')) {
 | 
			
		||||
			output += parts[i];
 | 
			
		||||
			if (!formatted) deep--;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		// <elm>
 | 
			
		||||
		else if (parts[i].search(/<\w/) > -1 && parts[i].search(/<\//) == -1 && parts[i].search(/\/>/) == -1 ) {
 | 
			
		||||
			output = !formatted ? output += _strRepeat(tab, deep++) + parts[i] : output += parts[i];
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		// <elm>...</elm>
 | 
			
		||||
		else if (parts[i].search(/<\w/) > -1 && parts[i].search(/<\//) > -1) {
 | 
			
		||||
			output = !formatted ? output += _strRepeat(tab, deep) + parts[i] : output += parts[i];
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		// </elm>
 | 
			
		||||
		else if (parts[i].search(/<\//) > -1) {
 | 
			
		||||
			output = !formatted ? output += _strRepeat(tab, --deep) + parts[i] : output += parts[i];
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		// <elm/>
 | 
			
		||||
		else if (parts[i].search(/\/>/) > -1) {
 | 
			
		||||
			output = !formatted ? output += _strRepeat(tab, deep) + parts[i] : output += parts[i];
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		// <?xml ... ?>
 | 
			
		||||
		else if (parts[i].search(/<\?/) > -1) {
 | 
			
		||||
			output += _strRepeat(tab, deep) + parts[i];
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		// xmlns
 | 
			
		||||
		else if (parts[i].search(/xmlns\:/) > -1  || parts[i].search(/xmlns\=/) > -1) {
 | 
			
		||||
			output += _strRepeat(tab, deep) + parts[i];
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		else {
 | 
			
		||||
			output += parts[i];
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return output;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
'use strict';
 | 
			
		||||
 | 
			
		||||
import { commands, ExtensionContext } from 'vscode';
 | 
			
		||||
import { formatXml, linearizeXml } from './features/xmlFormatting';
 | 
			
		||||
import { commands, languages, ExtensionContext } from 'vscode';
 | 
			
		||||
import { linearizeXml, XmlDocumentFormattingProvider, XmlRangeFormattingProvider } from './features/xmlFormatting';
 | 
			
		||||
import { evaluateXPath } from './features/xmlXPathEngine';
 | 
			
		||||
import { checkForUpdates } from './utils/UpdateNotifier';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,10 @@ export function activate(ctx: ExtensionContext) {
 | 
			
		|||
	checkForUpdates();
 | 
			
		||||
	
 | 
			
		||||
	// register palette commands
 | 
			
		||||
	ctx.subscriptions.push(commands.registerTextEditorCommand('xmltools.formatXml', formatXml));
 | 
			
		||||
	ctx.subscriptions.push(commands.registerTextEditorCommand('xmltools.linearizeXml', linearizeXml));
 | 
			
		||||
	ctx.subscriptions.push(commands.registerTextEditorCommand('xmltools.evaluateXPath', evaluateXPath));
 | 
			
		||||
	
 | 
			
		||||
	// register formatting providers
 | 
			
		||||
	ctx.subscriptions.push(languages.registerDocumentFormattingEditProvider('xml', new XmlDocumentFormattingProvider()));
 | 
			
		||||
	ctx.subscriptions.push(languages.registerDocumentRangeFormattingEditProvider('xml', new XmlRangeFormattingProvider()));
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue