import { ComponentBase, ComponentState } from './componentBase'; // This import decides which languages are supported by `highlight.js`. See // their docs for details: // // https://github.com/highlightjs/highlight.js#importing-the-library import hljs from 'highlight.js/lib/common'; import { Language } from 'highlight.js'; import { LayoutContext } from '../layouting'; import { getElementHeight, getElementWidth } from '../layoutHelpers'; import { copyToClipboard, firstDefined } from '../utils'; import { applyIcon } from '../designApplication'; export type CodeBlockState = ComponentState & { _type_: 'CodeBlock-builtin'; source?: string; language?: string | null; display_controls?: boolean; }; // Converts a `
`;
let headerElement = div.querySelector(
'.rio-code-block-header'
) as HTMLDivElement;
let labelElement = headerElement.querySelector(
'.rio-code-block-language'
) as HTMLDivElement;
let copyButton = headerElement.querySelector(
'.rio-code-block-copy-button'
) as HTMLButtonElement;
let codeElement = div.querySelector('code') as HTMLElement;
// See if hljs recognizes the language
if (language !== null && hljs.getLanguage(language) === undefined) {
language = null;
}
// Strip any empty leading/trailing lines from the source
sourceCode = sourceCode ? sourceCode.replace(/^\n+|\n+$/g, '') : '';
// Add syntax highlighting and apply the source. This will also detect the
// actual language.
let hljsLanguage: Language | undefined = undefined;
if (language === null) {
let hlResult = hljs.highlightAuto(sourceCode);
codeElement.innerHTML = hlResult.value;
if (hlResult.language !== undefined) {
hljsLanguage = hljs.getLanguage(hlResult.language);
}
} else {
let hlResult = hljs.highlight(sourceCode, {
language: language,
ignoreIllegals: true,
});
codeElement.innerHTML = hlResult.value;
hljsLanguage = hljs.getLanguage(language);
}
// Are controls enabled?
if (displayControls) {
// What's the language's name?
let languageNiceName = hljsLanguage?.name ?? '';
labelElement.textContent = languageNiceName;
// Initialize the copy button
applyIcon(
copyButton,
'material/content-copy',
'var(--rio-local-text-color)'
);
copyButton.addEventListener('click', (event) => {
const codeToCopy = (codeElement as HTMLElement).textContent ?? '';
copyToClipboard(codeToCopy);
copyButton.title = 'Copied!';
applyIcon(
copyButton,
'material/done',
'var(--rio-local-text-color)'
);
setTimeout(() => {
copyButton.title = 'Copy code';
applyIcon(
copyButton,
'material/content-copy',
'var(--rio-local-text-color)'
);
}, 5000);
event.stopPropagation();
});
} else {
headerElement.remove();
}
}
export class CodeBlockComponent extends ComponentBase {
state: Required