import React from 'react';
import hljs from 'highlight.js/lib/core';
import bash from 'highlight.js/lib/languages/bash';
import js from 'highlight.js/lib/languages/javascript';
import json from 'highlight.js/lib/languages/json';
import markdown from 'highlight.js/lib/languages/markdown';
import python from 'highlight.js/lib/languages/python';
import xml from 'highlight.js/lib/languages/xml';
import { BaseProps } from '@digigov/react-core/Base';
import CodeBlockContainer from '@digigov/react-core/CodeBlockContainer';
import CodeBlockContent from '@digigov/react-core/CodeBlockContent';
import CodeBlockHeader from '@digigov/react-core/CodeBlockHeader';
import { CopyToClipboard } from '@digigov/ui/feedback';
import { PhaseBannerTag } from '@digigov/ui/feedback/PhaseBanner';
import { Button } from '@digigov/ui/form/Button';
export interface CodeBlockProps extends BaseProps<'div'> {
language?: 'javascript' | 'bash' | 'xml' | 'python' | 'markdown' | 'json';
copyToClipboard?: boolean;
highlighted?: boolean;
showLineNumbers?: boolean;
phaseBannerTagName?: string;
highlightLines?: number[];
}
const languageMap = {
javascript: js,
python: python,
bash: bash,
xml: xml,
markdown: markdown,
json: json,
};
const addLineNumbers = (code: string, highlightLines: number[]): string => {
return code
.split('\n')
.map((line, index) => {
const isHighlighted = highlightLines.includes(index + 1);
const lineClass = isHighlighted ? 'ds-code--highlighted-line' : '';
return `${index + 1} ${line}`;
})
.join('\n');
};
export const CodeBlock = React.forwardRef(
function CodeBlock(
{
children,
language,
copyToClipboard,
highlighted,
showLineNumbers,
phaseBannerTagName,
highlightLines,
...props
},
ref
) {
const Tag = 'span';
const codeString = typeof children === 'string' ? children : '';
let displayingCode = codeString;
if (highlighted && codeString) {
try {
hljs.configure({ classPrefix: 'ds-code--' });
let highlightedCode = hljs.highlightAuto(codeString).value;
if (language) {
hljs.registerLanguage(language, languageMap[language]);
highlightedCode = hljs.highlight(codeString, {
language: language,
}).value;
}
displayingCode = showLineNumbers
? addLineNumbers(highlightedCode, highlightLines || [])
: highlightedCode;
} catch (error) {
console.error('Highlighting failed:', error);
}
}
return (
{phaseBannerTagName && (
{phaseBannerTagName}
)}
{copyToClipboard && (
)}
{highlighted && codeString ? (
) : (
children
)}
);
}
);
export * from '@digigov/react-core/CodeBlockContent';
export * from '@digigov/react-core/CodeBlockHeader';
export * from '@digigov/react-core/CodeBlockContainer';
export default CodeBlock;