提交 ef9e03c8 编写于 作者: M Martin Aeschlimann

[html] Format onPaste issues with HTML. Fixes #21218

上级 2ef2602c
......@@ -8,9 +8,9 @@
"resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-2.0.1.tgz"
},
"vscode-html-languageservice": {
"version": "2.0.2-next.2",
"version": "2.0.3",
"from": "vscode-html-languageservice@next",
"resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-2.0.2-next.2.tgz"
"resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-2.0.3.tgz"
},
"vscode-jsonrpc": {
"version": "3.1.0-alpha.1",
......
......@@ -9,7 +9,7 @@
},
"dependencies": {
"vscode-css-languageservice": "^2.0.1",
"vscode-html-languageservice": "^2.0.2-next.2",
"vscode-html-languageservice": "^2.0.3",
"vscode-languageserver": "^3.1.0-alpha.1",
"vscode-nls": "^2.0.2",
"vscode-uri": "^1.0.0"
......
......@@ -10,6 +10,7 @@ import { TextDocument, Diagnostic, DocumentLink, Range, SymbolInformation } from
import { getLanguageModes, LanguageModes } from './modes/languageModes';
import { format } from './modes/formatting';
import { pushAll } from './utils/arrays';
import * as url from 'url';
import * as path from 'path';
......@@ -165,14 +166,6 @@ function validateTextDocument(textDocument: TextDocument): void {
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
}
function pushAll<T>(to: T[], from: T[]) {
if (from) {
for (var i = 0; i < from.length; i++) {
to.push(from[i]);
}
}
}
connection.onCompletion(textDocumentPosition => {
let document = documents.get(textDocumentPosition.textDocument.uri);
let mode = languageModes.getModeAtPosition(document, textDocumentPosition.position);
......
......@@ -7,8 +7,11 @@
import { applyEdits } from '../utils/edits';
import { TextDocument, Range, TextEdit, FormattingOptions } from 'vscode-languageserver-types';
import { LanguageModes } from './languageModes';
import { pushAll } from '../utils/arrays';
export function format(languageModes: LanguageModes, document: TextDocument, formatRange: Range, formattingOptions: FormattingOptions, enabledModes: { [mode: string]: boolean }) {
let result: TextEdit[] = [];
// run the html formatter on the full range and pass the result content to the embedded formatters.
// from the final content create a single edit
// advantages of this approach are
......@@ -16,6 +19,25 @@ export function format(languageModes: LanguageModes, document: TextDocument, for
// - correct initial indent for embedded formatters
// - no worrying of overlapping edits
// make sure we start in html
let allRanges = languageModes.getModesInRange(document, formatRange);
let i = 0;
let startPos = formatRange.start;
while (i < allRanges.length && allRanges[i].mode.getId() !== 'html') {
let range = allRanges[i];
if (!range.attributeValue && range.mode.format) {
let edits = range.mode.format(document, Range.create(startPos, range.end), formattingOptions);
pushAll(result, edits);
}
startPos = range.end;
i++;
}
if (i === allRanges.length) {
return result;
}
// modify the range
formatRange = Range.create(startPos, formatRange.end);
// perform a html format and apply changes to a new document
let htmlMode = languageModes.getMode('html');
let htmlEdits = htmlMode.format(document, formatRange, formattingOptions);
......@@ -40,14 +62,16 @@ export function format(languageModes: LanguageModes, document: TextDocument, for
};
if (embeddedEdits.length === 0) {
return htmlEdits;
pushAll(result, htmlEdits);
return result;
}
// apply all embedded format edits and create a single edit for all changes
let resultContent = applyEdits(newDocument, embeddedEdits);
let resultReplaceText = resultContent.substring(document.offsetAt(formatRange.start), resultContent.length - afterFormatRangeLength);
return [TextEdit.replace(formatRange, resultReplaceText)];
result.push(TextEdit.replace(formatRange, resultReplaceText));
return result;
} finally {
languageModes.onDocumentRemoved(newDocument);
}
......
......@@ -17,6 +17,7 @@
</script>
</head>
<body> </body>
<body>
</body>
</html>
\ No newline at end of file
......@@ -17,6 +17,7 @@
</script>
</head>
<body> </body>
<body>
</body>
</html>
\ No newline at end of file
......@@ -17,6 +17,7 @@
</script>
</head>
<body> </body>
<body>
</body>
</html>
\ No newline at end of file
<app-route path="/module" element="page-module" bindRouter onUrlChange="updateModel"></app-route>
<script>
Polymer({
});
......
......@@ -15,7 +15,7 @@ import { format } from '../modes/formatting';
suite('HTML Embedded Formatting', () => {
function assertFormat(value: string, expected: string, options?: any, formatOptions?: FormattingOptions): void {
function assertFormat(value: string, expected: string, options?: any, formatOptions?: FormattingOptions, message?: string): void {
var languageModes = getLanguageModes({ css: true, javascript: true });
if (options) {
languageModes.getAllModes().forEach(m => m.configure(options));
......@@ -41,13 +41,13 @@ suite('HTML Embedded Formatting', () => {
let result = format(languageModes, document, range, formatOptions, { css: true, javascript: true });
let actual = applyEdits(document, result);
assert.equal(actual, expected);
assert.equal(actual, expected, message);
}
function assertFormatWithFixture(fixtureName: string, expectedPath: string, options?: any, formatOptions?: FormattingOptions): void {
let input = fs.readFileSync(path.join(__dirname, 'fixtures', 'inputs', fixtureName)).toString();
let expected = fs.readFileSync(path.join(__dirname, 'fixtures', 'expected', expectedPath)).toString();
assertFormat(input, expected, options, formatOptions);
assertFormat(input, expected, options, formatOptions, expectedPath);
}
test('HTML only', function (): any {
......@@ -64,10 +64,9 @@ suite('HTML Embedded Formatting', () => {
assertFormat('<html><head>\n <script>\nvar x=4;\nconsole.log("Hi");\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 4;\n console.log("Hi");\n\n </script>\n</head>\n\n</html>');
assertFormat('<html><head>\n |<script>\nvar x=5;\n</script>|</head></html>', '<html><head>\n <script>\n var x = 5;\n\n </script></head></html>');
assertFormat('<html><head>\n <script>\n|var x=6;|\n</script></head></html>', '<html><head>\n <script>\n var x = 6;\n</script></head></html>');
});
test('HTLM & Scripts - Fixtures', function() {
test('HTLM & Scripts - Fixtures', function () {
assertFormatWithFixture('19813.html', '19813.html');
assertFormatWithFixture('19813.html', '19813-4spaces.html', void 0, FormattingOptions.create(4, true));
assertFormatWithFixture('19813.html', '19813-tab.html', void 0, FormattingOptions.create(1, false));
......@@ -99,6 +98,11 @@ suite('HTML Embedded Formatting', () => {
assertFormat('<html><head><script>\nvar x=1;\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 1;\n\n </script>\n</head>\n\n</html>\n', options);
});
test('Inside script', function (): any {
assertFormat('<html><head>\n <script>\n|var x=6;|\n</script></head></html>', '<html><head>\n <script>\n var x = 6;\n</script></head></html>');
assertFormat('<html><head>\n <script>\n|var x=6;\nvar y= 9;|\n</script></head></html>', '<html><head>\n <script>\n var x = 6;\n var y = 9;\n</script></head></html>');
});
});
function applyEdits(document: TextDocument, edits: TextEdit[]): string {
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
export function pushAll<T>(to: T[], from: T[]) {
if (from) {
for (var i = 0; i < from.length; i++) {
to.push(from[i]);
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册