How the Code Extraction Utility Parses HTML from LLM Responses
The extract_html_content function in backend/codegen/utils.py strips markdown fences and applies cascading regex patterns to isolate valid HTML from noisy LLM outputs, returning the original text when no HTML is detected.
The abi/screenshot-to-code repository converts UI screenshots into functional HTML using large language models. Because LLM responses often contain markdown formatting, explanatory prose, and inconsistent HTML boundaries, the code extraction utility provides a robust sanitization layer that operates directly on raw response strings without requiring heavy DOM parsing libraries.
Strip Markdown Fences First
Many LLM assistants wrap code blocks in triple backticks. The utility removes these fences before attempting HTML extraction to ensure regex patterns match actual markup rather than markdown syntax.
text = re.sub(r'^```html?\s*\n?', '', text, flags=re.MULTILINE)
text = re.sub(r'\n?```\s*$', '', text, flags=re.MULTILINE)
Source: [backend/codegen/utils.py](https://github.com/abi/screenshot-to-code/blob/main/backend/codegen/utils.py), lines 5‑8
Match Full HTML Documents
The parser prioritizes complete HTML5 documents by searching for a <!DOCTYPE html> declaration followed by an <html> element. This captures the intended page structure when the LLM supplies standards-compliant markup.
match_with_doctype = re.search(
r"(<!DOCTYPE\s+html[^>]*>.*?<html.*?>.*?</html>)",
text, re.DOTALL | re.IGNORECASE,
)
Source: [backend/codegen/utils.py](https://github.com/abi/screenshot-to-code/blob/main/backend/codegen/utils.py), lines 9‑13
Extract HTML Fragments
When the doctype is absent, the utility falls back to matching any <html> tag pair. This handles partial snippets or template fragments that omit the document type declaration.
match = re.search(r"(<html.*?>.*?</html>)", text, re.DOTALL)
Source: [backend/codegen/utils.py](https://github.com/abi/screenshot-to-code/blob/main/backend/codegen/utils.py), lines 16‑19
Graceful Degradation
If no HTML tags are present, the function returns the original payload unchanged and prints a diagnostic message. This allows upstream logic to handle plain text responses or trigger alternative processing pipelines.
Source: [backend/codegen/utils.py](https://github.com/abi/screenshot-to-code/blob/main/backend/codegen/utils.py), lines 20‑25
Design Rationale
The implementation is deliberately lightweight. By using cascading regex patterns instead of a full HTML parser, the utility minimizes latency in the request-response workflow while handling common LLM output variations:
- Full HTML pages with DOCTYPE: Returns the complete
<!DOCTYPE …><html>…</html>block. - HTML snippets without DOCTYPE: Returns the first
<html>element found. - Explanatory prose before code: The
re.DOTALLflag allows patterns to span newlines, ignoring surrounding text (verified by testtest_extract_html_content_some_explanation_before). - Markdown-wrapped code: Fences are stripped before regex evaluation (verified by tests
test_markdown_tagsandtest_doctype_text).
Practical Usage Examples
The following examples demonstrate how extract_html_content handles various LLM output formats:
from codegen.utils import extract_html_content
# LLM response with markdown fence and doctype
response = """```html
<!DOCTYPE html>
<html lang="en"><head></head><body>Hello</body></html>
```"""
print(extract_html_content(response))
# → '<!DOCTYPE html><html lang="en"><head></head><body>Hello</body></html>'
# LLM response that includes explanation before the snippet
response = """Sure! Here’s the updated markup:
<html><body><h1>Title</h1></body></html>"""
print(extract_html_content(response))
# → '<html><body><h1>Title</h1></body></html>'
# Plain text with no HTML (passes through unchanged)
response = "I couldn't find a suitable layout."
print(extract_html_content(response))
# → 'I couldn\'t find a suitable layout.'
Key Files and Testing
| File | Role |
|---|---|
[backend/codegen/utils.py](https://github.com/abi/screenshot-to-code/blob/main/backend/codegen/utils.py) |
Core implementation of extract_html_content with fence stripping and HTML extraction logic. |
[backend/codegen/test_utils.py](https://github.com/abi/screenshot-to-code/blob/main/backend/codegen/test_utils.py) |
Unit tests covering markdown tags, doctype variations, explanatory text, and edge cases. |
[backend/debug/DebugFileWriter.py](https://github.com/abi/screenshot-to-code/blob/main/backend/debug/DebugFileWriter.py) |
Alternate extraction used for debugging that splits on the first <html>/</html> pair. |
Summary
- The code extraction utility is implemented in
backend/codegen/utils.pyas theextract_html_contentfunction. - It strips markdown code fences using regex substitution before parsing.
- It prefers full
<!DOCTYPE html>declarations with complete<html>elements over bare fragments. - It employs
re.DOTALLandre.IGNORECASEflags to handle multiline responses and case variations. - When no HTML is detected, it returns the original text unchanged to support fallback handling.
- The lightweight design avoids heavy dependencies, optimizing for low-latency LLM interactions.
Frequently Asked Questions
What regex pattern does the code extraction utility use to find complete HTML documents?
The utility uses the pattern r"(<!DOCTYPE\s+html[^>]*>.*?<html.*?>.*?</html>)" with re.DOTALL | re.IGNORECASE flags to match a DOCTYPE declaration followed by an HTML element. This ensures it captures the full document when the LLM generates standards-compliant markup.
How does the utility handle LLM responses that include explanatory text before the code?
The regex patterns scan the entire input string using the re.DOTALL flag, which causes . to match newlines. This allows the parser to ignore surrounding explanatory prose and extract only the HTML block, as demonstrated in the test_extract_html_content_some_explanation_before test case.
Why doesn't the utility use a proper HTML parser like Beautiful Soup?
The implementation prioritizes low latency and minimal dependencies. According to the screenshot-to-code source code, avoiding full HTML parsing libraries keeps the request-response workflow lightweight whilestill handling the predictable output formats generated by LLMs.
Where are the unit tests for the HTML extraction logic?
The test suite is located in [backend/codegen/test_utils.py](https://github.com/abi/screenshot-to-code/blob/main/backend/codegen/test_utils.py). It includes tests for markdown fence removal (test_markdown_tags), doctype handling (test_doctype_text), and HTML extraction from text with leading explanations (test_extract_html_content_some_explanation_before).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →