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

PrismLight using results in regular [object Object] output (but only in production) #513

Open
MatchuPitchu opened this issue Apr 11, 2023 · 11 comments · May be fixed by #521
Open

PrismLight using results in regular [object Object] output (but only in production) #513

MatchuPitchu opened this issue Apr 11, 2023 · 11 comments · May be fixed by #521

Comments

@MatchuPitchu
Copy link

MatchuPitchu commented Apr 11, 2023

Describe the bug
I'm using import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter'; which results in regular [object Object] [object Object] ... output (around 7 of 10 refreshs of my webpage) for my code blocks (but only in production). Notice: import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; has the same problem. Every 4th to 5th refresh, it's working correctly, otherwise it's rendering [object Object] ...

To Reproduce
Steps to reproduce the behavior: This is my implementation, notice that the processedCode output of the process function is always correct (also in production). But even without this process function, the problem persists.

import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter';
import tsx from 'react-syntax-highlighter/dist/esm/languages/prism/tsx';
import typescript from 'react-syntax-highlighter/dist/esm/languages/prism/typescript';
import { vs, vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';

SyntaxHighlighter.registerLanguage('tsx', tsx);
SyntaxHighlighter.registerLanguage('typescript', typescript);

interface ICodeBlock {
  code: string;
  language: 'typescript' | 'tsx';
}

const process = (code = '') => {
  let skippedLeadingEmptyLines = false;
  let lastNonEmptyLineIndex = 0;
  let minRawStringIndentation = Number.MAX_SAFE_INTEGER;
  let numberOfRemovedLines = 0;

  const processNonEmptyLine = (line: string, index: number) => {
    // keep track of the index of the last non-empty line
    lastNonEmptyLineIndex = index - numberOfRemovedLines;
    // determine the minimum indentation level
    minRawStringIndentation = Math.min(minRawStringIndentation, Math.max(0, line.search(/\S/)));
    // return the processed line
    return [line.trimEnd()];
  };

  // split code into lines
  const codeLines = code.split('\n');

  // remove empty lines, and process non-empty lines
  const nonEmptyLinesAtStart = codeLines.flatMap((line, index) => {
    if (!skippedLeadingEmptyLines) {
      if (line.match(/^\s*$/)) {
        numberOfRemovedLines += 1;
        return [];
      }

      skippedLeadingEmptyLines = true;
      return processNonEmptyLine(line, index);
    }

    if (line.match(/^\s*$/)) return [''];

    return processNonEmptyLine(line, index);
  });

  const nonEmptyLinesStartAndEnd = nonEmptyLinesAtStart.slice(0, lastNonEmptyLineIndex + 1);

  // If there are no non-empty lines, return an empty string
  if (nonEmptyLinesStartAndEnd.length === 0) return '';

  const nonRawStringIndentationLines =
    minRawStringIndentation !== 0
      ? nonEmptyLinesStartAndEnd.map((line) => line.substring(minRawStringIndentation))
      : nonEmptyLinesStartAndEnd;

  return nonRawStringIndentationLines.join('\n');
};

export const CodeBlock = ({ code, language }: ICodeBlock) => {
  const { isLight } = useThemeContext();

  const processedCode = process(code);

  const theme = isLight ? vs : vscDarkPlus;

  return (
    <pre className={classes.pre}>
      <SyntaxHighlighter language={language} style={theme}>
        {processedCode}
      </SyntaxHighlighter>
    </pre>
  );
};

It's working when I do a bad workaround to force reloading of the component:

// ...
useEffect(() => {
  const timerId = setTimeout(() => setIsReloaded(true), 0);

  return () => clearTimeout(timerId);
}, []);

return isReloaded ? (
  <pre className={classes.pre}>
    <SyntaxHighlighter language={language} style={theme}>
      {processedCode}
    </SyntaxHighlighter>
  </pre>
) : null;

Expected behavior
Output my code string (it's a simple code string of a React Component) instead of [object Object] in some cases. Oddly enough in my dev environment it's always working fine, only in production is the rendering issue with [object Object]

Screenshots
grafik

Desktop (please complete the following information):

  • Browser firefox
  • Version 111.0.1 (64-Bit)
@matronator
Copy link

matronator commented Apr 14, 2023

Same issue here. On production it randomly outputs [object Object]..., but works fine on localhost. After a few refreshes it starts working again, until you force reload the page with cache.

Snímek obrazovky 2023-04-14 v 16 41 55

@lritter79
Copy link

I'm getting this issue on a non-local environment as well

Screen Shot 2023-05-01 at 10 32 59 AM

@humphd
Copy link

humphd commented May 2, 2023

We see this same issue intermittently with PrismAsyncLight as well.

@humphd
Copy link

humphd commented May 2, 2023

I wonder if this is due to using refractor 3.x vs. 4.x as also seen in wooorm/refractor#59.

@jtsorlinis
Copy link

For others with this issue, using @fenkx's fork fixes the issue, the easiest way to switch is just change this line in your package.json:

"react-syntax-highlighter": "npm:@fengkx/react-syntax-highlighter@15.6.1"

@bodinsamuel
Copy link

I have the same issue but I guess this package is not maintained anymore 😕

@ShaofeiZi
Copy link

I had the same problem, but the above scenario didn't solve my problem.

@FujiwaraChoki
Copy link

+1

@C5H8NNaO4
Copy link

This happens to me as well, what can I do about this?

@jeremyckahn
Copy link

I'm experiencing this issue as well. I was able to work around it by adding this to my index.tsx file before I render my React app:

import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter'

ReactDOM.createRoot(document.createElement('div')).render(
  <SyntaxHighlighter language="" children={''} />
)

jeremyckahn added a commit to jeremyckahn/chitchatter that referenced this issue Mar 13, 2024
* chore(vite): use vite

* fix(vite): alias lib directory

* chore(vite): set type: module

* chore: update vite and MUI

* fix(vite): make MUI components load

* fix: use node path resolution

* chore(vite): add svg support

* fix(vite): polyfill global

* fix(vite): use import.meta

* fix(vite): use correct svg module resolution

* chore(vite): migrate to vitest

* fix(vite): remove PUBLIC_URL

* fix(tests): mock audio service

* chore(deps): upgrade to react test library 14

* refactor(tests): simplify room test setup

* refactor(tests): make Date.now() mockable

* refactor(vite): remove bootstrap shim

* chore(deps): drop react-scripts

* chore(deps): remove source-map-explorer

Source maps do not currently work with MUI and Vite:
vitejs/vite#15012

Because of this, source map utilities are currently removed.

* refactor(vite): use TypeScript for Vite config

* chore(actions): update actions config for new paths

* fix(service-worker): use VITE_HOMEPAGE for service worker resolution

* fix(vercel): use quotes for build command

* fix(vite): use import.meta.env.MODE

* fix(service-worker): use correct definition for publicUrl

* feat(vite): use vite-plugin-pwa

* fix(pwa): make update prompt work

* fix(types): use vite/client types

* docs(readme): update building instructions

* refactor(vite): simplify theme loading workaround

* refactor(vite): use manifest object

* docs(readme): update tool references

* chore(deps): run `npm audit fix`

* fix(vite): make syntax highlighter work consistently

See: react-syntax-highlighter/react-syntax-highlighter#513

* fix(pwa): remove manifest.json references

* refactor(deps): remove jest references

* refactor(types): remove react-scripts reference

* chore(deps): use TypeScript 5

* refactor(tests): improve persisted storage mocking
@C5H8NNaO4
Copy link

C5H8NNaO4 commented Mar 13, 2024

Unfortunately this doesn't work for me. This issue is not present when I use createRoot in a production build.

It's only present when I use SSR and hydrateRoot. This workaround doesn't seem to have any effect when used with hydrateRoot.

Any idea how I could workaround this issue when using partial hydration?

Update: I switched to rehype-highlight which works well on SSR production builds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
10 participants