diff --git a/package.json b/package.json index 32f0db29f2..8f927c7bca 100644 --- a/package.json +++ b/package.json @@ -199,7 +199,7 @@ "decoderWorker\\.min\\.wasm": "/__mocks__/empty.js", "waveWorker\\.min\\.js": "/__mocks__/empty.js", "workers/(.+)\\.worker\\.ts": "/__mocks__/workerMock.js", - "^!!raw-loader!.*": "jest-raw-loader" + "^!!raw-loader!.*": "jest-raw-loader", "RecorderWorklet": "/__mocks__/empty.js" }, "transformIgnorePatterns": [ diff --git a/src/utils/exportUtils/Exporter.ts b/src/utils/exportUtils/Exporter.ts index f975e76ddd..92f2c3e3d2 100644 --- a/src/utils/exportUtils/Exporter.ts +++ b/src/utils/exportUtils/Exporter.ts @@ -98,7 +98,8 @@ export default abstract class Exporter { } protected downloadPlainText(fileName: string, text: string) { - saveAs(new Blob[text], fileName); + const content = new Blob([text], { type: "text" }); + saveAs(content, fileName); } protected setEventMetadata(event: MatrixEvent): MatrixEvent { diff --git a/src/utils/exportUtils/PlainTextExport.ts b/src/utils/exportUtils/PlainTextExport.ts index 7ab4748848..7421118470 100644 --- a/src/utils/exportUtils/PlainTextExport.ts +++ b/src/utils/exportUtils/PlainTextExport.ts @@ -16,7 +16,7 @@ limitations under the License. import Exporter from "./Exporter"; import { Room } from "matrix-js-sdk/src/models/room"; -import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { IContent, MatrixEvent } from "matrix-js-sdk/src/models/event"; import { formatFullDateNoDay } from "../../DateUtils"; import { _t } from "../../languageHandler"; import { haveTileForEvent } from "../../components/views/rooms/EventTile"; @@ -42,10 +42,9 @@ export default class PlainTextExporter extends Exporter { : _t("Media omitted - file size limit exceeded"); } - public textForReplyEvent = (ev: MatrixEvent) => { - const REPLY_REGEX = /> <(.*?)>(.*?)\n\n(.*)/; + public textForReplyEvent = (content: IContent) => { + const REPLY_REGEX = /> <(.*?)>(.*?)\n\n(.*)/s; const REPLY_SOURCE_MAX_LENGTH = 32; - const content = ev.getContent(); const match = REPLY_REGEX.exec(content.body); @@ -55,7 +54,7 @@ export default class PlainTextExporter extends Exporter { const rplName = match[1]; const rplText = match[3]; - rplSource = match[2].substring(1, REPLY_SOURCE_MAX_LENGTH); + rplSource = match[2].substring(1); // Get the first non-blank line from the source. const lines = rplSource.split('\n').filter((line) => !/^\s*$/.test(line)); if (lines.length > 0) { @@ -99,7 +98,7 @@ export default class PlainTextExporter extends Exporter { } } else mediaText = ` (${this.mediaOmitText})`; } - if (this.isReply(mxEv)) return senderDisplayName + ": " + this.textForReplyEvent(mxEv) + mediaText; + if (this.isReply(mxEv)) return senderDisplayName + ": " + this.textForReplyEvent(mxEv.getContent()) + mediaText; else return textForEvent(mxEv) + mediaText; }; diff --git a/test/utils/export-test.tsx b/test/utils/export-test.tsx index 25bf17d0ea..141fbe1280 100644 --- a/test/utils/export-test.tsx +++ b/test/utils/export-test.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { MatrixClient, Room } from "matrix-js-sdk"; +import { IContent, MatrixClient, Room } from "matrix-js-sdk"; import { MatrixClientPeg } from "../../src/MatrixClientPeg"; import { textForFormat, IExportOptions, ExportTypes } from "../../src/utils/exportUtils/exportUtils"; import '../skinned-sdk'; @@ -30,6 +30,10 @@ function generateRoomId() { return '!' + Math.random().toString().slice(2, 10) + ':domain'; } +interface ITestContent extends IContent { + expectedText: string; +} + describe('export', function() { stubClient(); client = MatrixClientPeg.get(); @@ -63,7 +67,7 @@ describe('export', function() { const events = mkEvents(); const room = createRoom(); - console.log(events, room); + console.log(events); function createRoom() { const room = new Room(generateRoomId(), null, client.getUserId()); return room; @@ -74,8 +78,8 @@ describe('export', function() { const ts0 = Date.now(); for (let i = 0; i < 10; i++) { events.push(TestUtilsMatrix.mkMessage({ - event: true, room: "!room:id", user: "@user:id", - ts: ts0 + i * 1000, + event: true, room: "!room:id", user: "@user:id", + ts: ts0 + i * 1000, })); } return events; @@ -118,14 +122,34 @@ describe('export', function() { } }); - // it('checks if the reply regex executes correctly', function() { - // const eventContents = [ - // { - // "msgtype": "m.text", - // "body": "> <@me:here> Testing....\n\nTest", - // "expectedText": "", - // }, - // ]; - // }); + it('checks if the reply regex executes correctly', function() { + const eventContents: ITestContent[] = [ + { + "msgtype": "m.text", + "body": "> <@me:here> Source\n\nReply", + "expectedText": "<@me:here \"Source\"> Reply", + }, + { + "msgtype": "m.text", + // if the reply format is invalid, then return the original string as it is + "body": "Invalid reply format", + "expectedText": "Invalid reply format", + }, + { + "msgtype": "m.text", + "body": "> <@me:here> The source is more than 32 characters\n\nReply", + "expectedText": "<@me:here \"The source is more than 32 chara...\"> Reply", + }, + { + "msgtype": "m.text", + "body": "> <@me:here> This\nsource\nhas\nnew\nlines\n\nReply", + "expectedText": "<@me:here \"This\"> Reply", + }, + ]; + const exporter = new PlainTextExporter(room, ExportTypes.BEGINNING, mockExportOptions, null); + for (const content of eventContents) { + expect(exporter.textForReplyEvent(content)).toBe(content.expectedText); + } + }); });