Skip to content

Instantly share code, notes, and snippets.

@maolion
Last active December 8, 2017 10:52
Show Gist options
  • Save maolion/f17b314e5a686b2bcefe59b0125361ee to your computer and use it in GitHub Desktop.
Save maolion/f17b314e5a686b2bcefe59b0125361ee to your computer and use it in GitHub Desktop.
parse html
var startTagReg = /^<([^\s!/>]+)[^>]*[^/]?>/;
var endTagReg = /^<\/([^>\s]+)>/;
var selfCloseTagReg = /^<([^\s>!/]+)[^>]*\/>/;
var textContentTagReg = /^[^<]+/;
var commentTagReg = /^<!--[\s\S]*?-->/;
var selfCloseTagsNameReg = /^img|link|meta|br|hr|base$/i;
function parseHTML(html) {
var rootChildren = [];
var stack = [{ children: rootChildren }];
var pendingContent = html;
var match = undefined;
var cursorPosition = 0;
while (pendingContent.length) {
var closetTag = stack[stack.length - 1];
var source;
if ((match = pendingContent.match(startTagReg))) {
appendElementNode(match[1], match[0], isSelfCloseTag(match[1]));
} else if ((match = pendingContent.match(endTagReg))) {
var source = match[0];
if (closetTag.name === match[1]) {
closetTag.endAt = closetTag.endAt + source.length;
closetTag = stack.pop();
} else {
appendTextContentNode(source);
}
} else if ((match = pendingContent.match(selfCloseTagReg))) {
appendElementNode(match[1], match[0], true);
} else if ((match = pendingContent.match(commentTagReg))) {
appendCommentNode(match[0]);
} else if ((match = pendingContent.match(textContentTagReg))) {
appendTextContentNode(match[0]);
} else if (pendingContent.charAt(0) === "<") {
match = ["<"];
appendTextContentNode(match[0]);
}
if (match) {
source = match[0];
cursorPosition += source.length;
pendingContent = pendingContent.slice(source.length);
closetTag.endAt = cursorPosition + source.length;
}
}
return rootChildren;
function appendElementNode(name, source, closeSelf) {
let node = {
name: name,
type: "element",
source: source,
startAt: cursorPosition,
endAt: cursorPosition + source.length
};
if (closeSelf) {
node.closeSelf = closeSelf;
} else {
node.children = [];
stack.push(node);
}
closetTag.children.push(node);
}
function appendCommentNode(source) {
closetTag.children.push({
type: "comment",
source: source,
startAt: cursorPosition,
endAt: cursorPosition + source.length
});
}
function appendTextContentNode(source) {
let node = closetTag.children[closetTag.children.length - 1];
if (!node || node.type !== "textContent") {
node = {
type: "textContent",
source: source,
startAt: cursorPosition,
endAt: cursorPosition + source.length
};
closetTag.children.push(node);
} else {
node.source += source;
node.endAt += source.length;
}
}
}
function isSelfCloseTag(tagName) {
return selfCloseTagsNameReg.test(tagName);
}
@hao-ji-xing
Copy link

666

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment