mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-28 05:15:54 +00:00
4.20.26
* Fixed: Remove console debugging. * API Added: Link embeds and tooltips now support markdown. * API Fixed: Bug when setting raw HTML while using `createElement`.
This commit is contained in:
parent
e73534dd75
commit
e87c99f206
4 changed files with 81 additions and 28 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "frankerfacez",
|
"name": "frankerfacez",
|
||||||
"author": "Dan Salvato LLC",
|
"author": "Dan Salvato LLC",
|
||||||
"version": "4.20.25",
|
"version": "4.20.26",
|
||||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -63,8 +63,6 @@ export default class RichContent extends Module {
|
||||||
data = await data;
|
data = await data;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('data', data);
|
|
||||||
|
|
||||||
if ( ! data )
|
if ( ! data )
|
||||||
data = {
|
data = {
|
||||||
error: {type: 'i18n', key: 'card.empty', phrase: 'No data was returned.'}
|
error: {type: 'i18n', key: 'card.empty', phrase: 'No data was returned.'}
|
||||||
|
|
|
@ -83,7 +83,9 @@ export function findReactFragment(frag, criteria, depth = 25, current = 0, visit
|
||||||
export function createElement(tag, props, ...children) {
|
export function createElement(tag, props, ...children) {
|
||||||
const el = document.createElement(tag);
|
const el = document.createElement(tag);
|
||||||
|
|
||||||
if ( children.length === 1)
|
if ( children.length === 0)
|
||||||
|
children = null;
|
||||||
|
else if ( children.length === 1)
|
||||||
children = children[0];
|
children = children[0];
|
||||||
|
|
||||||
if ( typeof props === 'string' )
|
if ( typeof props === 'string' )
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
import {has} from 'utilities/object';
|
import {has} from 'utilities/object';
|
||||||
|
import Markdown from 'markdown-it';
|
||||||
|
import MILA from 'markdown-it-link-attributes';
|
||||||
|
|
||||||
export const TOKEN_TYPES = {};
|
export const TOKEN_TYPES = {};
|
||||||
|
|
||||||
|
@ -22,6 +24,26 @@ const VALID_WEIGHTS = ['regular', 'bold', 'semibold'],
|
||||||
huge: 'huge'
|
huge: 'huge'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Markdown
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
const md = new Markdown({
|
||||||
|
html: false,
|
||||||
|
linkify: true
|
||||||
|
}).disable('image');
|
||||||
|
|
||||||
|
md.use(MILA, {
|
||||||
|
attrs: {
|
||||||
|
class: 'ffz-tooltip',
|
||||||
|
target: '_blank',
|
||||||
|
rel: 'noopener',
|
||||||
|
'data-tooltip-type': 'link'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Render Tokens
|
// Render Tokens
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
@ -127,10 +149,13 @@ export function getRoundClass(value) {
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
|
||||||
export function renderWithCapture(tokens, createElement, ctx) {
|
export function renderWithCapture(tokens, createElement, ctx, markdown) {
|
||||||
const old_capture = ctx.text_capture;
|
const old_capture = ctx.text_capture, old_markdown = ctx.markdown;
|
||||||
ctx.text_capture = [];
|
ctx.text_capture = [];
|
||||||
|
|
||||||
|
if ( markdown )
|
||||||
|
ctx.markdown = true;
|
||||||
|
|
||||||
const content = renderTokens(tokens, createElement, ctx);
|
const content = renderTokens(tokens, createElement, ctx);
|
||||||
|
|
||||||
let title = ctx.text_capture.join('').trim();
|
let title = ctx.text_capture.join('').trim();
|
||||||
|
@ -138,17 +163,22 @@ export function renderWithCapture(tokens, createElement, ctx) {
|
||||||
title = null;
|
title = null;
|
||||||
|
|
||||||
ctx.text_capture = old_capture;
|
ctx.text_capture = old_capture;
|
||||||
|
ctx.markdown = old_markdown;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content,
|
content,
|
||||||
title
|
title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function renderTokens(tokens, createElement, ctx, markdown) {
|
||||||
export function renderTokens(tokens, createElement, ctx) {
|
|
||||||
if ( tokens == null )
|
if ( tokens == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
const old_markdown = ctx.markdown;
|
||||||
|
if ( markdown )
|
||||||
|
ctx.markdown = true;
|
||||||
|
|
||||||
let out = [];
|
let out = [];
|
||||||
if ( ! Array.isArray(tokens) )
|
if ( ! Array.isArray(tokens) )
|
||||||
tokens = [tokens];
|
tokens = [tokens];
|
||||||
|
@ -164,7 +194,26 @@ export function renderTokens(tokens, createElement, ctx) {
|
||||||
const val = String(token);
|
const val = String(token);
|
||||||
if ( ctx.text_capture )
|
if ( ctx.text_capture )
|
||||||
ctx.text_capture.push(val);
|
ctx.text_capture.push(val);
|
||||||
out.push(val);
|
|
||||||
|
if ( ctx.markdown ) {
|
||||||
|
const content = md.render(val);
|
||||||
|
if ( content === val )
|
||||||
|
out.push(val);
|
||||||
|
else if ( ctx.vue )
|
||||||
|
out.push(createElement('span', {
|
||||||
|
domProps: {
|
||||||
|
innerHTML: content
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
else
|
||||||
|
out.push(createElement('span', {
|
||||||
|
dangerouslySetInnerHTML: {
|
||||||
|
__html: content
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
} else
|
||||||
|
out.push(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
@ -184,6 +233,7 @@ export function renderTokens(tokens, createElement, ctx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.markdown = old_markdown;
|
||||||
if ( ! out.length )
|
if ( ! out.length )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
@ -214,14 +264,15 @@ TOKEN_TYPES.box = function(token, createElement, ctx) {
|
||||||
applySpacing('pd', token, classes, style);
|
applySpacing('pd', token, classes, style);
|
||||||
applySpacing('mg', token, classes, style);
|
applySpacing('mg', token, classes, style);
|
||||||
|
|
||||||
const capture = token.ellipsis || token.lines;
|
const capture = token.ellipsis || token.lines,
|
||||||
|
markdown = token.markdown;
|
||||||
let content, title = null;
|
let content, title = null;
|
||||||
|
|
||||||
if ( capture ) {
|
if ( capture ) {
|
||||||
const out = renderWithCapture(token.content, createElement, ctx);
|
const out = renderWithCapture(token.content, createElement, ctx, markdown);
|
||||||
content = out.content; title = out.title;
|
content = out.content; title = out.title;
|
||||||
} else
|
} else
|
||||||
content = renderTokens(token.content, createElement, ctx);
|
content = renderTokens(token.content, createElement, ctx, markdown);
|
||||||
|
|
||||||
if ( ctx.vue )
|
if ( ctx.vue )
|
||||||
return createElement('div', {class: classes, style, attrs: {title}}, content);
|
return createElement('div', {class: classes, style, attrs: {title}}, content);
|
||||||
|
@ -264,8 +315,9 @@ TOKEN_TYPES.fieldset = function(token, createElement, ctx) {
|
||||||
if ( ! field )
|
if ( ! field )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const name = renderTokens(field.name, createElement, ctx),
|
|
||||||
value = renderTokens(field.value, createElement, ctx);
|
const name = renderTokens(field.name, createElement, ctx, token.markdown),
|
||||||
|
value = renderTokens(field.value, createElement, ctx, token.markdown);
|
||||||
|
|
||||||
if ( name == null || value == null )
|
if ( name == null || value == null )
|
||||||
continue;
|
continue;
|
||||||
|
@ -352,7 +404,7 @@ TOKEN_TYPES.flex = function(token, createElement, ctx) {
|
||||||
applySpacing('pd', token, classes, style);
|
applySpacing('pd', token, classes, style);
|
||||||
applySpacing('mg', token, classes, style);
|
applySpacing('mg', token, classes, style);
|
||||||
|
|
||||||
const content = renderTokens(token.content, createElement, ctx);
|
const content = renderTokens(token.content, createElement, ctx, token.markdown);
|
||||||
if ( ctx.vue )
|
if ( ctx.vue )
|
||||||
return createElement('div', {class: classes, style}, content);
|
return createElement('div', {class: classes, style}, content);
|
||||||
|
|
||||||
|
@ -460,7 +512,7 @@ function header_vue(token, h, ctx) {
|
||||||
let content = [];
|
let content = [];
|
||||||
|
|
||||||
if ( token.title ) {
|
if ( token.title ) {
|
||||||
const out = renderWithCapture(token.title, h, ctx);
|
const out = renderWithCapture(token.title, h, ctx, token.markdown);
|
||||||
content.push(h('div', {
|
content.push(h('div', {
|
||||||
class: 'tw-ellipsis tw-semibold tw-mg-x-05',
|
class: 'tw-ellipsis tw-semibold tw-mg-x-05',
|
||||||
attrs: {
|
attrs: {
|
||||||
|
@ -470,7 +522,7 @@ function header_vue(token, h, ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( token.subtitle ) {
|
if ( token.subtitle ) {
|
||||||
const out = renderWithCapture(token.subtitle, h, ctx);
|
const out = renderWithCapture(token.subtitle, h, ctx, token.markdown);
|
||||||
content.push(h('div', {
|
content.push(h('div', {
|
||||||
class: 'tw-ellipsis tw-c-text-alt-2 tw-mg-x-05',
|
class: 'tw-ellipsis tw-c-text-alt-2 tw-mg-x-05',
|
||||||
attrs: {
|
attrs: {
|
||||||
|
@ -480,7 +532,7 @@ function header_vue(token, h, ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( token.extra ) {
|
if ( token.extra ) {
|
||||||
const out = renderWithCapture(token.extra, h, ctx);
|
const out = renderWithCapture(token.extra, h, ctx, token.markdown);
|
||||||
content.push(h('div', {
|
content.push(h('div', {
|
||||||
class: 'tw-ellipsis tw-c-text-alt-2 tw-mg-x-05',
|
class: 'tw-ellipsis tw-c-text-alt-2 tw-mg-x-05',
|
||||||
attrs: {
|
attrs: {
|
||||||
|
@ -555,7 +607,7 @@ function header_normal(token, createElement, ctx) {
|
||||||
let content = [];
|
let content = [];
|
||||||
|
|
||||||
if ( token.title ) {
|
if ( token.title ) {
|
||||||
const out = renderWithCapture(token.title, createElement, ctx);
|
const out = renderWithCapture(token.title, createElement, ctx, token.markdown);
|
||||||
content.push(createElement('div', {
|
content.push(createElement('div', {
|
||||||
className: `tw-ellipsis tw-semibold ${token.compact ? 'tw-mg-r-1' : ''}`,
|
className: `tw-ellipsis tw-semibold ${token.compact ? 'tw-mg-r-1' : ''}`,
|
||||||
title: out.title
|
title: out.title
|
||||||
|
@ -563,7 +615,7 @@ function header_normal(token, createElement, ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( token.subtitle ) {
|
if ( token.subtitle ) {
|
||||||
const out = renderWithCapture(token.subtitle, createElement, ctx);
|
const out = renderWithCapture(token.subtitle, createElement, ctx, token.markdown);
|
||||||
content.push(createElement('div', {
|
content.push(createElement('div', {
|
||||||
className: `tw-ellipsis tw-c-text-alt-2`,
|
className: `tw-ellipsis tw-c-text-alt-2`,
|
||||||
title: out.title
|
title: out.title
|
||||||
|
@ -571,7 +623,7 @@ function header_normal(token, createElement, ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( token.extra ) {
|
if ( token.extra ) {
|
||||||
const out = renderWithCapture(token.extra, createElement, ctx);
|
const out = renderWithCapture(token.extra, createElement, ctx, token.markdown);
|
||||||
content.push(createElement('div', {
|
content.push(createElement('div', {
|
||||||
className: 'tw-ellipsis tw-c-text-alt-2',
|
className: 'tw-ellipsis tw-c-text-alt-2',
|
||||||
title: out.title
|
title: out.title
|
||||||
|
@ -749,7 +801,8 @@ TOKEN_TYPES.i18n = function(token, createElement, ctx) {
|
||||||
return renderTokens(
|
return renderTokens(
|
||||||
ctx.i18n.tList(token.key, token.phrase, token.content),
|
ctx.i18n.tList(token.key, token.phrase, token.content),
|
||||||
createElement,
|
createElement,
|
||||||
ctx
|
ctx,
|
||||||
|
token.markdown
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,7 +812,7 @@ TOKEN_TYPES.i18n = function(token, createElement, ctx) {
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
TOKEN_TYPES.link = function(token, createElement, ctx) {
|
TOKEN_TYPES.link = function(token, createElement, ctx) {
|
||||||
const content = renderTokens(token.content, createElement, ctx);
|
const content = renderTokens(token.content, createElement, ctx, token.markdown);
|
||||||
|
|
||||||
const klass = [];
|
const klass = [];
|
||||||
if ( token.interactive )
|
if ( token.interactive )
|
||||||
|
@ -800,13 +853,13 @@ TOKEN_TYPES.link = function(token, createElement, ctx) {
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
TOKEN_TYPES.overlay = function(token, createElement, ctx) {
|
TOKEN_TYPES.overlay = function(token, createElement, ctx) {
|
||||||
const content = renderTokens(token.content, createElement, ctx);
|
const content = renderTokens(token.content, createElement, ctx, token.markdown);
|
||||||
if ( ! content )
|
if ( ! content )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const corners = [];
|
const corners = [];
|
||||||
for(const corner of ['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right']) {
|
for(const corner of ['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right']) {
|
||||||
const stuff = renderTokens(token[corner], createElement, ctx);
|
const stuff = renderTokens(token[corner], createElement, ctx, token.markdown);
|
||||||
if ( stuff )
|
if ( stuff )
|
||||||
corners.push(ctx.vue ?
|
corners.push(ctx.vue ?
|
||||||
createElement('div', {class: `ffz--overlay__bit`, attrs:{'data-side':corner}}, stuff) :
|
createElement('div', {class: `ffz--overlay__bit`, attrs:{'data-side':corner}}, stuff) :
|
||||||
|
@ -883,10 +936,10 @@ TOKEN_TYPES.style = function(token, createElement, ctx) {
|
||||||
let content, title = null;
|
let content, title = null;
|
||||||
|
|
||||||
if ( capture ) {
|
if ( capture ) {
|
||||||
const out = renderWithCapture(token.content, createElement, ctx);
|
const out = renderWithCapture(token.content, createElement, ctx, token.markdown);
|
||||||
content = out.content; title = out.title;
|
content = out.content; title = out.title;
|
||||||
} else
|
} else
|
||||||
content = renderTokens(token.content, createElement, ctx);
|
content = renderTokens(token.content, createElement, ctx, token.markdown);
|
||||||
|
|
||||||
if ( ctx.vue )
|
if ( ctx.vue )
|
||||||
return createElement('span', {class: classes, style, attrs: {title}}, content);
|
return createElement('span', {class: classes, style, attrs: {title}}, content);
|
||||||
|
@ -957,7 +1010,7 @@ TOKEN_TYPES.tag = function(token, createElement, ctx) {
|
||||||
if ( tag === 'video' || tag === 'audio' )
|
if ( tag === 'video' || tag === 'audio' )
|
||||||
attrs.loadedmetadata = ctx.onload;
|
attrs.loadedmetadata = ctx.onload;
|
||||||
|
|
||||||
const content = renderTokens(token.content, createElement, ctx);
|
const content = renderTokens(token.content, createElement, ctx, token.markdown);
|
||||||
|
|
||||||
if ( ctx.vue )
|
if ( ctx.vue )
|
||||||
return createElement(tag, {
|
return createElement(tag, {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue