UNPKG

@wordpress/editor

Version:
197 lines (196 loc) 7.26 kB
// packages/editor/src/components/post-revisions-preview/revisions-code-diff.js import { diffLines } from "diff"; import { Spinner } from "@wordpress/components"; import { store as coreStore } from "@wordpress/core-data"; import { useSelect } from "@wordpress/data"; import { useMemo } from "@wordpress/element"; import { __, _x } from "@wordpress/i18n"; import { VisuallyHidden } from "@wordpress/ui"; import { store as editorStore } from "../../store/index.mjs"; import { buildRevisionsPageQuery } from "../../store/private-selectors.mjs"; import { unlock } from "../../lock-unlock.mjs"; import { jsx, jsxs } from "react/jsx-runtime"; var MAX_DIFF_EDIT_LENGTH = 1e3; var DIFF_TIMEOUT = 100; function splitLines(value) { const lines = value.split("\n"); if (lines[lines.length - 1] === "") { lines.pop(); } return lines; } function getCodeDiffRows(previousContent, currentContent, showDiff) { let parts = [{ value: currentContent }]; if (showDiff) { parts = diffLines(previousContent, currentContent, { maxEditLength: MAX_DIFF_EDIT_LENGTH, timeout: DIFF_TIMEOUT }); if (!parts) { parts = [ { value: previousContent, removed: true }, { value: currentContent, added: true } ]; } } let previousLineNumber = 1; let currentLineNumber = 1; return parts.flatMap((part) => { let status = "unchanged"; if (part.added) { status = "added"; } else if (part.removed) { status = "removed"; } return splitLines(part.value).map((value) => { const row = { value, status, previousLineNumber: null, currentLineNumber: null }; if (status !== "added" && showDiff) { row.previousLineNumber = previousLineNumber++; } if (status !== "removed") { row.currentLineNumber = currentLineNumber++; } return row; }); }); } function getCodeDiffDisplayState({ previousRevision, showDiff, hasOlderRevisionPage, hasFinishedPreviousRevision }) { const needsPreviousRevision = showDiff && previousRevision === null && hasOlderRevisionPage; return { showDiff: showDiff && !(needsPreviousRevision && hasFinishedPreviousRevision), isPreviousRevisionLoading: needsPreviousRevision && !hasFinishedPreviousRevision }; } function ConnectedRevisionsCodeDiff() { const revisionDiff = useSelect((select) => { const editorSelectors = select(editorStore); const coreSelectors = select(coreStore); const { getCurrentRevision, getPreviousRevision, getRevisionPage, getRevisionsPerPage, isShowingRevisionDiff } = unlock(editorSelectors); const _previousRevision = getPreviousRevision(); const _showDiff = isShowingRevisionDiff(); const revisionPage = getRevisionPage(); const totalPages = Math.ceil( editorSelectors.getCurrentPostRevisionsCount() / getRevisionsPerPage() ) || 1; const hasOlderRevisionPage = revisionPage < totalPages; let hasFinishedPreviousRevision = true; if (_showDiff && _previousRevision === null && hasOlderRevisionPage) { const postType = editorSelectors.getCurrentPostType(); const postId = editorSelectors.getCurrentPostId(); const entityConfig = coreSelectors.getEntityConfig( "postType", postType ); const revisionKey = entityConfig?.revisionKey || "id"; hasFinishedPreviousRevision = coreSelectors.hasFinishedResolution( "getRevisions", [ "postType", postType, postId, buildRevisionsPageQuery(revisionKey, revisionPage + 1) ] ); } return { revision: getCurrentRevision(), previousRevision: _previousRevision, ...getCodeDiffDisplayState({ previousRevision: _previousRevision, showDiff: _showDiff, hasOlderRevisionPage, hasFinishedPreviousRevision }) }; }, []); return /* @__PURE__ */ jsx(RevisionsCodeDiff, { ...revisionDiff }); } function RevisionsCodeDiff({ revision, previousRevision, showDiff, isPreviousRevisionLoading }) { const rows = useMemo(() => { if (!revision || isPreviousRevisionLoading) { return []; } return getCodeDiffRows( previousRevision?.content?.raw ?? "", revision.content?.raw ?? "", showDiff ); }, [revision, previousRevision, showDiff, isPreviousRevisionLoading]); if (!revision || isPreviousRevisionLoading) { return /* @__PURE__ */ jsx("div", { className: "editor-revisions-canvas__loading", children: /* @__PURE__ */ jsx(Spinner, {}) }); } const label = showDiff ? __("Code changes") : __("Revision code"); return /* @__PURE__ */ jsx( "div", { className: "editor-revisions-code-diff", role: "region", "aria-label": label, tabIndex: 0, children: rows.length ? /* @__PURE__ */ jsxs("table", { className: "editor-revisions-code-diff__table", children: [ /* @__PURE__ */ jsx(VisuallyHidden, { render: /* @__PURE__ */ jsx("caption", {}), children: label }), /* @__PURE__ */ jsx(VisuallyHidden, { render: /* @__PURE__ */ jsx("thead", {}), children: /* @__PURE__ */ jsxs("tr", { children: [ showDiff && /* @__PURE__ */ jsx("th", { children: __("Previous line") }), /* @__PURE__ */ jsx("th", { children: __("Current line") }), showDiff && /* @__PURE__ */ jsx("th", { children: _x("Change", "noun") }), /* @__PURE__ */ jsx("th", { children: __("Code") }) ] }) }), /* @__PURE__ */ jsx("tbody", { children: rows.map((row, index) => { let marker = ""; let statusLabel = __("Unchanged"); if (row.status === "added") { marker = "+"; statusLabel = __("Added"); } else if (row.status === "removed") { marker = "−"; statusLabel = __("Removed"); } return /* @__PURE__ */ jsxs( "tr", { className: `editor-revisions-code-diff__line is-${row.status}`, children: [ showDiff && /* @__PURE__ */ jsx("td", { className: "editor-revisions-code-diff__line-number is-previous", children: row.previousLineNumber }), /* @__PURE__ */ jsx("td", { className: "editor-revisions-code-diff__line-number is-current", children: row.currentLineNumber }), showDiff && /* @__PURE__ */ jsxs("td", { className: "editor-revisions-code-diff__marker", children: [ /* @__PURE__ */ jsx(VisuallyHidden, { children: statusLabel }), /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: marker }) ] }), /* @__PURE__ */ jsx("td", { className: "editor-revisions-code-diff__code", children: /* @__PURE__ */ jsx("code", { children: row.value }) }) ] }, index ); }) }) ] }) : /* @__PURE__ */ jsx("p", { className: "editor-revisions-code-diff__empty", children: __("This revision is empty.") }) } ); } export { RevisionsCodeDiff, ConnectedRevisionsCodeDiff as default, getCodeDiffDisplayState, getCodeDiffRows }; //# sourceMappingURL=revisions-code-diff.mjs.map