Fix some entities
Small refactor of RichTextProcessor
This commit is contained in:
parent
7f746738f5
commit
ee4d05c9e5
84
src/layer.d.ts
vendored
84
src/layer.d.ts
vendored
@ -3795,125 +3795,166 @@ export namespace ReplyMarkup {
|
||||
/**
|
||||
* @link https://core.telegram.org/type/MessageEntity
|
||||
*/
|
||||
export type MessageEntity = MessageEntity.messageEntityUnknown | MessageEntity.messageEntityMention | MessageEntity.messageEntityHashtag | MessageEntity.messageEntityBotCommand | MessageEntity.messageEntityUrl | MessageEntity.messageEntityEmail | MessageEntity.messageEntityBold | MessageEntity.messageEntityItalic | MessageEntity.messageEntityCode | MessageEntity.messageEntityPre | MessageEntity.messageEntityTextUrl | MessageEntity.messageEntityMentionName | MessageEntity.inputMessageEntityMentionName | MessageEntity.messageEntityPhone | MessageEntity.messageEntityCashtag | MessageEntity.messageEntityUnderline | MessageEntity.messageEntityStrike | MessageEntity.messageEntityBlockquote | MessageEntity.messageEntityBankCard;
|
||||
export type MessageEntity = MessageEntity.messageEntityUnknown | MessageEntity.messageEntityMention | MessageEntity.messageEntityHashtag | MessageEntity.messageEntityBotCommand | MessageEntity.messageEntityUrl | MessageEntity.messageEntityEmail | MessageEntity.messageEntityBold | MessageEntity.messageEntityItalic | MessageEntity.messageEntityCode | MessageEntity.messageEntityPre | MessageEntity.messageEntityTextUrl | MessageEntity.messageEntityMentionName | MessageEntity.inputMessageEntityMentionName | MessageEntity.messageEntityPhone | MessageEntity.messageEntityCashtag | MessageEntity.messageEntityUnderline | MessageEntity.messageEntityStrike | MessageEntity.messageEntityBlockquote | MessageEntity.messageEntityBankCard | MessageEntity.messageEntityEmoji | MessageEntity.messageEntityHighlight | MessageEntity.messageEntityLinebreak;
|
||||
|
||||
export namespace MessageEntity {
|
||||
export type messageEntityUnknown = {
|
||||
_: 'messageEntityUnknown',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityMention = {
|
||||
_: 'messageEntityMention',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityHashtag = {
|
||||
_: 'messageEntityHashtag',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityBotCommand = {
|
||||
_: 'messageEntityBotCommand',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityUrl = {
|
||||
_: 'messageEntityUrl',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityEmail = {
|
||||
_: 'messageEntityEmail',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityBold = {
|
||||
_: 'messageEntityBold',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityItalic = {
|
||||
_: 'messageEntityItalic',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityCode = {
|
||||
_: 'messageEntityCode',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityPre = {
|
||||
_: 'messageEntityPre',
|
||||
offset: number,
|
||||
length: number,
|
||||
language: string
|
||||
language: string,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityTextUrl = {
|
||||
_: 'messageEntityTextUrl',
|
||||
offset: number,
|
||||
length: number,
|
||||
url: string
|
||||
url: string,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityMentionName = {
|
||||
_: 'messageEntityMentionName',
|
||||
offset: number,
|
||||
length: number,
|
||||
user_id: number
|
||||
user_id: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type inputMessageEntityMentionName = {
|
||||
_: 'inputMessageEntityMentionName',
|
||||
offset: number,
|
||||
length: number,
|
||||
user_id: InputUser
|
||||
user_id: InputUser,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityPhone = {
|
||||
_: 'messageEntityPhone',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityCashtag = {
|
||||
_: 'messageEntityCashtag',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityUnderline = {
|
||||
_: 'messageEntityUnderline',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityStrike = {
|
||||
_: 'messageEntityStrike',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityBlockquote = {
|
||||
_: 'messageEntityBlockquote',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityBankCard = {
|
||||
_: 'messageEntityBankCard',
|
||||
offset: number,
|
||||
length: number
|
||||
length: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityEmoji = {
|
||||
_: 'messageEntityEmoji',
|
||||
offset?: number,
|
||||
length?: number,
|
||||
unicode?: string,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityHighlight = {
|
||||
_: 'messageEntityHighlight',
|
||||
offset?: number,
|
||||
length?: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
|
||||
export type messageEntityLinebreak = {
|
||||
_: 'messageEntityLinebreak',
|
||||
offset?: number,
|
||||
length?: number,
|
||||
nested?: Array<MessageEntity>
|
||||
};
|
||||
}
|
||||
|
||||
@ -8918,6 +8959,9 @@ export interface ConstructorDeclMap {
|
||||
'messageReplyHeader': MessageReplyHeader.messageReplyHeader,
|
||||
'messageReplies': MessageReplies.messageReplies,
|
||||
'peerBlocked': PeerBlocked.peerBlocked,
|
||||
'messageEntityEmoji': MessageEntity.messageEntityEmoji,
|
||||
'messageEntityHighlight': MessageEntity.messageEntityHighlight,
|
||||
'messageEntityLinebreak': MessageEntity.messageEntityLinebreak,
|
||||
}
|
||||
|
||||
export type InvokeAfterMsg = {
|
||||
|
@ -674,7 +674,7 @@ export class AppDialogsManager {
|
||||
let lastMessageText = appMessagesManager.getRichReplyText(lastMessage, '');
|
||||
|
||||
let messageText = lastMessage.message;
|
||||
let entities = RichTextProcessor.parseEntities(messageText.replace(/\n/g, ' '), {noLinebreakers: true});
|
||||
let entities = RichTextProcessor.parseEntities(messageText.replace(/\n/g, ' '));
|
||||
let regExp = new RegExp(escapeRegExp(highlightWord), 'gi');
|
||||
let match: any;
|
||||
|
||||
|
@ -2498,7 +2498,7 @@ export class AppMessagesManager {
|
||||
// * 80 for chatlist in landscape orientation
|
||||
text = limitSymbols(text, 75, 80);
|
||||
|
||||
let entities = RichTextProcessor.parseEntities(text.replace(/\n/g, ' '), {noLinebreakers: true});
|
||||
let entities = RichTextProcessor.parseEntities(text.replace(/\n/g, ' '));
|
||||
|
||||
messageWrapped = RichTextProcessor.wrapRichText(text, {
|
||||
noLinebreaks: true,
|
||||
|
@ -4,18 +4,17 @@ import Config from './config';
|
||||
import emojiRegExp from '../emoji/regex';
|
||||
import { encodeEmoji } from '../emoji';
|
||||
import { MOUNT_CLASS_TO } from './mtproto/mtproto_config';
|
||||
import { MessageEntity } from '../layer';
|
||||
|
||||
var EmojiHelper = {
|
||||
const EmojiHelper = {
|
||||
emojiMap: (code: string) => { return code; },
|
||||
shortcuts: [] as any,
|
||||
emojis: [] as any
|
||||
};
|
||||
|
||||
var emojiData = Config.Emoji;
|
||||
var emojiSupported = navigator.userAgent.search(/OS X|iPhone|iPad|iOS/i) != -1/* && false *//* || true */,
|
||||
emojiCode;
|
||||
const emojiData = Config.Emoji;
|
||||
|
||||
var alphaCharsRegExp = 'a-z' +
|
||||
const alphaCharsRegExp = 'a-z' +
|
||||
'\\u00c0-\\u00d6\\u00d8-\\u00f6\\u00f8-\\u00ff' + // Latin-1
|
||||
'\\u0100-\\u024f' + // Latin Extended A and B
|
||||
'\\u0253\\u0254\\u0256\\u0257\\u0259\\u025b\\u0263\\u0268\\u026f\\u0272\\u0289\\u028b' + // IPA Extensions
|
||||
@ -40,10 +39,10 @@ var alphaCharsRegExp = 'a-z' +
|
||||
'\\uff21-\\uff3a\\uff41-\\uff5a' + // full width Alphabet
|
||||
'\\uff66-\\uff9f' + // half width Katakana
|
||||
'\\uffa1-\\uffdc'; // half width Hangul (Korean)
|
||||
var alphaNumericRegExp = '0-9\_' + alphaCharsRegExp;
|
||||
var domainAddChars = '\u00b7';
|
||||
const alphaNumericRegExp = '0-9\_' + alphaCharsRegExp;
|
||||
const domainAddChars = '\u00b7';
|
||||
// Based on Regular Expression for URL validation by Diego Perini
|
||||
var urlRegExp = '((?:https?|ftp)://|mailto:)?' +
|
||||
const urlRegExp = '((?:https?|ftp)://|mailto:)?' +
|
||||
// user:pass authentication
|
||||
'(?:\\S{1,64}(?::\\S{0,64})?@)?' +
|
||||
'(?:' +
|
||||
@ -61,32 +60,35 @@ var urlRegExp = '((?:https?|ftp)://|mailto:)?' +
|
||||
'(?::\\d{2,5})?' +
|
||||
// resource path
|
||||
'(?:/(?:\\S{0,255}[^\\s.;,(\\[\\]{}<>"\'])?)?';
|
||||
var usernameRegExp = '[a-zA-Z\\d_]{5,32}';
|
||||
var botCommandRegExp = '\\/([a-zA-Z\\d_]{1,32})(?:@(' + usernameRegExp + '))?(\\b|$)';
|
||||
var fullRegExp = new RegExp('(^| )(@)(' + usernameRegExp + ')|(' + urlRegExp + ')|(\\n)|(' + emojiRegExp + ')|(^|[\\s\\(\\]])(#[' + alphaNumericRegExp + ']{2,64})|(^|\\s)' + botCommandRegExp, 'i')
|
||||
var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
var markdownTestRegExp = /[`_*@]/;
|
||||
var markdownRegExp = /(^|\s|\n)(````?)([\s\S]+?)(````?)([\s\n\.,:?!;]|$)|(^|\s)(`|\*\*|__)([^\n]+?)\7([\s\.,:?!;]|$)|@(\d+)\s*\((.+?)\)/m;
|
||||
var siteHashtags: any = {
|
||||
const usernameRegExp = '[a-zA-Z\\d_]{5,32}';
|
||||
const botCommandRegExp = '\\/([a-zA-Z\\d_]{1,32})(?:@(' + usernameRegExp + '))?(\\b|$)';
|
||||
const fullRegExp = new RegExp('(^| )(@)(' + usernameRegExp + ')|(' + urlRegExp + ')|(\\n)|(' + emojiRegExp + ')|(^|[\\s\\(\\]])(#[' + alphaNumericRegExp + ']{2,64})|(^|\\s)' + botCommandRegExp, 'i')
|
||||
const emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
const markdownTestRegExp = /[`_*@]/;
|
||||
const markdownRegExp = /(^|\s|\n)(````?)([\s\S]+?)(````?)([\s\n\.,:?!;]|$)|(^|\s)(`|\*\*|__)([^\n]+?)\7([\s\.,:?!;]|$)|@(\d+)\s*\((.+?)\)/m;
|
||||
const siteHashtags: {[siteName: string]: string} = {
|
||||
Telegram: 'tg://search_hashtag?hashtag={1}',
|
||||
Twitter: 'https://twitter.com/hashtag/{1}',
|
||||
Instagram: 'https://instagram.com/explore/tags/{1}/',
|
||||
'Google Plus': 'https://plus.google.com/explore/{1}'
|
||||
};
|
||||
|
||||
var siteMentions: any = {
|
||||
const siteMentions: {[siteName: string]: string} = {
|
||||
Telegram: '#/im?p=%40{1}',
|
||||
Twitter: 'https://twitter.com/{1}',
|
||||
Instagram: 'https://instagram.com/{1}/',
|
||||
GitHub: 'https://github.com/{1}'
|
||||
};
|
||||
var markdownEntities = {
|
||||
const markdownEntities = {
|
||||
'`': 'messageEntityCode',
|
||||
'**': 'messageEntityBold',
|
||||
'__': 'messageEntityItalic'
|
||||
};
|
||||
|
||||
function getEmojiSpritesheetCoords(emojiCode: string) {
|
||||
namespace RichTextProcessor {
|
||||
export const emojiSupported = navigator.userAgent.search(/OS X|iPhone|iPad|iOS/i) != -1/* && false *//* || true */;
|
||||
|
||||
export function getEmojiSpritesheetCoords(emojiCode: string) {
|
||||
let unified = encodeEmoji(emojiCode)/* .replace(/(-fe0f|fe0f)/g, '') */;
|
||||
|
||||
if(unified == '1f441-200d-1f5e8') {
|
||||
@ -101,10 +103,12 @@ function getEmojiSpritesheetCoords(emojiCode: string) {
|
||||
|
||||
return unified.replace(/(-fe0f|fe0f)/g, '');
|
||||
}
|
||||
function parseEntities(text: string, options = {}) {
|
||||
|
||||
export function parseEntities(text: string) {
|
||||
var match;
|
||||
var raw = text, url;
|
||||
var entities = [], matchIndex;
|
||||
const entities: MessageEntity[] = [];
|
||||
let matchIndex;
|
||||
var rawOffset = 0;
|
||||
// var start = tsNow()
|
||||
while((match = raw.match(fullRegExp))) {
|
||||
@ -173,11 +177,11 @@ function parseEntities(text: string, options = {}) {
|
||||
unicode: emojiCoords
|
||||
});
|
||||
}
|
||||
} else if(match[10]) { // Hashtag
|
||||
} else if(match[11]) { // Hashtag
|
||||
entities.push({
|
||||
_: 'messageEntityHashtag',
|
||||
offset: matchIndex + (match[9] ? match[9].length : 0),
|
||||
length: match[10].length
|
||||
offset: matchIndex + (match[10] ? match[10].length : 0),
|
||||
length: match[11].length
|
||||
});
|
||||
} else if(match[12]) { // Bot command
|
||||
entities.push({
|
||||
@ -194,9 +198,10 @@ function parseEntities(text: string, options = {}) {
|
||||
// if (entities.length) {
|
||||
// console.log('parse entities', text, entities.slice())
|
||||
// }
|
||||
return entities
|
||||
return entities;
|
||||
}
|
||||
function parseEmojis(text: string) {
|
||||
|
||||
/* export function parseEmojis(text: string) {
|
||||
return text.replace(/:([a-z0-9\-\+\*_]+?):/gi, function (all, shortcut) {
|
||||
var emojiCode = EmojiHelper.shortcuts[shortcut]
|
||||
if (emojiCode !== undefined) {
|
||||
@ -204,8 +209,9 @@ function parseEmojis(text: string) {
|
||||
}
|
||||
return all
|
||||
})
|
||||
}
|
||||
function parseMarkdown(text: string, entities: any[], noTrim?: any) {
|
||||
} */
|
||||
|
||||
export function parseMarkdown(text: string, entities: MessageEntity[], noTrim?: any) {
|
||||
if(!markdownTestRegExp.test(text)) {
|
||||
return noTrim ? text : text.trim();
|
||||
}
|
||||
@ -251,7 +257,7 @@ function parseMarkdown(text: string, entities: any[], noTrim?: any) {
|
||||
newText.push(text)
|
||||
entities.push({
|
||||
_: 'messageEntityMentionName',
|
||||
user_id: match[10],
|
||||
user_id: +match[10],
|
||||
offset: matchIndex,
|
||||
length: text.length
|
||||
})
|
||||
@ -271,33 +277,26 @@ function parseMarkdown(text: string, entities: any[], noTrim?: any) {
|
||||
}
|
||||
return newText
|
||||
}
|
||||
function mergeEntities(currentEntities: any[], newEntities: any[], fromApi: any) {
|
||||
var totalEntities = newEntities.slice();
|
||||
var i;
|
||||
var len = currentEntities.length;
|
||||
var j;
|
||||
var len2 = newEntities.length;
|
||||
var startJ = 0;
|
||||
var curEntity;
|
||||
var newEntity;
|
||||
var start, end;
|
||||
var cStart, cEnd;
|
||||
var bad;
|
||||
for(i = 0; i < len; i++) {
|
||||
curEntity = currentEntities[i];
|
||||
if (fromApi &&
|
||||
|
||||
export function mergeEntities(currentEntities: MessageEntity[], newEntities: MessageEntity[], fromApi?: boolean) {
|
||||
const totalEntities = newEntities.slice();
|
||||
const newLength = newEntities.length;
|
||||
let startJ = 0;
|
||||
for(let i = 0, length = currentEntities.length; i < length; i++) {
|
||||
const curEntity = currentEntities[i];
|
||||
/* if(fromApi &&
|
||||
curEntity._ != 'messageEntityLinebreak' &&
|
||||
curEntity._ != 'messageEntityEmoji') {
|
||||
continue;
|
||||
}
|
||||
} */
|
||||
// console.log('s', curEntity, newEntities);
|
||||
start = curEntity.offset;
|
||||
end = start + curEntity.length;
|
||||
bad = false;
|
||||
for(j = startJ; j < len2; j++) {
|
||||
newEntity = newEntities[j];
|
||||
cStart = newEntity.offset;
|
||||
cEnd = cStart + newEntity.length;
|
||||
const start = curEntity.offset;
|
||||
const end = start + curEntity.length;
|
||||
let bad = false;
|
||||
for(let j = startJ; j < newLength; j++) {
|
||||
const newEntity = newEntities[j];
|
||||
const cStart = newEntity.offset;
|
||||
const cEnd = cStart + newEntity.length;
|
||||
if(cStart <= start) {
|
||||
startJ = j;
|
||||
}
|
||||
@ -305,8 +304,7 @@ function mergeEntities(currentEntities: any[], newEntities: any[], fromApi: any)
|
||||
if(start >= cStart && start < cEnd ||
|
||||
end > cStart && end <= cEnd) {
|
||||
// console.log('bad', curEntity, newEntity)
|
||||
if(fromApi &&
|
||||
start >= cStart && end <= cEnd) {
|
||||
if(fromApi && start >= cStart && end <= cEnd) {
|
||||
if(newEntity.nested === undefined) {
|
||||
newEntity.nested = [];
|
||||
}
|
||||
@ -337,7 +335,8 @@ function mergeEntities(currentEntities: any[], newEntities: any[], fromApi: any)
|
||||
// console.log('merge', currentEntities, newEntities, totalEntities)
|
||||
return totalEntities;
|
||||
}
|
||||
function wrapRichNestedText(text: string, nested: any, options: any) {
|
||||
|
||||
export function wrapRichNestedText(text: string, nested: MessageEntity[], options: any) {
|
||||
if(nested === undefined) {
|
||||
return encodeEntities(text);
|
||||
}
|
||||
@ -345,8 +344,9 @@ function wrapRichNestedText(text: string, nested: any, options: any) {
|
||||
options.hasNested = true;
|
||||
return wrapRichText(text, {entities: nested, nested: true});
|
||||
}
|
||||
function wrapRichText(text: string, options: Partial<{
|
||||
entities: any,
|
||||
|
||||
export function wrapRichText(text: string, options: Partial<{
|
||||
entities: MessageEntity[],
|
||||
contextSite: string,
|
||||
highlightUsername: string,
|
||||
noLinks: boolean,
|
||||
@ -358,27 +358,18 @@ function wrapRichText(text: string, options: Partial<{
|
||||
contextHashtag?: string
|
||||
}> = {}) {
|
||||
if(!text || !text.length) {
|
||||
return ''
|
||||
return '';
|
||||
}
|
||||
|
||||
var entities = options.entities;
|
||||
var contextSite = options.contextSite || 'Telegram';
|
||||
var contextExternal = contextSite != 'Telegram';
|
||||
var emojiFound = false;
|
||||
if(entities === undefined) {
|
||||
entities = parseEntities(text, options);
|
||||
}
|
||||
const entities = options.entities || parseEntities(text);
|
||||
const contextSite = options.contextSite || 'Telegram';
|
||||
const contextExternal = contextSite != 'Telegram';
|
||||
|
||||
//console.log('wrapRichText got entities:', text, entities);
|
||||
var len = entities.length;
|
||||
var entity;
|
||||
var entityText;
|
||||
var skipEntity;
|
||||
var url;
|
||||
var html = [];
|
||||
var lastOffset = 0;
|
||||
for(var i = 0; i < len; i++) {
|
||||
entity = entities[i];
|
||||
const html: string[] = [];
|
||||
let lastOffset = 0;
|
||||
for(let i = 0, len = entities.length; i < len; i++) {
|
||||
const entity = entities[i];
|
||||
if(entity.offset > lastOffset) {
|
||||
html.push(
|
||||
encodeEntities(text.substr(lastOffset, entity.offset - lastOffset))
|
||||
@ -387,8 +378,8 @@ function wrapRichText(text: string, options: Partial<{
|
||||
continue;
|
||||
}
|
||||
|
||||
skipEntity = false;
|
||||
entityText = text.substr(entity.offset, entity.length);
|
||||
let skipEntity = false;
|
||||
const entityText = text.substr(entity.offset, entity.length);
|
||||
switch(entity._) {
|
||||
case 'messageEntityMention':
|
||||
var contextUrl = !options.noLinks && siteMentions[contextSite]
|
||||
@ -412,27 +403,31 @@ function wrapRichText(text: string, options: Partial<{
|
||||
encodeEntities(entityText),
|
||||
'</a>'
|
||||
)
|
||||
break
|
||||
break;
|
||||
|
||||
case 'messageEntityMentionName':
|
||||
if(options.noLinks) {
|
||||
skipEntity = true
|
||||
break
|
||||
skipEntity = true;
|
||||
break;
|
||||
}
|
||||
|
||||
html.push(
|
||||
'<a href="#/im?p=u',
|
||||
encodeURIComponent(entity.user_id),
|
||||
'">',
|
||||
encodeEntities(entityText),
|
||||
'</a>'
|
||||
)
|
||||
break
|
||||
);
|
||||
break;
|
||||
|
||||
case 'messageEntityHashtag':
|
||||
var contextUrl = !options.noLinks && siteHashtags[contextSite]
|
||||
var contextUrl = !options.noLinks && siteHashtags[contextSite];
|
||||
if(!contextUrl) {
|
||||
skipEntity = true
|
||||
break
|
||||
skipEntity = true;
|
||||
break;
|
||||
}
|
||||
var hashtag = entityText.substr(1)
|
||||
|
||||
var hashtag = entityText.substr(1);
|
||||
html.push(
|
||||
'<a ',
|
||||
contextExternal ? ' target="_blank" rel="noopener noreferrer" ' : '',
|
||||
@ -442,32 +437,37 @@ function wrapRichText(text: string, options: Partial<{
|
||||
'">',
|
||||
encodeEntities(entityText),
|
||||
'</a>'
|
||||
)
|
||||
break
|
||||
);
|
||||
break;
|
||||
|
||||
case 'messageEntityEmail':
|
||||
if(options.noLinks) {
|
||||
skipEntity = true
|
||||
break
|
||||
skipEntity = true;
|
||||
break;
|
||||
}
|
||||
|
||||
html.push(
|
||||
'<a href="',
|
||||
encodeEntities('mailto:' + entityText),
|
||||
'" target="_blank" rel="noopener noreferrer">',
|
||||
encodeEntities(entityText),
|
||||
'</a>'
|
||||
)
|
||||
break
|
||||
);
|
||||
break;
|
||||
|
||||
case 'messageEntityUrl':
|
||||
case 'messageEntityTextUrl':
|
||||
var inner
|
||||
let inner: string;
|
||||
let url: string;
|
||||
if (entity._ == 'messageEntityTextUrl') {
|
||||
url = entity.url
|
||||
url = wrapUrl(url, true)
|
||||
inner = wrapRichNestedText(entityText, entity.nested, options)
|
||||
url = (entity as MessageEntity.messageEntityTextUrl).url;
|
||||
url = wrapUrl(url, true);
|
||||
inner = wrapRichNestedText(entityText, entity.nested, options);
|
||||
} else {
|
||||
url = wrapUrl(entityText, false)
|
||||
inner = encodeEntities(replaceUrlEncodings(entityText))
|
||||
url = wrapUrl(entityText, false);
|
||||
inner = encodeEntities(replaceUrlEncodings(entityText));
|
||||
}
|
||||
|
||||
if(options.noLinks) {
|
||||
html.push(inner);
|
||||
} else {
|
||||
@ -477,41 +477,45 @@ function wrapRichText(text: string, options: Partial<{
|
||||
'" target="_blank" rel="noopener noreferrer">',
|
||||
inner,
|
||||
'</a>'
|
||||
)
|
||||
);
|
||||
}
|
||||
break
|
||||
break;
|
||||
|
||||
case 'messageEntityLinebreak':
|
||||
html.push(options.noLinebreaks ? ' ' : '<br/>')
|
||||
break
|
||||
html.push(options.noLinebreaks ? ' ' : '<br/>');
|
||||
break;
|
||||
|
||||
case 'messageEntityEmoji':
|
||||
html.push(emojiSupported ?
|
||||
`<span class="emoji" contenteditable="false">${encodeEntities(entityText)}</span>` :
|
||||
`<img src="assets/img/emoji/${entity.unicode}.png" alt="${encodeEntities(entityText)}" class="emoji">`);
|
||||
break;
|
||||
|
||||
emojiFound = true;
|
||||
break
|
||||
case 'messageEntityBotCommand':
|
||||
if(options.noLinks || options.noCommands || contextExternal) {
|
||||
skipEntity = true
|
||||
break
|
||||
skipEntity = true;
|
||||
break;
|
||||
}
|
||||
var command = entityText.substr(1)
|
||||
var bot
|
||||
var atPos
|
||||
|
||||
var command = entityText.substr(1);
|
||||
var bot;
|
||||
var atPos;
|
||||
if ((atPos = command.indexOf('@')) != -1) {
|
||||
bot = command.substr(atPos + 1)
|
||||
command = command.substr(0, atPos)
|
||||
bot = command.substr(atPos + 1);
|
||||
command = command.substr(0, atPos);
|
||||
} else {
|
||||
bot = options.fromBot
|
||||
bot = options.fromBot;
|
||||
}
|
||||
|
||||
html.push(
|
||||
'<a href="',
|
||||
encodeEntities('tg://bot_command?command=' + encodeURIComponent(command) + (bot ? '&bot=' + encodeURIComponent(bot) : '')),
|
||||
'">',
|
||||
encodeEntities(entityText),
|
||||
'</a>'
|
||||
)
|
||||
break
|
||||
);
|
||||
break;
|
||||
|
||||
case 'messageEntityBold':
|
||||
if(options.noTextFormat) {
|
||||
html.push(wrapRichNestedText(entityText, entity.nested, options));
|
||||
@ -522,8 +526,9 @@ function wrapRichText(text: string, options: Partial<{
|
||||
'<strong>',
|
||||
wrapRichNestedText(entityText, entity.nested, options),
|
||||
'</strong>'
|
||||
)
|
||||
break
|
||||
);
|
||||
break;
|
||||
|
||||
case 'messageEntityItalic':
|
||||
if(options.noTextFormat) {
|
||||
html.push(wrapRichNestedText(entityText, entity.nested, options));
|
||||
@ -534,15 +539,25 @@ function wrapRichText(text: string, options: Partial<{
|
||||
'<em>',
|
||||
wrapRichNestedText(entityText, entity.nested, options),
|
||||
'</em>'
|
||||
)
|
||||
break
|
||||
);
|
||||
break;
|
||||
|
||||
case 'messageEntityHighlight':
|
||||
html.push(
|
||||
'<i>',
|
||||
wrapRichNestedText(entityText, entity.nested, options),
|
||||
'</i>'
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case 'messageEntityStrike':
|
||||
html.push(
|
||||
'<del>',
|
||||
wrapRichNestedText(entityText, entity.nested, options),
|
||||
'</del>'
|
||||
);
|
||||
break;
|
||||
|
||||
case 'messageEntityCode':
|
||||
if(options.noTextFormat) {
|
||||
html.push(encodeEntities(entityText));
|
||||
@ -553,8 +568,9 @@ function wrapRichText(text: string, options: Partial<{
|
||||
'<code>',
|
||||
encodeEntities(entityText),
|
||||
'</code>'
|
||||
)
|
||||
break
|
||||
);
|
||||
break;
|
||||
|
||||
case 'messageEntityPre':
|
||||
if(options.noTextFormat) {
|
||||
html.push(encodeEntities(entityText));
|
||||
@ -565,33 +581,31 @@ function wrapRichText(text: string, options: Partial<{
|
||||
'<pre><code', (entity.language ? ' class="language-' + encodeEntities(entity.language) + '"' : ''), '>',
|
||||
encodeEntities(entityText),
|
||||
'</code></pre>'
|
||||
)
|
||||
break
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
skipEntity = true
|
||||
skipEntity = true;
|
||||
}
|
||||
lastOffset = entity.offset + (skipEntity ? 0 : entity.length)
|
||||
|
||||
lastOffset = entity.offset + (skipEntity ? 0 : entity.length);
|
||||
}
|
||||
|
||||
html.push(encodeEntities(text.substr(lastOffset))); // may be empty string
|
||||
//console.log(html);
|
||||
text = html.join('')//$sanitize(html.join(''))
|
||||
/* if (!options.nested && (emojiFound || options.hasNested)) {
|
||||
text = text.replace(/\ufe0f|️|�|‍/g, '', text)
|
||||
var emojiSizeClass = curEmojiSize == 18 ? '' : (' emoji-w' + curEmojiSize)
|
||||
text = text.replace(/<span((?: [^>]*)?) class="emoji emoji-(\d)-(\d+)-(\d+)"(.+?)<\/span>/g,
|
||||
'<span$1 class="emoji ' + emojiSizeClass + ' emoji-spritesheet-$2" style="background-position: -$3px -$4px;" $5</span>')
|
||||
} */
|
||||
return text;//$sce.trustAs('html', text)
|
||||
text = html.join('');
|
||||
|
||||
return text;
|
||||
}
|
||||
function wrapDraftText (text: string, options: any = {}) {
|
||||
|
||||
export function wrapDraftText(text: string, options: any = {}) {
|
||||
if(!text || !text.length) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var entities = options.entities;
|
||||
if(entities === undefined) {
|
||||
entities = parseEntities(text, options);
|
||||
entities = parseEntities(text);
|
||||
}
|
||||
var i = 0;
|
||||
var len = entities.length;
|
||||
@ -659,7 +673,8 @@ function wrapDraftText (text: string, options: any = {}) {
|
||||
code.push(text.substr(lastOffset));
|
||||
return code.join('');
|
||||
}
|
||||
function checkBrackets(url: string) {
|
||||
|
||||
export function checkBrackets(url: string) {
|
||||
var urlLength = url.length;
|
||||
var urlOpenBrackets = url.split('(').length - 1;
|
||||
var urlCloseBrackets = url.split(')').length - 1;
|
||||
@ -675,7 +690,7 @@ function checkBrackets(url: string) {
|
||||
return url;
|
||||
}
|
||||
|
||||
function replaceUrlEncodings(urlWithEncoded: string) {
|
||||
export function replaceUrlEncodings(urlWithEncoded: string) {
|
||||
return urlWithEncoded.replace(/(%[A-Z\d]{2})+/g, (str) => {
|
||||
try {
|
||||
return decodeURIComponent(str);
|
||||
@ -685,7 +700,7 @@ function replaceUrlEncodings(urlWithEncoded: string) {
|
||||
});
|
||||
}
|
||||
|
||||
function wrapPlainText(text: any, options: any = {}) {
|
||||
export function wrapPlainText(text: any) {
|
||||
if(emojiSupported) {
|
||||
return text;
|
||||
}
|
||||
@ -703,7 +718,8 @@ function wrapPlainText(text: any, options: any = {}) {
|
||||
text.push(raw.substr(0, match.index))
|
||||
if(match[8]) {
|
||||
// @ts-ignore
|
||||
if((emojiCode = EmojiHelper.emojiMap[match[8]]) &&
|
||||
const emojiCode = EmojiHelper.emojiMap[match[8]];
|
||||
if(emojiCode &&
|
||||
// @ts-ignore
|
||||
(emojiTitle = emojiData[emojiCode][1][0])) {
|
||||
text.push(':' + emojiTitle + ':');
|
||||
@ -719,13 +735,15 @@ function wrapPlainText(text: any, options: any = {}) {
|
||||
text.push(raw);
|
||||
return text.join('');
|
||||
}
|
||||
function wrapEmojiText(text: string) {
|
||||
|
||||
export function wrapEmojiText(text: string) {
|
||||
if(!text) return '';
|
||||
|
||||
let entities = parseEntities(text).filter(e => e._ == 'messageEntityEmoji');
|
||||
return wrapRichText(text, {entities});
|
||||
}
|
||||
function wrapUrl(url: string, unsafe: number | boolean): string {
|
||||
|
||||
export function wrapUrl(url: string, unsafe: number | boolean): string {
|
||||
if(!url.match(/^https?:\/\//i)) {
|
||||
url = 'http://' + url;
|
||||
}
|
||||
@ -777,26 +795,13 @@ function wrapUrl(url: string, unsafe: number | boolean): string {
|
||||
return url;
|
||||
}
|
||||
|
||||
function matchUrl(text: string) {
|
||||
export function matchUrl(text: string) {
|
||||
return text.match(urlRegExp);
|
||||
}
|
||||
|
||||
let RichTextProcessor = {
|
||||
wrapRichText,
|
||||
wrapPlainText,
|
||||
wrapDraftText,
|
||||
wrapUrl,
|
||||
wrapEmojiText,
|
||||
parseEntities,
|
||||
parseMarkdown,
|
||||
parseEmojis,
|
||||
mergeEntities,
|
||||
getEmojiSpritesheetCoords,
|
||||
emojiSupported,
|
||||
matchUrl
|
||||
};
|
||||
}
|
||||
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.RichTextProcessor = RichTextProcessor);
|
||||
|
||||
export {RichTextProcessor};
|
||||
export default RichTextProcessor;
|
||||
|
||||
|
@ -34,7 +34,7 @@ const appSidebarLeft = AppSidebarLeft;
|
||||
const appMediaViewer = AppMediaViewer;
|
||||
const appDialogsManager = AppDialogsManager;
|
||||
|
||||
(window as any).Services = {
|
||||
const Services = {
|
||||
appUsersManager,
|
||||
appChatsManager,
|
||||
apiUpdatesManager,
|
||||
@ -53,3 +53,10 @@ const appDialogsManager = AppDialogsManager;
|
||||
appMediaViewer
|
||||
//appSharedMediaManager
|
||||
};
|
||||
|
||||
(window as any).Services = Services;
|
||||
|
||||
for(let i in Services) {
|
||||
// @ts-ignore
|
||||
(window as any)[i] = Services[i];
|
||||
}
|
||||
|
@ -10,7 +10,12 @@ for(const constructor of additional) {
|
||||
param.type = 'flags.-1?' + param.type;
|
||||
});
|
||||
|
||||
const realConstructor = mtproto.constructors.find(c => c.predicate == constructor.predicate);
|
||||
if(constructor.type) {
|
||||
mtproto.constructors.push(constructor);
|
||||
}
|
||||
|
||||
const realConstructor = constructor.type ? constructor : mtproto.constructors.find(c => c.predicate == constructor.predicate);
|
||||
|
||||
/* constructor.params.forEach(param => {
|
||||
const index = realConstructor.params.findIndex(_param => _param.predicate == param.predicate);
|
||||
if(index !== -1) {
|
||||
|
@ -91,4 +91,124 @@
|
||||
"params": [
|
||||
{"name": "rAbout", "type": "string"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityEmoji",
|
||||
"params": [
|
||||
{"name": "offset", "type": "number"},
|
||||
{"name": "length", "type": "number"},
|
||||
{"name": "unicode", "type": "string"},
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
],
|
||||
"type": "MessageEntity"
|
||||
}, {
|
||||
"predicate": "messageEntityHighlight",
|
||||
"params": [
|
||||
{"name": "offset", "type": "number"},
|
||||
{"name": "length", "type": "number"},
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
],
|
||||
"type": "MessageEntity"
|
||||
}, {
|
||||
"predicate": "messageEntityLinebreak",
|
||||
"params": [
|
||||
{"name": "offset", "type": "number"},
|
||||
{"name": "length", "type": "number"},
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
],
|
||||
"type": "MessageEntity"
|
||||
}, {
|
||||
"predicate": "messageEntityUnknown",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityMention",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityHashtag",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityBotCommand",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityUrl",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityEmail",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityBold",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityItalic",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityCode",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityPre",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityTextUrl",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityMentionName",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityPhone",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityCashtag",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityUnderline",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityStrike",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityBlockquote",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEntityBankCard",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "inputMessageEntityMentionName",
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}]
|
Loading…
x
Reference in New Issue
Block a user