-
-
Notifications
You must be signed in to change notification settings - Fork 733
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
How to export the page as html #42
Comments
Unfortunately, this is currently out of our scope. For now, you can only serialize the editor state into JSON, and pass the JSON to the editor to reload the state. If you still need to export to HTML, you'll likely need to fiddle around with the JSON output and create your own HTML code generator. |
You could also build a separate version of your Editor and user components that render the editor state as "read only" and then select the |
The Quill editor runs into similar problems when trying to render static markup. Luckily, React saves the day here with the ReactDOMServer.renderToStaticMarkup() method. |
@Enva2712 @jasonadkison Can you guys provide some sample code, please? It will be very helpful for this key common requirement. |
Sure, here's an example function that takes the editor's exported state and returns markup. It depends on the user components that the editor was given to produce the state. import ReactDOMServer from 'react-dom/server';
import { Editor, Frame } from '@craftjs/core';
import userComponents from './user-components';
function renderMarkup(JSONStateString) {
return ReactDOMServer.renderToStaticMarkup(<Editor enabled={false} resolver={userComponents}>
<Frame json={JSONStateString} />
</Editor>);
} |
@Enva2712 I have tried this but not lucks using the official landing page example, it returns an empty string {
"base64Str": "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",
"json": `"{"canvas-ROOT":{"type":{"resolvedName":"Container"},"isCanvas":true,"props":{"flexDirection":"column","alignItems":"flex-start","justifyContent":"flex-start","fillSpace":"no","padding":["40","40","40","40"],"margin":["0","0","0","0"],"background":{"r":255,"g":255,"b":255,"a":1},"color":{"r":0,"g":0,"b":0,"a":1},"shadow":0,"radius":0,"width":"800px","height":"auto"},"parent":null,"nodes":["canvas-bevrghtgq"],"custom":{"displayName":"App"},"displayName":"Container"},"canvas-bevrghtgq":{"type":{"resolvedName":"Container"},"isCanvas":true,"props":{"flexDirection":"row","alignItems":"flex-start","justifyContent":"flex-start","fillSpace":"no","padding":["40","40","40","40"],"margin":["0","0","40","0"],"background":{"r":255,"g":255,"b":255,"a":1},"color":{"r":0,"g":0,"b":0,"a":1},"shadow":0,"radius":0,"width":"100%","height":"auto"},"parent":"canvas-ROOT","nodes":["canvas-dWPqjcHaB","canvas-QtJ8b6-Eg"],"custom":{"displayName":"Introduction"},"displayName":"Container"},"canvas-dWPqjcHaB":{"type":{"resolvedName":"Container"},"isCanvas":true,"props":{"flexDirection":"column","alignItems":"flex-start","justifyContent":"flex-start","fillSpace":"no","padding":["0","20","0","20"],"margin":["0","0","0","0"],"background":{"r":255,"g":255,"b":255,"a":1},"color":{"r":0,"g":0,"b":0,"a":1},"shadow":0,"radius":0,"width":"40%","height":"100%"},"parent":"canvas-bevrghtgq","nodes":["node-XTYy5V-6ur"],"custom":{"displayName":"Heading"},"displayName":"Container"},"canvas-QtJ8b6-Eg":{"type":{"resolvedName":"Container"},"isCanvas":true,"props":{"flexDirection":"column","alignItems":"flex-start","justifyContent":"flex-start","fillSpace":"no","padding":["0","20","0","20"],"margin":["0","0","0","0"],"background":{"r":255,"g":255,"b":255,"a":1},"color":{"r":0,"g":0,"b":0,"a":1},"shadow":0,"radius":0,"width":"60%","height":"100%"},"parent":"canvas-bevrghtgq","nodes":[],"custom":{"displayName":"Description"},"displayName":"Container"},"canvas-l949P_Ck0c":{"type":{"resolvedName":"Container"},"isCanvas":true,"props":{"flexDirection":"row","alignItems":"flex-start","justifyContent":"flex-start","fillSpace":"no","padding":["0","0","0","0"],"margin":["30","0","0","0"],"background":{"r":76,"g":78,"b":78,"a":0},"color":{"r":0,"g":0,"b":0,"a":1},"shadow":0,"radius":0,"width":"100%","height":"auto"},"parent":"canvas-0KWCrWNmn","nodes":["canvas-hzB7Zr0Vvk","canvas-3Q32LXSUcg"],"custom":{"displayName":"Content"},"displayName":"Container"},"node-XTYy5V-6ur":{"type":{"resolvedName":"Text"},"props":{"fontSize":"23","textAlign":"left","fontWeight":"400","color":{"r":92,"g":90,"b":90,"a":1},"margin":[0,0,0,0],"shadow":0,"text":"Jeff is awesomeddsadjhiojoijoijioja"},"parent":"canvas-dWPqjcHaB","custom":{"displayName":"Text"},"displayName":"Text"},"canvas-XSWv35297I":{"type":{"resolvedName":"Container"},"isCanvas":true,"props":{"flexDirection":"column","alignItems":"flex-start","justifyContent":"flex-start","fillSpace":"yes","padding":["0","0","0","20"],"margin":["0","0","0","0"],"background":{"r":0,"g":0,"b":0,"a":0},"color":{"r":0,"g":0,"b":0,"a":1},"shadow":0,"radius":0,"width":"55%","height":"100%"},"parent":"canvas-9n2A5pEPX","nodes":["node-tvZsTGgH-w","node-0MBnHeqPpa"],"custom":{"displayName":"Content"},"displayName":"Container"},"node-tuogLV8hNj":{"type":{"resolvedName":"Text"},"props":{"fontSize":"14","textAlign":"left","fontWeight":"400","color":{"r":92,"g":90,"b":90,"a":1},"margin":[0,0,0,0],"shadow":0,"text":"Govern what goes in and out of your components"},"parent":"canvas-B0C7EBoLM","custom":{"displayName":"Text"},"displayName":"Text"},"canvas-hzB7Zr0Vvk":{"type":{"resolvedName":"Container"},"isCanvas":true,"props":{"flexDirection":"row","alignItems":"flex-start","justifyContent":"flex-start","fillSpace":"no","padding":["0","20","0","0"],"margin":["0","0","0","0"],"background":{"r":0,"g":0,"b":0,"a":0},"color":{"r":0,"g":0,"b":0,"a":1},"shadow":0,"radius":0,"width":"45%","height":"auto"},"parent":"canvas-l949P_Ck0c","nodes":["node-ccyOvn51tL"],"custom":{"displayName":"Left"},"displayName":"Container"},"canvas-3Q32LXSUcg":{"type":{"resolvedName":"Container"},"isCanvas":true,"props":{"flexDirection":"column","alignItems":"flex-start","justifyContent":"flex-start","fillSpace":"no","padding":["0","0","0","20"],"margin":["0","0","0","0"],"background":{"r":0,"g":0,"b":0,"a":0},"color":{"r":0,"g":0,"b":0,"a":1},"shadow":0,"radius":0,"width":"55%","height":"auto"},"parent":"canvas-l949P_Ck0c","nodes":["node-RlIM3yp8Uu","node--RA_SY_JEt"],"custom":{"displayName":"Right"},"displayName":"Container"},"node-tvZsTGgH-w":{"type":{"resolvedName":"Text"},"props":{"fontSize":"20","textAlign":"left","fontWeight":"500","color":{"r":"255","g":"255","b":"255","a":"1"},"margin":["0","0","18","0"],"shadow":0,"text":"Design complex components"},"parent":"canvas-XSWv35297I","custom":{"displayName":"Text"},"displayName":"Text"},"node-0MBnHeqPpa":{"type":{"resolvedName":"Text"},"props":{"fontSize":"14","textAlign":"left","fontWeight":"400","color":{"r":"255","g":"255","b":"255","a":"0.8"},"margin":[0,0,0,0],"shadow":0,"text":"You can define areas within your React component which users can drop other components into. <br/><br />You can even design how the component should be edited — content editable, drag to resize, have inputs on toolbars — anything really."},"parent":"canvas-XSWv35297I","custom":{"displayName":"Text"},"displayName":"Text"},"node-ccyOvn51tL":{"type":{"resolvedName":"Custom1"},"props":{"flexDirection":"column","alignItems":"flex-start","justifyContent":"flex-start","fillSpace":"no","padding":["20","20","20","20"],"margin":["0","0","0","0"],"background":{"r":119,"g":219,"b":165,"a":1},"color":{"r":0,"g":0,"b":0,"a":1},"shadow":40,"radius":0,"width":"100%","height":"auto"},"parent":"canvas-hzB7Zr0Vvk","_childCanvas":{"wow":"canvas-rsWrTbsnRt"},"custom":{"displayName":"Custom 1"},"displayName":"Custom 1"},"node-RlIM3yp8Uu":{"type":{"resolvedName":"Custom2"},"props":{"flexDirection":"row","alignItems":"center","justifyContent":"flex-start","fillSpace":"no","padding":["0","0","0","20"],"margin":["0","0","0","0"],"background":{"r":108,"g":126,"b":131,"a":1},"color":{"r":0,"g":0,"b":0,"a":1},"shadow":40,"radius":0,"width":"100%","height":"125px"},"parent":"canvas-3Q32LXSUcg","_childCanvas":{"wow":"canvas-Ad114XWFph"},"custom":{},"displayName":"Custom 2"},"node--RA_SY_JEt":{"type":{"resolvedName":"Custom3"},"props":{"flexDirection":"column","alignItems":"flex-start","justifyContent":"flex-start","fillSpace":"no","padding":["20","20","20","20"],"margin":["20","0","0","0"],"background":{"r":134,"g":187,"b":201,"a":1},"color":{"r":0,"g":0,"b":0,"a":1},"shadow":40,"radius":0,"width":"100%","height":"auto"},"parent":"canvas-3Q32LXSUcg","_childCanvas":{"wow":"canvas-NMH3A38bMs"},"custom":{},"displayName":"Custom 3"},"canvas-rsWrTbsnRt":{"type":{"resolvedName":"OnlyButtons"},"isCanvas":true,"props":{"children":[{"type":{"resolvedName":"Button"},"props":{}},{"type":{"resolvedName":"Button"},"props":{"buttonStyle":"outline","color":{"r":255,"g":255,"b":255,"a":1}}}],"className":"w-full mt-5"},"parent":"node-ccyOvn51tL","nodes":["node-EUPfH162gd","node-71k8cGarve"],"custom":{},"displayName":"OnlyButtons"},"canvas-Ad114XWFph":{"type":{"resolvedName":"Custom2VideoDrop"},"isCanvas":true,"props":{"children":[{"type":{"resolvedName":"Video"},"props":{}}],"className":"flex-1 ml-5 h-full"},"parent":"node-RlIM3yp8Uu","nodes":["node-IV4oYPDURM"],"custom":{},"displayName":"Custom2VideoDrop"},"canvas-NMH3A38bMs":{"type":{"resolvedName":"Custom3BtnDrop"},"isCanvas":true,"props":{"children":[{"type":{"resolvedName":"Button"},"props":{"background":{"r":184,"g":247,"b":247,"a":1}}}],"className":"w-full h-full"},"parent":"node--RA_SY_JEt","nodes":["node-sQTl2cXS4P"],"custom":{},"displayName":"Custom3BtnDrop"},"node-EUPfH162gd":{"type":{"resolvedName":"Button"},"props":{"background":{"r":255,"g":255,"b":255,"a":0.5},"color":{"r":92,"g":90,"b":90,"a":1},"buttonStyle":"full","text":"Button","margin":["5","0","5","0"],"textComponent":{"fontSize":"15","textAlign":"center","fontWeight":"500","color":{"r":92,"g":90,"b":90,"a":1},"margin":[0,0,0,0],"shadow":0,"text":"Text"}},"parent":"canvas-rsWrTbsnRt","custom":{},"displayName":"Button"},"node-71k8cGarve":{"type":{"resolvedName":"Button"},"props":{"background":{"r":255,"g":255,"b":255,"a":0.5},"color":{"r":255,"g":255,"b":255,"a":1},"buttonStyle":"outline","text":"Button","margin":["5","0","5","0"],"textComponent":{"fontSize":"15","textAlign":"center","fontWeight":"500","color":{"r":92,"g":90,"b":90,"a":1},"margin":[0,0,0,0],"shadow":0,"text":"Text"}},"parent":"canvas-rsWrTbsnRt","custom":{},"displayName":"Button"},"node-IV4oYPDURM":{"type":{"resolvedName":"Video"},"props":{"videoId":"IwzUs1IMdyQ"},"parent":"canvas-Ad114XWFph","custom":{},"displayName":"Video"},"node-sQTl2cXS4P":{"type":{"resolvedName":"Button"},"props":{"background":{"r":184,"g":247,"b":247,"a":1},"color":{"r":92,"g":90,"b":90,"a":1},"buttonStyle":"full","text":"Button","margin":["5","0","5","0"],"textComponent":{"fontSize":"15","textAlign":"center","fontWeight":"500","color":{"r":92,"g":90,"b":90,"a":1},"margin":[0,0,0,0],"shadow":0,"text":"Text"}},"parent":"canvas-NMH3A38bMs","custom":{},"displayName":"Button"}}"`
} |
this works fine with me function CraftEditor = () => {
const ref = useRef(null)
return (
<Editor>
<div ref={ref}>
<Frame>
<Canvas>
</Canvas>
</Frame>
</div>
</Editor>
)
} const html = ref.current.firstChild.firstChild.outerHTML |
Do you maybe have a more elaborate example? Like how would I be able to access the ref from a different component? (like an export button) |
@khusseini if it's a child pass it as a prop |
Does anyone have any working methods for generating HTML strings on the server? I tried |
Alright, I have a working method to take some serialized nodes, and generate HTML. Our use case is that we need to render PDF's using an external service that takes HTML as an input. The main issue is the use of Replacement import { NodeId, Element as CraftJsElement } from '@craftjs/core';
import React from 'react';
export type Element<T extends React.ElementType> = {
id?: NodeId;
is?: T;
custom?: Record<string, any>;
children?: React.ReactNode;
canvas?: boolean;
isSSR?: boolean;
} & React.ComponentProps<T>;
export function Element<T extends React.ElementType>({
is,
id,
children,
isSSR,
...elementProps
}: Element<T>): JSX.Element {
return isSSR ? (
React.createElement(is, elementProps, children)
) : (
<CraftJsElement id={id} {...elementProps}>
{children}
</CraftJsElement>
);
} Util functions export type SerializedNodeWithId = SerializedNode & { id: string };
export const deserializeNodes = (nodes: SerializedNodes): SerializedNodeWithId[] => {
return Object.entries(nodes).map(([id, val]) => ({ id, ...val }));
};
export const getNodeById = (nodes: SerializedNodeWithId[], id: NodeId) => {
return _.find(nodes, (node) => node.id === id);
};
export function getDescendants(
nodes: SerializedNodeWithId[],
id: NodeId,
deep = false,
includeOnly?: 'linkedNodes' | 'childNodes',
): SerializedNodeWithId[] {
function appendChildNode(id: NodeId, descendants: NodeId[] = [], depth: number = 0) {
if (deep || (!deep && depth === 0)) {
const node = getNodeById(nodes, id);
if (!node) {
return descendants;
}
if (includeOnly !== 'childNodes') {
// Include linkedNodes if any
const linkedNodes = node.linkedNodes;
_.each(linkedNodes, (nodeId) => {
descendants.push(nodeId);
descendants = appendChildNode(nodeId, descendants, depth + 1);
});
}
if (includeOnly !== 'linkedNodes') {
const childNodes = node.nodes;
_.each(childNodes, (nodeId) => {
descendants.push(nodeId);
descendants = appendChildNode(nodeId, descendants, depth + 1);
});
}
return descendants;
}
return descendants;
}
return _.compact(_.map(appendChildNode(id), (nid) => getNodeById(nodes, nid)));
}
export const renderNode = (
nodes: SerializedNodeWithId[],
resolver: Resolver,
nodeId: NodeId,
): JSX.Element => {
const node = getNodeById(nodes, nodeId);
if (!node) {
throw new Error(`Could not find node with id ${nodeId}`);
}
const resolvedComponent = _.get(resolver, (node.type as any).resolvedName);
const descendants = getDescendants(nodes, nodeId);
const children = _.map(descendants, (descendant) => renderNode(nodes, resolver, descendant.id));
return (
<NodeProvider key={node.id} id={node.id}>
{React.createElement(resolvedComponent, { ...node.props, isSSR: true }, children)}
</NodeProvider>
);
};
export const renderNodesToJSX = (
nodes: SerializedNodeWithId[],
resolver: Resolver,
nodeId: NodeId,
): JSX.Element => {
return (
<Editor enabled={false} resolver={resolver}>
{renderNode(nodes, resolver, nodeId)}
</Editor>
);
}; You can use it like so: const nodes = deserializeNodes(serializedNodesFromDb);
const jsx = renderNodesToJSX(nodes, RESOLVERS, 'ROOT');
const html = ReactDOMServer.renderToString(jsx); I hope this helps anyone looking to render out a non-editable static representation of a CraftJS node tree. |
@dbousamra can you create an example in codesanbox? |
i think you forget getDescendants function from where? |
I can, but not right now. I'll do after work.
Thanks. I've added it |
I'm facing this problem, and i foune your answer here if you can provide a sandbox that would be very helpful. |
I have tackled this issue by just creating another page which reads the serialized nodes and renders the tree.
|
https://codesandbox.io/s/keen-fast-m3y2z?file=/src/index.tsx |
I believe this is so trivial that it should be core feature @dbousamra any change we can open a new PR? |
this is not working with js project facing problem with lodash |
|
I have my project in jsx and when I tried to add this file I face lodash error |
Is there a solution for this? I've been stuck for 3 days with no progress, and I'm in the last stage of my project timeline, can't switch everything now : ( |
@derit Any way there can be a jsx implementation, I have tried for a js workaround, but it fails with error "Cannot read id of null" at renderTostaticMarkup call
|
This is slightly confusing. Did you create new readonly versions (TextReadOnly, ButtonReadOnly, etc) for each component? |
I have exported HTML from JSON. But i don't see js in file. How can do it ? |
@wbmag ive just implemented that solution and yes basically its the same component but without the |
@mattvb91 so you could pass a SSR flag to the same component, to either read the props from useNode or from props? |
Hi all, I'm trying to export the page as HTML on every node change using the Editor's The error gets thrown when calling See below where i'm calling Any help would be appreciated!
However when calling
|
@tsaunde123 Did you ever succeed with this problem? In the same place you were with that solution edit: For posterity, I solved this by replacing all the |
I created this small solution that, should work without being in the Keep in mind, the way in which Maybe something that we could change in order to have a full conversion to HTML from the JSON object, the workaround for me now is to add the first element as a div with no props. |
I added a POC solution using Next.js https://github.com/reboottime/craftjs-nextjs-ssr-poc after testing some of above ideas. |
Links not working |
"use client";
import { Editor, Frame } from "@craftjs/core";
// all the user component
import * as UserComponents from "../../components/user";
// your saved json
const pTemplate = require("@/data/page1.json");
export default function Page() {
return (
<div className="relative" style={{ maxWidth: 700, marginInline: "auto" }}>
<div>
<Editor enabled={false} resolver={UserComponents}>
<Frame data={pTemplate} />
</Editor>
</div>
</div>
);
}
|
It working great, let me know if anybody need any help |
@bzaman that's not in plain html format. The discussion topic above was about how to transform the serialized json to plain html IMO |
was there any solution to this? have the same problem, need static files (html js css) from the craft.js json |
I don't know how to export my page
The text was updated successfully, but these errors were encountered: