Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Ignore permalink_prefix when serializing Markdown #11725

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/editor/serialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ export function mdSerialize(model: EditorModel): string {
case Type.AtRoomPill:
return html + part.text;
case Type.RoomPill: {
const url = makeGenericPermalink(part.resourceId);
const url = makeGenericPermalink(part.resourceId, true);
// Escape square brackets and backslashes
// Here we use the resourceId for compatibility with non-rich text clients
// See https://github.com/vector-im/element-web/issues/16660
const title = part.resourceId.replace(/[[\\\]]/g, (c) => "\\" + c);
return html + `[${title}](${url})`;
}
case Type.UserPill: {
const url = makeGenericPermalink(part.resourceId);
const url = makeGenericPermalink(part.resourceId, true);
// Escape square brackets and backslashes; convert newlines to HTML
const title = part.text.replace(/[[\\\]]/g, (c) => "\\" + c).replace(/\n/g, "<br>");
return html + `[${title}](${url})`;
Expand Down
21 changes: 15 additions & 6 deletions src/utils/permalinks/ElementPermalinkConstructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,32 @@ export default class ElementPermalinkConstructor extends PermalinkConstructor {
}
}

public forEvent(roomId: string, eventId: string, serverCandidates: string[]): string {
public forEvent(roomId: string, eventId: string, serverCandidates: string[], ispill = false): string {
if (ispill) {
return `https://matrix.to/#/${roomId}/${eventId}${this.encodeServerCandidates(serverCandidates)}`;
}
return `${this.elementUrl}/#/room/${roomId}/${eventId}${this.encodeServerCandidates(serverCandidates)}`;
}

public forRoom(roomIdOrAlias: string, serverCandidates?: string[]): string {
public forRoom(roomIdOrAlias: string, serverCandidates?: string[], ispill = false): string {
if (ispill) {
return `https://matrix.to/#/${roomIdOrAlias}${this.encodeServerCandidates(serverCandidates)}`;
}
return `${this.elementUrl}/#/room/${roomIdOrAlias}${this.encodeServerCandidates(serverCandidates)}`;
}

public forUser(userId: string): string {
public forUser(userId: string, ispill = false): string {
if (ispill) {
return `https://matrix.to/#/${userId}`;
}
return `${this.elementUrl}/#/user/${userId}`;
}

public forEntity(entityId: string): string {
public forEntity(entityId: string, ispill = false): string {
if (entityId[0] === "!" || entityId[0] === "#") {
return this.forRoom(entityId);
return this.forRoom(entityId, [], ispill);
} else if (entityId[0] === "@") {
return this.forUser(entityId);
return this.forUser(entityId, ispill);
} else throw new Error("Unrecognized entity");
}

Expand Down
8 changes: 4 additions & 4 deletions src/utils/permalinks/PermalinkConstructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ limitations under the License.
* TODO: Convert this to a real TypeScript interface
*/
export default class PermalinkConstructor {
public forEvent(roomId: string, eventId: string, serverCandidates: string[] = []): string {
public forEvent(roomId: string, eventId: string, serverCandidates: string[] = [], ispill = false): string {
throw new Error("Not implemented");
}

public forRoom(roomIdOrAlias: string, serverCandidates: string[] = []): string {
public forRoom(roomIdOrAlias: string, serverCandidates: string[] = [], ispill = false): string {
throw new Error("Not implemented");
}

public forUser(userId: string): string {
public forUser(userId: string, ispill = false): string {
throw new Error("Not implemented");
}

public forEntity(entityId: string): string {
public forEntity(entityId: string, ispill = false): string {
throw new Error("Not implemented");
}

Expand Down
12 changes: 6 additions & 6 deletions src/utils/permalinks/Permalinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,26 +269,26 @@ export class RoomPermalinkCreator {
};
}

export function makeGenericPermalink(entityId: string): string {
return getPermalinkConstructor().forEntity(entityId);
export function makeGenericPermalink(entityId: string, ispill = false): string {
return getPermalinkConstructor().forEntity(entityId, ispill);
}

export function makeUserPermalink(userId: string): string {
export function makeUserPermalink(userId: string, ispill = false): string {
return getPermalinkConstructor().forUser(userId);
}

export function makeRoomPermalink(matrixClient: MatrixClient, roomId: string): string {
export function makeRoomPermalink(matrixClient: MatrixClient, roomId: string, ispill = false): string {
if (!roomId) {
throw new Error("can't permalink a falsy roomId");
}

// If the roomId isn't actually a room ID, don't try to list the servers.
// Aliases are already routable, and don't need extra information.
if (roomId[0] !== "!") return getPermalinkConstructor().forRoom(roomId, []);
if (roomId[0] !== "!") return getPermalinkConstructor().forRoom(roomId, [], ispill);

const room = matrixClient.getRoom(roomId);
if (!room) {
return getPermalinkConstructor().forRoom(roomId, []);
return getPermalinkConstructor().forRoom(roomId, [], ispill);
}
const permalinkCreator = new RoomPermalinkCreator(room);
permalinkCreator.load();
Expand Down
30 changes: 30 additions & 0 deletions test/editor/serialize-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { mocked } from "jest-mock";

import EditorModel from "../../src/editor/model";
import { htmlSerializeIfNeeded } from "../../src/editor/serialize";
import { createPartCreator } from "./mock";
import { IConfigOptions } from "../../src/IConfigOptions";
import SettingsStore from "../../src/settings/SettingsStore";
import SdkConfig from "../../src/SdkConfig";

describe("editor/serialize", function () {
describe("with markdown", function () {
Expand Down Expand Up @@ -104,6 +108,32 @@ describe("editor/serialize", function () {
const html = htmlSerializeIfNeeded(model, {});
expect(html).toBe('<ol start="2021">\n<li>foo</li>\n</ol>\n');
});
describe("with permalink_prefix set", function () {
const sdkConfigGet = SdkConfig.get;
beforeEach(() => {
jest.spyOn(SdkConfig, "get").mockImplementation((key: keyof IConfigOptions, altCaseName?: string) => {
if (key === "permalink_prefix") {
return "https://element.fs.tld";
} else return sdkConfigGet(key, altCaseName);
});
});

it("user pill uses matrix.to", function () {
const pc = createPartCreator();
const model = new EditorModel([pc.userPill("Alice", "@alice:hs.tld")], pc);
const html = htmlSerializeIfNeeded(model, {});
expect(html).toBe('<a href="https://matrix.to/#/@alice:hs.tld">Alice</a>');
});
it("room pill uses matrix.to", function () {
const pc = createPartCreator();
const model = new EditorModel([pc.roomPill("#room:hs.tld")], pc);
const html = htmlSerializeIfNeeded(model, {});
expect(html).toBe('<a href="https://matrix.to/#/#room:hs.tld">#room:hs.tld</a>');
});
afterEach(() => {
mocked(SdkConfig.get).mockRestore();
});
});
});

describe("with plaintext", function () {
Expand Down
13 changes: 13 additions & 0 deletions test/utils/permalinks/Permalinks-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {
parsePermalink,
RoomPermalinkCreator,
} from "../../../src/utils/permalinks/Permalinks";
import { IConfigOptions } from "../../../src/IConfigOptions";
import SdkConfig from "../../../src/SdkConfig";
import { getMockClientWithEventEmitter } from "../../test-utils";

describe("Permalinks", function () {
Expand Down Expand Up @@ -390,6 +392,17 @@ describe("Permalinks", function () {
expect(result).toBe("https://matrix.to/#/@someone:example.org");
});

it("should use permalink_prefix for permalinks", function () {
const sdkConfigGet = SdkConfig.get;
jest.spyOn(SdkConfig, "get").mockImplementation((key: keyof IConfigOptions, altCaseName?: string) => {
if (key === "permalink_prefix") {
return "https://element.fs.tld";
} else return sdkConfigGet(key, altCaseName);
});
const result = makeUserPermalink("@someone:example.org");
expect(result).toBe("https://element.fs.tld/#/user/@someone:example.org");
});

describe("parsePermalink", () => {
it("should correctly parse room permalinks with a via argument", () => {
const result = parsePermalink("https://matrix.to/#/!room_id:server?via=some.org");
Expand Down