UNPKG

next

Version:

The React Framework

243 lines (241 loc) • 11.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "PseudoHtmlDiff", { enumerable: true, get: function() { return PseudoHtmlDiff; } }); const _jsxruntime = require("react/jsx-runtime"); const _react = require("react"); const _CollapseIcon = require("../../icons/CollapseIcon"); function getAdjacentProps(isAdj) { return { 'data-nextjs-container-errors-pseudo-html--tag-adjacent': isAdj }; } function PseudoHtmlDiff(param) { let { componentStackFrames, firstContent, secondContent, hydrationMismatchType, reactOutputComponentDiff, ...props } = param; const isHtmlTagsWarning = hydrationMismatchType === 'tag'; const isReactHydrationDiff = !!reactOutputComponentDiff; // For text mismatch, mismatched text will take 2 rows, so we display 4 rows of component stack const MAX_NON_COLLAPSED_FRAMES = isHtmlTagsWarning ? 6 : 4; const [isHtmlCollapsed, toggleCollapseHtml] = (0, _react.useState)(true); const htmlComponents = (0, _react.useMemo)(()=>{ const componentStacks = []; // React 19 unified mismatch if (isReactHydrationDiff) { let currentComponentIndex = componentStackFrames.length - 1; const reactComponentDiffLines = reactOutputComponentDiff.split('\n'); const diffHtmlStack = []; reactComponentDiffLines.forEach((line, index)=>{ let trimmedLine = line.trim(); const isDiffLine = trimmedLine[0] === '+' || trimmedLine[0] === '-'; const spaces = ' '.repeat(Math.max(componentStacks.length * 2, 1)); if (isDiffLine) { const sign = trimmedLine[0]; trimmedLine = trimmedLine.slice(1).trim() // trim spaces after sign ; diffHtmlStack.push(/*#__PURE__*/ (0, _jsxruntime.jsxs)("span", { "data-nextjs-container-errors-pseudo-html--diff": sign === '+' ? 'add' : 'remove', children: [ sign, spaces, trimmedLine, '\n' ] }, 'comp-diff' + index)); } else if (currentComponentIndex >= 0) { const isUserLandComponent = trimmedLine.startsWith('<' + componentStackFrames[currentComponentIndex].component); // If it's matched userland component or it's ... we will keep the component stack in diff if (isUserLandComponent || trimmedLine === '...') { currentComponentIndex--; componentStacks.push(/*#__PURE__*/ (0, _jsxruntime.jsxs)("span", { children: [ spaces, trimmedLine, '\n' ] }, 'comp-diff' + index)); } else if (!isHtmlCollapsed) { componentStacks.push(/*#__PURE__*/ (0, _jsxruntime.jsxs)("span", { children: [ spaces, trimmedLine, '\n' ] }, 'comp-diff' + index)); } } else if (!isHtmlCollapsed) { // In general, if it's not collapsed, show the whole diff componentStacks.push(/*#__PURE__*/ (0, _jsxruntime.jsxs)("span", { children: [ spaces, trimmedLine, '\n' ] }, 'comp-diff' + index)); } }); return componentStacks.concat(diffHtmlStack); } const nestedHtmlStack = []; const tagNames = isHtmlTagsWarning ? [ firstContent.replace(/<|>/g, ''), secondContent.replace(/<|>/g, '') ] : []; let lastText = ''; const componentStack = componentStackFrames.map((frame)=>frame.component).reverse(); // [child index, parent index] const matchedIndex = [ -1, -1 ]; if (isHtmlTagsWarning) { // Reverse search for the child tag for(let i = componentStack.length - 1; i >= 0; i--){ if (componentStack[i] === tagNames[0]) { matchedIndex[0] = i; break; } } // Start searching parent tag from child tag above for(let i = matchedIndex[0] - 1; i >= 0; i--){ if (componentStack[i] === tagNames[1]) { matchedIndex[1] = i; break; } } } componentStack.forEach((component, index, componentList)=>{ const spaces = ' '.repeat(nestedHtmlStack.length * 2); // When component is the server or client tag name, highlight it const isHighlightedTag = isHtmlTagsWarning ? index === matchedIndex[0] || index === matchedIndex[1] : tagNames.includes(component); const isAdjacentTag = isHighlightedTag || Math.abs(index - matchedIndex[0]) <= 1 || Math.abs(index - matchedIndex[1]) <= 1; const isLastFewFrames = !isHtmlTagsWarning && index >= componentList.length - 6; const adjProps = getAdjacentProps(isAdjacentTag); if (isHtmlTagsWarning && isAdjacentTag || isLastFewFrames) { const codeLine = /*#__PURE__*/ (0, _jsxruntime.jsxs)("span", { children: [ spaces, /*#__PURE__*/ (0, _jsxruntime.jsx)("span", { ...adjProps, ...isHighlightedTag ? { 'data-nextjs-container-errors-pseudo-html--tag-error': true } : undefined, children: "<" + component + ">\n" }) ] }); lastText = component; const wrappedCodeLine = /*#__PURE__*/ (0, _jsxruntime.jsxs)(_react.Fragment, { children: [ codeLine, isHighlightedTag && /*#__PURE__*/ (0, _jsxruntime.jsx)("span", { "data-nextjs-container-errors-pseudo-html--hint": true, children: spaces + '^'.repeat(component.length + 2) + '\n' }) ] }, nestedHtmlStack.length); nestedHtmlStack.push(wrappedCodeLine); } else { if (nestedHtmlStack.length >= MAX_NON_COLLAPSED_FRAMES && isHtmlCollapsed) { return; } if (!isHtmlCollapsed || isLastFewFrames) { nestedHtmlStack.push(/*#__PURE__*/ (0, _react.createElement)("span", { ...adjProps, key: nestedHtmlStack.length, children: [ spaces, '<' + component + '>\n' ] })); } else if (isHtmlCollapsed && lastText !== '...') { lastText = '...'; nestedHtmlStack.push(/*#__PURE__*/ (0, _react.createElement)("span", { ...adjProps, key: nestedHtmlStack.length, children: [ spaces, '...\n' ] })); } } }); // Hydration mismatch: text or text-tag if (!isHtmlTagsWarning) { const spaces = ' '.repeat(nestedHtmlStack.length * 2); let wrappedCodeLine; if (hydrationMismatchType === 'text') { // hydration type is "text", represent [server content, client content] wrappedCodeLine = /*#__PURE__*/ (0, _jsxruntime.jsxs)(_react.Fragment, { children: [ /*#__PURE__*/ (0, _jsxruntime.jsx)("span", { "data-nextjs-container-errors-pseudo-html--diff": "remove", children: spaces + ('"' + firstContent + '"\n') }), /*#__PURE__*/ (0, _jsxruntime.jsx)("span", { "data-nextjs-container-errors-pseudo-html--diff": "add", children: spaces + ('"' + secondContent + '"\n') }) ] }, nestedHtmlStack.length); } else if (hydrationMismatchType === 'text-in-tag') { // hydration type is "text-in-tag", represent [parent tag, mismatch content] wrappedCodeLine = /*#__PURE__*/ (0, _jsxruntime.jsxs)(_react.Fragment, { children: [ /*#__PURE__*/ (0, _jsxruntime.jsx)("span", { "data-nextjs-container-errors-pseudo-html--tag-adjacent": true, children: spaces + ("<" + secondContent + ">\n") }), /*#__PURE__*/ (0, _jsxruntime.jsx)("span", { "data-nextjs-container-errors-pseudo-html--diff": "remove", children: spaces + (' "' + firstContent + '"\n') }) ] }, nestedHtmlStack.length); } nestedHtmlStack.push(wrappedCodeLine); } return nestedHtmlStack; }, [ componentStackFrames, isHtmlCollapsed, firstContent, secondContent, isHtmlTagsWarning, hydrationMismatchType, MAX_NON_COLLAPSED_FRAMES, isReactHydrationDiff, reactOutputComponentDiff ]); return /*#__PURE__*/ (0, _jsxruntime.jsxs)("div", { "data-nextjs-container-errors-pseudo-html": true, children: [ /*#__PURE__*/ (0, _jsxruntime.jsx)("button", { tabIndex: 10, "data-nextjs-container-errors-pseudo-html-collapse": true, onClick: ()=>toggleCollapseHtml(!isHtmlCollapsed), children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_CollapseIcon.CollapseIcon, { collapsed: isHtmlCollapsed }) }), /*#__PURE__*/ (0, _jsxruntime.jsx)("pre", { ...props, children: /*#__PURE__*/ (0, _jsxruntime.jsx)("code", { children: htmlComponents }) }) ] }); } if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') { Object.defineProperty(exports.default, '__esModule', { value: true }); Object.assign(exports.default, exports); module.exports = exports.default; } //# sourceMappingURL=component-stack-pseudo-html.js.map