Skip to content

Commit

Permalink
fix(EuiCopy): fix code block copy button not including the last chara…
Browse files Browse the repository at this point in the history
…cter if it's a question mark
  • Loading branch information
tkajtoch committed May 22, 2023
1 parent f8bc384 commit 805ec38
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
8 changes: 7 additions & 1 deletion src/components/code/code_block_copy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useInnerText } from '../inner_text';
import { EuiCopy } from '../copy';
import { useEuiI18n } from '../i18n';
import { EuiButtonIcon } from '../button';
import { NEW_LINE_REGEX_GLOBAL } from './utils';

/**
* Hook that returns copy-related state/logic/utils
Expand All @@ -26,7 +27,12 @@ export const useCopy = ({
}) => {
const [innerTextRef, _innerText] = useInnerText('');
const innerText = useMemo(
() => _innerText?.replace(/[\r\n?]{2}|\n\n/g, '\n') || '',
() =>
_innerText
// Normalize line terminations to match native JS format
?.replace(NEW_LINE_REGEX_GLOBAL, '\n')
// Reduce two or more consecutive new line characters to a single one
.replace(/\n{2,}/g, '\n') || '',
[_innerText]
);
const textToCopy = isVirtualized ? `${children}` : innerText; // Virtualized code blocks do not have inner text
Expand Down
20 changes: 18 additions & 2 deletions src/components/code/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ export type EuiCodeSharedProps = CommonProps &
export const SUPPORTED_LANGUAGES = listLanguages();
export const DEFAULT_LANGUAGE = 'text';

/**
* Platform-agnostic new line regex that safely matches all standard
* line termination conventions:
* - LF: Unix-based platforms and JS-native sources like text areas
* - CRLF: Windows
* - CR: Mac Classic; to support files saved a long time ago
*/
export const NEW_LINE_REGEX = /\r\n|\r|\n/;

/**
* Platform-agnostic global new line regex that safely matches all standard
* line termination conventions.
* See [NEW_LINE_REGEX]{@link NEW_LINE_REGEX} for more details.
*/
export const NEW_LINE_REGEX_GLOBAL = new RegExp(NEW_LINE_REGEX, 'g');

export const checkSupportedLanguage = (language: string): string => {
return SUPPORTED_LANGUAGES.includes(language) ? language : DEFAULT_LANGUAGE;
};
Expand Down Expand Up @@ -139,12 +155,12 @@ const addLineData = (
return nodes.reduce<ExtendedRefractorNode[]>((result, node) => {
const lineStart = data.lineNumber;
if (node.type === 'text') {
if (!node.value.match(/\r\n?|\n/)) {
if (!node.value.match(NEW_LINE_REGEX)) {
node.lineStart = lineStart;
node.lineEnd = lineStart;
result.push(node);
} else {
const lines = node.value.split(/\r\n?|\n/);
const lines = node.value.split(NEW_LINE_REGEX);
lines.forEach((line, i) => {
const num = i === 0 ? data.lineNumber : ++data.lineNumber;
result.push({
Expand Down

0 comments on commit 805ec38

Please sign in to comment.