Skip to main content
Version: 3.x

Customize WYSIWYG Platform

Since version 3.4

In this guide, you will learn the different WYSIWYG implementations available on Front-Commerce and how to customize them.

If you want to learn how the core WYSIWYG component works instead, please refer to Display WYSIWYG content.

Each platform has a specific type of WYSIWYG. This allows to change how your content is rendered depending on its origin. For instance, a content from WordPress might
have some specific media shortcodes while Magento will have some widgets to
display a category name. In the following section you will learn about the one
implemented in Front-Commerce:

Definitions:

  • a shortcode is a specific string structure that is meant to be transformed into actual content
  • a transform is a function that replaces an HTML tag with a React Component

DefaultWysiwyg

The goal of this WYSIWYG type is to remain as simple as possible. It is not meant to fetch data from additional services.

No shortcodes

Default transforms

  • <a> tags are transformed into theme/components/atoms/Typography/Link components when the href attribute does not contain a domain.

MagentoWysiwyg

The MagentoWyswiyg's goal is to support all the default features in Magento 1 & 2. If you notice that some features are missing, please contact us and we'll look into implementing it.

Supported shortcodes

  • {% raw %}{{media url="*"}}{% endraw %}
  • {% raw %}{{store url="*"}}{% endraw %}
  • {% raw %}{{widget type="*" attribute="value"}}{% endraw %}

Default transforms

  • <a> tags are transformed into theme/components/atoms/Typography/Link components when the href attribute does not contain a domain.
  • <widget> tags are transformed into theme/modules/Wysiwyg/MagentoWysiwyg/Widget/Widget.js components. However, you shouldn't write a <widget> tag manually. It comes from the {% raw %}{{widget}}{% endraw %} shortcode.
  • <style> tags are transformed to support Magento's Page Builder format. The #html-body selector is replaced with the <Wysiwyg> root selector. See WYSIWYG dynamic styles for details.

Add a custom Magento Widget

Custom widgets will be automatically parsed. However, you will still need to map the widget's type to custom React Components. If you don't, they will be ignored and nothing will be rendered in the final page.

To do so, please override theme/modules/Wysiwyg/MagentoWysiwyg/Widget/getWidgetComponent.js in your own theme.

Now, within your newly created getWidgetComponent.js file, you will be able to add your own behavior. For instance, if you've created a widget in Magento that uses the type acme/product-preview, you will need to update the Widget.js
file:

theme/modules/Wysiwyg/MagentoWysiwyg/Widget/getWidgetComponent.js
import { Suspense, lazy } from "react";
import Spinner from "theme/components/atoms/Spinner";
const ProductPreview = lazy(() => import("theme/path/to/ProductPreview.js"));

function ProductPreviewLazy(props) {
return (
<Suspense fallback={null}>
<ProductPreview {...props} />
</Suspense>
);
}

const defaultWidgetsMap = {
"acme/product-preview": ProductPreviewLazy,
};

// ... rest of the file is intact

If you restart your application, you will notice that the new widget component is displayed. Hurray!

However, in most cases, you will need to fetch data to display all the needed information in your widget. For instance, if the widget is {% raw %}{{ widget type="acme/product-preview" sku="VSK12" }}{% endraw %} you will want to fetch the product associated with the given SKU.

Register your widget type at the GraphQL level

  1. First make sure that your dependencies are up to date in your GraphQL module, and register a new WidgetData type in your schema

    extensions/acme-extension/modules/wysiwyg/index.ts
    import { createGraphQLModule } from "@front-commerce/core/graphql";

    export default createGraphQLModule({
    namespace: "ACME/Cms",
    loadRuntime: () => import("./runtime"),
    dependencies: [
    "Magento2/Wysiwyg", // ensure that Widget related features are available
    "Magento2/Catalog/Product", // ensure that you can fetch a product in your Wysiwyg data
    ],
    typeDefs: /* GraphQL */ `
    type WidgetProductPreviewData implements WidgetData {
    dataId: ID
    product: Product
    }
    `,
    });
  2. After that you can setup the resolvers to tell GraphQL how to fetch the product field and register the widget type from Magento and associate it with the GraphQL type

    extensions/acme-extension/modules/wysiwyg/runtime.ts
    import { createGraphQLRuntime } from "@front-commerce/core/graphql";

    export default createGraphQLRuntime({
    resolvers: {
    WidgetProductPreviewData: {
    product: ({ node }, _, { loaders }) => {
    const productSkuAttribute = node.attrs.find(
    ({ name }) => name === "sku"
    );
    if (!productSkuAttribute) {
    return null;
    }
    return loaders.Product.load(productSkuAttribute.value);
    },
    },
    },
    contextEnhancer: ({ loaders }) => {
    loaders.MagentoWidget.registerWidgetType(
    // the tag name in your HTML
    "acme/product-preview",
    // The associated GraphQL type name
    "WidgetProductPreviewData"
    );
    },
    });

Get the data in your component

  1. Override the theme/modules/Wysiwyg/MagentoWysiwyg/MagentoWysiwygFragment.gql to fetch the new data needed for your widget
    theme/modules/Wysiwyg/MagentoWysiwyg/MagentoWysiwygFragment.gql
    fragment MagentoWysiwygFragment on MagentoWysiwyg {
    childNodes
    data {
    dataId
    ... on WysiwygWidgetData {
    data {
    ... on WidgetInvalidData {
    dataId
    }
    ... on WidgetProductPreviewData {
    product {
    sku
    name
    }
    }
    }
    }
    }
    }
  2. Use the fetched data in the data props in your final widget component (the theme/path/to/ProductPreview.js mentioned above)