From 1190045299de4f33f38d1eda2113672bb3498eb0 Mon Sep 17 00:00:00 2001 From: Georgii Gorbachev Date: Wed, 29 Nov 2023 03:51:43 +0100 Subject: [PATCH] Keep only react-diff-viewer-continued --- package.json | 8 - .../shared-ux/code_editor/code_editor.tsx | 42 +- ...e_diff_tab_react_diff_viewer_continued.tsx | 4 +- .../rule_details/mark_edits_by_word.tsx | 241 --------- .../rule_diff_tab_app_experience_team_poc.tsx | 154 ------ .../rule_details/rule_diff_tab_diff2html.tsx | 55 --- .../rule_details/rule_diff_tab_monaco.tsx | 57 --- .../rule_diff_tab_react_diff_view.tsx | 459 ------------------ .../components/rule_details/unidiff.d.ts | 16 - .../upgrade_prebuilt_rules_table_context.tsx | 73 +-- yarn.lock | 160 +----- 11 files changed, 31 insertions(+), 1238 deletions(-) rename x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/{ => json_diff}/rule_diff_tab_react_diff_viewer_continued.tsx (95%) delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/mark_edits_by_word.tsx delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_app_experience_team_poc.tsx delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_diff2html.tsx delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_monaco.tsx delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_react_diff_view.tsx delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/unidiff.d.ts diff --git a/package.json b/package.json index 3d3e286079c9f..677575fed98ef 100644 --- a/package.json +++ b/package.json @@ -910,9 +910,6 @@ "deep-freeze-strict": "^1.1.1", "deepmerge": "^4.2.2", "del": "^6.1.0", - "diff-match-patch": "^1.0.5", - "diff-match-patch-line-and-word": "^0.1.3", - "diff2html": "^3.4.45", "elastic-apm-node": "^4.1.0", "email-addresses": "^5.0.0", "execa": "^5.1.1", @@ -1020,13 +1017,10 @@ "react": "^17.0.2", "react-ace": "^7.0.5", "react-color": "^2.13.8", - "react-diff-view": "^3.2.0", - "react-diff-viewer": "^3.1.1", "react-diff-viewer-continued": "^3.3.1", "react-dom": "^17.0.2", "react-dropzone": "^4.2.9", "react-fast-compare": "^2.0.4", - "react-gh-like-diff": "^2.0.2", "react-grid-layout": "^1.3.4", "react-hook-form": "^7.44.2", "react-intl": "^2.8.0", @@ -1084,7 +1078,6 @@ "type-detect": "^4.0.8", "typescript-fsa": "^3.0.0", "typescript-fsa-reducers": "^1.2.2", - "unidiff": "^1.0.4", "unified": "9.2.2", "use-resize-observer": "^9.1.0", "usng.js": "^0.4.5", @@ -1340,7 +1333,6 @@ "@types/dedent": "^0.7.0", "@types/deep-freeze-strict": "^1.1.0", "@types/delete-empty": "^2.0.0", - "@types/diff": "^5.0.8", "@types/ejs": "^3.0.6", "@types/enzyme": "^3.10.12", "@types/eslint": "^8.44.2", diff --git a/packages/shared-ux/code_editor/code_editor.tsx b/packages/shared-ux/code_editor/code_editor.tsx index 1f5862a6112bf..e6d54ddbff04d 100644 --- a/packages/shared-ux/code_editor/code_editor.tsx +++ b/packages/shared-ux/code_editor/code_editor.tsx @@ -8,7 +8,7 @@ import React, { useState, useRef, useCallback, useMemo, useEffect, KeyboardEvent } from 'react'; import { useResizeDetector } from 'react-resize-detector'; -import ReactMonacoEditor, { MonacoDiffEditor } from 'react-monaco-editor'; +import ReactMonacoEditor from 'react-monaco-editor'; import { htmlIdGenerator, EuiToolTip, @@ -151,7 +151,6 @@ export const CodeEditor: React.FC = ({ }), isCopyable = false, allowFullScreen = false, - original, }) => { const { colorMode, euiTheme } = useEuiTheme(); const useDarkTheme = useDarkThemeProp ?? colorMode === 'DARK'; @@ -163,8 +162,6 @@ export const CodeEditor: React.FC = ({ typeof ReactMonacoEditor === 'function' && ReactMonacoEditor.name === 'JestMockEditor'; return isMockedComponent ? (ReactMonacoEditor as unknown as () => typeof ReactMonacoEditor)() - : original - ? MonacoDiffEditor : ReactMonacoEditor; }, []); @@ -389,27 +386,23 @@ export const CodeEditor: React.FC = ({ textboxMutationObserver.current.observe(textbox, { attributes: true }); } - if (editor.onKeyDown && editor.onDidBlurEditorText) { - editor.onKeyDown(onKeydownMonaco); - editor.onDidBlurEditorText(onBlurMonaco); - } + editor.onKeyDown(onKeydownMonaco); + editor.onDidBlurEditorText(onBlurMonaco); - if (editor.getContribution) { - // "widget" is not part of the TS interface but does exist - // @ts-expect-errors - const suggestionWidget = editor.getContribution('editor.contrib.suggestController')?.widget - ?.value; - - // As I haven't found official documentation for "onDidShow" and "onDidHide" - // we guard from possible changes in the underlying lib - if (suggestionWidget && suggestionWidget.onDidShow && suggestionWidget.onDidHide) { - suggestionWidget.onDidShow(() => { - isSuggestionMenuOpen.current = true; - }); - suggestionWidget.onDidHide(() => { - isSuggestionMenuOpen.current = false; - }); - } + // "widget" is not part of the TS interface but does exist + // @ts-expect-errors + const suggestionWidget = editor.getContribution('editor.contrib.suggestController')?.widget + ?.value; + + // As I haven't found official documentation for "onDidShow" and "onDidHide" + // we guard from possible changes in the underlying lib + if (suggestionWidget && suggestionWidget.onDidShow && suggestionWidget.onDidHide) { + suggestionWidget.onDidShow(() => { + isSuggestionMenuOpen.current = true; + }); + suggestionWidget.onDidHide(() => { + isSuggestionMenuOpen.current = false; + }); } editorDidMount?.(editor); @@ -479,7 +472,6 @@ export const CodeEditor: React.FC = ({ Change[]; - diffWords: (oldStr: string, newStr: string) => Change[]; - diffWordsWithSpace: (oldStr: string, newStr: string) => Change[]; - diffLines: (oldStr: string, newStr: string) => Change[]; - diffTrimmedLines: (oldStr: string, newStr: string) => Change[]; - diffSentences: (oldStr: string, newStr: string) => Change[]; - diffCss: (oldStr: string, newStr: string) => Change[]; - diffJson: (oldObject: Record, newObject: Record) => Change[]; -} - -const jsDiff: JsDiff = diff; - -export enum DiffMethod { - CHARS = 'diffChars', - WORDS = 'diffWords', - WORDS_WITH_SPACE = 'diffWordsWithSpace', - LINES = 'diffLines', - TRIMMED_LINES = 'diffTrimmedLines', - SENTENCES = 'diffSentences', - CSS = 'diffCss', - JSON = 'diffJson', - WORDS_CUSTOM_USING_DMP = 'diffWordsCustomUsingDmp', -} - -const { DIFF_EQUAL, DIFF_DELETE, DIFF_INSERT } = DiffMatchPatch; - -function findChangeBlocks(changes: ChangeData[]): ChangeData[][] { - const start = findIndex(changes, (change) => !isNormal(change)); - - if (start === -1) { - return []; - } - - const end = findIndex(changes, (change) => !!isNormal(change), start); - - if (end === -1) { - return [changes.slice(start)]; - } - - return [changes.slice(start, end), ...findChangeBlocks(changes.slice(end))]; -} - -function groupDiffs(diffs: Diff[]): [Diff[], Diff[]] { - return diffs.reduce<[Diff[], Diff[]]>( - // eslint-disable-next-line @typescript-eslint/no-shadow - ([oldDiffs, newDiffs], diff) => { - const [type] = diff; - - switch (type) { - case DIFF_INSERT: - newDiffs.push(diff); - break; - case DIFF_DELETE: - oldDiffs.push(diff); - break; - default: - oldDiffs.push(diff); - newDiffs.push(diff); - break; - } - - return [oldDiffs, newDiffs]; - }, - [[], []] - ); -} - -function splitDiffToLines(diffs: Diff[]): Diff[][] { - return diffs.reduce( - (lines, [type, value]) => { - const currentLines = value.split('\n'); - - const [currentLineRemaining, ...nextLines] = currentLines.map( - (line: string): Diff => [type, line] - ); - const next: Diff[][] = [ - ...lines.slice(0, -1), - [...lines[lines.length - 1], currentLineRemaining], - ...nextLines.map((line: string) => [line]), - ]; - return next; - }, - [[]] - ); -} - -function diffsToEdits(diffs: Diff[], lineNumber: number): RangeTokenNode[] { - const output = diffs.reduce<[RangeTokenNode[], number]>( - // eslint-disable-next-line @typescript-eslint/no-shadow - (output, diff) => { - const [edits, start] = output; - const [type, value] = diff; - if (type !== DIFF_EQUAL) { - const edit: RangeTokenNode = { - type: 'edit', - lineNumber, - start, - length: value.length, - }; - edits.push(edit); - } - - return [edits, start + value.length]; - }, - [[], 0] - ); - - return output[0]; -} - -function convertToLinesOfEdits(linesOfDiffs: Diff[][], startLineNumber: number) { - return flatMap(linesOfDiffs, (diffs, i) => diffsToEdits(diffs, startLineNumber + i)); -} - -/* - UPDATE: I figured that there's a way to do it without relying on "diff-match-patch-line-and-word". - See a new function "diffBy" below. Leaving this function here for comparison. -*/ -function diffByWord(x: string, y: string): [Diff[], Diff[]] { - /* - This is a modified version of "diffText" from react-diff-view. - Original: https://github.com/otakustay/react-diff-view/blob/49cebd0958ef323c830395c1a1da601560a71781/src/tokenize/markEdits.ts#L96 - */ - const dmp = new DiffMatchPatch(); - /* - "diff_wordMode" comes from "diff-match-patch-line-and-word". - "diff-match-patch-line-and-word" adds word-level diffing to Google's "diff-match-patch" lib by - adding a new method "diff_wordMode" to the prototype of DiffMatchPatch. - There's an instruction how to do it in the "diff-match-patch" docs and somebody just made it into a package. - https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs#word-mode - */ - const diffs = dmp.diff_wordMode(x, y); - - if (diffs.length <= 1) { - return [[], []]; - } - - return groupDiffs(diffs); -} - -function diffBy(diffMethod: DiffMethod, x: string, y: string): [Diff[], Diff[]] { - const jsDiffChanges: Change[] = jsDiff[diffMethod](x, y); - const diffs: Diff[] = diff.convertChangesToDMP(jsDiffChanges); - - if (diffs.length <= 1) { - return [[], []]; - } - - return groupDiffs(diffs); -} - -function diffChangeBlock( - changes: ChangeData[], - diffMethod: DiffMethod -): [RangeTokenNode[], RangeTokenNode[]] { - /* Convert ChangeData array to two strings representing old source and new source of a change block, like - - "created_at": "2023-11-20T16:47:52.801Z", - "created_by": "elastic", - ... - - and - - "created_at": "1970-01-01T00:00:00.000Z", - "created_by": "", - ... - */ - const [oldSource, newSource] = changes.reduce( - // eslint-disable-next-line @typescript-eslint/no-shadow - ([oldSource, newSource], change) => - isDelete(change) - ? [oldSource + (oldSource ? '\n' : '') + change.content, newSource] - : [oldSource, newSource + (newSource ? '\n' : '') + change.content], - ['', ''] - ); - - const [oldDiffs, newDiffs] = - diffMethod === DiffMethod.WORDS_CUSTOM_USING_DMP // <-- That's basically the only change I made to allow word-level diffing - ? diffByWord(oldSource, newSource) - : diffBy(diffMethod, oldSource, newSource); - - if (oldDiffs.length === 0 && newDiffs.length === 0) { - return [[], []]; - } - - const getLineNumber = (change: ChangeData | undefined) => { - if (!change || isNormal(change)) { - return undefined; - } - - return change.lineNumber; - }; - const oldStartLineNumber = getLineNumber(changes.find(isDelete)); - const newStartLineNumber = getLineNumber(changes.find(isInsert)); - - if (oldStartLineNumber === undefined || newStartLineNumber === undefined) { - throw new Error('Could not find start line number for edit'); - } - - const oldEdits = convertToLinesOfEdits(splitDiffToLines(oldDiffs), oldStartLineNumber); - const newEdits = convertToLinesOfEdits(splitDiffToLines(newDiffs), newStartLineNumber); - - return [oldEdits, newEdits]; -} - -export function markEditsBy(hunks: HunkData[], diffMethod: DiffMethod): TokenizeEnhancer { - const changeBlocks = flatMap( - hunks.map((hunk) => hunk.changes), - findChangeBlocks - ); - - const [oldEdits, newEdits] = changeBlocks - .map((changes) => diffChangeBlock(changes, diffMethod)) - .reduce( - // eslint-disable-next-line @typescript-eslint/no-shadow - ([oldEdits, newEdits], [currentOld, currentNew]) => [ - oldEdits.concat(currentOld), - newEdits.concat(currentNew), - ], - [[], []] - ); - - return pickRanges(flatten(oldEdits), flatten(newEdits)); -} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_app_experience_team_poc.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_app_experience_team_poc.tsx deleted file mode 100644 index 474933a4ec970..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_app_experience_team_poc.tsx +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useMemo } from 'react'; -import { css } from '@emotion/react'; -import { euiThemeVars } from '@kbn/ui-theme'; -import type { Change } from 'diff'; -import { diffLines } from 'diff'; -import { EuiSpacer, useEuiBackgroundColor, tint } from '@elastic/eui'; -import type { RuleResponse } from '../../../../../common/api/detection_engine/model/rule_schema/rule_schemas.gen'; -import { sortAndStringifyJson } from './json_diff/sort_stringify_json'; - -interface RuleDiffTabProps { - oldRule: RuleResponse; - newRule: RuleResponse; -} - -export const RuleDiffTabAppExperienceTeamPoc = ({ oldRule, newRule }: RuleDiffTabProps) => { - const diff = useDiff(oldRule, newRule); - - return ( - <> - - {diff.map((change, i) => ( - - ))} - - ); -}; - -const useDiff = (oldRule: RuleResponse, newRule: RuleResponse) => { - const memoizedDiff = useMemo(() => { - const oldSource = sortAndStringifyJson(oldRule); - const newSource = sortAndStringifyJson(newRule); - - return diffLines(JSON.stringify(oldSource), JSON.stringify(newSource), { - ignoreWhitespace: false, - }); - }, [oldRule, newRule]); - - return memoizedDiff; -}; - -// ------------------------------------------------------------------------------------------------- -// DiffSegment component - -const indicatorCss = css` - position: absolute; - width: ${euiThemeVars.euiSizeS}; - height: 100%; - margin-left: calc(-${euiThemeVars.euiSizeS} - calc(${euiThemeVars.euiSizeXS} / 2)); - text-align: center; - line-height: ${euiThemeVars.euiFontSizeM}; - font-weight: ${euiThemeVars.euiFontWeightMedium}; -`; - -const matchIndicatorCss = css` - &:before { - content: '+'; - ${indicatorCss} - background-color: ${euiThemeVars.euiColorSuccess}; - color: ${euiThemeVars.euiColorLightestShade}; - } -`; - -const diffIndicatorCss = css` - &:before { - content: '-'; - ${indicatorCss} - background-color: ${tint(euiThemeVars.euiColorDanger, 0.25)}; - color: ${euiThemeVars.euiColorLightestShade}; - } -`; - -const DiffSegment = ({ - change, - diffMode, - showDiffDecorations, -}: { - change: Change; - diffMode: 'lines' | undefined; - showDiffDecorations: boolean | undefined; -}) => { - const matchBackgroundColor = useEuiBackgroundColor('success'); - const diffBackgroundColor = useEuiBackgroundColor('danger'); - - const matchCss = { - backgroundColor: matchBackgroundColor, - color: euiThemeVars.euiColorSuccessText, - }; - - const diffCss = { - backgroundColor: diffBackgroundColor, - color: euiThemeVars.euiColorDangerText, - }; - - const highlightCss = change.added ? matchCss : change.removed ? diffCss : undefined; - - const paddingCss = useMemo(() => { - if (diffMode === 'lines') { - return css` - padding-left: calc(${euiThemeVars.euiSizeXS} / 2); - `; - } - }, [diffMode]); - - const decorationCss = useMemo(() => { - if (!showDiffDecorations) { - return undefined; - } - - if (diffMode === 'lines') { - if (change.added) { - return matchIndicatorCss; - } else if (change.removed) { - return diffIndicatorCss; - } - } else { - if (change.added) { - return css` - text-decoration: underline; - `; - } else if (change.removed) { - return css` - text-decoration: line-through; - `; - } - } - }, [change.added, change.removed, diffMode, showDiffDecorations]); - - return ( -
- {change.value} -
- ); -}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_diff2html.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_diff2html.tsx deleted file mode 100644 index e2c669c4c967e..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_diff2html.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useMemo } from 'react'; -import * as Diff2Html from 'diff2html'; -import { formatLines, diffLines } from 'unidiff'; -import 'diff2html/bundles/css/diff2html.min.css'; -import { EuiSpacer } from '@elastic/eui'; -import type { RuleResponse } from '../../../../../common/api/detection_engine/model/rule_schema/rule_schemas.gen'; -import { sortAndStringifyJson } from './json_diff/sort_stringify_json'; - -interface RuleDiffTabProps { - oldRule: RuleResponse; - newRule: RuleResponse; -} - -export const RuleDiffTabDiff2Html = ({ oldRule, newRule }: RuleDiffTabProps) => { - const diffHtml = useDiffHtml(oldRule, newRule); - - return ( - <> - -
- - ); -}; - -const useDiffHtml = (oldRule: RuleResponse, newRule: RuleResponse): string => { - const memoizedDiffHtml = useMemo(() => { - const unifiedDiffString = formatLines( - diffLines(sortAndStringifyJson(oldRule), sortAndStringifyJson(newRule)), - { context: 3 } - ); - - return Diff2Html.html(unifiedDiffString, { - inputFormat: 'json', - drawFileList: false, - fileListToggle: false, - fileListStartVisible: false, - fileContentToggle: false, - matching: 'lines', // "lines" or "words" - diffStyle: 'word', // "word" or "char" - outputFormat: 'side-by-side', - synchronisedScroll: true, - highlight: true, - renderNothingWhenEmpty: false, - }); - }, [oldRule, newRule]); - - return memoizedDiffHtml; -}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_monaco.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_monaco.tsx deleted file mode 100644 index 98e2926256452..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_monaco.tsx +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useMemo } from 'react'; -import { CodeEditorField } from '@kbn/kibana-react-plugin/public'; -import { XJsonLang } from '@kbn/monaco'; -import { EuiSpacer } from '@elastic/eui'; -import type { RuleResponse } from '../../../../../common/api/detection_engine/model/rule_schema/rule_schemas.gen'; -import { sortAndStringifyJson } from './json_diff/sort_stringify_json'; - -interface RuleDiffTabProps { - oldRule: RuleResponse; - newRule: RuleResponse; -} - -export const RuleDiffTabMonaco = ({ oldRule, newRule }: RuleDiffTabProps) => { - const [oldRuleString, newRuleString] = useMemo(() => { - return [sortAndStringifyJson(oldRule), sortAndStringifyJson(newRule)]; - }, [oldRule, newRule]); - - return ( - <> - - - - ); -}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_react_diff_view.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_react_diff_view.tsx deleted file mode 100644 index 4d4d20fc20778..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab_react_diff_view.tsx +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useState, useMemo, useCallback } from 'react'; -import type { ReactElement } from 'react'; -import { css, Global } from '@emotion/react'; -import { - Diff, - Hunk, - useSourceExpansion, - useMinCollapsedLines, - Decoration, - getCollapsedLinesCountBetween, - parseDiff, - tokenize, - markEdits, -} from 'react-diff-view'; -import 'react-diff-view/style/index.css'; -import type { RenderGutter, HunkData, DecorationProps, TokenizeOptions } from 'react-diff-view'; -import unidiff from 'unidiff'; -import { EuiSpacer, EuiIcon, EuiLink, useEuiTheme, EuiSwitch, EuiRadioGroup } from '@elastic/eui'; -import type { RuleResponse } from '../../../../../common/api/detection_engine/model/rule_schema/rule_schemas.gen'; -import { markEditsBy, DiffMethod } from './mark_edits_by_word'; -import { sortAndStringifyJson } from './json_diff/sort_stringify_json'; - -interface UnfoldProps extends Omit { - start: number; - end: number; - direction: 'up' | 'down' | 'none'; - onExpand: (start: number, end: number) => void; -} - -function Unfold({ start, end, direction, onExpand, ...props }: UnfoldProps) { - const expand = useCallback(() => onExpand(start, end), [onExpand, start, end]); - - const linesCount = end - start; - - const iconType = { - up: 'sortUp', - down: 'sortDown', - none: 'sortable', - }; - - return ( - - - - {`Expand ${linesCount}${direction !== 'none' ? ' more' : ''} hidden line${ - linesCount > 1 ? 's' : '' - }`} - - - ); -} - -interface UnfoldCollapsedProps { - previousHunk: HunkData; - currentHunk?: HunkData; - linesCount: number; - onExpand: (start: number, end: number) => void; -} - -function UnfoldCollapsed({ - previousHunk, - currentHunk, - linesCount, - onExpand, -}: UnfoldCollapsedProps) { - if (!currentHunk) { - const nextStart = previousHunk.oldStart + previousHunk.oldLines; - const collapsedLines = linesCount - nextStart + 1; - - if (collapsedLines <= 0) { - return null; - } - - return ( - <> - {collapsedLines > 10 && ( - - )} - - - ); - } - - const collapsedLines = getCollapsedLinesCountBetween(previousHunk, currentHunk); - - if (!previousHunk) { - if (!collapsedLines) { - return null; - } - - const start = Math.max(currentHunk.oldStart - 10, 1); - - return ( - <> - - {collapsedLines > 10 && ( - - )} - - ); - } - - const collapsedStart = previousHunk.oldStart + previousHunk.oldLines; - const collapsedEnd = currentHunk.oldStart; - - if (collapsedLines < 10) { - return ( - - ); - } - - return ( - <> - - - - - ); -} - -const useExpand = (hunks: HunkData[], oldSource: string, newSource: string) => { - // useMemo(() => {}, [oldSource, newSource]); - const [hunksWithSourceExpanded, expandRange] = useSourceExpansion(hunks, oldSource); // Operates on hunks to allow "expansion" behaviour - substitutes two hunks with one hunk including data from two hunks and everything in between - const hunksWithMinLinesCollapsed = useMinCollapsedLines(0, hunksWithSourceExpanded, oldSource); - - return { - expandRange, - hunks: hunksWithMinLinesCollapsed, - }; -}; - -const useTokens = (hunks: HunkData[], diffMethod: DiffMethod, oldSource: string) => { - if (!hunks) { - return undefined; - } - - const options: TokenizeOptions = { - oldSource, - highlight: false, - enhancers: [ - /* - "markEditsBy" is a slightly modified version of "markEdits" enhancer from react-diff-view - to enable word-level highlighting. - */ - diffMethod === DiffMethod.CHARS - ? markEdits(hunks, { type: 'block' }) // Using built-in "markEdits" enhancer for char-level diffing - : markEditsBy(hunks, diffMethod), // Using custom "markEditsBy" enhancer for other-level diffing - ], - }; - - try { - /* - Synchroniously applies all the enhancers to the hunks and returns an array of tokens. - There's also a way to use a web worker to tokenize in a separate thread. - Example can be found here: https://github.com/otakustay/react-diff-view/blob/49cebd0958ef323c830395c1a1da601560a71781/site/components/DiffView/index.tsx#L43 - It didn't work for me right away, but theoretically the possibility is there. - */ - return tokenize(hunks, options); - } catch (ex) { - return undefined; - } -}; - -const convertToDiffFile = (oldSource: string, newSource: string) => { - /* - "diffLines" call below converts two strings of text into an array of Change objects. - Change objects look like this: - [ - ... - { - "count": 2, - "removed": true, - "value": "\"from\": \"now-540s\"" - }, - { - "count": 1, - "added": true, - "value": "\"from\": \"now-9m\"" - }, - ... - ] - - "formatLines" takes an array of Change objects and turns it into one big "unified Git diff" string. - Unified Git diff is a string with Git markers added. Looks something like this: - ` - @@ -3,16 +3,15 @@ - "author": ["Elastic"], - - "from": "now-540s", - + "from": "now-9m", - "history_window_start": "now-14d", - ` - */ - - const unifiedDiff: string = unidiff.formatLines(unidiff.diffLines(oldSource, newSource), { - context: 3, - }); - - /* - "parseDiff" converts a unified diff string into a JSDiff File object. - */ - const [diffFile] = parseDiff(unifiedDiff, { - nearbySequences: 'zip', - }); - /* - File object contains some metadata and the "hunks" property - an array of Hunk objects. - At this stage Hunks represent changed lines of code plus a few unchanged lines above and below for context. - Hunk objects look like this: - [ - ... - { - content: ' "from": "now-9m",' - isInsert: true, - lineNumber: 14, - type: "insert" - }, - { - content: ' "from": "now-540s",' - isDelete: true, - lineNumber: 15, - type: "delete" - }, - ... - ] - */ - - return diffFile; -}; - -interface DiffViewProps { - oldSource: string; - newSource: string; - diffMethod: DiffMethod; -} - -interface HunksProps { - hunks: HunkData[]; - oldSource: string; - expandRange: (start: number, end: number) => void; -} - -const Hunks = ({ hunks, oldSource, expandRange }: HunksProps) => { - const linesCount = oldSource.split('\n').length; - - const hunkElements = hunks.reduce((children: ReactElement[], hunk: HunkData, index: number) => { - const previousElement = children[children.length - 1]; - - children.push( - - ); - - children.push(); - - const isLastHunk = index === hunks.length - 1; - if (isLastHunk && oldSource) { - children.push( - - ); - } - - return children; - }, []); - - return <>{hunkElements}; -}; - -const CODE_CLASS_NAME = 'rule-update-diff-code'; -const GUTTER_CLASS_NAME = 'rule-update-diff-gutter'; - -interface CustomStylesProps { - children: React.ReactNode; -} - -const CustomStyles = ({ children }: CustomStylesProps) => { - const { euiTheme } = useEuiTheme(); - const [enabled, setEnabled] = useState(false); - - const customCss = css` - .${CODE_CLASS_NAME}.diff-code, .${GUTTER_CLASS_NAME}.diff-gutter { - background: transparent; - } - - .${CODE_CLASS_NAME}.diff-code-delete .diff-code-edit, - .${CODE_CLASS_NAME}.diff-code-insert .diff-code-edit { - background: transparent; - } - - .${CODE_CLASS_NAME}.diff-code-delete .diff-code-edit { - color: ${euiTheme.colors.dangerText}; - text-decoration: line-through; - } - - .${CODE_CLASS_NAME}.diff-code-insert .diff-code-edit { - color: ${euiTheme.colors.successText}; - } - `; - - return ( - <> - {enabled && } - { - setEnabled(!enabled); - }} - /> - - {children} - - ); -}; - -function DiffView({ oldSource, newSource, diffMethod }: DiffViewProps) { - /* - "react-diff-view" components consume diffs not as a strings, but as something they call "hunks". - So we first need to convert our "before" and "after" strings into these "hunks". - "hunks" are objects describing changed sections of code plus a few unchanged lines above and below for context. - */ - - /* - "diffFile" is essentially an object containing "hunks" and some metadata. - */ - const diffFile = useMemo(() => convertToDiffFile(oldSource, newSource), [oldSource, newSource]); - - /* - Sections of diff without changes are hidden by default, because they are not present in the "hunks" array. - - "useExpand" allows to show these hidden sections when user clicks on "Expand hidden lines" button. - - "expandRange" basically merges two hunks into one: takes first hunk, appends all the lines between it and the second hunk and finally appends the second hunk. - - returned "hunks" is the resulting array of hunks with hidden section expanded. - */ - const { expandRange, hunks } = useExpand(diffFile.hunks, oldSource, newSource); - - /* - Here we go over each hunk and extract tokens from it. For example, splitting strings into words, - so we can later highlight changes on a word-by-word basis vs line-by-line. - */ - const tokens = useTokens(hunks, diffMethod, oldSource); - - return ( - - {/* eslint-disable-next-line @typescript-eslint/no-shadow */} - {(hunks) => } - - ); -} - -const renderGutter: RenderGutter = ({ change }) => { - /* - Custom gutter (a column where you normally see line numbers). - Here's I am returning "+" or "-" so the diff is more readable by colorblind people. - */ - if (change.type === 'insert') { - return '+'; - } - - if (change.type === 'delete') { - return '-'; - } - - if (change.type === 'normal') { - return null; - } -}; - -interface RuleDiffTabProps { - oldRule: RuleResponse; - newRule: RuleResponse; -} - -export const RuleDiffTabReactDiffView = ({ oldRule, newRule }: RuleDiffTabProps) => { - const options = [ - { - id: DiffMethod.CHARS, - label: 'Chars', - }, - { - id: DiffMethod.WORDS, - label: 'Words', - }, - { - id: DiffMethod.WORDS_CUSTOM_USING_DMP, - label: 'Words, alternative method (using "diff-match-patch" library)', - }, - { - id: DiffMethod.LINES, - label: 'Lines', - }, - { - id: DiffMethod.SENTENCES, - label: 'Sentences', - }, - ]; - - const [diffMethod, setDiffMethod] = useState(DiffMethod.CHARS); - - const [oldSource, newSource] = useMemo(() => { - return [sortAndStringifyJson(oldRule), sortAndStringifyJson(newRule)]; - }, [oldRule, newRule]); - - return ( - <> - - { - setDiffMethod(optionId as DiffMethod); - }} - legend={{ - children: {'Diffing algorthm'}, - }} - /> - - - - - - ); -}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/unidiff.d.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/unidiff.d.ts deleted file mode 100644 index 0ae55f9542bcb..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/unidiff.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -declare module 'unidiff' { - export interface FormatOptions { - context?: number; - } - - export function diffLines(x: string, y: string): string[]; - - export function formatLines(line: string[], options?: FormatOptions): string; -} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx index 697d6833ebaff..0b2092385e173 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx @@ -32,11 +32,7 @@ import * as i18n from './translations'; import { MlJobUpgradeModal } from '../../../../../detections/components/modals/ml_job_upgrade_modal'; -import { RuleDiffTabAppExperienceTeamPoc } from '../../../../rule_management/components/rule_details/rule_diff_tab_app_experience_team_poc'; -import { RuleDiffTabReactDiffViewerContinued } from '../../../../rule_management/components/rule_details/rule_diff_tab_react_diff_viewer_continued'; -import { RuleDiffTabReactDiffView } from '../../../../rule_management/components/rule_details/rule_diff_tab_react_diff_view'; -import { RuleDiffTabMonaco } from '../../../../rule_management/components/rule_details/rule_diff_tab_monaco'; -import { RuleDiffTabDiff2Html } from '../../../../rule_management/components/rule_details/rule_diff_tab_diff2html'; +import { RuleDiffTabReactDiffViewerContinued } from '../../../../rule_management/components/rule_details/json_diff/rule_diff_tab_react_diff_viewer_continued'; export interface UpgradePrebuiltRulesTableState { /** @@ -266,8 +262,6 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ actions, ]); - // console.log('ReactDiffViewer pre', ReactDiffViewer); - return ( <> @@ -299,9 +293,7 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ } getRuleTabs={(rule, defaultTabs) => { const activeRule = filteredRules.find(({ id }) => rule.id); - const diff = activeRule?.diff; - - if (!diff) { + if (!activeRule) { return defaultTabs; } @@ -318,66 +310,7 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ ), }; - const diffTabReactDiffView = { - id: 'react-diff-view', - name: 'react-diff-view', - content: ( - - - - ), - }; - - const diffTabMonaco = { - id: 'monaco', - name: 'monaco', - content: ( - - - - ), - }; - - const diffTabDiff2Html = { - id: 'diff2html', - name: 'diff2html', - content: ( - - - - ), - }; - - const diffTabAppExperienceTeamPoc = { - id: 'app-experience-team-poc', - name: 'app-experience-team-poc', - content: ( - - - - ), - }; - - return [ - diffTabReactDiffViewerContinued, - diffTabReactDiffView, - diffTabMonaco, - diffTabDiff2Html, - diffTabAppExperienceTeamPoc, - ...defaultTabs, - ]; + return [diffTabReactDiffViewerContinued, ...defaultTabs]; }} /> )} diff --git a/yarn.lock b/yarn.lock index b639e0bd2063c..bc958e8e1c98f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1876,18 +1876,7 @@ "@emotion/utils" "0.11.3" babel-plugin-emotion "^10.0.27" -"@emotion/css@^11.11.0": - version "11.11.0" - resolved "https://registry.yarnpkg.com/@emotion/css/-/css-11.11.0.tgz#dad6a27a77d5e5cbb0287674c3ace76d762563ca" - integrity sha512-m4g6nKzZyiKyJ3WOfdwrBdcujVcpaScIWHAnyNKPm/A/xJKwfXPfQAbEVi1kgexWTDakmg+r2aDj0KvnMTo4oQ== - dependencies: - "@emotion/babel-plugin" "^11.11.0" - "@emotion/cache" "^11.11.0" - "@emotion/serialize" "^1.1.2" - "@emotion/sheet" "^1.2.2" - "@emotion/utils" "^1.2.1" - -"@emotion/css@^11.11.2": +"@emotion/css@^11.11.0", "@emotion/css@^11.11.2": version "11.11.2" resolved "https://registry.yarnpkg.com/@emotion/css/-/css-11.11.2.tgz#e5fa081d0c6e335352e1bc2b05953b61832dca5a" integrity sha512-VJxe1ucoMYMS7DkiMdC2T7PWNbrEI0a39YRiyDvK2qq4lXwjRbVP/z4lpG+odCsRzadlR+1ywwrTzhdm5HNdew== @@ -8975,11 +8964,6 @@ resolved "https://registry.yarnpkg.com/@types/delete-empty/-/delete-empty-2.0.0.tgz#1647ae9e68f708a6ba778531af667ec55bc61964" integrity sha512-sq+kwx8zA9BSugT9N+Jr8/uWjbHMZ+N/meJEzRyT3gmLq/WMtx/iSIpvdpmBUi/cvXl6Kzpvve8G2ESkabFwmg== -"@types/diff@^5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@types/diff/-/diff-5.0.8.tgz#28dc501cc3e7c62d4c5d096afe20755170acf276" - integrity sha512-kR0gRf0wMwpxQq6ME5s+tWk9zVCfJUl98eRkD05HWWRbhPB/eu4V1IbyZAsvzC1Gn4znBJ0HN01M4DGXdBEV8Q== - "@types/ejs@^3.0.6": version "3.0.6" resolved "https://registry.yarnpkg.com/@types/ejs/-/ejs-3.0.6.tgz#aca442289df623bfa8e47c23961f0357847b83fe" @@ -13640,16 +13624,6 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.0.0" -create-emotion@^10.0.14, create-emotion@^10.0.27: - version "10.0.27" - resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-10.0.27.tgz#cb4fa2db750f6ca6f9a001a33fbf1f6c46789503" - integrity sha512-fIK73w82HPPn/RsAij7+Zt8eCE8SptcJ3WoRMfxMtjteYxud8GDTKKld7MYwAX2TVhrw29uR1N/bVGxeStHILg== - dependencies: - "@emotion/cache" "^10.0.27" - "@emotion/serialize" "^0.11.15" - "@emotion/sheet" "0.9.4" - "@emotion/utils" "0.11.3" - create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" @@ -14894,12 +14868,7 @@ diacritics@^1.3.0: resolved "https://registry.yarnpkg.com/diacritics/-/diacritics-1.3.0.tgz#3efa87323ebb863e6696cebb0082d48ff3d6f7a1" integrity sha1-PvqHMj67hj5mls67AILUj/PW96E= -diff-match-patch-line-and-word@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/diff-match-patch-line-and-word/-/diff-match-patch-line-and-word-0.1.3.tgz#0f267c26ab7840785667cccd8c9dc1fb8b288964" - integrity sha512-CR+842NECOQO9qOvlyOf/9IAXMEW8km1Em9YrH8J4wVaeICXtEVJ8H9AZ5Xa0QBTSZUe4DFijGM5dZD5Dl3bEg== - -diff-match-patch@^1.0.0, diff-match-patch@^1.0.4, diff-match-patch@^1.0.5: +diff-match-patch@^1.0.0, diff-match-patch@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37" integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw== @@ -14919,26 +14888,11 @@ diff-sequences@^29.4.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA== -diff2html@^3.1.6, diff2html@^3.4.45: - version "3.4.45" - resolved "https://registry.yarnpkg.com/diff2html/-/diff2html-3.4.45.tgz#6b8cc7af9bb18359635527e5128f40cf3d34ef94" - integrity sha512-1SxsjYZYbxX0GGMYJJM7gM0SpMSHqzvvG0UJVROCDpz4tylH2T+EGiinm2boDmTrMlLueVxGfKNxGNLZ9zDlkQ== - dependencies: - diff "5.1.0" - hogan.js "3.0.2" - optionalDependencies: - highlight.js "11.8.0" - -diff@5.0.0, diff@^5.0.0: +diff@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== -diff@5.1.0, diff@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" - integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== - diff@^1.3.2: version "1.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" @@ -14954,6 +14908,11 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.0.0, diff@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + diffie-hellman@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" @@ -14963,13 +14922,6 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -difflib@^0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/difflib/-/difflib-0.2.4.tgz#b5e30361a6db023176d562892db85940a718f47e" - integrity sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w== - dependencies: - heap ">= 0.2.0" - digest-fetch@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/digest-fetch/-/digest-fetch-1.3.0.tgz#898e69264d00012a23cf26e8a3e40320143fc661" @@ -15446,14 +15398,6 @@ emoticon@^3.2.0: resolved "https://registry.yarnpkg.com/emoticon/-/emoticon-3.2.0.tgz#c008ca7d7620fac742fe1bf4af8ff8fed154ae7f" integrity sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg== -emotion@^10.0.14: - version "10.0.27" - resolved "https://registry.yarnpkg.com/emotion/-/emotion-10.0.27.tgz#f9ca5df98630980a23c819a56262560562e5d75e" - integrity sha512-2xdDzdWWzue8R8lu4G76uWX5WhyQuzATon9LmNeCy/2BHVC6dsEpfhN1a0qhELgtDVdjyEA6J8Y/VlI5ZnaH0g== - dependencies: - babel-plugin-emotion "^10.0.27" - create-emotion "^10.0.27" - enabled@2.0.x: version "2.0.0" resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" @@ -17536,11 +17480,6 @@ git-hooks-list@1.0.3: resolved "https://registry.yarnpkg.com/git-hooks-list/-/git-hooks-list-1.0.3.tgz#be5baaf78203ce342f2f844a9d2b03dba1b45156" integrity sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ== -gitdiff-parser@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/gitdiff-parser/-/gitdiff-parser-0.3.1.tgz#5eb3e66eb7862810ba962fab762134071601baa5" - integrity sha512-YQJnY8aew65id8okGxKCksH3efDCJ9HzV7M9rsvd65habf39Pkh4cgYJ27AaoDMqo1X98pgNJhNMrm/kpV7UVQ== - github-from-package@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" @@ -18270,11 +18209,6 @@ he@1.2.0, he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -"heap@>= 0.2.0": - version "0.2.7" - resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc" - integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg== - heap@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" @@ -18285,11 +18219,6 @@ hexoid@^1.0.0: resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== -highlight.js@11.8.0: - version "11.8.0" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.8.0.tgz#966518ea83257bae2e7c9a48596231856555bb65" - integrity sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg== - highlight.js@^10.1.1, highlight.js@~10.4.0: version "10.4.1" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.4.1.tgz#d48fbcf4a9971c4361b3f95f302747afe19dbad0" @@ -18328,14 +18257,6 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hogan.js@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd" - integrity sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg== - dependencies: - mkdirp "0.3.0" - nopt "1.0.10" - hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.5, hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -21914,11 +21835,6 @@ memfs@^3.1.2, memfs@^3.4.3: resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0" integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA== -memoize-one@^5.0.4: - version "5.2.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" - integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== - memoize-one@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" @@ -22367,11 +22283,6 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" - integrity sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew== - "mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -23063,13 +22974,6 @@ nodemailer@^6.6.2: resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.6.2.tgz#e184c9ed5bee245a3e0bcabc7255866385757114" integrity sha512-YSzu7TLbI+bsjCis/TZlAXBoM4y93HhlIgo0P5oiA2ua9Z4k+E2Fod//ybIzdJxOlXGRcHIh/WaeCBehvxZb/Q== -nopt@1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== - dependencies: - abbrev "1" - nopt@^4.0.1, nopt@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" @@ -25406,18 +25310,6 @@ react-colorful@^5.1.2: resolved "https://registry.yarnpkg.com/react-colorful/-/react-colorful-5.5.1.tgz#29d9c4e496f2ca784dd2bb5053a3a4340cfaf784" integrity sha512-M1TJH2X3RXEt12sWkpa6hLc/bbYS0H6F4rIqjQZ+RxNBstpY67d9TrFXtqdZwhpmBXcCwEi7stKqFue3ZRkiOg== -react-diff-view@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-diff-view/-/react-diff-view-3.2.0.tgz#8fbf04782d78423903a59202ce7533f6312c1cc3" - integrity sha512-p58XoqMxgt71ujpiDQTs9Za3nqTawt1E4bTzKsYSqr8I8br6cjQj1b66HxGnV8Yrc6MD6iQPqS1aZiFoGqEw+g== - dependencies: - classnames "^2.3.2" - diff-match-patch "^1.0.5" - gitdiff-parser "^0.3.1" - lodash "^4.17.21" - shallow-equal "^3.1.0" - warning "^4.0.3" - react-diff-viewer-continued@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/react-diff-viewer-continued/-/react-diff-viewer-continued-3.3.1.tgz#1ef6af86fc92ad721a5461f8f3c44f74381ea81d" @@ -25429,18 +25321,6 @@ react-diff-viewer-continued@^3.3.1: memoize-one "^6.0.0" prop-types "^15.8.1" -react-diff-viewer@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/react-diff-viewer/-/react-diff-viewer-3.1.1.tgz#21ac9c891193d05a3734bfd6bd54b107ee6d46cc" - integrity sha512-rmvwNdcClp6ZWdS11m1m01UnBA4OwYaLG/li0dB781e/bQEzsGyj+qewVd6W5ztBwseQ72pO7nwaCcq5jnlzcw== - dependencies: - classnames "^2.2.6" - create-emotion "^10.0.14" - diff "^4.0.1" - emotion "^10.0.14" - memoize-one "^5.0.4" - prop-types "^15.6.2" - react-docgen-typescript@^2.0.0, react-docgen-typescript@^2.1.1: version "2.2.2" resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz#4611055e569edc071204aadb20e1c93e1ab1659c" @@ -25554,16 +25434,6 @@ react-focus-on@^3.9.1: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-gh-like-diff@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/react-gh-like-diff/-/react-gh-like-diff-2.0.2.tgz#9a0f91511d7af20407666e5950d2056db0600d62" - integrity sha512-Cd5Kjijx74kz0POQNCSRvFnpfvY4E28NxWea8z0UPZ1J6b2RThRkMBfoD/FwaFvrT/7XeYk5SrQ8qtc0e8iRoA== - dependencies: - diff2html "^3.1.6" - difflib "^0.2.4" - prop-types "^15.7.2" - recompose "^0.30.0" - react-grid-layout@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-1.3.4.tgz#4fa819be24a1ba9268aa11b82d63afc4762a32ff" @@ -27322,11 +27192,6 @@ shallow-copy@~0.0.1: resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" integrity sha1-QV9CcC1z2BAzApLMXuhurhoRoXA= -shallow-equal@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-3.1.0.tgz#e7a54bac629c7f248eff6c2f5b63122ba4320bec" - integrity sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg== - shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" @@ -29626,13 +29491,6 @@ unicode-trie@^2.0.0: pako "^0.2.5" tiny-inflate "^1.0.0" -unidiff@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unidiff/-/unidiff-1.0.4.tgz#45096a898285821c51e22e84be4215c05d6511cd" - integrity sha512-ynU0vsAXw0ir8roa+xPCUHmnJ5goc5BTM2Kuc3IJd8UwgaeRs7VSD5+eeaQL+xp1JtB92hu/Zy/Lgy7RZcr1pQ== - dependencies: - diff "^5.1.0" - unified@9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.0.tgz#67a62c627c40589edebbf60f53edfd4d822027f8" @@ -30642,7 +30500,7 @@ walker@^1.0.7, walker@^1.0.8, walker@~1.0.5: dependencies: makeerror "1.0.12" -warning@^4.0.2, warning@^4.0.3: +warning@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==