@phoenix-plugin-registry/hirse.outline-list
Version:
Displays a list of the functions or definitions in the currently opened document. Works with CSS, CoffeeScript, HTML, Haxe, Jade, JavaScript, JSX, LESS, Markdown, PHP, Python, Ruby, SCSS, SVG, Stylus, and XML.
90 lines (84 loc) • 3.04 kB
JavaScript
define(function XMLParser(require, exports, module) {
"use strict";
var htmlparser = require("thirdparty/htmlparser2");
var Promise = require("thirdparty/promise");
/**
* Get the location (line and column) for an index.
* @param {string} source The source code
* @param {number} index Nesting level
* @returns {object} Location with line and column
*/
function _getLocation(source, index) {
var loc = {
line: 0,
ch: 0
};
var count = 0;
while (count < index) {
if (source[count] === "\n") {
loc.line++;
loc.ch = 0;
} else {
loc.ch++;
}
count++;
}
return loc;
}
/**
* Traverse the tree revcursively.
* @param {object[]} dom List of dom node objects
* @param {string} source The source code
* @param {number} level Nesting level
* @returns {objct[]} The code structure
*/
function _traverse(dom, source, level) {
return dom.reduce(function (result, entry) {
if (entry.type === "tag") {
// Skip eRuby tags
if (entry.name.indexOf("%") === 0) {
return result.concat(_traverse(entry.children, source, level));
}
var loc = _getLocation(source, entry.startIndex);
var classes = (entry.attribs.class || "").split(/ +/).filter(function (clazz) {
return clazz;
});
result.push({
name: entry.name.indexOf(":") === -1 ? entry.name : entry.name.split(":")[1],
namespace: entry.name.indexOf(":") === -1 ? "" : entry.name.split(":")[0],
level: level,
id: entry.attribs.id || "",
class: classes,
line: loc.line,
ch: loc.ch
});
return result.concat(_traverse(entry.children, source, level + 1));
}
return result;
}, []);
}
/**
* Parse the source and extract the code structure.
* @param {string} source The source code.
* @returns {Promise<object[]>} Promise of the code structure.
*/
function parse(source) {
return new Promise(function (resolve, reject) {
var parser = new htmlparser.Parser(new htmlparser.DomHandler(function (error, dom) {
if (error) {
reject(error);
} else {
resolve(_traverse(dom, source, 0));
}
}, {
withStartIndices: true,
withEndIndices: true
}));
parser.write(source);
parser.done();
});
}
module.exports = {
parse: parse
};
});