Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable option to use custom mjml parser instead of default one #341

Merged
merged 5 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This plugin enables the usage of [MJML](https://mjml.io/) components inside the
<p align="center"><img src="http://grapesjs.com/img/grapesjs-mjml-demo.jpg" alt="GrapesJS" align="center"/></p>
<br/>

Supported MJML components:
Supported MJML components (using default mjml-browser parser):
`mj-mjml`
`mj-head`
`mj-body`
Expand Down Expand Up @@ -41,10 +41,12 @@ Supported MJML components:
|`blocks`|Which blocks to add|(all)|
|`block`|Add custom block options, based on block id.|`(blockId) => ({})`|
|`codeViewerTheme`|Code viewer theme.|`hopscotch`|
|`customComponents`|List of components which will be added to default one |`[]` |
|`fonts`|Custom fonts on exported HTML header [more info](https://github.com/mjmlio/mjml#inside-nodejs)|`{}`|
|`importPlaceholder`|Placeholder MJML template for the import modal|`''`|
|`imagePlaceholderSrc`|Image placeholder source|`'https://via.placeholder.com/350x250/78c5d6/fff'`|
|`i18n`|I18n object containing language [more info](https://grapesjs.com/docs/modules/I18n.html#configuration)|`{}`|
|`mjmlParser`|Custom [mjml-browser](https://www.npmjs.com/package/mjml-browser) instance. Allows to extend MJML functionality or add custom MJML components |`(input: string \| MJMLJsonObject, opt: MJMLParsingOptions) => MJMLParseResults`|
|`overwriteExport`|Overwrite default export command|`true`|
|`preMjml`|String before the MJML in export code|`''`|
|`postMjml`|String after the MJML in export code|`''`|
Expand Down Expand Up @@ -181,6 +183,39 @@ editor.on('load', () => {
});
```

### Using Independent mjml-browser Build

In case, you have your own version of MJML with custom or extended components, it is possible
to override default [mjml parser](https://github.com/mjmlio/mjml/tree/master/packages/mjml-browser)
with custom one and create custom grapesJS components.

For further info how to create MJML Component, you can
[visit components folder](https://github.com/GrapesJS/mjml/tree/master/src/components)
or you can go to [docs](https://grapesjs.com/docs/modules/Components.html#define-custom-component-type).

```ts
import 'grapesjs/dist/css/grapes.min.css'
import grapesJS from 'grapesjs'
import grapesJSMJML from 'grapesjs-mjml'
import customMjmlParser from 'custom-mjml-parser';

import customImage from 'custom/components/path'

grapesJS.init({
fromElement: true,
container: '#gjs',
plugins: [grapesJSMJML],
pluginsOpts: {
[grapesJSMJML]: {
mjmlParser: customMjmlParser,
customComponents: [
customImage,
]
}
},
});
```

## Development

Clone the repository
Expand Down
49 changes: 49 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"author": "Artur Arseniev",
"license": "BSD-3-Clause",
"dependencies": {
"@types/mjml": "^4.7.4",
"mjml-browser": "^4.13.0"
},
"babel": {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default (editor: Editor, opts: RequiredPluginOptions) => {

Commands.add(cmdGetMjmlToHtml, (ed, _, opt) => {
const mjml = Commands.run(cmdGetMjml);
return mjmlConvert(mjml, opts.fonts, opt);
return mjmlConvert(opts.mjmlParser, mjml, opts.fonts, opt);
});

openExportMjml(editor, opts, cmdOpenExport);
Expand Down
3 changes: 2 additions & 1 deletion src/components/Body.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Specs: https://documentation.mjml.io/#mj-body
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { type as typeHero } from './Hero';
import { type as typeRaw } from './Raw';
import { type as typeSection } from './Section';
Expand All @@ -8,7 +9,7 @@ import { componentsToQuery, getName, isComponentType } from './utils';

export const type = 'mj-body';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),
model: {
Expand Down
3 changes: 2 additions & 1 deletion src/components/Button.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Specs: https://documentation.mjml.io/#mj-button
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType } from './utils';
import { type as typeColumn } from './Column';
import { type as typeHero } from './Hero';

export const type = 'mj-button';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),
extend: 'link',
Expand Down
6 changes: 4 additions & 2 deletions src/components/Column.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Specs: https://documentation.mjml.io/#mj-column
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType, mjmlConvert } from './utils';
import { type as typeSection } from './Section';


export const type = 'mj-column';

export default (editor: Editor, { opt, coreMjmlModel, coreMjmlView, sandboxEl }: any) => {
export default (editor: Editor, { opt, coreMjmlModel, coreMjmlView, sandboxEl }: ComponentPluginOptions) => {
const clmPadd = opt.columnsPadding;

editor.Components.addType(type, {
Expand Down Expand Up @@ -37,7 +39,7 @@ export default (editor: Editor, { opt, coreMjmlModel, coreMjmlView, sandboxEl }:
getTemplateFromMjml() {
const mjmlTmpl = this.getMjmlTemplate();
const innerMjml = this.getInnerMjmlTemplate();
const htmlOutput = mjmlConvert(`${mjmlTmpl.start}
const htmlOutput = mjmlConvert(opt.mjmlParser, `${mjmlTmpl.start}
${innerMjml.start}${innerMjml.end}${mjmlTmpl.end}`, opt.fonts);
const html = htmlOutput.html;

Expand Down
3 changes: 2 additions & 1 deletion src/components/Divider.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Specs: https://documentation.mjml.io/#mj-divider
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType } from './utils';
import { type as typeColumn } from './Column';
import { type as typeHero } from './Hero';

export const type = 'mj-divider';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),
model: {
Expand Down
5 changes: 3 additions & 2 deletions src/components/Font.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Specs: https://documentation.mjml.io/#mj-font
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, isComponentType, mjmlConvert } from './utils';
import { type as typeHead } from './Head';

export const type = 'mj-font';

export default (editor: Editor, { opt, coreMjmlModel, coreMjmlView, sandboxEl }: any) => {
export default (editor: Editor, { opt, coreMjmlModel, coreMjmlView, sandboxEl }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),
model: {
Expand Down Expand Up @@ -40,7 +41,7 @@ export default (editor: Editor, { opt, coreMjmlModel, coreMjmlView, sandboxEl }:
getTemplateFromMjml() {
let mjmlTmpl = this.getMjmlTemplate();
let innerMjml = this.getInnerMjmlTemplate();
const htmlOutput = mjmlConvert(`${mjmlTmpl.start}
const htmlOutput = mjmlConvert(opt.mjmlParser, `${mjmlTmpl.start}
${innerMjml.start}${innerMjml.end}${mjmlTmpl.end}`, opt.fonts);
let html = htmlOutput.html;
let start = html.indexOf('<head>') + 6;
Expand Down
3 changes: 2 additions & 1 deletion src/components/Group.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Specs: https://documentation.mjml.io/#mj-group
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType } from './utils';
import { type as typeSection } from './Section';
import { type as typeColumn } from './Column';

export const type = 'mj-group';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),
model: {
Expand Down
3 changes: 2 additions & 1 deletion src/components/Hero.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Specs: https://documentation.mjml.io/#mj-hero
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType } from './utils';
import { type as typeBody } from './Body';
import { type as typeText } from './Text';
Expand All @@ -12,7 +13,7 @@ import { type as typeSpacer } from './Spacer';

export const type = 'mj-hero';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),
model: {
Expand Down
3 changes: 2 additions & 1 deletion src/components/Image.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// Specs: https://documentation.mjml.io/#mj-image
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType } from './utils';
import { type as typeSection } from './Section';
import { type as typeColumn } from './Column';
import { type as typeHero } from './Hero';

export const type = 'mj-image';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),
extend: 'image',
Expand Down
5 changes: 3 additions & 2 deletions src/components/NavBar.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// Specs https://documentation.mjml.io/#mj-navbar
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType, mjmlConvert } from './utils';
import { type as typeColumn } from './Column';
import { type as typeHero } from './Hero';
import { type as typeNavBarLink } from './NavBarLink';

export const type = 'mj-navbar';

export default (editor: Editor, { opt, coreMjmlModel, coreMjmlView, sandboxEl }: any) => {
export default (editor: Editor, { opt, coreMjmlModel, coreMjmlView, sandboxEl }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),
model: {
Expand Down Expand Up @@ -51,7 +52,7 @@ export default (editor: Editor, { opt, coreMjmlModel, coreMjmlView, sandboxEl }:
getTemplateFromMjml() {
const mjmlTmpl = this.getMjmlTemplate();
const innerMjml = this.getInnerMjmlTemplate();
const htmlOutput = mjmlConvert(`${mjmlTmpl.start}
const htmlOutput = mjmlConvert(opt.mjmlParser, `${mjmlTmpl.start}
${innerMjml.start}${innerMjml.end}${mjmlTmpl.end}`, opt.fonts);
const html = htmlOutput.html;

Expand Down
3 changes: 2 additions & 1 deletion src/components/NavBarLink.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Specs: https://documentation.mjml.io/#mj-navbar-link
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType } from './utils';
import { type as typeNavBar } from './NavBar';

export const type = 'mj-navbar-link';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),
extend: 'link',
Expand Down
3 changes: 2 additions & 1 deletion src/components/Raw.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Specs: https://documentation.mjml.io/#mj-raw
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType } from './utils';
import { type as typeBody } from './Body';
import { type as typeHead } from './Head';

export const type = 'mj-raw';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),
model: {
Expand Down
3 changes: 2 additions & 1 deletion src/components/Section.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Specs: https://documentation.mjml.io/#mj-section
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType } from './utils';
import { type as typeBody } from './Body';
import { type as typeWrapper } from './Wrapper';
Expand All @@ -8,7 +9,7 @@ import { type as typeGroup } from './Group';

export const type = 'mj-section';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),

Expand Down
3 changes: 2 additions & 1 deletion src/components/Social.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// Specs: https://documentation.mjml.io/#mjml-social
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType } from './utils';
import { type as typeColumn } from './Column';
import { type as typeHero } from './Hero';
import { type as typeSocialElement } from './SocialElement';

export const type = 'mj-social';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),

Expand Down
3 changes: 2 additions & 1 deletion src/components/SocialElement.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Specs: https://documentation.mjml.io/#mjml-social
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType } from './utils';
import { type as typeSocial } from './Social';

export const type = 'mj-social-element';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),

Expand Down
3 changes: 2 additions & 1 deletion src/components/Spacer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Specs: https://documentation.mjml.io/#mjml-spacer
import type { Editor } from 'grapesjs';
import { ComponentPluginOptions } from '.';
import { componentsToQuery, getName, isComponentType } from './utils';
import { type as typeColumn } from './Column';
import { type as typeHero } from './Hero';

export const type = 'mj-spacer';

export default (editor: Editor, { coreMjmlModel, coreMjmlView }: any) => {
export default (editor: Editor, { coreMjmlModel, coreMjmlView }: ComponentPluginOptions) => {
editor.Components.addType(type, {
isComponent: isComponentType(type),

Expand Down
Loading
Loading