Apply prettier formatting

This commit is contained in:
Michael Weimann
2022-12-12 12:24:14 +01:00
parent 1cac306093
commit 526645c791
1576 changed files with 65384 additions and 62477 deletions
+27 -27
View File
@@ -48,9 +48,10 @@ export default abstract class Exporter {
protected exportOptions: IExportOptions,
protected setProgressText: React.Dispatch<React.SetStateAction<string>>,
) {
if (exportOptions.maxSize < 1 * 1024 * 1024|| // Less than 1 MB
if (
exportOptions.maxSize < 1 * 1024 * 1024 || // Less than 1 MB
exportOptions.maxSize > 8000 * 1024 * 1024 || // More than 8 GB
exportOptions.numberOfMessages > 10**8
exportOptions.numberOfMessages > 10 ** 8
) {
throw new Error("Invalid export options");
}
@@ -64,7 +65,7 @@ export default abstract class Exporter {
protected onBeforeUnload(e: BeforeUnloadEvent): string {
e.preventDefault();
return e.returnValue = _t("Are you sure you want to exit during this export?");
return (e.returnValue = _t("Are you sure you want to exit during this export?"));
}
protected updateProgress(progress: string, log = true, show = true): void {
@@ -84,8 +85,7 @@ export default abstract class Exporter {
// First try to use the real name of the room, then a translated copy of a generic name,
// then finally hardcoded default to guarantee we'll have a name.
const safeRoomName = sanitizeFilename(this.room.name ?? _t("Unnamed Room")).trim() || "Unnamed Room";
const safeDate = formatFullDateNoDayISO(new Date())
.replace(/:/g, '-'); // ISO format automatically removes a lot of stuff for us
const safeDate = formatFullDateNoDayISO(new Date()).replace(/:/g, "-"); // ISO format automatically removes a lot of stuff for us
const safeBrand = sanitizeFilename(brand);
return `${safeBrand} - ${safeRoomName} - Chat Export - ${safeDate}`;
}
@@ -93,7 +93,7 @@ export default abstract class Exporter {
protected async downloadZIP(): Promise<string | void> {
const filename = this.destinationFileName;
const filenameWithoutExt = filename.substring(0, filename.length - 4); // take off the .zip
const { default: JSZip } = await import('jszip');
const { default: JSZip } = await import("jszip");
const zip = new JSZip();
// Create a writable stream to the directory
@@ -125,13 +125,9 @@ export default abstract class Exporter {
protected setEventMetadata(event: MatrixEvent): MatrixEvent {
const roomState = this.client.getRoom(this.room.roomId).currentState;
event.sender = roomState.getSentinelMember(
event.getSender(),
);
event.sender = roomState.getSentinelMember(event.getSender());
if (event.getType() === "m.room.member") {
event.target = roomState.getSentinelMember(
event.getStateKey(),
);
event.target = roomState.getSentinelMember(event.getStateKey());
}
return event;
}
@@ -146,7 +142,7 @@ export default abstract class Exporter {
limit = 40;
break;
default:
limit = 10**8;
limit = 10 ** 8;
}
return limit;
}
@@ -154,7 +150,7 @@ export default abstract class Exporter {
protected async getRequiredEvents(): Promise<MatrixEvent[]> {
const eventMapper = this.client.getEventMapper();
let prevToken: string|null = null;
let prevToken: string | null = null;
let limit = this.getLimit();
const events: MatrixEvent[] = [];
@@ -188,26 +184,30 @@ export default abstract class Exporter {
}
if (this.exportType === ExportType.LastNMessages) {
this.updateProgress(_t("Fetched %(count)s events out of %(total)s", {
count: events.length,
total: this.exportOptions.numberOfMessages,
}));
this.updateProgress(
_t("Fetched %(count)s events out of %(total)s", {
count: events.length,
total: this.exportOptions.numberOfMessages,
}),
);
} else {
this.updateProgress(_t("Fetched %(count)s events so far", {
count: events.length,
}));
this.updateProgress(
_t("Fetched %(count)s events so far", {
count: events.length,
}),
);
}
prevToken = res.end;
}
// Reverse the events so that we preserve the order
for (let i = 0; i < Math.floor(events.length/2); i++) {
for (let i = 0; i < Math.floor(events.length / 2); i++) {
[events[i], events[events.length - i - 1]] = [events[events.length - i - 1], events[i]];
}
const decryptionPromises = events
.filter(event => event.isEncrypted())
.map(event => {
.filter((event) => event.isEncrypted())
.map((event) => {
return this.client.decryptEventIfNeeded(event, {
isRetry: true,
emit: false,
@@ -242,11 +242,11 @@ export default abstract class Exporter {
}
public splitFileName(file: string): string[] {
const lastDot = file.lastIndexOf('.');
const lastDot = file.lastIndexOf(".");
if (lastDot === -1) return [file, ""];
const fileName = file.slice(0, lastDot);
const ext = file.slice(lastDot + 1);
return [fileName, '.' + ext];
return [fileName, "." + ext];
}
public getFilePath(event: MatrixEvent): string {
@@ -271,7 +271,7 @@ export default abstract class Exporter {
if (event.getType() === "m.sticker") fileExt = ".png";
if (isVoiceMessage(event)) fileExt = ".ogg";
return fileDirectory + "/" + fileName + '-' + fileDate + fileExt;
return fileDirectory + "/" + fileName + "-" + fileDate + fileExt;
}
protected isReply(event: MatrixEvent): boolean {
+72 -71
View File
@@ -106,31 +106,27 @@ export default class HTMLExporter extends Exporter {
const exportedText = renderToStaticMarkup(
<p>
{ _t(
{_t(
"This is the start of export of <roomName/>. Exported by <exporterDetails/> at %(exportDate)s.",
{
exportDate,
},
{
roomName: () => <b>{ this.room.name }</b>,
roomName: () => <b>{this.room.name}</b>,
exporterDetails: () => (
<a
href={`https://matrix.to/#/${exporter}`}
target="_blank"
rel="noopener noreferrer"
>
{ exporterName ? (
<a href={`https://matrix.to/#/${exporter}`} target="_blank" rel="noopener noreferrer">
{exporterName ? (
<>
<b>{ exporterName }</b>
{ " (" + exporter + ")" }
<b>{exporterName}</b>
{" (" + exporter + ")"}
</>
) : (
<b>{ exporter }</b>
) }
<b>{exporter}</b>
)}
</a>
),
},
) }
)}
</p>,
);
@@ -224,12 +220,7 @@ export default class HTMLExporter extends Exporter {
protected getAvatarURL(event: MatrixEvent): string {
const member = event.sender;
return (
member.getMxcAvatarUrl() &&
mediaFromMxc(member.getMxcAvatarUrl()).getThumbnailOfSourceHttp(
30,
30,
"crop",
)
member.getMxcAvatarUrl() && mediaFromMxc(member.getMxcAvatarUrl()).getThumbnailOfSourceHttp(30, 30, "crop")
);
}
@@ -241,7 +232,7 @@ export default class HTMLExporter extends Exporter {
this.avatars.set(member.userId, true);
const image = await fetch(avatarUrl);
const blob = await image.blob();
this.addFile(`users/${member.userId.replace(/:/g, '-')}.png`, blob);
this.addFile(`users/${member.userId.replace(/:/g, "-")}.png`, blob);
} catch (err) {
logger.log("Failed to fetch user's avatar" + err);
}
@@ -264,32 +255,34 @@ export default class HTMLExporter extends Exporter {
}
public getEventTile(mxEv: MatrixEvent, continuation: boolean) {
return <div className="mx_Export_EventWrapper" id={mxEv.getId()}>
<MatrixClientContext.Provider value={this.client}>
<EventTile
mxEvent={mxEv}
continuation={continuation}
isRedacted={mxEv.isRedacted()}
replacingEventId={mxEv.replacingEventId()}
forExport={true}
readReceipts={null}
alwaysShowTimestamps={true}
readReceiptMap={null}
showUrlPreview={false}
checkUnmounting={() => false}
isTwelveHour={false}
last={false}
lastInSection={false}
permalinkCreator={this.permalinkCreator}
lastSuccessful={false}
isSelectedEvent={false}
getRelationsForEvent={null}
showReactions={false}
layout={Layout.Group}
showReadReceipts={false}
/>
</MatrixClientContext.Provider>
</div>;
return (
<div className="mx_Export_EventWrapper" id={mxEv.getId()}>
<MatrixClientContext.Provider value={this.client}>
<EventTile
mxEvent={mxEv}
continuation={continuation}
isRedacted={mxEv.isRedacted()}
replacingEventId={mxEv.replacingEventId()}
forExport={true}
readReceipts={null}
alwaysShowTimestamps={true}
readReceiptMap={null}
showUrlPreview={false}
checkUnmounting={() => false}
isTwelveHour={false}
last={false}
lastInSection={false}
permalinkCreator={this.permalinkCreator}
lastSuccessful={false}
isSelectedEvent={false}
getRelationsForEvent={null}
showReactions={false}
layout={Layout.Group}
showReadReceipts={false}
/>
</MatrixClientContext.Provider>
</div>
);
}
protected async getEventTileMarkup(mxEv: MatrixEvent, continuation: boolean, filePath?: string) {
@@ -305,11 +298,8 @@ export default class HTMLExporter extends Exporter {
) {
// to linkify textual events, we'll need lifecycle methods which won't be invoked in renderToString
// So, we'll have to render the component into a temporary root element
const tempRoot = document.createElement('div');
ReactDOM.render(
EventTile,
tempRoot,
);
const tempRoot = document.createElement("div");
ReactDOM.render(EventTile, tempRoot);
eventTileMarkup = tempRoot.innerHTML;
} else {
eventTileMarkup = renderToStaticMarkup(EventTile);
@@ -319,17 +309,17 @@ export default class HTMLExporter extends Exporter {
const mxc = mxEv.getContent().url ?? mxEv.getContent().file?.url;
eventTileMarkup = eventTileMarkup.split(mxc).join(filePath);
}
eventTileMarkup = eventTileMarkup.replace(/<span class="mx_MFileBody_info_icon".*?>.*?<\/span>/, '');
eventTileMarkup = eventTileMarkup.replace(/<span class="mx_MFileBody_info_icon".*?>.*?<\/span>/, "");
if (hasAvatar) {
eventTileMarkup = eventTileMarkup.replace(
encodeURI(this.getAvatarURL(mxEv)).replace(/&/g, '&amp;'),
encodeURI(this.getAvatarURL(mxEv)).replace(/&/g, "&amp;"),
`users/${mxEv.sender.userId.replace(/:/g, "-")}.png`,
);
}
return eventTileMarkup;
}
protected createModifiedEvent(text: string, mxEv: MatrixEvent, italic=true) {
protected createModifiedEvent(text: string, mxEv: MatrixEvent, italic = true) {
const modifiedContent = {
msgtype: "m.text",
body: `${text}`,
@@ -337,8 +327,8 @@ export default class HTMLExporter extends Exporter {
formatted_body: `${text}`,
};
if (italic) {
modifiedContent.formatted_body = '<em>' + modifiedContent.formatted_body + '</em>';
modifiedContent.body = '*' + modifiedContent.body + '*';
modifiedContent.formatted_body = "<em>" + modifiedContent.formatted_body + "</em>";
modifiedContent.body = "*" + modifiedContent.body + "*";
}
const modifiedEvent = new MatrixEvent();
modifiedEvent.event = mxEv.event;
@@ -402,15 +392,20 @@ export default class HTMLExporter extends Exporter {
let prevEvent = null;
for (let i = start; i < Math.min(start + 1000, events.length); i++) {
const event = events[i];
this.updateProgress(_t("Processing event %(number)s out of %(total)s", {
number: i + 1,
total: events.length,
}), false, true);
this.updateProgress(
_t("Processing event %(number)s out of %(total)s", {
number: i + 1,
total: events.length,
}),
false,
true,
);
if (this.cancelled) return this.cleanUp();
if (!haveRendererForEvent(event, false)) continue;
content += this.needsDateSeparator(event, prevEvent) ? this.getDateSeparator(event) : "";
const shouldBeJoined = !this.needsDateSeparator(event, prevEvent) &&
const shouldBeJoined =
!this.needsDateSeparator(event, prevEvent) &&
shouldFormContinuation(prevEvent, event, false, this.threadsEnabled);
const body = await this.createMessageBody(event, shouldBeJoined);
this.totalSize += Buffer.byteLength(body);
@@ -427,10 +422,14 @@ export default class HTMLExporter extends Exporter {
const res = await this.getRequiredEvents();
const fetchEnd = performance.now();
this.updateProgress(_t("Fetched %(count)s events in %(seconds)ss", {
count: res.length,
seconds: (fetchEnd - fetchStart) / 1000,
}), true, false);
this.updateProgress(
_t("Fetched %(count)s events in %(seconds)ss", {
count: res.length,
seconds: (fetchEnd - fetchStart) / 1000,
}),
true,
false,
);
this.updateProgress(_t("Creating HTML..."));
@@ -438,8 +437,8 @@ export default class HTMLExporter extends Exporter {
for (let page = 0; page < res.length / 1000; page++) {
const html = await this.createHTML(res, page * 1000);
const document = new DOMParser().parseFromString(html, "text/html");
document.querySelectorAll("*").forEach(element => {
element.classList.forEach(c => usedClasses.add(c));
document.querySelectorAll("*").forEach((element) => {
element.classList.forEach((c) => usedClasses.add(c));
});
this.addFile(`messages${page ? page + 1 : ""}.html`, new Blob([html]));
}
@@ -456,10 +455,12 @@ export default class HTMLExporter extends Exporter {
logger.info("Export cancelled successfully");
} else {
this.updateProgress(_t("Export successful!"));
this.updateProgress(_t("Exported %(count)s events in %(seconds)s seconds", {
count: res.length,
seconds: (exportEnd - fetchStart) / 1000,
}));
this.updateProgress(
_t("Exported %(count)s events in %(seconds)s seconds", {
count: res.length,
seconds: (exportEnd - fetchStart) / 1000,
}),
);
}
this.cleanUp();
+10 -7
View File
@@ -84,10 +84,14 @@ export default class JSONExporter extends Exporter {
protected async createOutput(events: MatrixEvent[]) {
for (let i = 0; i < events.length; i++) {
const event = events[i];
this.updateProgress(_t("Processing event %(number)s out of %(total)s", {
number: i + 1,
total: events.length,
}), false, true);
this.updateProgress(
_t("Processing event %(number)s out of %(total)s", {
number: i + 1,
total: events.length,
}),
false,
true,
);
if (this.cancelled) return this.cleanUp();
if (!haveRendererForEvent(event, false)) continue;
this.messages.push(await this.getJSONString(event));
@@ -103,7 +107,7 @@ export default class JSONExporter extends Exporter {
const res = await this.getRequiredEvents();
const fetchEnd = performance.now();
logger.log(`Fetched ${res.length} events in ${(fetchEnd - fetchStart)/1000}s`);
logger.log(`Fetched ${res.length} events in ${(fetchEnd - fetchStart) / 1000}s`);
logger.info("Creating output...");
const text = await this.createOutput(res);
@@ -122,10 +126,9 @@ export default class JSONExporter extends Exporter {
logger.info("Export cancelled successfully");
} else {
logger.info("Export successful!");
logger.log(`Exported ${res.length} events in ${(exportEnd - fetchStart)/1000} seconds`);
logger.log(`Exported ${res.length} events in ${(exportEnd - fetchStart) / 1000} seconds`);
}
this.cleanUp();
}
}
+11 -8
View File
@@ -61,7 +61,7 @@ export default class PlainTextExporter extends Exporter {
rplSource = match[2].substring(1);
// Get the first non-blank line from the source.
const lines = rplSource.split('\n').filter((line) => !/^\s*$/.test(line));
const lines = rplSource.split("\n").filter((line) => !/^\s*$/.test(line));
if (lines.length > 0) {
// Cut to a maximum length.
rplSource = lines[0].substring(0, REPLY_SOURCE_MAX_LENGTH);
@@ -111,10 +111,14 @@ export default class PlainTextExporter extends Exporter {
let content = "";
for (let i = 0; i < events.length; i++) {
const event = events[i];
this.updateProgress(_t("Processing event %(number)s out of %(total)s", {
number: i + 1,
total: events.length,
}), false, true);
this.updateProgress(
_t("Processing event %(number)s out of %(total)s", {
number: i + 1,
total: events.length,
}),
false,
true,
);
if (this.cancelled) return this.cleanUp();
if (!haveRendererForEvent(event, false)) continue;
const textForEvent = await this.plainTextForEvent(event);
@@ -131,7 +135,7 @@ export default class PlainTextExporter extends Exporter {
const res = await this.getRequiredEvents();
const fetchEnd = performance.now();
logger.log(`Fetched ${res.length} events in ${(fetchEnd - fetchStart)/1000}s`);
logger.log(`Fetched ${res.length} events in ${(fetchEnd - fetchStart) / 1000}s`);
this.updateProgress(_t("Creating output..."));
const text = await this.createOutput(res);
@@ -150,10 +154,9 @@ export default class PlainTextExporter extends Exporter {
logger.info("Export cancelled successfully");
} else {
logger.info("Export successful!");
logger.log(`Exported ${res.length} events in ${(exportEnd - fetchStart)/1000} seconds`);
logger.log(`Exported ${res.length} events in ${(exportEnd - fetchStart) / 1000} seconds`);
}
this.cleanUp();
}
}
+9 -7
View File
@@ -52,7 +52,7 @@ async function getRulesFromCssFile(path: string): Promise<CSSStyleSheet> {
// doesn't cull rules which won't apply due to the full selector not matching but gets rid of a LOT of cruft anyway.
const getExportCSS = async (usedClasses: Set<string>): Promise<string> => {
// only include bundle.css and the data-mx-theme=light styling
const stylesheets = Array.from(document.styleSheets).filter(s => {
const stylesheets = Array.from(document.styleSheets).filter((s) => {
return s.href?.endsWith("bundle.css") || isLightTheme(s);
});
@@ -70,12 +70,14 @@ const getExportCSS = async (usedClasses: Set<string>): Promise<string> => {
const selectorText = (rule as CSSStyleRule).selectorText;
// only skip the rule if all branches (,) of the selector are redundant
if (selectorText?.split(",").every(selector => {
const classes = selector.match(cssSelectorTextClassesRegex);
if (classes && !classes.every(c => usedClasses.has(c.substring(1)))) {
return true; // signal as a redundant selector
}
})) {
if (
selectorText?.split(",").every((selector) => {
const classes = selector.match(cssSelectorTextClassesRegex);
if (classes && !classes.every((c) => usedClasses.has(c.substring(1)))) {
return true; // signal as a redundant selector
}
})
) {
continue; // skip this rule as it is redundant
}
+2 -4
View File
@@ -32,9 +32,8 @@ limitations under the License.
bottom: 30px;
font-size: 17px;
padding: 6px 16px;
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir,
segoe ui, helvetica neue, helvetica, Ubuntu, roboto, noto, arial,
sans-serif;
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu,
roboto, noto, arial, sans-serif;
font-weight: 400;
line-height: 1.43;
border-radius: 4px;
@@ -126,7 +125,6 @@ a.mx_reply_anchor:hover {
.mx_RedactedBody,
.mx_HiddenBody {
padding-left: unset;
}
+2 -3
View File
@@ -33,10 +33,9 @@ function showToast(text) {
}
window.onload = () => {
document.querySelectorAll('.mx_reply_anchor').forEach(element => {
element.addEventListener('click', event => {
document.querySelectorAll(".mx_reply_anchor").forEach((element) => {
element.addEventListener("click", (event) => {
showToastIfNeeded(event.target.dataset.scrollTo);
});
});
};