From 5b2c36833ce834466cc93e734551bba091e05beb Mon Sep 17 00:00:00 2001 From: Jorik Schellekens Date: Mon, 10 Aug 2020 12:35:15 +0100 Subject: [PATCH] Remove federtaed argument --- src/parser/parser.test.ts | 104 +++++++-------- src/parser/parser.ts | 274 +++++++++++++++++++------------------- src/parser/types.ts | 54 ++++---- 3 files changed, 205 insertions(+), 227 deletions(-) diff --git a/src/parser/parser.test.ts b/src/parser/parser.test.ts index 873fa5a..758dce2 100644 --- a/src/parser/parser.test.ts +++ b/src/parser/parser.test.ts @@ -1,78 +1,64 @@ +/* eslint-disable no-fallthrough */ + import { - parseHash, - parsePermalink, - parseArgs, - verifiers, - identifyTypeFromRegex, - toURL, + parseHash, + parsePermalink, + parseArgs, + verifiers, + identifyTypeFromRegex, + toURL, } from "./parser"; -import { LinkDiscriminator } from "./types"; +import { LinkKind } from "./types"; -function identifierType(id: string) { - return identifyTypeFromRegex(id, verifiers, LinkDiscriminator.ParseFailed); -} +const identifierType = (id: string): LinkKind => + identifyTypeFromRegex(id, verifiers, LinkKind.ParseFailed); it("types identifiers correctly", () => { - expect(identifierType("@user:matrix.org")).toEqual(LinkDiscriminator.UserId); - expect(identifierType("!room:matrix.org")).toEqual(LinkDiscriminator.RoomId); - expect(identifierType("!somewhere:example.org/$event:example.org")).toEqual( - LinkDiscriminator.Permalink - ); - expect(identifierType("+group:matrix.org")).toEqual( - LinkDiscriminator.GroupId - ); - expect(identifierType("#alias:matrix.org")).toEqual(LinkDiscriminator.Alias); + expect(identifierType("@user:matrix.org")).toEqual(LinkKind.UserId); + expect(identifierType("!room:matrix.org")).toEqual(LinkKind.RoomId); + expect(identifierType("!somewhere:example.org/$event:example.org")).toEqual( + LinkKind.Permalink + ); + expect(identifierType("+group:matrix.org")).toEqual(LinkKind.GroupId); + expect(identifierType("#alias:matrix.org")).toEqual(LinkKind.Alias); }); it("types garbage as such", () => { - expect(identifierType("sdfa;fdlkja")).toEqual(LinkDiscriminator.ParseFailed); - expect(identifierType("$event$matrix.org")).toEqual( - LinkDiscriminator.ParseFailed - ); - expect(identifierType("/user:matrix.org")).toEqual( - LinkDiscriminator.ParseFailed - ); + expect(identifierType("sdfa;fdlkja")).toEqual(LinkKind.ParseFailed); + expect(identifierType("$event$matrix.org")).toEqual(LinkKind.ParseFailed); + expect(identifierType("/user:matrix.org")).toEqual(LinkKind.ParseFailed); }); -it("parses vias", () => { - expect( - parseArgs("via=example.org&via=alt.example.org") - ).toHaveProperty("vias", ["example.org", "alt.example.org"]); -}); - -it("parses sharer", () => { - expect(parseArgs("sharer=blah")).toHaveProperty("sharer", "blah"); -}); - -it("parses client", () => { - expect(parseArgs("client=blah.com")).toHaveProperty("client", "blah.com"); -}); - -it("parses federated", () => { - expect(parseArgs("federated=true")).toHaveProperty("federated", true); - expect(parseArgs("federated=false")).toHaveProperty("federated", false); +it("parses args correctly", () => { + expect( + parseArgs("via=example.org&via=alt.example.org") + ).toHaveProperty("vias", ["example.org", "alt.example.org"]); + expect(parseArgs("sharer=blah")).toHaveProperty("sharer", "blah"); + expect(parseArgs("client=blah.com")).toHaveProperty("client", "blah.com"); }); it("parses permalinks", () => { - expect(parsePermalink("!somewhere:example.org/$event:example.org")).toEqual({ - roomKind: LinkDiscriminator.RoomId, - roomLink: "!somewhere:example.org", - eventId: "$event:example.org", - }); + expect(parsePermalink("!somewhere:example.org/$event:example.org")).toEqual( + { + roomKind: LinkKind.RoomId, + roomLink: "!somewhere:example.org", + eventId: "$event:example.org", + } + ); }); it("formats links correctly", () => { - const bigLink = - "!somewhere:example.org/$event:example.org?via=dfasdf&via=jfjafjaf"; - const origin = "https://matrix.org"; - const prefix = origin + "/#/"; - const parse = parseHash(bigLink); + const bigLink = + "!somewhere:example.org/$event:example.org?via=dfasdf&via=jfjafjaf"; + const origin = "https://matrix.org"; + const prefix = origin + "/#/"; + const parse = parseHash(bigLink); - switch (parse.kind) { - case LinkDiscriminator.ParseFailed: - fail("Parse failed"); - default: - expect(toURL(origin, parse).toString()).toEqual(prefix + bigLink); - } + switch (parse.kind) { + case LinkKind.ParseFailed: + fail("Parse failed"); + default: + expect(toURL(origin, parse).toString()).toEqual(prefix + bigLink); + } }); diff --git a/src/parser/parser.ts b/src/parser/parser.ts index 0ffea62..59a9a57 100644 --- a/src/parser/parser.ts +++ b/src/parser/parser.ts @@ -1,93 +1,134 @@ import forEach from "lodash/forEach"; import { - LinkDiscriminator, - SafeLink, - Link, - LinkContent, - Arguments, + LinkKind, + SafeLink, + Link, + LinkContent, + Arguments, + Permalink, } from "./types"; +/* + * Verifiers are regexes which will match valid + * identifiers to their type. (This is a lie, they + * can return anything) + */ +type Verifier = [RegExp, A]; +export const roomVerifiers: Verifier[] = [ + [/^#([^/:]+?):(.+)$/, LinkKind.Alias], + [/^!([^/:]+?):(.+)$/, LinkKind.RoomId], +]; +export const verifiers: Verifier[] = [ + [/^[!#]([^/:]+?):(.+?)\/\$([^/:]+?):(.+?)$/, LinkKind.Permalink], + [/^@([^/:]+?):(.+)$/, LinkKind.UserId], + [/^\+([^/:]+?):(.+)$/, LinkKind.GroupId], + ...roomVerifiers, +]; + +/* + * identifyTypeFromRegex applies the verifiers to the identifier and + * returns the identifier's type + */ +export function identifyTypeFromRegex( + identifier: string, + verifiers: Verifier[], + fail: F +): T | F { + if (identifier !== encodeURI(identifier)) { + return fail; + } + + return verifiers.reduce((kind, verifier) => { + if (kind !== fail) { + return kind; + } + + if (identifier.match(verifier[0])) { + return verifier[1]; + } + + return kind; + }, fail); +} + +/* + * Parses a permalink. + * Assumes the permalink is correct. + */ +export function parsePermalink(identifier: string): Permalink { + const [roomLink, eventId] = identifier.split("/"); + const roomKind = identifyTypeFromRegex( + roomLink, + roomVerifiers, + // This is hacky but we're assuming identifier is a valid permalink + LinkKind.Alias + ); + + return { + roomKind, + roomLink, + eventId, + }; +} + +/* + * Repalces null with undefined + */ +function bottomExchange(nullable: T | null): T | undefined { + if (nullable === null) return undefined; + return nullable; +} + +/* + * parseArgs parses the part of matrix.to links + */ +export function parseArgs(args: string): Arguments { + const params = new URLSearchParams(args); + + return { + vias: params.getAll("via"), + client: bottomExchange(params.get("client")), + sharer: bottomExchange(params.get("sharer")), + }; +} + /* * parseLink takes a striped matrix.to hash link (without the '#/' prefix) * and parses into a Link. If the parse failed the result will * be ParseFailed */ export function parseHash(hash: string): Link { - const [identifier, args] = hash.split("?"); + const [identifier, args] = hash.split("?"); - const kind = identifyTypeFromRegex( - identifier, - verifiers, - LinkDiscriminator.ParseFailed - ); + const kind = identifyTypeFromRegex( + identifier, + verifiers, + LinkKind.ParseFailed + ); - let parsedLink: LinkContent = { - identifier, - arguments: parseArgs(args), - originalLink: hash, - }; + const parsedLink: LinkContent = { + identifier, + arguments: parseArgs(args), + originalLink: hash, + }; - if (kind === LinkDiscriminator.Permalink) { - const { roomKind, roomLink, eventId } = parsePermalink(identifier); + if (kind === LinkKind.Permalink) { + const { roomKind, roomLink, eventId } = parsePermalink(identifier); + + return { + kind, + ...parsedLink, + roomKind, + roomLink, + eventId, + }; + } return { - kind, - ...parsedLink, - roomKind, - roomLink, - eventId, + kind, + ...parsedLink, }; - } - - return { - kind, - ...parsedLink, - }; -} - -/* - * Parses a permalink. - * Assumes the permalink is correct. - */ -export function parsePermalink(identifier: string) { - const [roomLink, eventId] = identifier.split("/"); - const roomKind = identifyTypeFromRegex( - roomLink, - roomVerifiers, - // This is hacky but we're assuming identifier is a valid permalink - LinkDiscriminator.Alias - ); - - return { - roomKind, - roomLink, - eventId, - }; -} - -/* - * parseArgs parses the part of matrix.to links - */ -export function parseArgs(args: string): Arguments { - const params = new URLSearchParams(args); - const _federated = params.get("federated"); - const federated = _federated !== null ? _federated === "true" : null; - - return { - vias: params.getAll("via"), - federated: bottomExchange(federated), - client: bottomExchange(params.get("client")), - sharer: bottomExchange(params.get("sharer")), - }; -} - -/* - * Repalces null with undefined - */ -function bottomExchange(nullable: T | null): T | undefined { - if (nullable === null) return undefined; - return nullable; } /* @@ -96,72 +137,27 @@ function bottomExchange(nullable: T | null): T | undefined { * This is handy function in case the Link was constructed. */ export function toURL(origin: string, link: SafeLink): URL { - switch (link.kind) { - case LinkDiscriminator.GroupId: - case LinkDiscriminator.UserId: - case LinkDiscriminator.RoomId: - case LinkDiscriminator.Alias: - case LinkDiscriminator.Permalink: - const params = new URLSearchParams(); - forEach(link.arguments, (value, key) => { - if (value === undefined) { - // do nothing - } else if (key === "vias") { - ((value)).forEach((via) => - params.append("via", via) - ); - } else { - params.append(key, value.toString()); - } - }); + const params = new URLSearchParams(); + const url = new URL(origin); + switch (link.kind) { + case LinkKind.GroupId: + case LinkKind.UserId: + case LinkKind.RoomId: + case LinkKind.Alias: + case LinkKind.Permalink: + forEach(link.arguments, (value, key) => { + if (value === undefined) { + // do nothing + } else if (key === "vias") { + (value as string[]).forEach((via) => + params.append("via", via) + ); + } else { + params.append(key, value.toString()); + } + }); - const url = new URL(origin); - url.hash = `/${link.identifier}?${params.toString()}`; - return url; - } -} - -/* - * Verifiers are regexes which will match valid - * identifiers to their type. (This is a lie, they - * can return anything) - */ -type Verifier = [RegExp, A]; -export const roomVerifiers: Verifier< - LinkDiscriminator.Alias | LinkDiscriminator.RoomId ->[] = [ - [/^#([^\/:]+?):(.+)$/, LinkDiscriminator.Alias], - [/^!([^\/:]+?):(.+)$/, LinkDiscriminator.RoomId], -]; -export const verifiers: Verifier[] = [ - [/^[\!#]([^\/:]+?):(.+?)\/\$([^\/:]+?):(.+?)$/, LinkDiscriminator.Permalink], - [/^@([^\/:]+?):(.+)$/, LinkDiscriminator.UserId], - [/^\+([^\/:]+?):(.+)$/, LinkDiscriminator.GroupId], - ...roomVerifiers, -]; - -/* - * identifyTypeFromRegex applies the verifiers to the identifier and - * returns the identifier's type - */ -export function identifyTypeFromRegex( - identifier: string, - verifiers: Verifier[], - fail: F -): T | F { - if (identifier !== encodeURI(identifier)) { - return fail; - } - - return verifiers.reduce((discriminator, verifier) => { - if (discriminator !== fail) { - return discriminator; + url.hash = `/${link.identifier}?${params.toString()}`; } - - if (identifier.match(verifier[0])) { - return verifier[1]; - } - - return discriminator; - }, fail); + return url; } diff --git a/src/parser/types.ts b/src/parser/types.ts index f629b90..f4366e5 100644 --- a/src/parser/types.ts +++ b/src/parser/types.ts @@ -1,56 +1,52 @@ export interface Arguments { - vias: string[]; - // Schemeless http identifier - client?: string; - // Indicates whether a room exists on a federating server (assumed to be the - // default), or if the client must connect via the server identified by the - // room ID or event ID - federated?: boolean; - // MXID - sharer?: string; + vias: string[]; + // Schemeless http identifier + client?: string; + // MXID + sharer?: string; } export interface LinkContent { - identifier: string; - arguments: Arguments; - originalLink: string; + identifier: string; + arguments: Arguments; + originalLink: string; } -export enum LinkDiscriminator { - Alias = "ALIAS", - RoomId = "ROOM_ID", - UserId = "USER_ID", - Permalink = "PERMALINK", - GroupId = "GROUP_ID", - ParseFailed = "PARSE_FAILED", +export enum LinkKind { + Alias = "ALIAS", + RoomId = "ROOM_ID", + UserId = "USER_ID", + Permalink = "PERMALINK", + GroupId = "GROUP_ID", + ParseFailed = "PARSE_FAILED", } export interface Alias extends LinkContent { - kind: LinkDiscriminator.Alias; + kind: LinkKind.Alias; } export interface RoomId extends LinkContent { - kind: LinkDiscriminator.RoomId; + kind: LinkKind.RoomId; } export interface UserId extends LinkContent { - kind: LinkDiscriminator.UserId; + kind: LinkKind.UserId; } export interface GroupId extends LinkContent { - kind: LinkDiscriminator.GroupId; + kind: LinkKind.GroupId; } export interface Permalink extends LinkContent { - kind: LinkDiscriminator.Permalink; - roomKind: LinkDiscriminator.RoomId | LinkDiscriminator.Alias; - roomLink: string; - eventId: string; + kind: LinkKind.Permalink; + roomKind: LinkKind.RoomId | LinkKind.Alias; + roomLink: string; + eventId: string; } export interface ParseFailed { - kind: LinkDiscriminator.ParseFailed; - originalLink: string; + kind: LinkKind.ParseFailed; + originalLink: string; } export type SafeLink = Alias | RoomId | UserId | Permalink | GroupId;