Add mjml-core package with initial typings (#49882)

* Add mjml-core package with initial typings

* refactoring mjml and mjml-core

* prettier

* fix linting

* revert export default

* Address PR suggestion and change maintainers

* Address comment about type names
This commit is contained in:
Ian Edington
2020-12-22 15:55:36 -05:00
committed by GitHub
parent 9bc42ea5d4
commit c0a8b63794
6 changed files with 348 additions and 50 deletions

265
types/mjml-core/index.d.ts vendored Normal file
View File

@@ -0,0 +1,265 @@
// Type definitions for mjml-core 4.7
// Project: https://mjml.io
// Definitions by: Ian Edington <https://github.com/IanEdington>
// Ryan Burr <https://github.com/ryanburr>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/**
* The main parser for MJML.
* This version doesn't contain any of the core components registered in the 'mjml' package.
*/
export default function mjml2html(input: string | MJMLJsonObject, options?: MJMLParsingOptions): MJMLParseResults;
/**
* Options passed as an object to the mjml2html function
*
* https://documentation.mjml.io/#inside-node-js
*/
export interface MJMLParsingOptions {
/**
* Default fonts imported in the HTML rendered by HTML
* ie. { 'Open Sans': 'https://fonts.googleapis.com/css?family=Open+Sans:300,400,500,700' }
*
* default: @see https://github.com/mjmlio/mjml/blob/master/packages/mjml-core/src/index.js
*/
fonts?: { [key: string]: string };
/**
* Option to keep comments in the HTML output
* default: true
*/
keepComments?: boolean;
/**
* @deprecated use js-beautify directly after processing the MJML
*
* Option to beautify the HTML output
* default: false
*/
beautify?: boolean;
/**
* @deprecated use html-minifier directly after processing the MJML
*
* Option to minify the HTML output
*
* default: false
*/
minify?: boolean;
/**
* @deprecated @see minify
*
* Options for html minifier, see mjml-cli documentation for more info
* Passed directly to html-minifier as options
*
* default: @see htmlMinify usage in mjml-core/src/index.js
*/
minifyOptions?: MJMLMinifyOptions;
/**
* How to validate your MJML
*
* skip: your document is rendered without going through validation
* soft: your document is going through validation and is rendered, even if it has errors
* strict: your document is going through validation and is not rendered if it has any error
*
* default: soft
*/
validationLevel?: 'strict' | 'soft' | 'skip';
/**
* Full path of the specified file to use when resolving paths from mj-include components
* default: '.'
*/
filePath?: string;
/**
* The path or directory of the .mjmlconfig file
* default: process.cwd()
*/
mjmlConfigPath?: string;
/**
* Use the config attribute defined in the .mjmlconfig file.
* The config passed into mjml2html overrides the .mjmlconfig.
* default: false
*/
useMjmlConfigOptions?: boolean;
/**
* optional setting when inlining css, see mjml-cli documentation for more info
*/
juicePreserveTags?: { [index: string]: { start: string; end: string } };
juiceOptions?: any;
/**
* undocumented
* a function returning html skeleton
* default: see mjml-core/src/helpers/skeleton.js
*/
skeleton?: string | (() => string);
actualPath?: string;
/**
* undocumented
* ignore mj-include elements
* default: false
*/
ignoreIncludes?: any;
/**
* see mjml-parser-xml
*/
preprocessors?: Array<((xml: string) => string)>;
}
export interface MJMLMinifyOptions {
collapseWhitespace?: boolean;
minifyCSS?: boolean;
removeEmptyAttributes?: boolean;
}
export interface MJMLParseResults {
html: string;
json: MJMLJsonObject;
errors: MJMLParseError[];
}
export interface MJMLParseError {
line: number;
message: string;
tagName: string;
formattedMessage: string;
}
export type MJMLJsonObject = MJMLJsonWithChildren | MJMLJsonWithContent | MJMLJsonSelfClosingTag;
export interface MJMLJsonWithChildren {
tagName: string;
attributes: object;
children: MJMLJsonObject[];
}
export interface MJMLJsonWithContent {
tagName: string;
attributes: object;
content: string;
}
export interface MJMLJsonSelfClosingTag {
tagName: string;
attributes: object;
}
/**
* An map of elements to handling component available to be used in mjml
*/
export const components: { [componentName: string]: Component | undefined };
/**
* Registers a component for use in mjml
*/
export function registerComponent(ComponentClass: typeof Component): void;
export abstract class BodyComponent extends Component {
constructor(initialData: unknown);
getStyles(): {};
/**
* takes a style attribute and tries to parse it's value
* ie. padding="1 2 3 4"
* getShorthandAttrValue("padding","left") => 1
*/
getShorthandAttrValue(attribute: any, direction: any): number;
getShorthandBorderValue(direction: any): number;
getBoxWidths(): {
totalWidth: number;
borders: number;
paddings: number;
box: number;
};
htmlAttributes(attributes: any): any;
styles(styles: any): any;
renderChildren(
children?: [],
options?: {
props?: Component['props'];
renderer?: (component: Component) => any;
attributes?: Record<string, string>;
rawXML?: boolean;
},
): string;
}
export abstract class HeadComponent extends Component {
constructor(initialData: unknown);
handlerChildren(): any;
render(): string;
}
export abstract class Component {
static getTagName(): any;
static isRawElement(): boolean;
static defaultAttributes: { [prop: string]: string | undefined };
props: {
children: any;
/** is first child */
first: boolean;
index: number;
/** is last child */
last: boolean;
/** number of sibling elements */
sibling: number;
nonRawSiblings: number;
};
attributes: Record<string, string>;
context: any;
constructor(initialData: unknown);
getChildContext(): any;
getAttribute(name: any): any;
getContent(): any;
/**
* Use if you want the CSS to be registered once
*
* @returns string css style string
*/
headStyle(breakpoint: number): string;
/**
* Use if you need custom styles for every instance of a component
*
* @returns string css style string
*/
componentHeadStyle(breakpoint: number): string;
/**
* If you want to return mjml from a component, it needs to be processed first, ie.
*
* render() {
* return this.renderMJML('<mj-text>hello world</mj-text>');
* }
*/
renderMJML(mjml: string, options?: {}): string;
/**
* Expected to return an html string
* @see renderMJML for returning an mjml string
*/
abstract render(): string;
}
export function suffixCssClasses(classes: string, suffix: string): string;

View File

@@ -0,0 +1,42 @@
import mjml2html, { BodyComponent, HeadComponent, Component, registerComponent } from 'mjml-core';
const simple_test = mjml2html('<mjml>');
const html = simple_test.html;
const errors = simple_test.errors;
let formattedMessage = errors[0].formattedMessage;
formattedMessage = 'force string test';
const minimal_opts_test = mjml2html('<mjml>', { beautify: true });
const validation_level_test = mjml2html('<mjml>', { validationLevel: 'strict' });
const filePath_test = mjml2html('<mjml>', { filePath: '.' });
const jsonObject = { tagName: 'mjml', attributes: { width: '100px' }, content: 'test content' };
const jsonObject_test = mjml2html(jsonObject);
const minify_opts_test = mjml2html('<mjml', { minifyOptions: { minifyCSS: true } });
const minify_opts_all_test = mjml2html('<mjml', {
minifyOptions: { minifyCSS: true, collapseWhitespace: true, removeEmptyAttributes: true },
});
class NewBodyComponent extends BodyComponent {
render() {
return this.renderMJML('<mj-text>hello world</mj-text');
}
}
class MjBreakpoint extends HeadComponent {
static endingTag = true;
static allowedAttributes = {
width: 'unit(px)',
};
handler() {
const { add } = this.context;
add('breakpoint', this.getAttribute('width'));
}
}
registerComponent(MjBreakpoint);
registerComponent(NewBodyComponent);

View File

@@ -0,0 +1,23 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"mjml-core-tests.ts"
]
}

View File

@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }

47
types/mjml/index.d.ts vendored
View File

@@ -1,46 +1,11 @@
// Type definitions for mjml 4.0
// Type definitions for mjml 4.7
// Project: https://github.com/mjmlio/mjml, https://mjml.io
// Definitions by: aahoughton <https://github.com/aahoughton>
// marpstar <https://github.com/marpstar>
// eiskalteschatten <https://github.com/eiskalteschatten>
// emrah88 <https://github.com/emrah88>
// Definitions by: aahoughton <https://github.com/aahoughton>
// marpstar <https://github.com/marpstar>
// emrah88 <https://github.com/emrah88>
// IanEdington <https://github.com/IanEdington>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
interface MJMLParsingOpts {
fonts?: { [key: string]: string; };
keepComments?: boolean;
beautify?: boolean;
minify?: boolean;
validationLevel?: 'strict' | 'soft' | 'skip';
filePath?: string;
minifyOptions?: MJMLMinifyOptions;
}
interface MJMLParseError {
line: number;
message: string;
tagName: string;
formattedMessage: string;
}
interface MJMLParseResults {
html: string;
errors: MJMLParseError[];
}
interface MJMLJsonObject {
tagName: string;
attributes: object;
children?: MJMLJsonObject[];
content?: string;
}
interface MJMLMinifyOptions {
collapseWhitespace?: boolean;
minifyCSS?: boolean;
removeEmptyAttributes?: boolean;
}
declare function mjml2html(inp: string | MJMLJsonObject, opts?: MJMLParsingOpts): MJMLParseResults;
import mjml2html from 'mjml-core';
export = mjml2html;

View File

@@ -1,17 +1,19 @@
import mjml2html = require("mjml");
import mjml2html = require('mjml');
const simple_test = mjml2html("<mjml>");
const simple_test = mjml2html('<mjml>');
const html = simple_test.html;
const errors = simple_test.errors;
let formattedMessage = errors[0].formattedMessage;
formattedMessage = "force string test";
formattedMessage = 'force string test';
const minimal_opts_test = mjml2html("<mjml>", {beautify: true});
const validation_level_test = mjml2html("<mjml>", {validationLevel: "strict"});
const filePath_test = mjml2html("<mjml>", {filePath: "."});
const minimal_opts_test = mjml2html('<mjml>', { beautify: true });
const validation_level_test = mjml2html('<mjml>', { validationLevel: 'strict' });
const filePath_test = mjml2html('<mjml>', { filePath: '.' });
const jsonObject = {tagName: "mjml", attributes: {width: "100px"}, content: "test content"};
const jsonObject = { tagName: 'mjml', attributes: { width: '100px' }, content: 'test content' };
const jsonObject_test = mjml2html(jsonObject);
const minify_opts_test = mjml2html("<mjml", {minifyOptions: {minifyCSS: true}});
const minify_opts_all_test = mjml2html("<mjml", {minifyOptions: {minifyCSS: true, collapseWhitespace: true, removeEmptyAttributes: true}});
const minify_opts_test = mjml2html('<mjml', { minifyOptions: { minifyCSS: true } });
const minify_opts_all_test = mjml2html('<mjml', {
minifyOptions: { minifyCSS: true, collapseWhitespace: true, removeEmptyAttributes: true },
});