dograma
Version:
NodeJS/Browser MTProto API Telegram client library,
208 lines (207 loc) • 7.73 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.HTMLParser = void 0;
const htmlparser2_1 = require("htmlparser2");
const tl_1 = require("../tl");
const index_1 = require("../index");
class HTMLToTelegramParser {
constructor() {
this.text = "";
this.entities = [];
this._buildingEntities = new Map();
this._openTags = [];
this._openTagsMeta = [];
}
onopentag(name, attributes) {
/*
* This fires when a new tag is opened.
*
* If you don't need an aggregated `attributes` object,
* have a look at the `onopentagname` and `onattribute` events.
*/
this._openTags.unshift(name);
this._openTagsMeta.unshift(undefined);
let EntityType;
const args = {};
if (name == "strong" || name == "b") {
EntityType = tl_1.Api.MessageEntityBold;
}
else if (name == "spoiler") {
EntityType = tl_1.Api.MessageEntitySpoiler;
}
else if (name == "em" || name == "i") {
EntityType = tl_1.Api.MessageEntityItalic;
}
else if (name == "u") {
EntityType = tl_1.Api.MessageEntityUnderline;
}
else if (name == "del" || name == "s") {
EntityType = tl_1.Api.MessageEntityStrike;
}
else if (name == "blockquote") {
EntityType = tl_1.Api.MessageEntityBlockquote;
}
else if (name == "code") {
const pre = this._buildingEntities.get("pre");
if (pre && pre instanceof tl_1.Api.MessageEntityPre) {
try {
pre.language = attributes.class.slice("language-".length, attributes.class.length);
}
catch (e) {
// no language block
}
}
else {
EntityType = tl_1.Api.MessageEntityCode;
}
}
else if (name == "pre") {
EntityType = tl_1.Api.MessageEntityPre;
args["language"] = "";
}
else if (name == "a") {
let url = attributes.href;
if (!url) {
return;
}
if (url.startsWith("mailto:")) {
url = url.slice("mailto:".length, url.length);
EntityType = tl_1.Api.MessageEntityEmail;
}
else {
EntityType = tl_1.Api.MessageEntityTextUrl;
args["url"] = url;
url = undefined;
}
this._openTagsMeta.shift();
this._openTagsMeta.unshift(url);
}
if (EntityType && !this._buildingEntities.has(name)) {
this._buildingEntities.set(name, new EntityType(Object.assign({ offset: this.text.length, length: 0 }, args)));
}
}
ontext(text) {
const previousTag = this._openTags.length > 0 ? this._openTags[0] : "";
if (previousTag == "a") {
const url = this._openTagsMeta[0];
if (url) {
text = url;
}
}
for (let [tag, entity] of this._buildingEntities) {
entity.length += text.length;
}
this.text += text;
}
onclosetag(tagname) {
this._openTagsMeta.shift();
this._openTags.shift();
const entity = this._buildingEntities.get(tagname);
if (entity) {
this._buildingEntities.delete(tagname);
this.entities.push(entity);
}
}
onattribute(name, value, quote) { }
oncdataend() { }
oncdatastart() { }
oncomment(data) { }
oncommentend() { }
onend() { }
onerror(error) { }
onopentagname(name) { }
onparserinit(parser) { }
onprocessinginstruction(name, data) { }
onreset() { }
}
class HTMLParser {
static parse(html) {
if (!html) {
return [html, []];
}
const handler = new HTMLToTelegramParser();
const parser = new htmlparser2_1.Parser(handler);
parser.write(html);
parser.end();
const text = index_1.helpers.stripText(handler.text, handler.entities);
return [text, handler.entities];
}
static unparse(text, entities, _offset = 0, _length) {
if (!text || !entities || !entities.length) {
return text;
}
if (_length == undefined) {
_length = text.length;
}
const html = [];
let lastOffset = 0;
for (let i = 0; i < entities.length; i++) {
const entity = entities[i];
if (entity.offset >= _offset + _length) {
break;
}
let relativeOffset = entity.offset - _offset;
if (relativeOffset > lastOffset) {
html.push(text.slice(lastOffset, relativeOffset));
}
else if (relativeOffset < lastOffset) {
continue;
}
let skipEntity = false;
let length = entity.length;
let entityText = this.unparse(text.slice(relativeOffset, relativeOffset + length), entities.slice(i + 1, entities.length), entity.offset, length);
if (entity instanceof tl_1.Api.MessageEntityBold) {
html.push(`<strong>${entityText}</strong>`);
}
else if (entity instanceof tl_1.Api.MessageEntitySpoiler) {
html.push(`<spoiler>${entityText}</spoiler>`);
}
else if (entity instanceof tl_1.Api.MessageEntityItalic) {
html.push(`<em>${entityText}</em>`);
}
else if (entity instanceof tl_1.Api.MessageEntityCode) {
html.push(`<code>${entityText}</code>`);
}
else if (entity instanceof tl_1.Api.MessageEntityUnderline) {
html.push(`<u>${entityText}</u>`);
}
else if (entity instanceof tl_1.Api.MessageEntityStrike) {
html.push(`<del>${entityText}</del>`);
}
else if (entity instanceof tl_1.Api.MessageEntityBlockquote) {
html.push(`<blockquote>${entityText}</blockquote>`);
}
else if (entity instanceof tl_1.Api.MessageEntityPre) {
if (entity.language) {
html.push(`<pre>
<code class="language-${entity.language}">
${entityText}
</code>
</pre>`);
}
else {
html.push(`<pre></pre><code>${entityText}</code><pre>`);
}
}
else if (entity instanceof tl_1.Api.MessageEntityEmail) {
html.push(`<a href="mailto:${entityText}">${entityText}</a>`);
}
else if (entity instanceof tl_1.Api.MessageEntityUrl) {
html.push(`<a href="${entityText}">${entityText}</a>`);
}
else if (entity instanceof tl_1.Api.MessageEntityTextUrl) {
html.push(`<a href="${entity.url}">${entityText}</a>`);
}
else if (entity instanceof tl_1.Api.MessageEntityMentionName) {
html.push(`<a href="tg://user?id=${entity.userId}">${entityText}</a>`);
}
else {
skipEntity = true;
}
lastOffset = relativeOffset + (skipEntity ? 0 : length);
}
html.push(text.slice(lastOffset, text.length));
return html.join("");
}
}
exports.HTMLParser = HTMLParser;