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

Nextjs build fails but runs locally with image resize extension #15

Open
Rchn1907 opened this issue Oct 7, 2024 · 2 comments
Open

Nextjs build fails but runs locally with image resize extension #15

Rchn1907 opened this issue Oct 7, 2024 · 2 comments
Assignees

Comments

@Rchn1907
Copy link

Rchn1907 commented Oct 7, 2024

Describe the bug
Hey guys,
i am encountering a different problem.
My next js app is running locally fine.
But when I reload the page where I use Tiptap this error occurs:
Bildschirmfoto 2024-10-04 um 15 52 35
The same Error occurs when I build my next App locally and in my CI/CD.
I searched a lot of solution on the internet but could not find any possible one.
I would be happy if some of you guys could help me.
Here is my Code:

import React, { useEffect, useRef, useState } from 'react';
import { EditorContent, useEditor } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import Bold from '@tiptap/extension-bold';
import Italic from '@tiptap/extension-italic';
import Underline from '@tiptap/extension-underline';
import Strike from '@tiptap/extension-strike';
import Link from '@tiptap/extension-link';
import Image from '@tiptap/extension-image';
import TextAlign from '@tiptap/extension-text-align';
import Heading from '@tiptap/extension-heading';
import BulletList from '@tiptap/extension-bullet-list';
import OrderedList from '@tiptap/extension-ordered-list';
import ListItem from '@tiptap/extension-list-item';
import Blockquote from '@tiptap/extension-blockquote';
import CodeBlock from '@tiptap/extension-code-block';
import Color from '@tiptap/extension-color';
import Highlight from '@tiptap/extension-highlight';
import TextStyle from '@tiptap/extension-text-style';
import HorizontalRule from '@tiptap/extension-horizontal-rule';
import TaskList from '@tiptap/extension-task-list';
import TaskItem from '@tiptap/extension-task-item';
import { Button, Box, TextField, ButtonGroup, Divider } from '@mui/material';
import authConfig from 'src/configs/auth';

import { 
  FormatBold, 
  FormatHeader1, 
  FormatHeader2, 
  FormatItalic, 
  FormatListBulleted, 
  FormatListNumbered, 
  FormatQuoteOpen, 
  FormatStrikethrough, 
  FormatUnderline, 
  CodeBraces, 
  FormatAlignLeft, 
  FormatAlignCenter, 
  FormatAlignRight, 
  ImageArea,
  FormatColorText,
  FormatColorHighlight,
  Minus,
  LinkVariant,
  LinkVariantOff,
  FormatHeader3,
  TableLargePlus,
  TableLargeRemove,
  TableRowPlusAfter,
  TableColumnPlusAfter,
  FormatHeader4
} from 'mdi-material-ui';
import toast from 'react-hot-toast';
import axios from 'axios';
import ImageResize from 'tiptap-extension-resize-image';
import Table from '@tiptap/extension-table';
import TableRow from '@tiptap/extension-table-row';
import TableCell from '@tiptap/extension-table-cell';
import TableHeader from '@tiptap/extension-table-header';

export default function TiptapEditor(props) {
  const {language, value, setValue, readOnly} = props;
  const fileInputRef = useRef(null); // Reference to the file input
  const textColorRef = useRef(null);
  const highlightColorRef = useRef(null);


  const editor = useEditor({
    extensions: [
      StarterKit,
      Bold,
      Italic,
      Underline,
      Strike,
      Link,
      Image,
      ImageResize,
      TextAlign.configure({ types: ['heading', 'paragraph'] }),
      Heading.configure({ levels: [1, 2, 3, 4, 5, 6] }),
      BulletList,
      OrderedList,
      ListItem,
      Blockquote,
      CodeBlock,
      Color,
      Highlight.configure({ multicolor: true }),
      TextStyle,
      HorizontalRule,
      TaskList,
      TaskItem.configure({ nested: true }),
      Table.configure({resizable: true}),
      TableRow,
      TableCell,
      TableHeader
    ],
    content: value,
    autofocus: true,
    editable: !readOnly,
    onUpdate: ({ editor }) => {
      setValue(editor.getHTML()); // Updates the state with the HTML content
    },
  });

  const handleTextColorChange = (e) => {
    editor.chain().focus().setColor(e.target.value).run();
    textColorRef.current.style.display = 'none'; // Hide the color input
  };
  
  const handleHighlightColorChange = (e) => {
    editor.chain().focus().toggleHighlight({ color:  `${e.target.value}` }).run();
    highlightColorRef.current.style.display = 'none'; // Hide the highlight input
  };  

  const handleSetLink = () => {
    const url = window.prompt('Enter the link URL:');
    if (url) {
      editor.chain().focus().setLink({ href: url }).run();
    }
  };

  // Function to handle image upload
  const handleImageUpload = async (event) => {
    const file = event.target.files[0];
    if (file) {
      // Assuming you have an API endpoint to upload the image
      const formData = new FormData();
      formData.append('file', file);

      try {
        const url = `Media?languageId=${language}`;
        const res = await axios.post(authConfig.defaultEndpoint + url, formData);
        let urlEncoded = encodeURIComponent(res.data.Data.Description);
        editor.chain().focus().setImage({src: `${authConfig.defaultEndpoint}Media/${urlEncoded}`}).run();
      } catch (error) {
        toast.error("Error uploading image");
        console.error('Error uploading image:', error.response || error.message);
      }
    }
  };

  if (!editor) {
    return null;
  }

  // Toolbar for editor controls with active state check
  const Toolbar = () => (
    <Box sx={{ display: 'flex', gap: '8px', mb: 2, mt: 2, flexWrap: 'wrap'}}>
      <ButtonGroup size='small' disabled={readOnly}>
        <Button 
          onClick={() => editor.chain().focus().toggleBold().run()} 
          variant={editor.isActive('bold') ? 'contained' : 'outlined'}
        >
          <FormatBold />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().toggleItalic().run()} 
          variant={editor.isActive('italic') ? 'contained' : 'outlined'}
        >
          <FormatItalic />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().toggleUnderline().run()} 
          variant={editor.isActive('underline') ? 'contained' : 'outlined'}
        >
          <FormatUnderline />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().toggleStrike().run()} 
          variant={editor.isActive('strike') ? 'contained' : 'outlined'}
        >
          <FormatStrikethrough />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().toggleBulletList().run()} 
          variant={editor.isActive('bulletList') ? 'contained' : 'outlined'}
        >
          <FormatListBulleted />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().toggleOrderedList().run()} 
          variant={editor.isActive('orderedList') ? 'contained' : 'outlined'}
        >
          <FormatListNumbered />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()} 
          variant={editor.isActive('heading', { level: 1 }) ? 'contained' : 'outlined'}
        >
          <FormatHeader1 />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()} 
          variant={editor.isActive('heading', { level: 2 }) ? 'contained' : 'outlined'}
        >
          <FormatHeader2 />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()} 
          variant={editor.isActive('heading', { level: 3 }) ? 'contained' : 'outlined'}
        >
          <FormatHeader3 />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()} 
          variant={editor.isActive('heading', { level: 4 }) ? 'contained' : 'outlined'}
        >
          <FormatHeader4 />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().toggleBlockquote().run()} 
          variant={editor.isActive('blockquote') ? 'contained' : 'outlined'}
        >
          <FormatQuoteOpen />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().toggleCodeBlock().run()} 
          variant={editor.isActive('codeBlock') ? 'contained' : 'outlined'}
        >
          <CodeBraces />
        </Button>
        <Button onClick={() => editor.chain().focus().setHorizontalRule().run()} variant="outlined">
          <Minus />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().setTextAlign('left').run()} 
          variant={editor.isActive({ textAlign: 'left' }) ? 'contained' : 'outlined'}
        >
          <FormatAlignLeft />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().setTextAlign('center').run()} 
          variant={editor.isActive({ textAlign: 'center' }) ? 'contained' : 'outlined'}
        >
          <FormatAlignCenter />
        </Button>
        <Button 
          onClick={() => editor.chain().focus().setTextAlign('right').run()} 
          variant={editor.isActive({ textAlign: 'right' }) ? 'contained' : 'outlined'}
        >
          <FormatAlignRight />
        </Button>
        {/* Color picker for text color */}
        <Button onClick={() => textColorRef.current.style.display = 'block'}>
          <FormatColorText />
        </Button>
        <input
          ref={textColorRef}
          type="color"
          style={{ display: 'none' }}  // Initially hidden
          onChange={handleTextColorChange}
        />

        <Button onClick={() => highlightColorRef.current.style.display = 'block'}>
          <FormatColorHighlight />
        </Button>
        <input
          ref={highlightColorRef}
          type="color"
          style={{ display: 'none' }}  // Initially hidden
          onChange={handleHighlightColorChange}
        />
        <Button onClick={handleSetLink} variant="outlined">
          <LinkVariant/>
        </Button>
        <Button onClick={() => editor.chain().focus().unsetLink().run()} variant="outlined">
          <LinkVariantOff/>
        </Button>
        <Button onClick={() => fileInputRef.current.click()} variant="outlined">
          <ImageArea />
        </Button>
        <input
          type="file"
          accept="image/*"
          style={{ display: 'none' }} // Hidden file input
          ref={fileInputRef}
          onChange={handleImageUpload}
        />
        <Button onClick={() => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()} variant="outlined">
          <TableLargePlus/>
        </Button>
        <Button onClick={() => editor.chain().focus().addRowAfter().run()} variant="outlined">
          <TableRowPlusAfter/>
        </Button>
        <Button onClick={() => editor.chain().focus().addColumnAfter().run()} variant="outlined">
          <TableColumnPlusAfter/>
        </Button>
        <Button onClick={() => editor.chain().focus().deleteTable().run()} variant="outlined">
          <TableLargeRemove/>
        </Button>
      </ButtonGroup>
    </Box>
  );

  return (
    <Box sx={{position: "relative", width: "100%", border: "3px solid #444", padding: 2}}>
      <Toolbar/> {/* Render toolbar */}
      <Divider/>
      <EditorContent editor={editor}/>
    </Box>
  );
}

Desktop (please complete the following information):

  • OS: MacOS
  • Browser safari

Additional context
Add any other context about the problem here.

@bae-sh
Copy link
Owner

bae-sh commented Oct 9, 2024

Hey @Rchn1907,

Could you remove import Image from @tiptap/extension-image? It's already being imported and extended in ImageResize, so having both might cause conflicts.

Also, StarterKit includes Bold, Italic, Strike, Heading, BulletList, OrderedList, ListItem, Blockquote, and CodeBlock, so there's no need to import those separately.

Let me know if this helps!

@bae-sh bae-sh self-assigned this Oct 9, 2024
@Rchn1907
Copy link
Author

Rchn1907 commented Oct 9, 2024

Hey @bae-sh ,
thank you for the advice with the starter kit!
I removed the image extension but the same error still occurs.
I would be happy if you can help!

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

2 participants