1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-28 05:15:54 +00:00
* 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:
SirStendec 2020-08-06 15:47:26 -04:00
parent e73534dd75
commit e87c99f206
4 changed files with 81 additions and 28 deletions

View file

@ -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": {

View file

@ -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.'}

View file

@ -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' )

View file

@ -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, {