Skip to content

Commit

Permalink
Merge branch 'fix-copy-function' of github.com:donotlb/storybook into…
Browse files Browse the repository at this point in the history
… fix-copy-function
  • Loading branch information
ndelangen committed Aug 22, 2022
2 parents 7b93cf4 + c265e67 commit 3848377
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export interface SyntaxHighlighterRendererProps {
useInlineStyles: boolean;
}

export type SyntaxHighlighterRenderer = (props: SyntaxHighlighterRendererProps) => ReactNode;

export interface SyntaxHighlighterCustomProps {
language: string;
copyable?: boolean;
Expand All @@ -15,7 +17,7 @@ export interface SyntaxHighlighterCustomProps {
format?: SyntaxHighlighterFormatTypes;
formatter?: (type: SyntaxHighlighterFormatTypes, source: string) => string;
className?: string;
renderer?: (props: SyntaxHighlighterRendererProps) => ReactNode;
renderer?: SyntaxHighlighterRenderer;
}

export type SyntaxHighlighterFormatTypes = boolean | 'dedent' | BuiltInParserName;
Expand Down
72 changes: 42 additions & 30 deletions code/lib/components/src/syntaxhighlighter/syntaxhighlighter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ import { createElement } from 'react-syntax-highlighter/dist/esm/index';
import { ActionBar } from '../ActionBar/ActionBar';
import { ScrollArea } from '../ScrollArea/ScrollArea';

import type { SyntaxHighlighterProps } from './syntaxhighlighter-types';
import type {
SyntaxHighlighterProps,
SyntaxHighlighterRenderer,
SyntaxHighlighterRendererProps,
} from './syntaxhighlighter-types';

const { navigator, document, window: globalWindow } = global;

Expand Down Expand Up @@ -143,45 +147,52 @@ const Code = styled.div(({ theme }) => ({
opacity: 1,
}));

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 used to process `span.linenumber` element in each line of code,
* which should only be enabled if `showLineNumbers = true`
* 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 renderer = ({
rows,
stylesheet,
useInlineStyles,
}: {
rows: any[];
stylesheet: any;
useInlineStyles: any;
}) => {
const defaultRenderer: SyntaxHighlighterRenderer = ({ rows, stylesheet, useInlineStyles }) => {
return rows.map((node: any, i: number) => {
const children = [...node.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 createElement({
node: { ...node, children },
node: processLineNumber(node),
stylesheet,
useInlineStyles,
key: `code-segement${i}`,
});
});
};

const wrapRenderer = (renderer: SyntaxHighlighterRenderer, 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;
}
Expand Down Expand Up @@ -216,6 +227,7 @@ export const SyntaxHighlighter: FC<SyntaxHighlighterProps> = ({
})
.catch(logger.error);
}, []);
const renderer = wrapRenderer(rest.renderer, showLineNumbers);

return (
<Wrapper
Expand All @@ -233,9 +245,9 @@ export const SyntaxHighlighter: FC<SyntaxHighlighterProps> = ({
useInlineStyles={false}
PreTag={Pre}
CodeTag={Code}
renderer={showLineNumbers ? renderer : undefined}
lineNumberContainerStyle={{}}
{...rest}
renderer={renderer}
>
{highlightableCode}
</ReactSyntaxHighlighter>
Expand Down

0 comments on commit 3848377

Please sign in to comment.