Skip to content

Instantly share code, notes, and snippets.

@bengry
Created January 4, 2022 12:32
Show Gist options
  • Save bengry/6cfc9464c6c83bbd0e732c07cb9dc14f to your computer and use it in GitHub Desktop.
Save bengry/6cfc9464c6c83bbd0e732c07cb9dc14f to your computer and use it in GitHub Desktop.
TypeScript types for MJML v4.6.x. Might be partial - I typed mostly the only things I used
type TODO = unknown;
/**
* @see https://github.com/mjmlio/mjml/blob/master/packages/mjml-core/src/types/index.js
*/
type ValidTypes = "boolean" | "enum" | "color" | "unit" | "string" | "integer";
type PrimitiveType<T> = T extends boolean
? "boolean"
: T extends string
? "string"
: T extends number
? "integer"
: never;
declare module "mjml-parser-xml" {
import { ComponentClass } from "mjml-core";
interface MJMLParserOptions {
addEmptyAttributes?: boolean;
components?: Record<string, ComponentClass>;
convertBooleans?: boolean;
keepComments?: boolean;
filePath?: string;
actualPath?: string;
ignoreIncludes?: boolean;
preprocessors?: readonly TODO[];
}
}
declare module "mjml-core" {
import { MJMLParserOptions } from "mjml-parser-xml";
type Attributes<K extends string = string> = Record<K, string | boolean | number | undefined>;
interface ComponentStatic<A extends Attributes> {
/**
* What the name suggests. Fallback value for `this.getAttribute('attribute-name')`.
*/
readonly defaultAttributes?: A;
/**
* Tells the validator which attributes are allowed.
*/
readonly allowedAttributes?: { [K in keyof A]: PrimitiveType<A[K]> };
}
type MJMLComponentXML = {
tagName?: string;
attributes?: Attributes;
} & ({ children?: readonly MJMLComponentXML[] } | { content?: string });
abstract class Component<A extends Attributes = {}> {
readonly context: unknown;
readonly props: Props;
readonly attributes: A;
getChildContext(): this["context"];
getAttribute<K extends keyof A>(name: K): A[K];
getContent(): string;
renderMJML(mjml: string, options?: MJMLParserOptions): string;
renderMJML(xml: MJMLComponentXML, options?: MJMLParserOptions): string;
}
interface ComponentClass<A extends Attributes = {}> extends ComponentStatic<A> {
new (initialDatas?: Partial<InitialDatas<A>>): Component<A>;
}
interface BodyComponentStatic<A extends Attributes> extends ComponentStatic<A> {
/**
* Tell the parser that our component won't contain other mjml tags.
*
* Useful if you need to access `this.props.children`.
*
* @default false
*/
readonly endingTag?: boolean;
/**
* @default false
*/
readonly rawElement?: boolean;
}
abstract class BodyComponent<A extends Attributes = {}, Styles extends string | never = never> extends Component<A> {
constructor(initialDatas?: Partial<InitialDatas<A>>);
/**
* Using this method is the recommended way to pass attributes to html tags.
*/
htmlAttributes<E extends keyof HTMLElementTagNameMap>(
options: Partial<Omit<HTMLElementTagNameMap[E], "style">> | Partial<Record<"style", Styles>>,
): string;
htmlAttributes(
options: Partial<Record<string, string | number | boolean>> | Partial<Record<"style", Styles>>,
): string;
componentHeadStyle(breakpoint: string): string;
/**
* This functions allows to define styles that can be used when rendering (see render() below)
*/
getStyles(): Record<Styles, Partial<CSSStyleDeclaration>>;
/**
* Render is the only required function in a component.
* It must return an html string.
*/
abstract render(): string;
readonly props: Props;
protected renderChildren<C extends BodyComponent<any>>(
children: Props["children"],
options?: {
props?: Props;
rawXML?: boolean;
attributes?: C["attributes"];
renderer?: (component: C) => BodyComponent["render"];
},
): string;
}
interface BodyComponentClass<A extends Attributes = {}, S extends string | never = never>
extends BodyComponentStatic<A> {
new (initialDatas?: Partial<InitialDatas<A>>): BodyComponent<A, S>;
}
interface InitialDatas<A extends Attributes = {}> {
attributes: A;
context: object;
props: Props;
globalAttributes: object;
content: string;
children: readonly MJMLComponentXML[];
}
interface Props {
content: InitialDatas["content"];
children: InitialDatas["children"];
first: boolean;
index: number;
last: boolean;
sibling: number;
nonRawSiblings: number;
}
function registerComponent<C extends BodyComponentClass<any, any>>(component: C): void;
}
declare module "mjml-validator" {
function registerDependencies<Self extends string, Parent extends string, Child extends string>(
options: Record<Parent, [Self]> | Record<Self, readonly (Child | RegExp)[]>,
): void;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment