unclecode / unclecode/crawl4ai

PruningContentFilter drops whitespace-only spans in <pre>/<code> — #1181's bug, still present on the fit_markdown path

Open
#2,110 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
83.9k
Forks
8.7k
Avg merge
3d 7h
Merged PRs (30d)
11

Description

Summary

#1181 ("importtorch") was fixed in v0.7.8 by skipping elements inside <pre>/<code> in remove_empty_elements_fast (content_scraping_strategy.py). PruningContentFilter has the same failure, unfixed: it scores and decomposes whitespace-only token spans inside highlighted code, so fit_markdown corrupts code that raw_markdown (post-0.7.8) preserves.

Environment

crawl4ai 0.9.2, Docker image unclecode/crawl4ai:0.9.2, REST /crawl. Code references are v0.9.2 (unchanged on develop).

Repro

crawler_configmarkdown_generator: DefaultMarkdownGenerator with content_filter: PruningContentFilter(threshold=0.48, threshold_type="fixed"). Fetch any page with <span>-based syntax highlighting and compare fit_markdown vs raw_markdown:

raw_markdown is intact in the same responses.

Root cause

content_filter_strategy.py: _prune_tree recurses into kept nodes and decompose()s any child scoring under threshold. For a highlighter whitespace span (<span class="w"> </span>), _compute_composite_score yields: text_density 0 (text_len 0) · link_density term 0.20 · tag_weight span=0.3 → 0.06 · text_length log(1)=0 → composite ≈ 0.26–0.36 < 0.48 → removed. This is the same arithmetic the v0.7.8 scraper fix bypasses via its <pre>/<code> guard ("This preserves whitespace-only spans (e.g., <span class="w"> </span>) in code blocks"); the filter never got the guard. Low-scoring whole <pre> blocks (huge tag_len from hundreds of spans → near-zero text density) are likewise decomposed (the MDN case).

Suggested fix

Port the scraper's guard into _prune_tree: skip scoring/pruning for <pre>/<code> subtrees. PR incoming.

Workaround (v0.9.1+)

PruningContentFilter(..., preserve_tags=["pre","code"]) (added by #1904) protects the whole subtree; or clients can fall back to raw_markdown when fit_markdown loses code fences.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in content_filter_strategy.py at _prune_tree and compare its behavior with the pre/code guard described for remove_empty_elements_fast. Reproduce the issue using the Kubernetes, DEV, or MDN examples and compare fit_markdown with raw_markdown. Done means highlighted code preserves whitespace and complete pre/code subtrees are retained.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.