Extract email styles into head (#4172)
* Extract email styles into head * tsc
This commit is contained in:
@@ -81,6 +81,7 @@ export default abstract class BaseEmail<T extends EmailProps, S = unknown> {
|
|||||||
previewText: this.preview(data),
|
previewText: this.preview(data),
|
||||||
component: this.render(data),
|
component: this.render(data),
|
||||||
text: this.renderAsText(data),
|
text: this.renderAsText(data),
|
||||||
|
headCSS: this.headCSS?.(data),
|
||||||
});
|
});
|
||||||
Metrics.increment("email.sent", {
|
Metrics.increment("email.sent", {
|
||||||
templateName,
|
templateName,
|
||||||
@@ -145,6 +146,14 @@ export default abstract class BaseEmail<T extends EmailProps, S = unknown> {
|
|||||||
*/
|
*/
|
||||||
protected abstract render(props: S & T): JSX.Element;
|
protected abstract render(props: S & T): JSX.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows injecting additional CSS into the head of the email.
|
||||||
|
*
|
||||||
|
* @param props Props in email constructor
|
||||||
|
* @returns A string of CSS
|
||||||
|
*/
|
||||||
|
protected headCSS?(props: T): string | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* beforeSend hook allows async loading additional data that was not passed
|
* beforeSend hook allows async loading additional data that was not passed
|
||||||
* through the serialized worker props. If false is returned then the email
|
* through the serialized worker props. If false is returned then the email
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { JSDOM } from "jsdom";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Document } from "@server/models";
|
import { Document } from "@server/models";
|
||||||
import BaseEmail from "./BaseEmail";
|
import BaseEmail from "./BaseEmail";
|
||||||
@@ -23,6 +24,8 @@ type InputProps = {
|
|||||||
|
|
||||||
type BeforeSend = {
|
type BeforeSend = {
|
||||||
document: Document;
|
document: Document;
|
||||||
|
css: string | undefined;
|
||||||
|
body: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = InputProps & BeforeSend;
|
type Props = InputProps & BeforeSend;
|
||||||
@@ -35,13 +38,27 @@ export default class DocumentNotificationEmail extends BaseEmail<
|
|||||||
InputProps,
|
InputProps,
|
||||||
BeforeSend
|
BeforeSend
|
||||||
> {
|
> {
|
||||||
protected async beforeSend({ documentId }: InputProps) {
|
protected async beforeSend({ documentId, content }: InputProps) {
|
||||||
const document = await Document.unscoped().findByPk(documentId);
|
const document = await Document.unscoped().findByPk(documentId);
|
||||||
if (!document) {
|
if (!document) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { document };
|
// extract the css styles so they can be injected into the head of email
|
||||||
|
// for best compatability
|
||||||
|
let css, body;
|
||||||
|
if (content) {
|
||||||
|
const dom = new JSDOM(content);
|
||||||
|
const styles = dom.window.document.querySelectorAll("style");
|
||||||
|
css = Array.from(styles)
|
||||||
|
.map((style) => style.innerHTML)
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
|
styles.forEach((style) => style.remove());
|
||||||
|
body = dom.window.document.body.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { document, body, css };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected subject({ document, eventName }: Props) {
|
protected subject({ document, eventName }: Props) {
|
||||||
@@ -68,6 +85,10 @@ Open Document: ${teamUrl}${document.url}
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected headCSS(props: Props) {
|
||||||
|
return props.css;
|
||||||
|
}
|
||||||
|
|
||||||
protected render({
|
protected render({
|
||||||
document,
|
document,
|
||||||
actorName,
|
actorName,
|
||||||
@@ -75,7 +96,7 @@ Open Document: ${teamUrl}${document.url}
|
|||||||
eventName = "published",
|
eventName = "published",
|
||||||
teamUrl,
|
teamUrl,
|
||||||
unsubscribeUrl,
|
unsubscribeUrl,
|
||||||
content,
|
body,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const link = `${teamUrl}${document.url}?ref=notification-email`;
|
const link = `${teamUrl}${document.url}?ref=notification-email`;
|
||||||
|
|
||||||
@@ -92,11 +113,11 @@ Open Document: ${teamUrl}${document.url}
|
|||||||
<a href={link}>{document.title}</a>, in the {collectionName}{" "}
|
<a href={link}>{document.title}</a>, in the {collectionName}{" "}
|
||||||
collection.
|
collection.
|
||||||
</p>
|
</p>
|
||||||
{content && (
|
{body && (
|
||||||
<>
|
<>
|
||||||
<EmptySpace height={20} />
|
<EmptySpace height={20} />
|
||||||
<Diff>
|
<Diff>
|
||||||
<div dangerouslySetInnerHTML={{ __html: content }} />
|
<div dangerouslySetInnerHTML={{ __html: body }} />
|
||||||
</Diff>
|
</Diff>
|
||||||
<EmptySpace height={20} />
|
<EmptySpace height={20} />
|
||||||
</>
|
</>
|
||||||
|
|||||||
Reference in New Issue
Block a user