MCPcopy Create free account
hub / github.com/donghaxkim/react-rewrite / mutateTextContent

Function mutateTextContent

packages/cli/src/transform.ts:568–693  ·  view source on GitHub ↗
(
  target: any,
  originalText: string,
  newText: string,
  source?: string,
  cursorOffset?: number,
  textAnchor?: TextEditAnchor,
)

Source from the content-addressed store, hash-verified

566 * 3. Expression match: text is in a JSXExpressionContainer StringLiteral
567 */
568export function mutateTextContent(
569 target: any,
570 originalText: string,
571 newText: string,
572 source?: string,
573 cursorOffset?: number,
574 textAnchor?: TextEditAnchor,
575): boolean {
576 const children = target.node.children;
577 const tag = target.node.openingElement?.name?.name || target.node.openingElement?.name?.property?.name || "?";
578 const line = target.node.openingElement?.loc?.start?.line;
579 const finish = (): true => {
580 canonicalizeEditedTextSubtree(target.node, source);
581 return true;
582 };
583 logger.debug(`[mutateText] target=<${tag}> line=${line} children=${children?.length ?? "null"} original="${originalText.slice(0,60)}" new="${newText.slice(0,60)}"`);
584 if (!children) return false;
585
586 // Diagnostic: dump children types and values to see what we're working with
587 for (let i = 0; i < children.length; i++) {
588 const c = children[i];
589 if (c.type === "JSXText") {
590 logger.debug(`[mutateText] child[${i}] JSXText: "${c.value.slice(0, 80).replace(/\n/g, "\\n")}"`);
591 } else if (c.type === "JSXElement") {
592 const childTag = c.openingElement?.name?.name || c.openingElement?.name?.property?.name || "?";
593 logger.debug(`[mutateText] child[${i}] JSXElement: <${childTag}>`);
594 } else if (c.type === "JSXExpressionContainer") {
595 logger.debug(`[mutateText] child[${i}] JSXExpr: ${c.expression?.type} = "${String(c.expression?.value ?? c.expression?.type).slice(0, 60)}"`);
596 } else {
597 logger.debug(`[mutateText] child[${i}] ${c.type}`);
598 }
599 }
600
601 // Case 1: Exact match against a single JSXText child
602 // Use normalizeWs because React collapses JSX whitespace (newlines → spaces)
603 // but the AST retains raw whitespace — DOM textContent won't match without this.
604 for (let i = 0; i < children.length; i++) {
605 const child = children[i];
606 if (child.type === "JSXText") {
607 const trimmed = child.value.trim();
608 if (normalizeWs(trimmed) === normalizeWs(originalText.trim())) {
609 const idx = child.value.indexOf(trimmed);
610 const prefixWs = child.value.slice(0, idx);
611 const suffixWs = child.value.slice(idx + trimmed.length);
612 child.value = prefixWs + newText + suffixWs;
613 return finish();
614 }
615 }
616 if (
617 child.type === "JSXExpressionContainer" &&
618 child.expression.type === "StringLiteral" &&
619 child.expression.value === originalText
620 ) {
621 child.expression.value = newText;
622 return finish();
623 }
624 }
625

Callers 2

applyOpFunction · 0.85
updateTextContentFunction · 0.85

Calls 10

finishFunction · 0.85
getRenderedElementTextFunction · 0.85
insertInJSXTextAtOffsetFunction · 0.85
replaceCrossElementTextFunction · 0.85
findFirstJSXTextFunction · 0.85
normalizeWsFunction · 0.70
findTextDiffFunction · 0.70
resolveAnchoredStartFunction · 0.70

Tested by

no test coverage detected