mirror of
https://github.com/thelounge/thelounge.git
synced 2024-05-17 05:36:36 +02:00
Chat is rendering
This commit is contained in:
parent
52c13f49c1
commit
f189e9766c
|
@ -14,7 +14,10 @@
|
|||
id="context-menu"
|
||||
ref="contextMenu"
|
||||
role="menu"
|
||||
:style="style"
|
||||
:style="{
|
||||
top: style.top + 'px',
|
||||
left: style.left + 'px',
|
||||
}"
|
||||
tabindex="-1"
|
||||
@mouseleave="activeItem = -1"
|
||||
@keydown.enter.prevent="clickActiveItem"
|
||||
|
|
|
@ -24,11 +24,6 @@ export default defineComponent({
|
|||
},
|
||||
focused: Boolean,
|
||||
},
|
||||
// methods: {
|
||||
// forceUpdate(){
|
||||
// this.$forceUpdate()
|
||||
// }
|
||||
// },
|
||||
setup(props) {
|
||||
const localeDate = computed(() => dayjs(props.message.time).format("D MMMM YYYY"));
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ import Message from "./Message.vue";
|
|||
import MessageCondensed from "./MessageCondensed.vue";
|
||||
import DateMarker from "./DateMarker.vue";
|
||||
import {
|
||||
defineExpose,
|
||||
computed,
|
||||
defineComponent,
|
||||
nextTick,
|
||||
|
@ -247,7 +248,7 @@ export default defineComponent({
|
|||
message: Msg | ClientMessage | CondensedMessageContainer,
|
||||
id: number
|
||||
) => {
|
||||
const previousMessage = condensedMessages[id - 1];
|
||||
const previousMessage = condensedMessages.value[id - 1];
|
||||
|
||||
if (!previousMessage) {
|
||||
return true;
|
||||
|
@ -431,6 +432,7 @@ export default defineComponent({
|
|||
shouldDisplayUnreadMarker,
|
||||
keepScrollPosition,
|
||||
isPreviousSource,
|
||||
jumpToBottom,
|
||||
onLinkPreviewToggle,
|
||||
};
|
||||
},
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {defineComponent, PropType} from "vue";
|
||||
import {computed, defineComponent, PropType} from "vue";
|
||||
import collapseNetwork from "../js/helpers/collapseNetwork";
|
||||
import roundBadgeNumber from "../js/helpers/roundBadgeNumber";
|
||||
import ChannelWrapper from "./ChannelWrapper.vue";
|
||||
|
@ -68,24 +68,34 @@ export default defineComponent({
|
|||
isFiltering: Boolean,
|
||||
},
|
||||
emits: ["toggle-join-channel"],
|
||||
computed: {
|
||||
channel(): ClientChan {
|
||||
return this.network.channels[0];
|
||||
},
|
||||
joinChannelLabel(): string {
|
||||
return this.isJoinChannelShown ? "Cancel" : "Join a channel…";
|
||||
},
|
||||
unreadCount(): string {
|
||||
return roundBadgeNumber(this.channel.unread);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onCollapseClick(): void {
|
||||
collapseNetwork(this.network, !this.network.isCollapsed);
|
||||
},
|
||||
getExpandLabel(network: ClientNetwork): string {
|
||||
setup(props) {
|
||||
const channel = computed(() => {
|
||||
return props.network.channels[0];
|
||||
});
|
||||
|
||||
const joinChannelLabel = computed(() => {
|
||||
return props.isJoinChannelShown ? "Cancel" : "Join a channel…";
|
||||
});
|
||||
|
||||
const unreadCount = computed(() => {
|
||||
return roundBadgeNumber(channel.value.unread);
|
||||
});
|
||||
|
||||
const onCollapseClick = () => {
|
||||
collapseNetwork(props.network, !props.network.isCollapsed);
|
||||
};
|
||||
|
||||
const getExpandLabel = (network: ClientNetwork) => {
|
||||
return network.isCollapsed ? "Expand" : "Collapse";
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
channel,
|
||||
joinChannelLabel,
|
||||
unreadCount,
|
||||
onCollapseClick,
|
||||
getExpandLabel,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import ParsedMessage from "../ParsedMessage.vue";
|
||||
import localetime from "../../js/helpers/localetime";
|
||||
import localeTime from "../../js/helpers/localetime";
|
||||
import {defineComponent, PropType} from "vue";
|
||||
import type {ClientNetwork, ClientChan} from "../../js/types";
|
||||
|
||||
|
@ -32,10 +32,14 @@ export default defineComponent({
|
|||
network: {type: Object as PropType<ClientNetwork>, required: true},
|
||||
channel: {type: Object as PropType<ClientChan>, required: true},
|
||||
},
|
||||
methods: {
|
||||
localetime(date: number | Date): string {
|
||||
return localetime(date);
|
||||
},
|
||||
setup() {
|
||||
const localetime = (date: number | Date) => {
|
||||
return localeTime(date);
|
||||
};
|
||||
|
||||
return {
|
||||
localetime,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -59,48 +59,65 @@
|
|||
import storage from "../../js/localStorage";
|
||||
import socket from "../../js/socket";
|
||||
import RevealPassword from "../RevealPassword.vue";
|
||||
import {defineComponent} from "vue";
|
||||
import {defineComponent, onBeforeUnmount, onMounted, ref} from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "SignIn",
|
||||
components: {
|
||||
RevealPassword,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
inFlight: false,
|
||||
errorShown: false,
|
||||
setup() {
|
||||
const inFlight = ref(false);
|
||||
const errorShown = ref(false);
|
||||
|
||||
const username = ref<HTMLInputElement | null>(null);
|
||||
const password = ref<HTMLInputElement | null>(null);
|
||||
|
||||
const onAuthFailed = () => {
|
||||
inFlight.value = false;
|
||||
errorShown.value = true;
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
socket.on("auth:failed", this.onAuthFailed);
|
||||
},
|
||||
beforeUnmount() {
|
||||
socket.off("auth:failed", this.onAuthFailed);
|
||||
},
|
||||
methods: {
|
||||
onAuthFailed() {
|
||||
this.inFlight = false;
|
||||
this.errorShown = true;
|
||||
},
|
||||
onSubmit(event) {
|
||||
|
||||
const onSubmit = (event: Event) => {
|
||||
event.preventDefault();
|
||||
|
||||
this.inFlight = true;
|
||||
this.errorShown = false;
|
||||
if (!username.value || !password.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
inFlight.value = true;
|
||||
errorShown.value = false;
|
||||
|
||||
const values = {
|
||||
user: this.$refs.username.value,
|
||||
password: this.$refs.password.value,
|
||||
user: username.value?.value,
|
||||
password: password.value?.value,
|
||||
};
|
||||
|
||||
storage.set("user", values.user);
|
||||
|
||||
socket.emit("auth:perform", values);
|
||||
},
|
||||
getStoredUser() {
|
||||
};
|
||||
|
||||
const getStoredUser = () => {
|
||||
return storage.get("user");
|
||||
},
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
socket.on("auth:failed", onAuthFailed);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
socket.off("auth:failed", onAuthFailed);
|
||||
});
|
||||
|
||||
return {
|
||||
inFlight,
|
||||
errorShown,
|
||||
username,
|
||||
password,
|
||||
onSubmit,
|
||||
getStoredUser,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -587,6 +587,12 @@ p {
|
|||
|
||||
/* End icons */
|
||||
|
||||
|
||||
#app {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#viewport {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Generates a string from "color-1" to "color-32" based on an input string
|
||||
export default (str) => {
|
||||
export default (str: string) => {
|
||||
let hash = 0;
|
||||
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
|
@ -11,5 +11,5 @@ export default (str) => {
|
|||
due to A being ascii 65 (100 0001)
|
||||
while a being ascii 97 (110 0001)
|
||||
*/
|
||||
return "color-" + (1 + (hash % 32));
|
||||
return "color-" + (1 + (hash % 32)).toString();
|
||||
};
|
||||
|
|
|
@ -120,7 +120,7 @@ function parse(text: string, message?: ClientMessage, network?: ClientNetwork) {
|
|||
rel: "noopener",
|
||||
},
|
||||
},
|
||||
fragments
|
||||
() => fragments
|
||||
);
|
||||
|
||||
if (!preview) {
|
||||
|
@ -159,8 +159,9 @@ function parse(text: string, message?: ClientMessage, network?: ClientNetwork) {
|
|||
dir: "auto",
|
||||
},
|
||||
},
|
||||
linkEls
|
||||
() => linkEls
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
} else if (textPart.channel) {
|
||||
return createElement(
|
||||
|
@ -171,8 +172,9 @@ function parse(text: string, message?: ClientMessage, network?: ClientNetwork) {
|
|||
channel: textPart.channel,
|
||||
},
|
||||
},
|
||||
fragments
|
||||
() => fragments
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
} else if (textPart.emoji) {
|
||||
// @ts-ignore
|
||||
|
@ -191,7 +193,7 @@ function parse(text: string, message?: ClientMessage, network?: ClientNetwork) {
|
|||
title: title,
|
||||
},
|
||||
},
|
||||
fragments
|
||||
() => fragments
|
||||
);
|
||||
// @ts-ignore
|
||||
} else if (textPart.nick) {
|
||||
|
@ -205,14 +207,14 @@ function parse(text: string, message?: ClientMessage, network?: ClientNetwork) {
|
|||
nick: textPart.nick,
|
||||
},
|
||||
// @ts-ignore
|
||||
channel: messageChannel,
|
||||
channel: textPart.channel,
|
||||
network,
|
||||
},
|
||||
attrs: {
|
||||
dir: "auto",
|
||||
},
|
||||
},
|
||||
fragments
|
||||
() => fragments
|
||||
);
|
||||
}
|
||||
|
||||
|
|
11
client/js/types.d.ts
vendored
11
client/js/types.d.ts
vendored
|
@ -79,13 +79,10 @@ declare module "*.vue" {
|
|||
}
|
||||
|
||||
declare module "vue" {
|
||||
interface ComponentCustomProperties {
|
||||
// vue-router should do this for us
|
||||
$router: import("vue-router").Router;
|
||||
|
||||
// TODO: Vue struggles with typing using the options API, so we should switch to composition API
|
||||
// $root
|
||||
}
|
||||
// interface ComponentCustomProperties {
|
||||
// // TODO: Vue struggles with typing using the options API, so we should switch to composition API
|
||||
// // $root
|
||||
// }
|
||||
}
|
||||
|
||||
declare module "vue-router" {
|
||||
|
|
|
@ -43,7 +43,7 @@ self.addEventListener("fetch", function (event) {
|
|||
return;
|
||||
}
|
||||
|
||||
event.respondWith(networkOrCache(event));
|
||||
return event.respondWith(networkOrCache(event));
|
||||
});
|
||||
|
||||
async function putInCache(request, response) {
|
||||
|
|
|
@ -1,29 +1,27 @@
|
|||
import {expect} from "chai";
|
||||
|
||||
import {renderToString} from "@vue/server-test-utils";
|
||||
import ParsedMessageTestWrapper from "../../components/ParsedMessageTestWrapper.vue";
|
||||
import {mount} from "@vue/test-utils";
|
||||
import ParsedMessage from "../../../../client/components/ParsedMessage.vue";
|
||||
import {ClientMessage} from "../../../../client/js/types";
|
||||
|
||||
async function getParsedMessageContents(text: any, message: any) {
|
||||
let contents = await renderToString(ParsedMessageTestWrapper, {
|
||||
propsData: {
|
||||
function getParsedMessageContents(text: string, message?: any) {
|
||||
const wrapper = mount(ParsedMessage, {
|
||||
props: {
|
||||
text,
|
||||
message,
|
||||
},
|
||||
});
|
||||
|
||||
// The wrapper adds a surrounding div to the message html, so we clean that out here
|
||||
contents = contents.replace(/^<div data-server-rendered="true">([^]+)<\/div>$/m, "$1");
|
||||
|
||||
return contents;
|
||||
return wrapper.html();
|
||||
}
|
||||
|
||||
describe("IRC formatted message parser", () => {
|
||||
it("should not introduce xss", async () => {
|
||||
it("should not introduce xss", () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "<img onerror='location.href=\"//youtube.com\"'>",
|
||||
expected:
|
||||
'<img onerror=\'location.href="<a href="http://youtube.com" dir="auto" target="_blank" rel="noopener">//youtube.com</a>"\'>',
|
||||
'<img onerror=\'location.href="<a href="http://youtube.com" dir="auto" target="_blank" rel="noopener">//youtube.com</a>"\'>',
|
||||
},
|
||||
{
|
||||
input: '#&">bug',
|
||||
|
@ -32,16 +30,13 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should skip all <32 ASCII codes except linefeed", async () => {
|
||||
it("should skip all <32 ASCII codes except linefeed", () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1B\x1D\x1D\x1E\x1Ftext\x0Awithcontrolcodestest",
|
||||
|
@ -50,16 +45,13 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should find urls", async () => {
|
||||
it("should find urls", () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "irc://irc.example.com/thelounge",
|
||||
|
@ -102,16 +94,13 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("url with a dot parsed correctly", async () => {
|
||||
it("url with a dot parsed correctly", () => {
|
||||
const input =
|
||||
"bonuspunkt: your URL parser misparses this URL: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx";
|
||||
const correctResult =
|
||||
|
@ -120,13 +109,12 @@ describe("IRC formatted message parser", () => {
|
|||
"https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx" +
|
||||
"</a>";
|
||||
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
const actual = await getParsedMessageContents(input);
|
||||
const actual = getParsedMessageContents(input);
|
||||
|
||||
expect(actual).to.deep.equal(correctResult);
|
||||
});
|
||||
|
||||
it("should balance brackets", async () => {
|
||||
it("should balance brackets", () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "<https://theos.kyriasis.com/~kyrias/stats/archlinux.html>",
|
||||
|
@ -162,16 +150,13 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should not find urls", async () => {
|
||||
it("should not find urls", () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "text www. text",
|
||||
|
@ -183,16 +168,13 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should find channels", async () => {
|
||||
it("should find channels", () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "#a",
|
||||
|
@ -241,16 +223,13 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should not find channels", async () => {
|
||||
it("should not find channels", () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "hi#test",
|
||||
|
@ -262,10 +241,7 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
|
@ -362,9 +338,8 @@ describe("IRC formatted message parser", () => {
|
|||
'<span class="irc-bold">bold</span>' + " " + '<span class="irc-bold">bold</span>',
|
||||
},
|
||||
].forEach(({name, input, expected}) => {
|
||||
it(`should handle style characters: ${name}`, async () => {
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
expect(await getParsedMessageContents(input)).to.equal(expected);
|
||||
it(`should handle style characters: ${name}`, () => {
|
||||
expect(getParsedMessageContents(input)).to.equal(expected);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -391,7 +366,7 @@ describe("IRC formatted message parser", () => {
|
|||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should not find nicks", async () => {
|
||||
it("should not find nicks", () => {
|
||||
const testCases = [
|
||||
{
|
||||
users: ["MaxLeiter, test"],
|
||||
|
@ -411,16 +386,13 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should go bonkers like mirc", async () => {
|
||||
it("should go bonkers like mirc", () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "\x02irc\x0f://\x1dirc.example.com\x0f/\x034,8thelounge",
|
||||
|
@ -443,10 +415,7 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
|
@ -521,13 +490,12 @@ describe("IRC formatted message parser", () => {
|
|||
'<span dir="auto" role="button" tabindex="0" class="inline-channel">#i❤️thelounge</span>',
|
||||
},
|
||||
].forEach(({name, input, expected}) => {
|
||||
it(`should find emoji: ${name}`, async () => {
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
expect(await getParsedMessageContents(input)).to.equal(expected);
|
||||
it(`should find emoji: ${name}`, () => {
|
||||
expect(getParsedMessageContents(input)).to.equal(expected);
|
||||
});
|
||||
});
|
||||
|
||||
it("should optimize generated html", async () => {
|
||||
it("should optimize generated html", () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: 'test \x0312#\x0312\x0312"te\x0312st\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312a',
|
||||
|
@ -539,16 +507,13 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should trim common protocols", async () => {
|
||||
it("should trim common protocols", () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "like..http://example.com",
|
||||
|
@ -568,16 +533,13 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should not find channel in fragment", async () => {
|
||||
it("should not find channel in fragment", () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "http://example.com/#hash",
|
||||
|
@ -588,19 +550,15 @@ describe("IRC formatted message parser", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const actual = await Promise.all(
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
||||
);
|
||||
const actual = testCases.map((testCase) => getParsedMessageContents(testCase.input));
|
||||
const expected = testCases.map((testCase) => testCase.expected);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should not overlap parts", async () => {
|
||||
it("should not overlap parts", () => {
|
||||
const input = "Url: http://example.com/path Channel: ##channel";
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
const actual = await getParsedMessageContents(input);
|
||||
const actual = getParsedMessageContents(input);
|
||||
|
||||
expect(actual).to.equal(
|
||||
'Url: <a href="http://example.com/path" dir="auto" target="_blank" rel="noopener">http://example.com/path</a> ' +
|
||||
|
@ -608,10 +566,9 @@ describe("IRC formatted message parser", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("should handle overlapping parts by using first starting", async () => {
|
||||
it("should handle overlapping parts by using first starting", () => {
|
||||
const input = "#test-https://example.com";
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
const actual = await getParsedMessageContents(input);
|
||||
const actual = getParsedMessageContents(input);
|
||||
|
||||
expect(actual).to.equal(
|
||||
'<span dir="auto" role="button" tabindex="0" class="inline-channel">' +
|
||||
|
@ -620,10 +577,9 @@ describe("IRC formatted message parser", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("should find links separated by tab character", async () => {
|
||||
it("should find links separated by tab character", () => {
|
||||
const input = "example.com\texample.org";
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
const actual = await getParsedMessageContents(input);
|
||||
const actual = getParsedMessageContents(input);
|
||||
|
||||
expect(actual).to.equal(
|
||||
'<a href="http://example.com" dir="auto" target="_blank" rel="noopener">example.com</a>' +
|
||||
|
|
Loading…
Reference in a new issue