diff options
author | Mike Rennie <Michael_Rennie@ca.ibm.com> | 2016-11-07 13:11:43 -0500 |
---|---|---|
committer | Mike Rennie <Michael_Rennie@ca.ibm.com> | 2016-11-07 13:11:43 -0500 |
commit | 13bea89ba0fb0f27c89718faabe37547f56cab96 (patch) | |
tree | c32457cee6011b68c7f676d020e56063a013ca63 | |
parent | 8c05af5d394f27b1109c70f1f27cec1349994433 (diff) | |
download | org.eclipse.orion.client-13bea89ba0fb0f27c89718faabe37547f56cab96.zip org.eclipse.orion.client-13bea89ba0fb0f27c89718faabe37547f56cab96.tar.gz org.eclipse.orion.client-13bea89ba0fb0f27c89718faabe37547f56cab96.tar.bz2 |
Bug 507125 - HTML outline spins forever
3 files changed, 216 insertions, 17 deletions
diff --git a/bundles/org.eclipse.orion.client.webtools/web/js-tests/webtools/htmlOutlineTests.js b/bundles/org.eclipse.orion.client.webtools/web/js-tests/webtools/htmlOutlineTests.js new file mode 100644 index 0000000..dde17e2 --- /dev/null +++ b/bundles/org.eclipse.orion.client.webtools/web/js-tests/webtools/htmlOutlineTests.js @@ -0,0 +1,202 @@ +/*******************************************************************************
+ * @license
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
+ *
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+/*eslint-env amd, mocha*/
+/* eslint-disable missing-nls */
+define([
+'chai/chai',
+'webtools/htmlOutliner',
+'webtools/htmlAstManager',
+'orion/Deferred',
+'mocha/mocha' //global export, stays last
+], function(chai, HTMLOutliner, ASTManager, Deferred) {
+ var assert = chai.assert,
+ astManager = new ASTManager.HtmlAstManager(),
+ outliner = new HTMLOutliner.HtmlOutliner(astManager);
+
+ /** + * @name setup + * @description Sets up the test + * @param {string} text The text of the compilation unit to outline + * @returns {?} An object with an outliner and editorContext instance + */ + function setup(text) {
+ return {
+ outliner: outliner,
+ editorContext: {
+ contentTypeId: "text/html",
+ /**
+ * get the text
+ */
+ getText: function() {
+ return new Deferred().resolve(text);
+ },
+
+ getFileMetadata: function() {
+ var o = Object.create(null);
+ o.contentType = Object.create(null);
+ o.contentType.id = this.contentTypeId;
+ o.location = 'html_outline_test.html';
+ return new Deferred().resolve(o);
+ }
+ }
+ };
+ }
+
+ /** + * @name assertOutlineElement + * @description Checks that the given label and start / end match up with wat we are expecting + * @param {?} element Te outline element to check + * @param {string} expected The expected full element label to check + * @param {number} start The expected start range of the element + * @param {number} end The expected end rnage of the element + */ + function assertOutlineElement(element, expected, start, end) {
+ assert(element, "The tested element cannot be null");
+ assert(element.label, "The outlined element must have a label");
+ if (element.start !== 0) {
+ assert(element.start, "The outlined element must have a start range");
+ }
+ assert(element.end, "The outlined element must have an end range");
+ var fullLabel = element.label;
+ if (element.labelPre){
+ fullLabel = element.labelPre + fullLabel;
+ }
+ if (element.labelPost){
+ fullLabel += element.labelPost;
+ }
+ assert.equal(fullLabel, expected, "The label is not the same");
+ assert.equal(element.start, start, "The start range is not the same");
+ assert.equal(element.end, end, "The end range is not the same");
+ }
+
+ describe('HTML Outliner Tests', function() {
+ /**
+ * @callback from Mocha after each test runs
+ */
+ afterEach(function() {
+ var _f = {file:{location: 'html_outline_test.html'}};
+ astManager.onModelChanging(_f);
+ });
+
+ it("Simple outline 1", function() {
+ var t = setup("<html></html>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length > 0, "An empty outline was returned");
+ assertOutlineElement(outline[0], "html", 0, 13);
+ });
+ });
+ it("Simple outline 2", function() {
+ var t = setup("<div></div>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length > 0, "An empty outline was returned");
+ assertOutlineElement(outline[0], "div", 0, 11);
+ });
+ });
+ it("Simple outline 3", function() {
+ var t = setup("<div><div></div></div>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length > 0, "An empty outline was returned");
+ assertOutlineElement(outline[0].children[0], "div", 5, 16);
+ });
+ });
+ it("Simple outline - no html tags, self-closed p", function() {
+ var t = setup("</p>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length > 0, "An empty outline was returned");
+ assertOutlineElement(outline[0], "p", 4, 4);
+ });
+ });
+ it("Simple outline - no html tags, p", function() {
+ var t = setup("<p></p>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length > 0, "An empty outline was returned");
+ assertOutlineElement(outline[0], "p", 0, 7);
+ });
+ });
+ it("Simple outline - no html tags, self-closed anchor", function() {
+ var t = setup("</a>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length === 0, "Should be nothing outlined for bad /a node");
+ });
+ });
+ it("Simple outline - no html tags, self-closed anchor", function() {
+ var t = setup("<a/>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length > 0, "An empty outline was returned");
+ assertOutlineElement(outline[0], "a", 0, 4);
+ });
+ });
+ it("Simple outline - no html tags, anchor", function() {
+ var t = setup("<a></a>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length > 0, "An empty outline was returned");
+ assertOutlineElement(outline[0], "a", 0, 7);
+ });
+ });
+ it("Skipped node - b", function() {
+ var t = setup("<b></b>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length === 0, "Should be nothing outlined for skipped node b");
+ });
+ });
+ it("Skipped node - i", function() {
+ var t = setup("<i></i>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length === 0, "Should be nothing outlined for skipped node i");
+ });
+ });
+ it("Skipped node - em", function() {
+ var t = setup("<em></em>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length === 0, "Should be nothing outlined for skipped node em");
+ });
+ });
+ it("Skipped node - tt", function() {
+ var t = setup("<tt></tt>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length === 0, "Should be nothing outlined for skipped node tt");
+ });
+ });
+ it("Skipped node - code", function() {
+ var t = setup("<code></code>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length === 0, "Should be nothing outlined for skipped node code");
+ });
+ });
+ it("Skipped node - blockquote", function() {
+ var t = setup("<blockquote></blockquote>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length === 0, "Should be nothing outlined for skipped node blockquote");
+ });
+ });
+ it("Skipped node - b", function() {
+ var t = setup("<b></b>");
+ return t.outliner.computeOutline(t.editorContext).then(function(outline) {
+ assert(outline, "There was no outline returned");
+ assert(outline.length === 0, "Should be nothing outlined for skipped node b");
+ });
+ });
+ });
+});
diff --git a/bundles/org.eclipse.orion.client.webtools/web/js-tests/webtools/webtoolsMochaTests.html b/bundles/org.eclipse.orion.client.webtools/web/js-tests/webtools/webtoolsMochaTests.html index 5e0e24b..10612ab 100644 --- a/bundles/org.eclipse.orion.client.webtools/web/js-tests/webtools/webtoolsMochaTests.html +++ b/bundles/org.eclipse.orion.client.webtools/web/js-tests/webtools/webtoolsMochaTests.html @@ -28,6 +28,7 @@ "js-tests/webtools/htmlParserTests", "js-tests/webtools/htmlContentAssistTests", "js-tests/webtools/htmlValidatorTests", + "js-tests/webtools/htmlOutlineTests" ], function(){ mocha.run(); }); diff --git a/bundles/org.eclipse.orion.client.webtools/web/webtools/htmlOutliner.js b/bundles/org.eclipse.orion.client.webtools/web/webtools/htmlOutliner.js index 0229acf..66c615a 100644 --- a/bundles/org.eclipse.orion.client.webtools/web/webtools/htmlOutliner.js +++ b/bundles/org.eclipse.orion.client.webtools/web/webtools/htmlOutliner.js @@ -1,6 +1,6 @@ /*******************************************************************************
* @license
- * Copyright (c) 2014 IBM Corporation and others.
+ * Copyright (c) 2014, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
@@ -19,7 +19,7 @@ define("webtools/htmlOutliner", [ * @description Creates a new validator
* @constructor
* @public
- * @param {Object} htmlAstManager The back AST manager to provide shared HTML DOMs
+ * @param {?} htmlAstManager The back AST manager to provide shared HTML DOMs
* @since 6.0
*/
function HtmlOutliner(htmlAstManager) {
@@ -32,10 +32,13 @@ define("webtools/htmlOutliner", [ * @callback
*/
computeOutline: function(editorContext, options) {
- var that = this;
- return that.htmlAstManager.getAST(editorContext).then(function(ast){
- return that.domToOutline(ast);
- });
+ return this.htmlAstManager.getAST(editorContext).then(function(ast){
+ var out = this.domToOutline(ast.children);
+ if(!Array.isArray(out)) {
+ return [];
+ }
+ return out;
+ }.bind(this));
},
/**
@@ -79,13 +82,12 @@ define("webtools/htmlOutliner", [ var element = {
label: this.domToLabel(node),
children: this.domToOutline(node.children),
- line: node.location.line,
- offset: node.location.col,
- length: node.name.length
+ start: node.range[0],
+ end: node.range[1]
};
outline.push(element);
}
- if (outline.length > 0){
+ if(outline.length > 0) {
return outline;
}
return null;
@@ -111,15 +113,9 @@ define("webtools/htmlOutliner", [ }
//skip paragraphs and other blocks of formatted text
- if (node.name === "p" || node.name === "tt" || node.name === "code" || node.name === "blockquote") { //$NON-NLS-0$ //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if (node.name === "tt" || node.name === "code" || node.name === "blockquote") { //$NON-NLS-0$ //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return true;
}
-
- //skip anchors
- if (node.name === "a") { //$NON-NLS-0$
- return true;
- }
-
//include the element if we have no reason to skip it
return false;
},
|