Skip to content

buildbug

buildbug #25

Workflow file for this run

name: buildbug
on: workflow_dispatch
jobs:
buildbug:
runs-on: ubuntu-22.04
steps:
- uses: actions/setup-node@v4
with:
node-version: 23
- run: |
cat > lexical.json << 'EOF'
{
"editorState": {
"root": {
"children": [
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "Welcome to the playground",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "heading",
"version": 1,
"tag": "h1"
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "In case you were wondering what the black box at the bottom is – it's the debug view, showing the current state of the editor. You can disable it by pressing on the settings control in the bottom-left of your screen and toggling the debug view setting.",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "quote",
"version": 1
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "The playground is a demo environment built with ",
"type": "text",
"version": 1
},
{
"detail": 0,
"format": 16,
"mode": "normal",
"style": "",
"text": "@lexical/react",
"type": "text",
"version": 1
},
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": ". Try typing in ",
"type": "text",
"version": 1
},
{
"detail": 0,
"format": 1,
"mode": "normal",
"style": "",
"text": "some text",
"type": "text",
"version": 1
},
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": " with ",
"type": "text",
"version": 1
},
{
"detail": 0,
"format": 2,
"mode": "normal",
"style": "",
"text": "different",
"type": "text",
"version": 1
},
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": " formats.",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "paragraph",
"version": 1,
"textFormat": 0,
"textStyle": ""
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "Make sure to check out the various plugins in the toolbar. You can also use ",
"type": "text",
"version": 1
},
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "#hashtags",
"type": "hashtag",
"version": 1
},
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": " or @-mentions too!",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "paragraph",
"version": 1,
"textFormat": 0,
"textStyle": ""
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "If you'd like to find out more about Lexical, you can:",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "paragraph",
"version": 1,
"textFormat": 0,
"textStyle": ""
},
{
"children": [
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "Visit the ",
"type": "text",
"version": 1
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "Lexical website",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "link",
"version": 1,
"rel": null,
"target": null,
"title": null,
"url": "https://lexical.dev/"
},
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": " for documentation and more information.",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "listitem",
"version": 1,
"value": 1
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "Check out the code on our ",
"type": "text",
"version": 1
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "GitHub repository",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "link",
"version": 1,
"rel": null,
"target": null,
"title": null,
"url": "https://github.com/facebook/lexical"
},
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": ".",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "listitem",
"version": 1,
"value": 2
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "Playground code can be found ",
"type": "text",
"version": 1
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "here",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "link",
"version": 1,
"rel": null,
"target": null,
"title": null,
"url": "https://github.com/facebook/lexical/tree/main/packages/lexical-playground"
},
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": ".",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "listitem",
"version": 1,
"value": 3
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "Join our ",
"type": "text",
"version": 1
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "Discord Server",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "link",
"version": 1,
"rel": null,
"target": null,
"title": null,
"url": "https://discord.com/invite/KmG4wQnnD9"
},
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": " and chat with the team.",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "listitem",
"version": 1,
"value": 4
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "list",
"version": 1,
"listType": "bullet",
"start": 1,
"tag": "ul"
},
{
"children": [
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": "Lastly, we're constantly adding cool new features to this playground. So make sure you check back here when you next get a chance ",
"type": "text",
"version": 1
},
{
"detail": 0,
"format": 0,
"mode": "token",
"style": "",
"text": "🙂",
"type": "emoji",
"version": 1,
"className": "emoji happysmile"
},
{
"detail": 0,
"format": 0,
"mode": "normal",
"style": "",
"text": ".",
"type": "text",
"version": 1
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "paragraph",
"version": 1,
"textFormat": 0,
"textStyle": ""
}
],
"direction": "ltr",
"format": "",
"indent": 0,
"type": "root",
"version": 1
}
},
"lastSaved": 1739541749446,
"source": "Playground",
"version": "0.24.0"
}
EOF
- run: |
cat > package.json << 'EOF'
{
"name": "lexical-cli-render",
"type": "module",
"private": true,
"version": "0.24.0",
"scripts": {},
"dependencies": {
"@lexical/headless": "^0.24.0",
"@lexical/html": "^0.24.0",
"@lexical/react": "0.24.0",
"jsdom": "^26.0.0",
"lexical": "0.24.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"ts-node": "^10.9.2"
},
"devDependencies": {
"@types/react": "^18.2.59",
"@types/react-dom": "^18.2.19",
"typescript": "^5.2.2"
}
}
EOF
- run: |
cat > tsconfig.json << 'EOF'
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"jsx": "react"
}
}
EOF
- run: |
cat > lexical-cli-render-tsx.ts << 'EOF'
import { EmojiNode } from "./EmojiNode.tsx";
import { TextNode, $getRoot, $selectAll } from "lexical";
import { createHeadlessEditor } from "@lexical/headless";
import { $generateHtmlFromNodes } from "@lexical/html";
import { JSDOM } from 'jsdom';
import { HeadingNode, QuoteNode } from "@lexical/rich-text";
import { LinkNode } from "@lexical/link";
import { HashtagNode } from "@lexical/hashtag";
import { ListNode, ListItemNode } from "@lexical/list";
let input : string = "", html : string = "";
const editor = createHeadlessEditor({
editable: false,
nodes: [TextNode, HeadingNode, QuoteNode, LinkNode, HashtagNode, ListNode, ListItemNode, EmojiNode],
onError: (error) => { throw error;},
});
const dom = new JSDOM();
global.window = dom.window;
global.document = dom.window.document;
process.stdin.on("data", (chunk) => { input += chunk; });
process.stdin.on("end", async () =>
{
try
{
const editorStateJson = JSON.parse(input).editorState;
const editorState = editor.parseEditorState(editorStateJson);
editor.setEditorState(editorState);
editor.update(() => { html = $generateHtmlFromNodes(editor, $selectAll()); });
console.log(html);
}
catch (error)
{
console.error("Error processing EditorState JSON:", error);
process.exit(1);
}
});
EOF
- run: |
cat > EmojiNode.tsx << 'EOF'
import type {
EditorConfig,
LexicalNode,
NodeKey,
SerializedTextNode,
Spread,
} from 'lexical';
import {$applyNodeReplacement, TextNode} from 'lexical';
export type SerializedEmojiNode = Spread<
{
className: string;
},
SerializedTextNode
>;
export class EmojiNode extends TextNode {
__className: string;
static getType(): string {
return 'emoji';
}
static clone(node: EmojiNode): EmojiNode {
return new EmojiNode(node.__className, node.__text, node.__key);
}
constructor(className: string, text: string, key?: NodeKey) {
super(text, key);
this.__className = className;
}
createDOM(config: EditorConfig): HTMLElement {
const dom = document.createElement('span');
const inner = super.createDOM(config);
dom.className = this.__className;
inner.className = 'emoji-inner';
dom.appendChild(inner);
return dom;
}
updateDOM(prevNode: this, dom: HTMLElement, config: EditorConfig): boolean {
const inner = dom.firstChild;
if (inner === null) {
return true;
}
super.updateDOM(prevNode, inner as HTMLElement, config);
return false;
}
static importJSON(serializedNode: SerializedEmojiNode): EmojiNode {
return $createEmojiNode(
serializedNode.className,
serializedNode.text,
).updateFromJSON(serializedNode);
}
exportJSON(): SerializedEmojiNode {
return {
...super.exportJSON(),
className: this.getClassName(),
};
}
getClassName(): string {
const self = this.getLatest();
return self.__className;
}
}
export function $isEmojiNode(
node: LexicalNode | null | undefined,
): node is EmojiNode {
return node instanceof EmojiNode;
}
export function $createEmojiNode(
className: string,
emojiText: string,
): EmojiNode {
const node = new EmojiNode(className, emojiText).setMode('token');
return $applyNodeReplacement(node);
}
EOF
- run: npm install
- run: |
#sed -i 's@"type": "module",@@' package.json
cat lexical.json | npx ts-node lexical-cli-render-tsx.ts