Skip to content

Instantly share code, notes, and snippets.

@fum1h1ro
Created February 20, 2021 08:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fum1h1ro/b048a09a9bbc61519c6698b05c8eb374 to your computer and use it in GitHub Desktop.
Save fum1h1ro/b048a09a9bbc61519c6698b05c8eb374 to your computer and use it in GitHub Desktop.
namespace Project
{
export class HtmlParser
{
public static Parse(html: string): HtmlParser
{
return new HtmlParser(html);
}
private constructor(private readonly html: string)
{
}
public Get(tag: string): string[]
{
if (tag[0] !== '<') return null;
const tagName = HtmlParser.ParseTag(tag)[0];
const result: string[] = [];
let tagStartPos = this.html.indexOf(tag);
while (tagStartPos >= 0)
{
let currentPos = tagStartPos + tag.length;
let level = 0;
while (currentPos < this.html.length)
{
const spos = this.html.indexOf('<', currentPos);
const epos = this.html.indexOf('>', spos + 1);
const t = HtmlParser.ParseTag(this.html.slice(spos, epos + 1));
const name = t[0];
const isClose = t[1];
if (name === tagName)
{
if (isClose)
{
--level;
if (level < 0)
{
result.push(this.html.slice(tagStartPos + tag.length, spos));
break;
}
}
else
{
++level;
}
}
currentPos = epos + 1;
}
tagStartPos = this.html.indexOf(tag, tagStartPos + tag.length);
}
return result;
}
private static ParseTag(tag: string): [string, boolean]
{
let isClose = false;
let idx = tag.indexOf('<') + 1;
if (idx >= tag.length) return [null, false];
if (tag[idx] === '/')
{
isClose = true;
++idx;
}
const blankPos = tag.indexOf(' ', idx);
const closePos = tag.indexOf('>', idx);
if (blankPos >= 0 && blankPos < closePos)
{
return [tag.slice(idx, blankPos), isClose];
}
if (closePos >= 0)
{
return [tag.slice(idx, closePos), isClose];
}
return [tag.slice(idx), isClose];
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment