aboutsummaryrefslogtreecommitdiff
path: root/vnext/src/utils/embed.js
diff options
context:
space:
mode:
Diffstat (limited to 'vnext/src/utils/embed.js')
-rw-r--r--vnext/src/utils/embed.js260
1 files changed, 130 insertions, 130 deletions
diff --git a/vnext/src/utils/embed.js b/vnext/src/utils/embed.js
index f16342cf..afec71b4 100644
--- a/vnext/src/utils/embed.js
+++ b/vnext/src/utils/embed.js
@@ -2,21 +2,21 @@ function htmlEscape(html) {
return html.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/</g, '&lt;')
- .replace(/>/g, '&gt;');
+ .replace(/>/g, '&gt;')
}
function insertAfter(newNode, referenceNode) {
- referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
+ referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling)
}
function setContent(containerNode, ...newNodes) {
- removeAllFrom(containerNode);
- newNodes.forEach(n => containerNode.appendChild(n));
- return containerNode;
+ removeAllFrom(containerNode)
+ newNodes.forEach(n => containerNode.appendChild(n))
+ return containerNode
}
function removeAllFrom(fromNode) {
- fromNode.innerHTML = '';
+ fromNode.innerHTML = ''
}
// rules :: [{pr: number, re: RegExp, with: string}]
@@ -24,96 +24,96 @@ function removeAllFrom(fromNode) {
// rules :: [{pr: number, re: RegExp, brackets: true, with: [string, string]}]
// rules :: [{pr: number, re: RegExp, brackets: true, with: [string, string, Function]}]
function formatText(txt, rules) {
- let idCounter = 0;
- function nextId() { return idCounter++; }
+ let idCounter = 0
+ function nextId() { return idCounter++ }
function ft(txt, rules) {
- let matches = rules.map(r => { r.re.lastIndex = 0; return [r, r.re.exec(txt)]; })
+ let matches = rules.map(r => { r.re.lastIndex = 0; return [r, r.re.exec(txt)] })
.filter(([, m]) => m !== null)
- .sort(([r1, m1], [r2, m2]) => (r1.pr - r2.pr) || (m1.index - m2.index));
+ .sort(([r1, m1], [r2, m2]) => (r1.pr - r2.pr) || (m1.index - m2.index))
if (matches && matches.length > 0) {
- let [rule, match] = matches[0];
- let subsequentRules = rules.filter(r => r.pr >= rule.pr);
- let idStr = `<>(${nextId()})<>`;
- let outerStr = txt.substring(0, match.index) + idStr + txt.substring(rule.re.lastIndex);
+ let [rule, match] = matches[0]
+ let subsequentRules = rules.filter(r => r.pr >= rule.pr)
+ let idStr = `<>(${nextId()})<>`
+ let outerStr = txt.substring(0, match.index) + idStr + txt.substring(rule.re.lastIndex)
let innerStr = (rule.brackets)
- ? (() => { let [l, r, f] = rule.with; return l + ft((f ? f(match[1]) : match[1]), subsequentRules) + r; })()
- : match[0].replace(rule.re, rule.with);
- return ft(outerStr, subsequentRules).replace(idStr, innerStr);
+ ? (() => { let [l, r, f] = rule.with; return l + ft((f ? f(match[1]) : match[1]), subsequentRules) + r })()
+ : match[0].replace(rule.re, rule.with)
+ return ft(outerStr, subsequentRules).replace(idStr, innerStr)
}
- return txt;
+ return txt
}
- return ft(htmlEscape(txt), rules); // idStr above relies on the fact the text is escaped
+ return ft(htmlEscape(txt), rules) // idStr above relies on the fact the text is escaped
}
function fixWwwLink(url) {
- return url.replace(/^(?!([a-z]+:)?\/\/)/i, '//');
+ return url.replace(/^(?!([a-z]+:)?\/\/)/i, '//')
}
function makeNewNode(embedType, aNode, reResult) {
const withClasses = el => {
if (embedType.className) {
- el.classList.add(...embedType.className.split(' '));
+ el.classList.add(...embedType.className.split(' '))
}
- return el;
- };
- return embedType.makeNode(aNode, reResult, withClasses(document.createElement('div')));
+ return el
+ }
+ return embedType.makeNode(aNode, reResult, withClasses(document.createElement('div')))
}
function makeIframe(src, w, h, scrolling = 'no') {
- let iframe = document.createElement('iframe');
- iframe.style.width = w;
- iframe.style.height = h;
- iframe.frameBorder = '0';
- iframe.scrolling = scrolling;
- iframe.setAttribute('allowFullScreen', '');
- iframe.src = src;
- iframe.innerHTML = 'Cannot show iframes.';
- return iframe;
+ let iframe = document.createElement('iframe')
+ iframe.style.width = w
+ iframe.style.height = h
+ iframe.frameBorder = '0'
+ iframe.scrolling = scrolling
+ iframe.setAttribute('allowFullScreen', '')
+ iframe.src = src
+ iframe.innerHTML = 'Cannot show iframes.'
+ return iframe
}
function makeResizableToRatio(element, ratio) {
- element.setAttribute('data-ratio', ratio);
- makeResizable(element, w => w * element.getAttribute('data-ratio'));
+ element.setAttribute('data-ratio', ratio)
+ makeResizable(element, w => w * element.getAttribute('data-ratio'))
}
// calcHeight :: Number -> Number -- calculate element height for a given width
function makeResizable(element, calcHeight) {
const setHeight = el => {
if (document.body.contains(el) && (el.offsetWidth > 0)) {
- el.style.height = (calcHeight(el.offsetWidth)).toFixed(2) + 'px';
+ el.style.height = (calcHeight(el.offsetWidth)).toFixed(2) + 'px'
}
- };
- window.addEventListener('resize', () => setHeight(element));
- setHeight(element);
+ }
+ window.addEventListener('resize', () => setHeight(element))
+ setHeight(element)
}
function extractDomain(url) {
- const domainRe = /^(?:https?:\/\/)?(?:[^@/\n]+@)?(?:www\.)?([^:/\n]+)/i;
- let result = domainRe.exec(url) || [];
+ const domainRe = /^(?:https?:\/\/)?(?:[^@/\n]+@)?(?:www\.)?([^:/\n]+)/i
+ let result = domainRe.exec(url) || []
if (result.length > 0) {
- return result[1];
+ return result[1]
}
}
function urlReplace(match, p1, p2, p3) {
- let isBrackets = (p1 !== undefined);
+ let isBrackets = (p1 !== undefined)
return (isBrackets)
? `<a href="${fixWwwLink(p2 || p3)}">${p1}</a>`
- : `<a href="${fixWwwLink(match)}">${extractDomain(match)}</a>`;
+ : `<a href="${fixWwwLink(match)}">${extractDomain(match)}</a>`
}
function urlReplaceInCode(match, p1, p2, p3) {
- let isBrackets = (p1 !== undefined);
+ let isBrackets = (p1 !== undefined)
return (isBrackets)
? `<a href="${fixWwwLink(p2 || p3)}">${match}</a>`
- : `<a href="${fixWwwLink(match)}">${match}</a>`;
+ : `<a href="${fixWwwLink(match)}">${match}</a>`
}
function messageReplyReplace(messageId) {
return function(match, mid, rid) {
- let replyPart = (rid && rid != '0') ? '#' + rid : '';
- return `<a href="/m/${mid || messageId}${replyPart}">${match}</a>`;
- };
+ let replyPart = (rid && rid != '0') ? '#' + rid : ''
+ return `<a href="/m/${mid || messageId}${replyPart}">${match}</a>`
+ }
}
/**
@@ -125,8 +125,8 @@ function messageReplyReplace(messageId) {
* @returns {string} formatted message
*/
function juickFormat(txt, messageId, isCode) {
- const urlRe = /(?:\[([^\][]+)\](?:\[([^\]]+)\]|\(((?:[a-z]+:\/\/|www\.|ftp\.)(?:\([-\S+*&@#/%=~|$?!:;,.]*\)|[-\S+*&@#/%=~|$?!:;,.])*(?:\([-\S+*&@#/%=~|$?!:;,.]*\)|[\S+*&@#/%=~|$]))\))|\b(?:[a-z]+:\/\/|www\.|ftp\.)(?:\([-\S+*&@#/%=~|$?!:;,.]*\)|[-\S+*&@#/%=~|$?!:;,.])*(?:\([-\S+*&@#/%=~|$?!:;,.]*\)|[\S+*&@#/%=~|$]))/gi;
- const bqReplace = m => m.replace(/^(?:>|&gt;)\s?/gmi, '');
+ const urlRe = /(?:\[([^\][]+)\](?:\[([^\]]+)\]|\(((?:[a-z]+:\/\/|www\.|ftp\.)(?:\([-\S+*&@#/%=~|$?!:;,.]*\)|[-\S+*&@#/%=~|$?!:;,.])*(?:\([-\S+*&@#/%=~|$?!:;,.]*\)|[\S+*&@#/%=~|$]))\))|\b(?:[a-z]+:\/\/|www\.|ftp\.)(?:\([-\S+*&@#/%=~|$?!:;,.]*\)|[-\S+*&@#/%=~|$?!:;,.])*(?:\([-\S+*&@#/%=~|$?!:;,.]*\)|[\S+*&@#/%=~|$]))/gi
+ const bqReplace = m => m.replace(/^(?:>|&gt;)\s?/gmi, '')
return (isCode)
? formatText(txt, [
{ pr: 1, re: urlRe, with: urlReplaceInCode },
@@ -142,7 +142,7 @@ function juickFormat(txt, messageId, isCode) {
{ pr: 2, re: /\B\/([^\n]+?)\/((?=\s)|(?=$)|(?=[!"#$%&'*+,\-./:;<=>?@[\]^_`{|}~()]+))/g, brackets: true, with: ['<i>', '</i>'] },
{ pr: 2, re: /\b_([^\n]+?)_((?=\s)|(?=$)|(?=[!"#$%&'*+,\-./:;<=>?@[\]^_`{|}~()]+))/g, brackets: true, with: ['<u>', '</u>'] },
{ pr: 3, re: /\n/g, with: '<br/>' },
- ]);
+ ])
}
/**
* @external RegExpExecArray
@@ -179,9 +179,9 @@ function getEmbeddableLinkTypes() {
re: /\.(jpe?g|png|svg)(:[a-zA-Z]+)?(?:\?[\w&;?=]*)?$/i,
makeNode: function(aNode, reResult, div) {
// dirty fix for dropbox urls
- let url = aNode.href.endsWith('dl=0') ? aNode.href.replace('dl=0', 'raw=1') : aNode.href;
- div.innerHTML = `<a href="${url}"><img src="${url}"></a>`;
- return div;
+ let url = aNode.href.endsWith('dl=0') ? aNode.href.replace('dl=0', 'raw=1') : aNode.href
+ div.innerHTML = `<a href="${url}"><img src="${url}"></a>`
+ return div
}
},
{
@@ -190,8 +190,8 @@ function getEmbeddableLinkTypes() {
className: 'picture compact',
re: /\.gif(:[a-zA-Z]+)?(?:\?[\w&;?=]*)?$/i,
makeNode: function(aNode, reResult, div) {
- div.innerHTML = `<a href="${aNode.href}"><img src="${aNode.href}"></a>`;
- return div;
+ div.innerHTML = `<a href="${aNode.href}"><img src="${aNode.href}"></a>`
+ return div
}
},
{
@@ -200,8 +200,8 @@ function getEmbeddableLinkTypes() {
className: 'video compact',
re: /\.(webm|mp4|m4v|ogv)(?:\?[\w&;?=]*)?$/i,
makeNode: function(aNode, reResult, div) {
- div.innerHTML = `<video src="${aNode.href}" title="${aNode.href}" controls></video>`;
- return div;
+ div.innerHTML = `<video src="${aNode.href}" title="${aNode.href}" controls></video>`
+ return div
}
},
{
@@ -210,8 +210,8 @@ function getEmbeddableLinkTypes() {
className: 'audio singleColumn',
re: /\.(mp3|ogg|weba|opus|m4a|oga|wav)(?:\?[\w&;?=]*)?$/i,
makeNode: function(aNode, reResult, div) {
- div.innerHTML = `<audio src="${aNode.href}" title="${aNode.href}" controls></audio>`;
- return div;
+ div.innerHTML = `<audio src="${aNode.href}" title="${aNode.href}" controls></audio>`
+ return div
}
},
{
@@ -220,37 +220,37 @@ function getEmbeddableLinkTypes() {
className: 'youtube resizableV singleColumn',
re: /^(?:https?:)?\/\/(?:www\.|m\.|gaming\.)?(?:youtu(?:(?:\.be\/|be\.com\/(?:v|embed)\/)([-\w]+)|be\.com\/watch)((?:(?:\?|&(?:amp;)?)(?:\w+=[-.\w]*[-\w]))*)|youtube\.com\/playlist\?list=([-\w]*)(&(amp;)?[-\w?=]*)?)/i,
makeNode: function(aNode, reResult, div) {
- let [, v, args, plist] = reResult;
- let iframeUrl;
+ let [, v, args, plist] = reResult
+ let iframeUrl
if (plist) {
- iframeUrl = '//www.youtube-nocookie.com/embed/videoseries?list=' + plist;
+ iframeUrl = '//www.youtube-nocookie.com/embed/videoseries?list=' + plist
} else {
let pp = {}; args.replace(/^\?/, '')
.split('&')
.map(s => s.split('='))
- .forEach(z => pp[z[0]] = z[1]);
+ .forEach(z => pp[z[0]] = z[1])
let embedArgs = {
rel: '0',
enablejsapi: '1',
origin: `${window.location.protocol}//${window.location.host}`
- };
+ }
if (pp.t) {
- const tre = /^(?:(\d+)|(?:(\d+)h)?(?:(\d+)m)?(\d+)s|(?:(\d+)h)?(\d+)m|(\d+)h)$/i;
- let [, t, h, m, s, h1, m1, h2] = tre.exec(pp.t);
- embedArgs['start'] = (+t) || ((+(h || h1 || h2 || 0)) * 60 * 60 + (+(m || m1 || 0)) * 60 + (+(s || 0)));
+ const tre = /^(?:(\d+)|(?:(\d+)h)?(?:(\d+)m)?(\d+)s|(?:(\d+)h)?(\d+)m|(\d+)h)$/i
+ let [, t, h, m, s, h1, m1, h2] = tre.exec(pp.t)
+ embedArgs['start'] = (+t) || ((+(h || h1 || h2 || 0)) * 60 * 60 + (+(m || m1 || 0)) * 60 + (+(s || 0)))
}
if (pp.list) {
- embedArgs['list'] = pp.list;
+ embedArgs['list'] = pp.list
}
- v = v || pp.v;
+ v = v || pp.v
let argsStr = Object.keys(embedArgs)
.map(k => `${k}=${embedArgs[k]}`)
- .join('&');
- iframeUrl = `//www.youtube-nocookie.com/embed/${v}?${argsStr}`;
+ .join('&')
+ iframeUrl = `//www.youtube-nocookie.com/embed/${v}?${argsStr}`
}
- let iframe = makeIframe(iframeUrl, '100%', '360px');
- iframe.onload = () => makeResizableToRatio(iframe, 9.0 / 16.0);
- return setContent(div, iframe);
+ let iframe = makeIframe(iframeUrl, '100%', '360px')
+ iframe.onload = () => makeResizableToRatio(iframe, 9.0 / 16.0)
+ return setContent(div, iframe)
}
},
{
@@ -259,9 +259,9 @@ function getEmbeddableLinkTypes() {
className: 'vimeo resizableV',
re: /^(?:https?:)?\/\/(?:www\.)?(?:player\.)?vimeo\.com\/(?:video\/|album\/[\d]+\/video\/)?([\d]+)/i,
makeNode: function(aNode, reResult, div) {
- let iframe = makeIframe('//player.vimeo.com/video/' + reResult[1], '100%', '360px');
- iframe.onload = () => makeResizableToRatio(iframe, 9.0 / 16.0);
- return setContent(div, iframe);
+ let iframe = makeIframe('//player.vimeo.com/video/' + reResult[1], '100%', '360px')
+ iframe.onload = () => makeResizableToRatio(iframe, 9.0 / 16.0)
+ return setContent(div, iframe)
}
},
{
@@ -273,9 +273,9 @@ function getEmbeddableLinkTypes() {
fetch('https://beta.juick.com/api/oembed?url=' + reResult[0])
.then(response => response.json())
.then(json => {
- div.innerHTML = json.html;
- }).catch(console.log);
- return div;
+ div.innerHTML = json.html
+ }).catch(console.log)
+ return div
}
},
{
@@ -284,10 +284,10 @@ function getEmbeddableLinkTypes() {
className: 'picture compact',
re: /https?:\/\/www\.?instagram\.com(\/p\/\w+)\/?/i,
makeNode: function(aNode, reResult, div) {
- let [, postId] = reResult;
- let mediaUrl = `https://instagr.am${postId}/media`;
- div.innerHTML = `<a href="${aNode.href}"><img src="${mediaUrl}"></a>`;
- return div;
+ let [, postId] = reResult
+ let mediaUrl = `https://instagr.am${postId}/media`
+ div.innerHTML = `<a href="${aNode.href}"><img src="${mediaUrl}"></a>`
+ return div
}
},
{
@@ -296,19 +296,19 @@ function getEmbeddableLinkTypes() {
className: 'tg compact',
re: /https?:\/\/t\.me\/(\S+)/i,
makeNode: function(aNode, reResult, div) {
- let [, post] = reResult;
+ let [, post] = reResult
// innerHTML cannot insert scripts, so...
- let script = document.createElement('script');
- script.src = 'https://telegram.org/js/telegram-widget.js?18';
- script.setAttribute('data-telegram-post', post);
- script.setAttribute('data-tme-mode', 'data-tme-mode');
- script.setAttribute('data-width', '100%');
- script.charset = 'utf-8';
- div.appendChild(script);
- return div;
+ let script = document.createElement('script')
+ script.src = 'https://telegram.org/js/telegram-widget.js?18'
+ script.setAttribute('data-telegram-post', post)
+ script.setAttribute('data-tme-mode', 'data-tme-mode')
+ script.setAttribute('data-width', '100%')
+ script.charset = 'utf-8'
+ div.appendChild(script)
+ return div
}
},
- ];
+ ]
}
/**
@@ -320,38 +320,38 @@ function getEmbeddableLinkTypes() {
* @returns { boolean } `true` when some link was embedded
*/
function embedLink(aNode, linkTypes, container, afterNode = false) {
- let anyEmbed = false;
- let linkId = (aNode.href.replace(/^https?:/i, '').replace(/'/gi, ''));
- let sameEmbed = container.querySelector(`*[data-linkid='${linkId}']`); // do not embed the same thing twice
+ let anyEmbed = false
+ let linkId = (aNode.href.replace(/^https?:/i, '').replace(/'/gi, ''))
+ let sameEmbed = container.querySelector(`*[data-linkid='${linkId}']`) // do not embed the same thing twice
if (!sameEmbed) {
anyEmbed = linkTypes.some((linkType) => {
- let reResult = linkType.re.exec(aNode.href);
+ let reResult = linkType.re.exec(aNode.href)
if (reResult) {
- if (linkType.match && (linkType.match(aNode, reResult) === false)) { return false; }
- let newNode = makeNewNode(linkType, aNode, reResult);
- if (!newNode) { return false; }
- newNode.setAttribute('data-linkid', linkId);
+ if (linkType.match && (linkType.match(aNode, reResult) === false)) { return false }
+ let newNode = makeNewNode(linkType, aNode, reResult)
+ if (!newNode) { return false }
+ newNode.setAttribute('data-linkid', linkId)
if (afterNode) {
- insertAfter(newNode, afterNode);
+ insertAfter(newNode, afterNode)
} else {
- container.appendChild(newNode);
+ container.appendChild(newNode)
}
- aNode.classList.add('embedLink');
- return true;
+ aNode.classList.add('embedLink')
+ return true
}
- });
+ })
}
- return anyEmbed;
+ return anyEmbed
}
function embedLinks(aNodes, container) {
- let anyEmbed = false;
- let embeddableLinkTypes = getEmbeddableLinkTypes();
+ let anyEmbed = false
+ let embeddableLinkTypes = getEmbeddableLinkTypes()
Array.from(aNodes).forEach(aNode => {
- let isEmbedded = embedLink(aNode, embeddableLinkTypes, container);
- anyEmbed = anyEmbed || isEmbedded;
- });
- return anyEmbed;
+ let isEmbedded = embedLink(aNode, embeddableLinkTypes, container)
+ anyEmbed = anyEmbed || isEmbedded
+ })
+ return anyEmbed
}
/**
@@ -364,19 +364,19 @@ function embedLinks(aNodes, container) {
* @param {string} allLinksSelector
*/
export function embedLinksToX(x, beforeNodeSelector, allLinksSelector) {
- let allLinks = x.querySelectorAll(allLinksSelector);
+ let allLinks = x.querySelectorAll(allLinksSelector)
- let existingContainer = x.querySelector('div.embedContainer');
+ let existingContainer = x.querySelector('div.embedContainer')
if (existingContainer) {
- embedLinks(allLinks, existingContainer);
+ embedLinks(allLinks, existingContainer)
} else {
- let embedContainer = document.createElement('div');
- embedContainer.className = 'embedContainer';
+ let embedContainer = document.createElement('div')
+ embedContainer.className = 'embedContainer'
- let anyEmbed = embedLinks(allLinks, embedContainer);
+ let anyEmbed = embedLinks(allLinks, embedContainer)
if (anyEmbed) {
- let beforeNode = x.querySelector(beforeNodeSelector);
- x.insertBefore(embedContainer, beforeNode);
+ let beforeNode = x.querySelector(beforeNodeSelector)
+ x.insertBefore(embedContainer, beforeNode)
}
}
}
@@ -385,11 +385,11 @@ export function embedLinksToX(x, beforeNodeSelector, allLinksSelector) {
* Embed all the links in all messages/replies on the page.
*/
export function embedAll() {
- let beforeNodeSelector = '.msg-txt + *';
- let allLinksSelector = '.msg-txt a';
+ let beforeNodeSelector = '.msg-txt + *'
+ let allLinksSelector = '.msg-txt a'
Array.from(document.querySelectorAll('#content .msg-cont')).forEach(msg => {
- embedLinksToX(msg, beforeNodeSelector, allLinksSelector);
- });
+ embedLinksToX(msg, beforeNodeSelector, allLinksSelector)
+ })
}
/**
* Embed URLs to container
@@ -397,8 +397,8 @@ export function embedAll() {
* @param {HTMLDivElement} embedContainer
*/
export function embedUrls(urls, embedContainer) {
- embedLinks(urls, embedContainer);
+ embedLinks(urls, embedContainer)
}
-export const format = juickFormat;
+export const format = juickFormat