Repository: storybookjs/storybook
File: code/core/src/components/components/syntaxhighlighter/syntaxhighlighter.tsx (TypeScript)

Code before:
  const processedLineNumberNode = {
    ...lineNumberNode,
    children: [],
    // empty the line-number element
    properties: {
      ...lineNumberNode.properties,
      'data-line-number': lineNumber,
      // remove the userSelect: none style, which will produce extra empty lines when copy-pasting in firefox
      style: { ...lineNumberNode.properties.style, userSelect: 'auto' },
    },
  };
  children[0] = processedLineNumberNode;
  return { ...row, children };
};

const defaultRenderer: SyntaxHighlighterRenderer = ({ rows, stylesheet, useInlineStyles }) => {
  return rows.map((node: any, i: number) => {
    return createElement({
      node: processLineNumber(node),
      stylesheet,
      useInlineStyles,
      key: `code-segement${i}`,
    });
  });
};

const wrapRenderer = (
  renderer: SyntaxHighlighterRenderer | undefined,
  showLineNumbers: boolean
) => {
  if (!showLineNumbers) {
    return renderer;
  }
  if (renderer) {
    return ({ rows, ...rest }: SyntaxHighlighterRendererProps) =>
      renderer({ rows: rows.map((row) => processLineNumber(row)), ...rest });
  }
  return defaultRenderer;
};

export interface SyntaxHighlighterState {
  copied: boolean;
}

export const SyntaxHighlighter = ({
  children,
  language = 'jsx',
  copyable = false,
  bordered = false,
  padded = false,
  format = true,

Review comment (suggestion):
```suggestion
/**
 * A custom renderer for handling `span.linenumber` element in each line of code, which is enabled
 * by default if no renderer is passed in from the parent component
 */
const defaultRenderer: SyntaxHighlighterRenderer = ({ rows, stylesheet, useInlineStyles }) => {
```

Code after:

const processLineNumber = (row: any) => {
  const children = [...row.children];
  const lineNumberNode = children[0];
  const lineNumber = lineNumberNode.children[0].value;
  const processedLineNumberNode = {
    ...lineNumberNode,
    // empty the line-number element
    children: [],
    properties: {
      ...lineNumberNode.properties,
      // add a data-line-number attribute to line-number element, so we can access the line number with `content: attr(data-line-number)`
      'data-line-number': lineNumber,
      // remove the 'userSelect: none' style, which will produce extra empty lines when copy-pasting in firefox
      style: { ...lineNumberNode.properties.style, userSelect: 'auto' },
    },
  };
  children[0] = processedLineNumberNode;
  return { ...row, children };
};

/**
 * A custom renderer for handling `span.linenumber` element in each line of code, which is enabled
 * by default if no renderer is passed in from the parent component
 */
const defaultRenderer: SyntaxHighlighterRenderer = ({ rows, stylesheet, useInlineStyles }) => {
  return rows.map((node: any, i: number) => {
    return createElement({
      node: processLineNumber(node),
      stylesheet,
      useInlineStyles,
      key: `code-segement${i}`,
    });
  });
};

const wrapRenderer = (
  renderer: SyntaxHighlighterRenderer | undefined,
  showLineNumbers: boolean
) => {
  if (!showLineNumbers) {
    return renderer;
  }
  if (renderer) {
    return ({ rows, ...rest }: SyntaxHighlighterRendererProps) =>
      renderer({ rows: rows.map((row) => processLineNumber(row)), ...rest });
  }
  return defaultRenderer;
};

export interface SyntaxHighlighterState {