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 intotheme/components/atoms/Typography/Link
components when thehref
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 intotheme/components/atoms/Typography/Link
components when thehref
attribute does not contain a domain.<widget>
tags are transformed intotheme/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:
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
-
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.tsimport { 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
}
`,
}); -
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 typeextensions/acme-extension/modules/wysiwyg/runtime.tsimport { 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
- Override the
theme/modules/Wysiwyg/MagentoWysiwyg/MagentoWysiwygFragment.gql
to fetch the new data needed for your widgettheme/modules/Wysiwyg/MagentoWysiwyg/MagentoWysiwygFragment.gqlfragment MagentoWysiwygFragment on MagentoWysiwyg {
childNodes
data {
dataId
... on WysiwygWidgetData {
data {
... on WidgetInvalidData {
dataId
}
... on WidgetProductPreviewData {
product {
sku
name
}
}
}
}
}
} - Use the fetched data in the
data
props in your final widget component (thetheme/path/to/ProductPreview.js
mentioned above)