Remove HTML version of parse()
This commit is contained in:
parent
d83dcc35e2
commit
e3ff385ae0
@ -28,8 +28,9 @@
|
|||||||
<span class="title">{{ channel.name }}</span>
|
<span class="title">{{ channel.name }}</span>
|
||||||
<span
|
<span
|
||||||
:title="channel.topic"
|
:title="channel.topic"
|
||||||
class="topic"
|
class="topic"><ParsedMessage
|
||||||
v-html="$options.filters.parse(channel.topic)"/>
|
v-if="channel.topic"
|
||||||
|
:text="channel.topic"/></span>
|
||||||
<button
|
<button
|
||||||
class="menu"
|
class="menu"
|
||||||
aria-label="Open the context menu"
|
aria-label="Open the context menu"
|
||||||
@ -86,6 +87,7 @@
|
|||||||
<script>
|
<script>
|
||||||
require("intersection-observer");
|
require("intersection-observer");
|
||||||
const socket = require("../js/socket");
|
const socket = require("../js/socket");
|
||||||
|
import ParsedMessage from "./ParsedMessage.vue";
|
||||||
import MessageList from "./MessageList.vue";
|
import MessageList from "./MessageList.vue";
|
||||||
import ChatInput from "./ChatInput.vue";
|
import ChatInput from "./ChatInput.vue";
|
||||||
import ChatUserList from "./ChatUserList.vue";
|
import ChatUserList from "./ChatUserList.vue";
|
||||||
@ -96,6 +98,7 @@ import ListIgnored from "./Special/ListIgnored.vue";
|
|||||||
export default {
|
export default {
|
||||||
name: "Chat",
|
name: "Chat",
|
||||||
components: {
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
MessageList,
|
MessageList,
|
||||||
ChatInput,
|
ChatInput,
|
||||||
ChatUserList,
|
ChatUserList,
|
||||||
|
@ -28,9 +28,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</span>
|
</span>
|
||||||
<span class="content">
|
<span class="content">
|
||||||
<span
|
<span class="text"><ParsedMessage :message="message"/></span>
|
||||||
ref="text"
|
|
||||||
class="text"><ParsedMessage :message="message"/></span>
|
|
||||||
|
|
||||||
<LinkPreview
|
<LinkPreview
|
||||||
v-for="preview in message.previews"
|
v-for="preview in message.previews"
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<span class="content">
|
<span class="content">
|
||||||
<template v-if="message.self">
|
<ParsedMessage
|
||||||
<i v-html="$options.filters.parse(message.text)"/>
|
v-if="message.self"
|
||||||
</template>
|
:message="message"/>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<Username :user="message.from"/>
|
<Username :user="message.from"/>
|
||||||
is away
|
is away
|
||||||
<i
|
<i class="away-message">(<ParsedMessage :message="message"/>)</i>
|
||||||
class="away-message"
|
|
||||||
v-html="'(' + $options.filters.parse(message.text) + ')'"/>
|
|
||||||
</template>
|
</template>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ParsedMessage from "../ParsedMessage.vue";
|
||||||
import Username from "../Username.vue";
|
import Username from "../Username.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MessageTypeAway",
|
name: "MessageTypeAway",
|
||||||
components: {
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<span class="content">
|
<span class="content">
|
||||||
<template v-if="message.self">
|
<ParsedMessage
|
||||||
<i v-html="$options.filters.parse(message.text)"/>
|
v-if="message.self"
|
||||||
</template>
|
:message="message"/>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<Username :user="message.from"/>
|
<Username :user="message.from"/>
|
||||||
is back
|
is back
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<span class="content">
|
<span class="content">
|
||||||
<Username :user="message.from"/>
|
<Username :user="message.from"/>
|
||||||
<span
|
<span class="ctcp-message"><ParsedMessage :text="message.ctcpMessage"/></span>
|
||||||
class="ctcp-message"
|
|
||||||
v-html="$options.filters.parse(message.ctcpMessage)"/>
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ParsedMessage from "../ParsedMessage.vue";
|
||||||
import Username from "../Username.vue";
|
import Username from "../Username.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MessageTypeCTCP",
|
name: "MessageTypeCTCP",
|
||||||
components: {
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -2,18 +2,18 @@
|
|||||||
<span class="content">
|
<span class="content">
|
||||||
<Username :user="message.from"/>
|
<Username :user="message.from"/>
|
||||||
sent a <abbr title="Client-to-client protocol">CTCP</abbr> request:
|
sent a <abbr title="Client-to-client protocol">CTCP</abbr> request:
|
||||||
<span
|
<span class="ctcp-message"><ParsedMessage :text="message.ctcpMessage"/></span>
|
||||||
class="ctcp-message"
|
|
||||||
v-html="$options.filters.parse(message.ctcpMessage)"/>
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ParsedMessage from "../ParsedMessage.vue";
|
||||||
import Username from "../Username.vue";
|
import Username from "../Username.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MessageTypeRequestCTCP",
|
name: "MessageTypeRequestCTCP",
|
||||||
components: {
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -6,16 +6,18 @@
|
|||||||
<Username
|
<Username
|
||||||
v-else
|
v-else
|
||||||
:user="message.target"/>
|
:user="message.target"/>
|
||||||
to <span v-html="$options.filters.parse(message.channel)"/>
|
to <ParsedMessage :text="message.channel"/>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ParsedMessage from "../ParsedMessage.vue";
|
||||||
import Username from "../Username.vue";
|
import Username from "../Username.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MessageTypeInvite",
|
name: "MessageTypeInvite",
|
||||||
components: {
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -5,17 +5,18 @@
|
|||||||
<Username :user="message.target"/>
|
<Username :user="message.target"/>
|
||||||
<i
|
<i
|
||||||
v-if="message.text"
|
v-if="message.text"
|
||||||
class="part-reason"
|
class="part-reason">(<ParsedMessage :message="message"/>)</i>
|
||||||
v-html="'(' + $options.filters.parse(message.text) + ')'"/>
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ParsedMessage from "../ParsedMessage.vue";
|
||||||
import Username from "../Username.vue";
|
import Username from "../Username.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MessageTypeKick",
|
name: "MessageTypeKick",
|
||||||
components: {
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -2,16 +2,18 @@
|
|||||||
<span class="content">
|
<span class="content">
|
||||||
<Username :user="message.from"/>
|
<Username :user="message.from"/>
|
||||||
sets mode
|
sets mode
|
||||||
<span v-html="$options.filters.parse(message.text)"/>
|
<ParsedMessage :message="message"/>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ParsedMessage from "../ParsedMessage.vue";
|
||||||
import Username from "../Username.vue";
|
import Username from "../Username.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MessageTypeMode",
|
name: "MessageTypeMode",
|
||||||
components: {
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -5,17 +5,18 @@
|
|||||||
has left the channel
|
has left the channel
|
||||||
<i
|
<i
|
||||||
v-if="message.text"
|
v-if="message.text"
|
||||||
class="part-reason"
|
class="part-reason">(<ParsedMessage :message="message"/>)</i>
|
||||||
v-html="'(' + $options.filters.parse(message.text) + ')'"/>
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ParsedMessage from "../ParsedMessage.vue";
|
||||||
import Username from "../Username.vue";
|
import Username from "../Username.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MessageTypePart",
|
name: "MessageTypePart",
|
||||||
components: {
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -5,17 +5,18 @@
|
|||||||
has quit
|
has quit
|
||||||
<i
|
<i
|
||||||
v-if="message.text"
|
v-if="message.text"
|
||||||
class="quit-reason"
|
class="quit-reason">(<ParsedMessage :message="message"/>)</i>
|
||||||
v-html="'(' + $options.filters.parse(message.text) + ')'"/>
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ParsedMessage from "../ParsedMessage.vue";
|
||||||
import Username from "../Username.vue";
|
import Username from "../Username.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MessageTypeQuit",
|
name: "MessageTypeQuit",
|
||||||
components: {
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -9,17 +9,18 @@
|
|||||||
</template>
|
</template>
|
||||||
<span
|
<span
|
||||||
v-if="message.text"
|
v-if="message.text"
|
||||||
class="new-topic"
|
class="new-topic"><ParsedMessage :message="message"/></span>
|
||||||
v-html="$options.filters.parse(message.text)"/>
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ParsedMessage from "../ParsedMessage.vue";
|
||||||
import Username from "../Username.vue";
|
import Username from "../Username.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MessageTypeTopic",
|
name: "MessageTypeTopic",
|
||||||
components: {
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
<template v-if="message.whois.real_name">
|
<template v-if="message.whois.real_name">
|
||||||
<dt>Real name:</dt>
|
<dt>Real name:</dt>
|
||||||
<dd v-html="$options.filters.parse(message.whois.real_name)"/>
|
<dd><ParsedMessage :text="message.whois.real_name"/></dd>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="message.whois.registered_nick">
|
<template v-if="message.whois.registered_nick">
|
||||||
@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
<template v-if="message.whois.channels">
|
<template v-if="message.whois.channels">
|
||||||
<dt>Channels:</dt>
|
<dt>Channels:</dt>
|
||||||
<dd v-html="$options.filters.parse(message.whois.channels)"/>
|
<dd><ParsedMessage :text="message.whois.channels"/></dd>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="message.whois.modes">
|
<template v-if="message.whois.modes">
|
||||||
@ -67,7 +67,7 @@
|
|||||||
|
|
||||||
<template v-if="message.whois.away">
|
<template v-if="message.whois.away">
|
||||||
<dt>Away:</dt>
|
<dt>Away:</dt>
|
||||||
<dd v-html="$options.filters.parse(message.whois.away)"/>
|
<dd><ParsedMessage :text="message.whois.away"/></dd>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="message.whois.secure">
|
<template v-if="message.whois.secure">
|
||||||
@ -94,11 +94,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ParsedMessage from "../ParsedMessage.vue";
|
||||||
import Username from "../Username.vue";
|
import Username from "../Username.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MessageTypeWhois",
|
name: "MessageTypeWhois",
|
||||||
components: {
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
Username,
|
Username,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -5,10 +5,15 @@ export default {
|
|||||||
name: "ParsedMessage",
|
name: "ParsedMessage",
|
||||||
functional: true,
|
functional: true,
|
||||||
props: {
|
props: {
|
||||||
|
text: String,
|
||||||
message: Object,
|
message: Object,
|
||||||
},
|
},
|
||||||
render(createElement, context) {
|
render(createElement, context) {
|
||||||
return parse(context.props.message.text, context.props.message, createElement);
|
if (typeof context.props.text !== "undefined") {
|
||||||
|
return parse(createElement, context.props.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parse(createElement, context.props.message.text, context.props.message);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -12,9 +12,7 @@
|
|||||||
v-for="ban in channel.data"
|
v-for="ban in channel.data"
|
||||||
:key="ban.hostmask">
|
:key="ban.hostmask">
|
||||||
<td class="hostmask">{{ ban.hostmask }}</td>
|
<td class="hostmask">{{ ban.hostmask }}</td>
|
||||||
<td
|
<td class="banned_by">{{ ban.banned_by }}</td>
|
||||||
class="banned_by"
|
|
||||||
v-html="$options.filters.parse(ban.banned_by)"/>
|
|
||||||
<td class="banned_at">{{ ban.banned_at | localetime }}</td>
|
<td class="banned_at">{{ ban.banned_at | localetime }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -14,21 +14,22 @@
|
|||||||
<tr
|
<tr
|
||||||
v-for="chan in channel.data"
|
v-for="chan in channel.data"
|
||||||
:key="chan.channel">
|
:key="chan.channel">
|
||||||
<td
|
<td class="channel"><ParsedMessage :text="chan.channel"/></td>
|
||||||
class="channel"
|
|
||||||
v-html="$options.filters.parse(chan.channel)"/>
|
|
||||||
<td class="users">{{ chan.num_users }}</td>
|
<td class="users">{{ chan.num_users }}</td>
|
||||||
<td
|
<td class="topic"><ParsedMessage :text="chan.topic"/></td>
|
||||||
class="topic"
|
|
||||||
v-html="$options.filters.parse(chan.topic)"/>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ParsedMessage from "../ParsedMessage.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ListChannels",
|
name: "ListChannels",
|
||||||
|
components: {
|
||||||
|
ParsedMessage,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
channel: Object,
|
channel: Object,
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const Handlebars = require("handlebars/runtime");
|
|
||||||
const parseStyle = require("./ircmessageparser/parseStyle");
|
const parseStyle = require("./ircmessageparser/parseStyle");
|
||||||
const findChannels = require("./ircmessageparser/findChannels");
|
const findChannels = require("./ircmessageparser/findChannels");
|
||||||
const findLinks = require("./ircmessageparser/findLinks");
|
const findLinks = require("./ircmessageparser/findLinks");
|
||||||
@ -12,58 +11,7 @@ const emojiMap = require("../fullnamemap.json");
|
|||||||
const LinkPreviewToggle = require("../../../components/LinkPreviewToggle.vue").default;
|
const LinkPreviewToggle = require("../../../components/LinkPreviewToggle.vue").default;
|
||||||
|
|
||||||
// Create an HTML `span` with styling information for a given fragment
|
// Create an HTML `span` with styling information for a given fragment
|
||||||
function createFragment(fragment) {
|
function createFragment(fragment, createElement) {
|
||||||
const classes = [];
|
|
||||||
|
|
||||||
if (fragment.bold) {
|
|
||||||
classes.push("irc-bold");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragment.textColor !== undefined) {
|
|
||||||
classes.push("irc-fg" + fragment.textColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragment.bgColor !== undefined) {
|
|
||||||
classes.push("irc-bg" + fragment.bgColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragment.italic) {
|
|
||||||
classes.push("irc-italic");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragment.underline) {
|
|
||||||
classes.push("irc-underline");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragment.strikethrough) {
|
|
||||||
classes.push("irc-strikethrough");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragment.monospace) {
|
|
||||||
classes.push("irc-monospace");
|
|
||||||
}
|
|
||||||
|
|
||||||
let attributes = classes.length ? ` class="${classes.join(" ")}"` : "";
|
|
||||||
const escapedText = Handlebars.Utils.escapeExpression(fragment.text);
|
|
||||||
|
|
||||||
if (fragment.hexColor) {
|
|
||||||
attributes += ` style="color:#${fragment.hexColor}`;
|
|
||||||
|
|
||||||
if (fragment.hexBgColor) {
|
|
||||||
attributes += `;background-color:#${fragment.hexBgColor}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
attributes += '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributes.length) {
|
|
||||||
return `<span${attributes}>${escapedText}</span>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return escapedText;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createVueFragment(fragment, createElement) {
|
|
||||||
const classes = [];
|
const classes = [];
|
||||||
|
|
||||||
if (fragment.bold) {
|
if (fragment.bold) {
|
||||||
@ -109,7 +57,7 @@ function createVueFragment(fragment, createElement) {
|
|||||||
|
|
||||||
// Transform an IRC message potentially filled with styling control codes, URLs,
|
// Transform an IRC message potentially filled with styling control codes, URLs,
|
||||||
// nicknames, and channels into a string of HTML elements to display on the client.
|
// nicknames, and channels into a string of HTML elements to display on the client.
|
||||||
module.exports = function parse(text, message = null, createElement = null) {
|
module.exports = function parse(createElement, text, message = null) {
|
||||||
// Extract the styling information and get the plain text version from it
|
// Extract the styling information and get the plain text version from it
|
||||||
const styleFragments = parseStyle(text);
|
const styleFragments = parseStyle(text);
|
||||||
const cleanText = styleFragments.map((fragment) => fragment.text).join("");
|
const cleanText = styleFragments.map((fragment) => fragment.text).join("");
|
||||||
@ -129,97 +77,69 @@ module.exports = function parse(text, message = null, createElement = null) {
|
|||||||
.concat(emojiParts)
|
.concat(emojiParts)
|
||||||
.concat(nameParts);
|
.concat(nameParts);
|
||||||
|
|
||||||
if (createElement) {
|
|
||||||
return merge(parts, styleFragments, cleanText).map((textPart) => {
|
|
||||||
const fragments = textPart.fragments.map((fragment) => createVueFragment(fragment, createElement));
|
|
||||||
|
|
||||||
// Wrap these potentially styled fragments with links and channel buttons
|
|
||||||
if (textPart.link) {
|
|
||||||
const preview = message && message.previews.find((p) => p.link === textPart.link);
|
|
||||||
const link = createElement("a", {
|
|
||||||
class: [
|
|
||||||
"inline-channel",
|
|
||||||
],
|
|
||||||
attrs: {
|
|
||||||
href: textPart.link,
|
|
||||||
target: "_blank",
|
|
||||||
rel: "noopener",
|
|
||||||
},
|
|
||||||
}, fragments);
|
|
||||||
|
|
||||||
if (!preview) {
|
|
||||||
return link;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [link, createElement(LinkPreviewToggle, {
|
|
||||||
class: ["toggle-button", "toggle-preview"],
|
|
||||||
props: {
|
|
||||||
link: preview,
|
|
||||||
},
|
|
||||||
}, fragments)];
|
|
||||||
} else if (textPart.channel) {
|
|
||||||
return createElement("span", {
|
|
||||||
class: [
|
|
||||||
"inline-channel",
|
|
||||||
],
|
|
||||||
attrs: {
|
|
||||||
"role": "button",
|
|
||||||
"tabindex": 0,
|
|
||||||
"data-chan": textPart.channel,
|
|
||||||
},
|
|
||||||
}, fragments);
|
|
||||||
} else if (textPart.emoji) {
|
|
||||||
return createElement("span", {
|
|
||||||
class: [
|
|
||||||
"emoji",
|
|
||||||
],
|
|
||||||
attrs: {
|
|
||||||
"role": "img",
|
|
||||||
"aria-label": emojiMap[textPart.emoji] ? `Emoji: ${emojiMap[textPart.emoji]}` : null,
|
|
||||||
},
|
|
||||||
}, fragments);
|
|
||||||
} else if (textPart.nick) {
|
|
||||||
return createElement("span", {
|
|
||||||
class: [
|
|
||||||
"user",
|
|
||||||
colorClass(textPart.nick),
|
|
||||||
],
|
|
||||||
attrs: {
|
|
||||||
"role": "button",
|
|
||||||
"data-name": textPart.nick,
|
|
||||||
},
|
|
||||||
}, fragments);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fragments;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge the styling information with the channels / URLs / nicks / text objects and
|
// Merge the styling information with the channels / URLs / nicks / text objects and
|
||||||
// generate HTML strings with the resulting fragments
|
// generate HTML strings with the resulting fragments
|
||||||
return merge(parts, styleFragments, cleanText).map((textPart) => {
|
return merge(parts, styleFragments, cleanText).map((textPart) => {
|
||||||
// Create HTML strings with styling information
|
const fragments = textPart.fragments.map((fragment) => createFragment(fragment, createElement));
|
||||||
const fragments = textPart.fragments.map(createFragment).join("");
|
|
||||||
|
|
||||||
// Wrap these potentially styled fragments with links and channel buttons
|
// Wrap these potentially styled fragments with links and channel buttons
|
||||||
if (textPart.link) {
|
if (textPart.link) {
|
||||||
const escapedLink = Handlebars.Utils.escapeExpression(textPart.link);
|
const preview = message && message.previews.find((p) => p.link === textPart.link);
|
||||||
return `<a href="${escapedLink}" target="_blank" rel="noopener">${fragments}</a>` +
|
const link = createElement("a", {
|
||||||
`<button class="toggle-button toggle-preview" data-url="${escapedLink}" hidden></button>`;
|
class: [
|
||||||
} else if (textPart.channel) {
|
"inline-channel",
|
||||||
const escapedChannel = Handlebars.Utils.escapeExpression(textPart.channel);
|
],
|
||||||
return `<span class="inline-channel" role="button" tabindex="0" data-chan="${escapedChannel}">${fragments}</span>`;
|
attrs: {
|
||||||
} else if (textPart.emoji) {
|
href: textPart.link,
|
||||||
if (!emojiMap[textPart.emoji]) {
|
target: "_blank",
|
||||||
return `<span class="emoji" role="img">${fragments}</span>`;
|
rel: "noopener",
|
||||||
|
},
|
||||||
|
}, fragments);
|
||||||
|
|
||||||
|
if (!preview) {
|
||||||
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `<span class="emoji" role="img" aria-label="Emoji: ${emojiMap[textPart.emoji]}" title="${emojiMap[textPart.emoji]}">${fragments}</span>`;
|
return [link, createElement(LinkPreviewToggle, {
|
||||||
|
class: ["toggle-button", "toggle-preview"],
|
||||||
|
props: {
|
||||||
|
link: preview,
|
||||||
|
},
|
||||||
|
}, fragments)];
|
||||||
|
} else if (textPart.channel) {
|
||||||
|
return createElement("span", {
|
||||||
|
class: [
|
||||||
|
"inline-channel",
|
||||||
|
],
|
||||||
|
attrs: {
|
||||||
|
"role": "button",
|
||||||
|
"tabindex": 0,
|
||||||
|
"data-chan": textPart.channel,
|
||||||
|
},
|
||||||
|
}, fragments);
|
||||||
|
} else if (textPart.emoji) {
|
||||||
|
return createElement("span", {
|
||||||
|
class: [
|
||||||
|
"emoji",
|
||||||
|
],
|
||||||
|
attrs: {
|
||||||
|
"role": "img",
|
||||||
|
"aria-label": emojiMap[textPart.emoji] ? `Emoji: ${emojiMap[textPart.emoji]}` : null,
|
||||||
|
},
|
||||||
|
}, fragments);
|
||||||
} else if (textPart.nick) {
|
} else if (textPart.nick) {
|
||||||
const nick = Handlebars.Utils.escapeExpression(textPart.nick);
|
return createElement("span", {
|
||||||
return `<span role="button" class="user ${colorClass(textPart.nick)}" data-name="${nick}">${fragments}</span>`;
|
class: [
|
||||||
|
"user",
|
||||||
|
colorClass(textPart.nick),
|
||||||
|
],
|
||||||
|
attrs: {
|
||||||
|
"role": "button",
|
||||||
|
"data-name": textPart.nick,
|
||||||
|
},
|
||||||
|
}, fragments);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fragments;
|
return fragments;
|
||||||
}).join("");
|
});
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
const Vue = require("vue").default;
|
const Vue = require("vue").default;
|
||||||
const App = require("../components/App.vue").default;
|
const App = require("../components/App.vue").default;
|
||||||
const roundBadgeNumber = require("./libs/handlebars/roundBadgeNumber");
|
const roundBadgeNumber = require("./libs/handlebars/roundBadgeNumber");
|
||||||
const parse = require("./libs/handlebars/parse");
|
|
||||||
const tz = require("./libs/handlebars/tz");
|
const tz = require("./libs/handlebars/tz");
|
||||||
const localetime = require("./libs/handlebars/localetime");
|
const localetime = require("./libs/handlebars/localetime");
|
||||||
const localedate = require("./libs/handlebars/localedate");
|
const localedate = require("./libs/handlebars/localedate");
|
||||||
@ -11,7 +10,6 @@ const friendlydate = require("./libs/handlebars/friendlydate");
|
|||||||
const friendlysize = require("./libs/handlebars/friendlysize");
|
const friendlysize = require("./libs/handlebars/friendlysize");
|
||||||
const colorClass = require("./libs/handlebars/colorClass");
|
const colorClass = require("./libs/handlebars/colorClass");
|
||||||
|
|
||||||
Vue.filter("parse", parse);
|
|
||||||
Vue.filter("tz", tz);
|
Vue.filter("tz", tz);
|
||||||
Vue.filter("localetime", localetime);
|
Vue.filter("localetime", localetime);
|
||||||
Vue.filter("localedate", localedate);
|
Vue.filter("localedate", localedate);
|
||||||
|
Loading…
Reference in New Issue
Block a user