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

"type": "module" in package.json breaks imports and prevents from execution on node 23 #2152

Open
vadimkantorov opened this issue Feb 15, 2025 · 0 comments

Comments

@vadimkantorov
Copy link

vadimkantorov commented Feb 15, 2025

I've got a *.ts file which imports a *.tsx file.
The pasted GitHub Actions workflow is a self-contained reproducer and completes successfully.

But if I remove sed -i 's@"type": "module",@@' package.json, it starts erroring out


Error: Cannot find module '/home/runner/work/lexical-cli-render/lexical-cli-render/EmojiNode' imported from /home/runner/work/lexical-cli-render/lexical-cli-render/lexical-cli-render-tsx.ts
Did you mean to import "./EmojiNode.tsx"?

If I change import { EmojiNode } from './EmojiNode' to import { EmojiNode } from './EmojiNode.tsx', the error becomes:

(node:1637) ExperimentalWarning: Type Stripping is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
TypeError: Unknown file extension ".tsx" for /home/runner/work/lexical-cli-render/lexical-cli-render/EmojiNode.tsx

# .github/workflows/buildbug.yml

name: buildbug
on: workflow_dispatch
jobs:
  buildbug:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: 23
      - 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.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 > lexical-cli-render-tsx.ts << 'EOF'
          import { EmojiNode } from "./EmojiNode";
          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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant