update
Browse files
app.py
CHANGED
|
@@ -288,6 +288,10 @@ Format Rules:
|
|
| 288 |
9. IMPORTANT: The SEARCH block must *exactly* match the current code, including indentation and whitespace.
|
| 289 |
10. For multi-file projects, specify which file you're modifying by starting with the filename before the search/replace block.
|
| 290 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 291 |
Example Modifying Code:
|
| 292 |
```
|
| 293 |
Some explanation...
|
|
@@ -1573,6 +1577,49 @@ def apply_search_replace_changes(original_content: str, changes_text: str) -> st
|
|
| 1573 |
if not changes_text.strip():
|
| 1574 |
return original_content
|
| 1575 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1576 |
# Split the changes text into individual search/replace blocks
|
| 1577 |
blocks = []
|
| 1578 |
current_block = ""
|
|
@@ -1628,7 +1675,41 @@ def apply_search_replace_changes(original_content: str, changes_text: str) -> st
|
|
| 1628 |
if search_text in modified_content:
|
| 1629 |
modified_content = modified_content.replace(search_text, replace_text)
|
| 1630 |
else:
|
| 1631 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1632 |
|
| 1633 |
return modified_content
|
| 1634 |
|
|
|
|
| 288 |
9. IMPORTANT: The SEARCH block must *exactly* match the current code, including indentation and whitespace.
|
| 289 |
10. For multi-file projects, specify which file you're modifying by starting with the filename before the search/replace block.
|
| 290 |
|
| 291 |
+
CSS Changes Guidance:
|
| 292 |
+
- When changing a CSS property that conflicts with other properties (e.g., replacing a gradient text with a solid color), replace the entire CSS rule for that selector instead of only adding the new property. For example, replace the full `.hero h1 { ... }` block, removing `background-clip` and `color: transparent` when setting `color: #fff`.
|
| 293 |
+
- Ensure search blocks match the current code exactly (spaces, indentation, and line breaks) so replacements apply correctly.
|
| 294 |
+
|
| 295 |
Example Modifying Code:
|
| 296 |
```
|
| 297 |
Some explanation...
|
|
|
|
| 1577 |
if not changes_text.strip():
|
| 1578 |
return original_content
|
| 1579 |
|
| 1580 |
+
# If the model didn't use the block markers, try a CSS-rule fallback where
|
| 1581 |
+
# provided blocks like `.selector { ... }` replace matching CSS rules.
|
| 1582 |
+
if (SEARCH_START not in changes_text) and (DIVIDER not in changes_text) and (REPLACE_END not in changes_text):
|
| 1583 |
+
try:
|
| 1584 |
+
import re # Local import to avoid global side effects
|
| 1585 |
+
updated_content = original_content
|
| 1586 |
+
replaced_any_rule = False
|
| 1587 |
+
# Find CSS-like rule blocks in the changes_text
|
| 1588 |
+
# This is a conservative matcher that looks for `selector { ... }`
|
| 1589 |
+
css_blocks = re.findall(r"([^{]+)\{([\s\S]*?)\}", changes_text, flags=re.MULTILINE)
|
| 1590 |
+
for selector_raw, body_raw in css_blocks:
|
| 1591 |
+
selector = selector_raw.strip()
|
| 1592 |
+
body = body_raw.strip()
|
| 1593 |
+
if not selector:
|
| 1594 |
+
continue
|
| 1595 |
+
# Build a regex to find the existing rule for this selector
|
| 1596 |
+
# Capture opening `{` and closing `}` to preserve them; replace inner body.
|
| 1597 |
+
pattern = re.compile(rf"({re.escape(selector)}\s*\{{)([\s\S]*?)(\}})")
|
| 1598 |
+
def _replace_rule(match):
|
| 1599 |
+
nonlocal replaced_any_rule
|
| 1600 |
+
replaced_any_rule = True
|
| 1601 |
+
prefix, existing_body, suffix = match.groups()
|
| 1602 |
+
# Preserve indentation of the existing first body line if present
|
| 1603 |
+
first_line_indent = ""
|
| 1604 |
+
for line in existing_body.splitlines():
|
| 1605 |
+
stripped = line.lstrip(" \t")
|
| 1606 |
+
if stripped:
|
| 1607 |
+
first_line_indent = line[: len(line) - len(stripped)]
|
| 1608 |
+
break
|
| 1609 |
+
# Re-indent provided body with the detected indent
|
| 1610 |
+
if body:
|
| 1611 |
+
new_body_lines = [first_line_indent + line if line.strip() else line for line in body.splitlines()]
|
| 1612 |
+
new_body_text = "\n" + "\n".join(new_body_lines) + "\n"
|
| 1613 |
+
else:
|
| 1614 |
+
new_body_text = existing_body # If empty body provided, keep existing
|
| 1615 |
+
return f"{prefix}{new_body_text}{suffix}"
|
| 1616 |
+
updated_content, num_subs = pattern.subn(_replace_rule, updated_content, count=1)
|
| 1617 |
+
if replaced_any_rule:
|
| 1618 |
+
return updated_content
|
| 1619 |
+
except Exception:
|
| 1620 |
+
# Fallback silently to the standard block-based application
|
| 1621 |
+
pass
|
| 1622 |
+
|
| 1623 |
# Split the changes text into individual search/replace blocks
|
| 1624 |
blocks = []
|
| 1625 |
current_block = ""
|
|
|
|
| 1675 |
if search_text in modified_content:
|
| 1676 |
modified_content = modified_content.replace(search_text, replace_text)
|
| 1677 |
else:
|
| 1678 |
+
# If exact block match fails, attempt a CSS-rule fallback using the replace_text
|
| 1679 |
+
try:
|
| 1680 |
+
import re
|
| 1681 |
+
updated_content = modified_content
|
| 1682 |
+
replaced_any_rule = False
|
| 1683 |
+
css_blocks = re.findall(r"([^{]+)\{([\s\S]*?)\}", replace_text, flags=re.MULTILINE)
|
| 1684 |
+
for selector_raw, body_raw in css_blocks:
|
| 1685 |
+
selector = selector_raw.strip()
|
| 1686 |
+
body = body_raw.strip()
|
| 1687 |
+
if not selector:
|
| 1688 |
+
continue
|
| 1689 |
+
pattern = re.compile(rf"({re.escape(selector)}\s*\{{)([\s\S]*?)(\}})")
|
| 1690 |
+
def _replace_rule(match):
|
| 1691 |
+
nonlocal replaced_any_rule
|
| 1692 |
+
replaced_any_rule = True
|
| 1693 |
+
prefix, existing_body, suffix = match.groups()
|
| 1694 |
+
first_line_indent = ""
|
| 1695 |
+
for line in existing_body.splitlines():
|
| 1696 |
+
stripped = line.lstrip(" \t")
|
| 1697 |
+
if stripped:
|
| 1698 |
+
first_line_indent = line[: len(line) - len(stripped)]
|
| 1699 |
+
break
|
| 1700 |
+
if body:
|
| 1701 |
+
new_body_lines = [first_line_indent + line if line.strip() else line for line in body.splitlines()]
|
| 1702 |
+
new_body_text = "\n" + "\n".join(new_body_lines) + "\n"
|
| 1703 |
+
else:
|
| 1704 |
+
new_body_text = existing_body
|
| 1705 |
+
return f"{prefix}{new_body_text}{suffix}"
|
| 1706 |
+
updated_content, num_subs = pattern.subn(_replace_rule, updated_content, count=1)
|
| 1707 |
+
if replaced_any_rule:
|
| 1708 |
+
modified_content = updated_content
|
| 1709 |
+
else:
|
| 1710 |
+
print(f"Warning: Search text not found in content: {search_text[:100]}...")
|
| 1711 |
+
except Exception:
|
| 1712 |
+
print(f"Warning: Search text not found in content: {search_text[:100]}...")
|
| 1713 |
|
| 1714 |
return modified_content
|
| 1715 |
|