@telegraf/entity
Version:
Convert Telegram entities to HTML or Markdown
136 lines (135 loc) • 4.9 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.toMarkdownV2 = exports.toHTML = exports.serialiseWith = exports.escapers = exports.serialisers = exports.toTree = exports.parse_markdown = exports.parse_html = void 0;
const serialisers = __importStar(require("./serialisers.js"));
exports.serialisers = serialisers;
const escapers = __importStar(require("./escapers.js"));
exports.escapers = escapers;
const index_js_1 = require("./parser/index.js");
exports.parse_html = index_js_1.Parser.parse_html;
exports.parse_markdown = index_js_1.Parser.parse_markdown;
// https://github.com/tdlib/td/blob/721300bcb4d0f2114505712f4dc6350af1ce1a09/td/telegram/MessageEntity.cpp#L39
const TYPE_PRIORITY = {
mention: 50,
hashtag: 50,
bot_command: 50,
url: 50,
email: 50,
bold: 90,
italic: 91,
code: 20,
pre: 11,
text_link: 49,
text_mention: 49,
cashtag: 50,
phone_number: 50,
underline: 92,
strikethrough: 93,
blockquote: 0,
spoiler: 94,
custom_emoji: 99,
expandable_blockquote: 0,
};
function findChildren(fromEntityIndex, parent, entities) {
const ret = [];
for (let i = fromEntityIndex + 1; i < entities.length; i++) {
const entity = entities[i];
if (entity.offset + entity.length > parent.offset + parent.length)
break;
ret.push(entity);
}
return ret;
}
const ends = (entity) => entity.offset + entity.length;
function toTree(msg, offset = 0, upto = Infinity) {
if (!msg.entities?.length)
return [msg.text.slice(offset, upto)];
const nodes = [];
let last = offset;
let i = 0;
while (i < msg.entities.length) {
const entity = msg.entities[i];
// there's some text that isn't in an entity
if (last < entity.offset) {
nodes.push(msg.text.slice(last, entity.offset));
last = entity.offset;
}
const children = findChildren(i, entity, msg.entities);
const node = {
...entity,
text: msg.text.slice(entity.offset, ends(entity)),
children: toTree({ text: msg.text, entities: children }, entity.offset, ends(entity)),
};
last = ends(node);
nodes.push(node);
i += children.length + 1;
}
if (last < upto) {
const final = msg.text.slice(last, upto);
if (final)
nodes.push(final);
}
return nodes;
}
exports.toTree = toTree;
function serialse(tree, serialiser, escaper) {
let ret = "";
for (const node of tree) {
if (typeof node === "string")
ret += escaper(node);
else
ret += serialiser(serialse(node.children, serialiser, escaper), node);
}
return ret;
}
const serialiseWith = (serialiser, escaper) => (message) => {
const msg = "text" in message ? message : { text: message.caption || "", entities: message.caption_entities };
if (!msg.entities || msg.entities.length === 0)
return serialiser(msg.text);
const entities = msg.entities.sort((a, b) => {
if (a.offset < b.offset)
return -1;
if (a.offset > b.offset)
return 1;
if (a.length > b.length)
return -1;
if (a.length < b.length)
return 1;
const a_priority = TYPE_PRIORITY[a.type];
const b_priority = TYPE_PRIORITY[b.type];
if (a_priority < b_priority)
return -1;
if (a_priority > b_priority)
return 1;
return 0;
});
return serialse(toTree({ text: msg.text, entities }), serialiser, escaper);
};
exports.serialiseWith = serialiseWith;
const toHTML = serialiseWith(serialisers.HTML, escapers.HTML);
exports.toHTML = toHTML;
const toMarkdownV2 = serialiseWith(serialisers.MarkdownV2, escapers.MarkdownV2);
exports.toMarkdownV2 = toMarkdownV2;