UNPKG

react-diff-viewer-continued

Version:

Continuation of a simple and beautiful text diff viewer component made with diff and React

419 lines (418 loc) 12.9 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import createEmotion from "@emotion/css/create-instance"; export default (styleOverride, useDarkTheme = false, nonce = "") => { const { variables: overrideVariables = {} } = styleOverride, styles = __rest(styleOverride, ["variables"]); const themeVariables = { light: Object.assign({ diffViewerBackground: "#fff", diffViewerColor: "#212529", addedBackground: "#e6ffed", addedColor: "#24292e", removedBackground: "#ffeef0", removedColor: "#24292e", changedBackground: "#fffbdd", wordAddedBackground: "#acf2bd", wordRemovedBackground: "#fdb8c0", addedGutterBackground: "#cdffd8", removedGutterBackground: "#ffdce0", gutterBackground: "#f7f7f7", gutterBackgroundDark: "#f3f1f1", highlightBackground: "#fffbdd", highlightGutterBackground: "#fff5b1", codeFoldGutterBackground: "#dbedff", codeFoldBackground: "#f1f8ff", emptyLineBackground: "#fafbfc", gutterColor: "#212529", addedGutterColor: "#212529", removedGutterColor: "#212529", codeFoldContentColor: "#212529", diffViewerTitleBackground: "#fafbfc", diffViewerTitleColor: "#212529", diffViewerTitleBorderColor: "#eee", }, (overrideVariables.light || {})), dark: Object.assign({ diffViewerBackground: "#2e303c", diffViewerColor: "#FFF", addedBackground: "#2ea04326", addedColor: "white", removedBackground: "#f851491a", removedColor: "white", changedBackground: "#3e302c", wordAddedBackground: "#2ea04366", wordRemovedBackground: "#f8514966", addedGutterBackground: "#3fb9504d", removedGutterBackground: "#f851494d", gutterBackground: "#2c2f3a", gutterBackgroundDark: "#262933", highlightBackground: "#2a3967", highlightGutterBackground: "#2d4077", codeFoldGutterBackground: "#262831", codeFoldBackground: "#262831", emptyLineBackground: "#363946", gutterColor: "#f0f6fc", addedGutterColor: "#f0f6fc", removedGutterColor: "#f0f6fc", codeFoldContentColor: "#9198a1", diffViewerTitleBackground: "#2f323e", diffViewerTitleColor: "#f0f6fc", diffViewerTitleBorderColor: "#353846", }, (overrideVariables.dark || {})), }; const variables = useDarkTheme ? themeVariables.dark : themeVariables.light; const { css, cx } = createEmotion({ key: "react-diff", nonce }); const content = css({ width: "auto", overflow: "hidden", label: "content", }); const splitView = css({ label: "split-view", }); const stickyHeader = css({ position: "sticky", top: 0, zIndex: 2, label: "sticky-header", }); const summary = css({ background: variables.diffViewerTitleBackground, color: variables.diffViewerTitleColor, padding: "0.5em 1em", display: "flex", alignItems: "center", gap: "0.5em", fontFamily: "monospace", fontSize: 12, fill: variables.diffViewerTitleColor, }); const columnHeaders = css({ display: "flex", label: "column-headers", }); const diffContainer = css({ width: "100%", minWidth: "1000px", overflowX: "auto", tableLayout: "fixed", fontSize: 12, background: variables.diffViewerBackground, pre: { margin: 0, whiteSpace: "pre-wrap", lineHeight: "1.6em", width: "fit-content", }, label: "diff-container", borderCollapse: "collapse", "@media (max-width: 768px)": { minWidth: "unset", }, }); const lineContent = css({ overflow: "hidden", width: "100%", }); const contentText = css({ color: variables.diffViewerColor, whiteSpace: "pre-wrap", fontFamily: "monospace", lineBreak: "anywhere", textDecoration: "none", label: "content-text", }); const unselectable = css({ userSelect: "none", label: "unselectable", }); const noWrap = css({ label: "no-wrap", pre: { whiteSpace: "pre", }, [`.${contentText}`]: { whiteSpace: "pre", lineBreak: "auto", }, }); const allExpandButton = css({ background: "transparent", border: "none", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", margin: 0, label: "all-expand-button", ":hover": { fill: variables.addedGutterColor, }, ":focus": { outline: `1px ${variables.addedGutterColor} solid`, }, }); const titleBlock = css({ background: variables.diffViewerTitleBackground, padding: "0.5em", lineHeight: "1.4em", height: "2.4em", overflow: "hidden", width: "50%", borderBottom: `1px solid ${variables.diffViewerTitleBorderColor}`, boxSizing: "border-box", fontSize: 12, label: "title-block", ":only-child": { width: "100%", }, ":last-child:not(:only-child)": { borderLeft: `1px solid ${variables.diffViewerTitleBorderColor}`, }, [`.${contentText}`]: { color: variables.diffViewerTitleColor, }, }); const lineNumber = css({ color: variables.gutterColor, label: "line-number", }); const diffRemoved = css({ background: variables.removedBackground, color: variables.removedColor, pre: { color: variables.removedColor, }, [`.${lineNumber}`]: { color: variables.removedGutterColor, }, label: "diff-removed", }); const diffAdded = css({ background: variables.addedBackground, color: variables.addedColor, pre: { color: variables.addedColor, }, [`.${lineNumber}`]: { color: variables.addedGutterColor, }, label: "diff-added", }); const diffChanged = css({ background: variables.changedBackground, [`.${lineNumber}`]: { color: variables.gutterColor, }, label: "diff-changed", }); const wordDiff = css({ display: "inline", textDecoration: "none", label: "word-diff", }); const wordAdded = css({ background: variables.wordAddedBackground, label: "word-added", }); const wordRemoved = css({ background: variables.wordRemovedBackground, label: "word-removed", }); const codeFoldGutter = css({ backgroundColor: variables.codeFoldGutterBackground, label: "code-fold-gutter", minWidth: "50px", width: "50px", textAlign: "center", fill: variables.codeFoldContentColor, }); const codeFoldContentContainer = css({ padding: "", }); const codeFoldExpandButton = css({ background: variables.codeFoldBackground, cursor: "pointer", display: "inline", margin: 0, border: "none", fill: variables.codeFoldContentColor, label: "code-fold-expand-button", }); const codeFoldContent = css({ color: variables.codeFoldContentColor, fontFamily: "monospace", label: "code-fold-content", }); const block = css({ display: "block", width: "10px", height: "10px", backgroundColor: "#ddd", borderWidth: "1px", borderStyle: "solid", borderColor: variables.diffViewerTitleBorderColor, }); const blockAddition = css({ backgroundColor: variables.wordAddedBackground, }); const blockDeletion = css({ backgroundColor: variables.wordRemovedBackground, }); const codeFold = css({ backgroundColor: variables.codeFoldBackground, fontSize: 12, alignItems: "center", userSelect: "none", fontWeight: 700, cursor: "pointer", label: "code-fold", "&:hover": { color: variables.diffViewerColor, fill: variables.diffViewerColor, "& *": { color: variables.diffViewerColor, fill: variables.diffViewerColor, }, }, a: { textDecoration: "underline !important", cursor: "pointer", pre: { display: "inline", }, }, }); const emptyLine = css({ backgroundColor: variables.emptyLineBackground, label: "empty-line", }); const marker = css({ width: 28, paddingLeft: 10, paddingRight: 10, userSelect: "none", label: "marker", [`&.${diffAdded}`]: { pre: { color: variables.addedColor, }, }, [`&.${diffRemoved}`]: { pre: { color: variables.removedColor, }, }, }); const highlightedLine = css({ background: variables.highlightBackground, label: "highlighted-line", [`.${wordAdded}, .${wordRemoved}`]: { backgroundColor: "initial", }, }); const highlightedGutter = css({ label: "highlighted-gutter", }); const gutter = css({ userSelect: "none", minWidth: 50, width: "50px", padding: "0 10px", whiteSpace: "nowrap", label: "gutter", textAlign: "center", color: variables.gutterColor, background: variables.gutterBackground, "&:hover": { cursor: "pointer", background: variables.gutterBackgroundDark, pre: { opacity: 1, }, }, pre: { opacity: 0.5, textAlign: "center", width: "100%", }, [`&.${diffAdded}`]: { background: variables.addedGutterBackground, }, [`&.${diffRemoved}`]: { background: variables.removedGutterBackground, }, [`&.${highlightedGutter}`]: { background: variables.highlightGutterBackground, "&:hover": { background: variables.highlightGutterBackground, }, }, }); const emptyGutter = css({ "&:hover": { background: variables.gutterBackground, cursor: "initial", }, label: "empty-gutter", }); const line = css({ verticalAlign: "baseline", label: "line", textDecoration: "none", }); const column = css({}); const defaultStyles = { diffContainer, diffRemoved, diffAdded, diffChanged, splitView, marker, highlightedGutter, highlightedLine, gutter, line, lineContent, wordDiff, wordAdded, summary, block, blockAddition, blockDeletion, wordRemoved, noSelect: unselectable, noWrap, codeFoldGutter, codeFoldExpandButton, codeFoldContentContainer, codeFold, emptyGutter, emptyLine, lineNumber, contentText, content, column, codeFoldContent, stickyHeader, columnHeaders, titleBlock, allExpandButton, }; const computerOverrideStyles = Object.keys(styles).reduce((acc, key) => (Object.assign(Object.assign({}, acc), { [key]: css(styles[key]), })), {}); return Object.keys(defaultStyles).reduce((acc, key) => (Object.assign(Object.assign({}, acc), { [key]: computerOverrideStyles[key] ? cx(defaultStyles[key], computerOverrideStyles[key]) : defaultStyles[key], })), {}); };