Add codeblocks, emojis from names, and emoticons

This commit is contained in:
Lorem Ipsum 2020-12-16 15:09:45 +00:00
parent 65c437908e
commit 2920ac4652
6 changed files with 142 additions and 99 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
testing/

View file

@ -1,9 +1,11 @@
# An embed visualizer # An embed visualizer
Visualizes embed or message content from JSON input. This can be used for visualizing bot embed commands. Displays embed or message content from JSON input. This can be used for visualizing bot embed commands.
This can be used for bot embed commands commands, although I understand that not every one understands JSON thus will add a GUI later. This can be used for bot embed commands commands, although I understand that not every one understands JSON thus will add a GUI later.
You can look into the [project boards](https://github.com/Glitchii/embedbuilder/projects/3) if you want to see what I'm currently working on or want to contribute You can look into the [project boards](https://github.com/Glitchii/embedbuilder/projects/3) if you want to see what is being worked on or want to contribute.
<br> <br>
<br> <br>
![Layout image](https://raw.githubusercontent.com/Glitchii/embedbuilder/master/assets/media/layout.png) ![Layout image](https://raw.githubusercontent.com/Glitchii/embedbuilder/master/assets/media/layout.png)
[To Do](https://github.com/Glitchii/embedbuilder/projects/3) | [Discussions](https://github.com/Glitchii/embedbuilder/discussions/1)

View file

@ -340,10 +340,14 @@ img[alt] {
.emoji { .emoji {
object-fit: contain; object-fit: contain;
width: 22px; width: 1.375em;
height: 22px; height: 1.375em;
margin: 0 .05em 0 .1em !important; vertical-align: bottom;
vertical-align: -.4em; }
.embed .emoji {
width: 18px;
height: 18px;
} }
.embedGrid { .embedGrid {
@ -471,6 +475,7 @@ img[alt] {
margin-top: 8px; margin-top: 8px;
gap: 8px; gap: 8px;
min-width: 0px; min-width: 0px;
grid-gap: 8px;
} }
.embedField { .embedField {
@ -583,6 +588,26 @@ u {
text-size-adjust: none; text-size-adjust: none;
} }
.embed blockquote {
max-width: 100%;
}
.blockquote {
display: flex;
}
.blockquote blockquote {
padding: 0 8px 0 12px;
box-sizing: border-box;
text-indent: 0;
}
.blockquote .blockquoteDivider {
width: 4px;
border-radius: 4px;
}
.blockquoteDivider {
background-color: var(--interactive-muted);
}
.container { .container {
display: grid; display: grid;
grid-auto-flow: row; grid-auto-flow: row;
@ -620,6 +645,10 @@ u {
white-space: pre-wrap; white-space: pre-wrap;
} }
.markup .markup :is(pre, blockquote) {
max-width: 90%;
}
.markup pre { .markup pre {
max-width: 90%; max-width: 90%;
border-radius: 4px; border-radius: 4px;
@ -632,11 +661,7 @@ u {
background-clip: border-box; background-clip: border-box;
} }
.markup pre.embeded { .embed code {
max-width: 100%;
}
.markup pre.embeded>code {
border: none; border: none;
background: var(--background-tertiary); background: var(--background-tertiary);
} }
@ -782,3 +807,16 @@ u {
margin-top: 5px; margin-top: 5px;
} }
} }
@media screen and (max-width: 530px) {
.msgEmbed {
margin: 20px 0px;
padding: 0.125rem 0 20px 65px;
}
.avatar {
left: 10px;
}
.main .side1 {
padding: 10px;
}
}

View file

@ -1,56 +1,58 @@
var emoticons = { var emoticons = {
">=-(": "angry", ">=-(": "😠",
"=\")": "blush", "=\")": "😊",
"=-\")": "blush", "=-\")": "😊",
"<\\3": "broken_heart", "<\\3": "💔",
"=-/": "confused", "=-/": "😕",
":'(": "cry", ":'(": "😢",
":'-(": "cry", ":'-(": "😢",
":,(": "cry", ":,(": "😢",
":,-(": "cry", ":,-(": "cr😢y",
"='(": "cry", "='(": "😢",
"='-(": "cry", "='-(": "😢",
"=,(": "cry", "=,(": "😢",
"=,-(": "cry", "=,-(": "😢",
"=-(": "frowning", "=-(": "😦",
"♡": "heart", "♡": "heart❤",
"]=-(": "imp", "]=-(": "👿",
"0=-)": "innocent", "0=-)": "😇",
":')": "joy", ":')": "😂",
":'-)": "joy", ":'-)": "😂",
":,)": "joy", ":,)": "😂",
":,-)": "joy", ":,-)": "😂",
":'D": "joy", ":'D": "😂",
":'-D": "joy", ":'-D": "😂",
":,D": "joy", ":,D": "😂",
":,-D": "joy", ":,-D": "😂",
"=')": "joy", "=')": "😂",
"='-)": "joy", "='-)": "😂",
"=,)": "joy", "=,)": "😂",
"=,-)": "joy", "=,-)": "😂",
"='D": "joy", "='D": "😂",
"='-D": "joy", "='-D": "😂",
"=-*": "kissing", "=-*": "😗",
"X-)": "laughing", "X-)": "😆",
"=-|": "neutral_face", "=-|": "😐",
"=-O": "open_mouth", "=-O": "😮",
"=-@": "rage", "=-@": "😡",
"=-D": "smile", "=-D": "😄",
"=-)": "slight_smile", ":)": "🙂",
"]=-)": "smiling_imp", ":-)": "🙂",
":,'(": "sob", "=-)": "🙂",
":,'-(": "sob", "]=-)": "😈",
";(": "sob", ":,'(": "😭",
";-(": "sob", ":,'-(": "😭",
"=,'(": "sob", ";(": "😭",
"=,'-(": "sob", ";-(": "😭",
"=-P": "stuck_out_tongue", "=,'(": "😭",
"B-)": "sunglasses", "=,'-(": "😭",
",=-(": "sweat", "=-P": "😛",
",=-)": "sweat_smile", "B-)": "😎",
"=-$": "unamused", ",=-(": "😓",
";)": "wink", ",=-)": "😅",
";-)": "wink" "=-$": "😒",
";)": "😉",
";-)": "😉"
}, emojis = { }, emojis = {
"open_hands": "👐", "open_hands": "👐",
"open_hands_tone1": "👐🏻", "open_hands_tone1": "👐🏻",
@ -2968,6 +2970,7 @@ var emoticons = {
"confused": "😕", "confused": "😕",
"cry": "😢", "cry": "😢",
"frowning": "😦", "frowning": "😦",
"frowning2": "☹️",
"imp": "👿", "imp": "👿",
"innocent": "😇", "innocent": "😇",
"joy": "😂", "joy": "😂",

View file

@ -12,7 +12,6 @@ window.onload = () => {
theme: 'material-darker', theme: 'material-darker',
scrollbarStyle: "overlay", scrollbarStyle: "overlay",
mode: "application/json", mode: "application/json",
// lineNumbers: true,
foldGutter: true, foldGutter: true,
gutters: ["CodeMirror-foldgutter", "CodeMirror-lint-markers"], gutters: ["CodeMirror-foldgutter", "CodeMirror-lint-markers"],
matchBrackets: true, matchBrackets: true,
@ -30,27 +29,26 @@ window.onload = () => {
if (html) notif.innerHTML = msg; if (html) notif.innerHTML = msg;
else notif.innerText = msg; else notif.innerText = msg;
notif.style.display = 'block'; notif.style.display = 'block';
// err && console.log(err); }, markup = (txt, opts) => {
}, markup = (txt, isEmbed) => {
txt = txt txt = txt
// Custom Emojis .replace(/<:[^:]+:(\d+)>/g, '<img class="emoji" src="https://cdn.discordapp.com/emojis/$1.png"/>')
.replace(/<a?:[^:]+?:(\d+)>/g, '<img class="emoji" src="https://cdn.discordapp.com/emojis/$1.png"/>') // .replace(/<a?:[^:]+?:(\d+)>/g, '<img class="emoji" src="https://cdn.discordapp.com/emojis/$1.gif" onerror="this.src=\'https://cdn.discordapp.com/emojis/$1.png\'"/>') // This will keep logging failed GET request errors in console .replace(/<a:[^:]+:(\d+)>/g, '<img class="emoji" src="https://cdn.discordapp.com/emojis/$1.gif"/>')
// MD
.replace(/~~(.+?)~~/g, '<s>$1</s>') .replace(/~~(.+?)~~/g, '<s>$1</s>')
.replace(/\`(?!\`)([^\`]+?)\`(?!\`)/g, '<code class="inline">$1</code>')
.replace(/\`\`(?!\`)([^\`]+?)\`\`(?!\`)/g, '<code class="inline">$1</code>')
.replace(/\*\*\*(.+?)\*\*\*/g, '<em><strong>$1</strong></em>') .replace(/\*\*\*(.+?)\*\*\*/g, '<em><strong>$1</strong></em>')
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>') .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
.replace(/__(.+?)__/g, '<u>$1</u>') .replace(/__(.+?)__/g, '<u>$1</u>')
.replace(/\*(.+?)\*/g, '<em>$1</em>') .replace(/\*(.+?)\*/g, '<em>$1</em>')
.replace(/_(.+?)_/g, '<em>$1</em>') .replace(/_(.+?)_/g, '<em>$1</em>')
// Block if (opts.inlineBlock) txt = txt.replace(/\`([^\`]+?)\`|\`\`([^\`]+?)\`\`|\`\`\`((?:\n|.)+?)\`\`\`/g, (m, x, y, z) => x ? `<code class="inline">${x}</code>` : y ? `<code class="inline">${y}</code>` : z ? `<code class="inline">${z}</code>` : m);
.replace(/\n/g, '<br>') else txt = txt.replace(/\`\`\`(\w{1,15})?\n((?:\n|.)+?)\`\`\`|\`\`(.+?)\`\`(?!\`)|\`([^\`]+?)\`/g, (m, w, x, y, z) => w && x ? `<pre><code class="${w}">${x}</code></pre>` : x ? `<pre><code class="hljs nohighlight">${x}</code></pre>` : y || z ? `<code class="inline">${y || z}</code>` : m);
.replace(/\`\`\`(\w{1,15})<br>((\n|.)+?)\`\`\`/g, isEmbed ? '<pre class="embeded"><code class="$1">$2</code></pre>' : '<pre><code class="$1">$2</code></pre>') if (opts.inEmbed) txt = txt.replace(/\[([^\[\]]+)\]\((.+?)\)/g, `<a title="$1" target="_blank" class="anchor" href="$2">$1</a>`);
.replace(/\`\`\`(\w{1,15})<br>((\n|.)+?)\`\`\`/g, isEmbed ? '<pre class="embeded"><code class="$1">$2</code></pre>' : '<pre><code class="$1">$2</code></pre>') if (opts.replaceEmojis) {
.replace(/\`\`\`(<br>)?((\n|.)+?)\`\`\`/g, isEmbed ? '<pre class="embeded"><code class="hljs nohighlight">$2</code></pre>' : '<pre><code class="hljs nohighlight">$2</code></pre>') txt = txt.replace(/(?<!code(?: \w+=".+")?>[^>]+)(?<!\/[^\s"]+?):((?!\/)\w+):/g, (match, x) => x && emojis[x] ? emojis[x] : match);
if (isEmbed) txt = txt !opts.noEmoticons && Object.keys(emoticons).forEach(e => txt = txt.replace(new RegExp(`(?<=^|\\s)${regEscape(e)}(?=$|\\s)`, 'g'), emoticons[e]));
.replace(/\[(.+)\]\((.+)\)/g, `<a title="$1" target="_blank" class="anchor" href="$2">$1</a>`); }
txt = txt
.replace(/(?<=\n|^)\s*>\s+([^\n]+)/g, '<div class="blockquote"><div class="blockquoteDivider"></div><blockquote>$1</blockquote></div>')
.replace(/\n/g, '<br>');
return txt; return txt;
}, },
content = document.querySelector('.messageContent'), content = document.querySelector('.messageContent'),
@ -77,15 +75,16 @@ window.onload = () => {
el.style.display = displayType || "unset"; el.style.display = displayType || "unset";
}, hide = el => el.style.removeProperty('display'), }, hide = el => el.style.removeProperty('display'),
regEscape = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),
toObj = jsonString => JSON.parse(jsonString.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (x, y) => y ? "" : x)), toObj = jsonString => JSON.parse(jsonString.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (x, y) => y ? "" : x)),
update = data => { update = data => {
try { try {
content.innerHTML = data.content ? markup(data.content) : ''; content.innerHTML = data.content ? markup(data.content, { replaceEmojis: true }) : '';
if (data.embed) { if (data.embed) {
let e = data.embed; let e = data.embed;
if (e.title) display(embedTitle, markup(`${e.url ? '<a class="anchor" target="_blank" href="' + url(e.url) + '">' + e.title + '</a>' : e.title}`)); if (e.title) display(embedTitle, markup(`${e.url ? '<a class="anchor" target="_blank" href="' + url(e.url) + '">' + e.title + '</a>' : e.title}`, { replaceEmojis: true, noEmoticons: true, inlineBlock: true }));
else hide(embedTitle); else hide(embedTitle);
if (e.description) display(embedDescription, markup(e.description, true)); if (e.description) display(embedDescription, markup(e.description, { inEmbed: true, replaceEmojis: true }));
else hide(embedDescription); else hide(embedDescription);
if (e.color) embed.closest('.embed').style.borderColor = (typeof e.color === 'number' ? '#' + e.color.toString(16) : e.color); if (e.color) embed.closest('.embed').style.borderColor = (typeof e.color === 'number' ? '#' + e.color.toString(16) : e.color);
else embed.closest('.embed').style.removeProperty('border-color'); else embed.closest('.embed').style.removeProperty('border-color');
@ -110,15 +109,15 @@ window.onload = () => {
let el = fields.insertBefore(document.createElement('div'), null); let el = fields.insertBefore(document.createElement('div'), null);
el.outerHTML = ` el.outerHTML = `
<div class="embedField" style="grid-column: 1 / 13;"> <div class="embedField" style="grid-column: 1 / 13;">
<div class="embedFieldName">${markup(f.name)}</div> <div class="embedFieldName">${markup(f.name, { inEmbed: true, replaceEmojis: true, inlineBlock: true })}</div>
<div class="embedFieldValue">${markup(f.value)}</div> <div class="embedFieldValue">${markup(f.value, { inEmbed: true, replaceEmojis: true })}</div>
</div>`; </div>`;
} else { } else {
el = fields.insertBefore(document.createElement('div'), null); el = fields.insertBefore(document.createElement('div'), null);
el.outerHTML = ` el.outerHTML = `
<div class="embedField ${num}" style="grid-column: ${colNum} / ${colNum + 4};"> <div class="embedField ${num}" style="grid-column: ${colNum} / ${colNum + 4};">
<div class="embedFieldName">${markup(f.name)}</div> <div class="embedFieldName">${markup(f.name, { inEmbed: true, replaceEmojis: true, inlineBlock: true })}</div>
<div class="embedFieldValue">${markup(f.value)}</div> <div class="embedFieldValue">${markup(f.value, { inEmbed: true, replaceEmojis: true })}</div>
</div>`; </div>`;
colNum = (colNum === 9 ? 1 : colNum + 4); colNum = (colNum === 9 ? 1 : colNum + 4);
num++; num++;
@ -127,16 +126,16 @@ window.onload = () => {
colNum = 1; colNum = 1;
let len = e.fields.filter(f => f.inline).length; let len = e.fields.filter(f => f.inline).length;
if (len === 2 || (len > 3 && len % 2 !== 0)) { if (len === 2 || (len > 3 && len % 2 !== 0)) {
let children = Array.from(fields.children), let children = Array.from(fields.children), arr = children.filter(x => x === children[len] || x === children[len - 1]);
arr = children.filter(x => x === children[len] || x === children[len - 1]);
arr[0].style.gridColumn = '1 / 7', arr[1].style.gridColumn = '7 / 13'; arr[0].style.gridColumn = '1 / 7', arr[1].style.gridColumn = '7 / 13';
} }
display(fields, undefined, 'grid'); display(fields, undefined, 'grid');
} else hide(fields); } else hide(fields);
embed.classList.remove('empty'); embed.classList.remove('empty');
let re = /"((icon_)?url")(: *)("(?!\w+?:\/\/).+?")/g.exec(editor.getValue()) let re = /"((icon_)?url")(: *)("(?!https?:\/\/).+?")/g.exec(editor.getValue())
if (re) error(`URLs should have a valid protocol (eg. https://) on this line <span class="inline">${makeShort(re[0], 30, 600)}</span>`, true); if (re) error(`URLs should start with <code>https://</code> or <code>http://</code> on this line <span class="inline full">${makeShort(re[0], 30, 600)}</span>`, true);
else notif.animate({ opacity: '0', bottom: '-50px', offset: 1 }, { easing: 'ease', duration: 500 }).onfinish = () => notif.style.removeProperty('display'); else notif.animate({ opacity: '0', bottom: '-50px', offset: 1 }, { easing: 'ease', duration: 500 }).onfinish = () => notif.style.removeProperty('display');
twemoji.parse(msgEmbed);
} }
} catch (e) { } catch (e) {
error(e); error(e);
@ -146,16 +145,14 @@ window.onload = () => {
editor.on('change', editor => { editor.on('change', editor => {
try { update(toObj(editor.getValue())); } try { update(toObj(editor.getValue())); }
catch (e) { catch (e) {
if (editor.getValue()) return; // error("Couldn't parse JSON; Invalid JSON syntax", e) if (editor.getValue()) return;
embed.classList.add('empty'); embed.classList.add('empty');
content.innerHTML = ''; content.innerHTML = '';
} }
document.querySelectorAll('.markup pre > code').forEach((block) => hljs.highlightBlock(block)); document.querySelectorAll('.markup pre > code').forEach((block) => hljs.highlightBlock(block));
twemoji.parse(msgEmbed);
}); });
update(toObj(editor.getValue())); update(toObj(editor.getValue()));
twemoji.parse(msgEmbed);
document.querySelector('.timeText').innerText = tstamp() document.querySelector('.timeText').innerText = tstamp()
document.querySelectorAll('.markup pre > code').forEach((block) => hljs.highlightBlock(block)) document.querySelectorAll('.markup pre > code').forEach((block) => hljs.highlightBlock(block))
!window.navigator.userAgent.match(/Firefox\/[\d\.]+$/g) && // Firefox pushes the text up a little !window.navigator.userAgent.match(/Firefox\/[\d\.]+$/g) && // Firefox pushes the text up a little

View file

@ -23,6 +23,8 @@
<script src="https://unpkg.com/jsonlint@1.6.3/web/jsonlint.js"></script> <script src="https://unpkg.com/jsonlint@1.6.3/web/jsonlint.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.3/addon/lint/lint.min.css" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.3/addon/lint/lint.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.3/addon/lint/lint.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.3/addon/lint/lint.min.js"></script>
<!-- <script src="https://glitchii.github.io/embedbuilder/assets/js/components.js"></script> -->
<script src="http://localhost:5500/assets/js/components.js"></script>
<script src="./assets/js/index.js"></script> <script src="./assets/js/index.js"></script>
</head> </head>
<body> <body>
@ -31,10 +33,10 @@
<div class="top item"> <div class="top item">
<textarea style="display: none;"> <textarea style="display: none;">
{ {
"content": "You can~~not~~ do `this`.```py\nAnd this.\nprint('Hi')```\n*italics* or _italics_ __*underline italics*__\n**bold** __**underline bold**__\n***bold italics*** __***underline bold italics***__\n__underline__ ~~Strikethrough~~", "content": "You can~~not~~ do `this`.```\nAnd :laughing:this.\nprint('Hi') :) ```\n*italics* or _italics_ __*underline italics*__\n**bold** __**underline bold**__\n***bold italics*** __***underline bold italics***__\n__underline__ ~~Strikethrough~~\n> Hi",
"embed": { "embed": {
"title": "Hello ~~people~~ world", "title": "Hello ~~people~~ world :wave:",
"description": "A description. You can use [links](https://discord.com).\nAnd also emojis 🙂\n```\nAlso code blocks```", "description": "You can use [links](https://discord.com), emojis 😎 :smile:, emoticons :-)\n```\nAlso code blocks```",
"color": 4321431, "color": 4321431,
"timestamp": "2020-12-08T13:37:35.401Z", "timestamp": "2020-12-08T13:37:35.401Z",
"url": "https://discord.com", "url": "https://discord.com",
@ -79,9 +81,9 @@
"inline": true "inline": true
}, },
{ {
"name": "Inline field", "name": "Another field",
"value": "value", "value": "> Nope, didn't forget about code blocks",
"inline": true "inline": false
} }
] ]
} }