This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Wednesday, 24 June 2026
क्लाउडफ्लेर's | " | मार्क डाउन मोड |" | AI क्रॉलर को रेंडरेड HTML के बजाय साफ पाठ देता है | . | StyloBot ऑपरेटरों को StyloExtract द्वारा समान क्षमता प्राप्त होती है & #44; , | स्थानीय रूप से Stylobot गेटवे पर चलता है & quot; , | गर्म पथ पर बैठने के लिए पर्याप्त तेजी से & #39; MSC6 | ऊपरी ओर साइट में कोई परिवर्तन की आवश्यकता नहीं होते हैं & #43; M SK7 | यह है जो Styloextract करता है& #44؛ , | इसे Stylo Bot में कैसे प्लग किया जाता है
क्लाउडफ्लेर एक विशेषता भेजता है जिसमें यदि कोई मान्यताप्राप्त एआई क्रॉलर एक पृष्ठ के लिए पूछता है, किनारे पूरी HTML को छोड़कर शरीर का मार्कडाउन रेन्डेशन सेवा करता है।
संरचना बाहर से स्पष्ट है।
एक स्टेलोबोट ऑपरेटर के लिए समान क्षमता तीन प्रतिबंध है क्लाउडफ्लेर नहीं
इसका स्टेलोबोट पक्ष पहले से ही किया गया थाBotType.AiBot) के साथ एक ही तेजी से DetectionPolicyMiddleware में 7.x निर्णय द्वारा नामित कार्रवाई नीतियों को भेजता है extract-markdown नीति के लिए "AiBot पर*एक कॉन्फ़िग लाइन है
कि StyloExtract1HTML-से-मार्कडाउन परत जो StyloBotके साथ जोड़ता है'के detection.के साथ एक छोटा एडप्टर पैक के रूप में इंटीग्रेशन जहाजMostlylucid.BotDetection.StyloExtract) और नियम जो यह चलाता है JSON के छह लाइनें हैं।
अगर आप मुख मान पर स्पेक्ट पढ़ते हैं, तो HTML को मार्कडाउन में बदलें.
वास्तविक-world वेब पृष्ठ हैं M SK1 boilerplate. जो लेख आप वास्तव में चाहते है दो या तीन wrapping के अंदर जीवन <div>दो या तीन सौ से अधिक में से s।
तो निष्कर्षक दो कार्य करना है
पहचान करना कठिन है। वेब सामग्री निष्कर्षण और स्थापित मानक WCXB है। टेम्प्लेट सीखना structural fingerprinting के माध्यम से
आकार है:
parse HTML → clean → fingerprint the structure → does this fingerprint
match a template I've seen on this host before?
yes → apply the cached extractor → render
no → run the heuristic classifier → induce a fresh extractor →
cache it under this host's fingerprint → render
पहली बार गेटवे एक होस्ट से एक पृष्ठ देखता है, यह एक मध्यम पृष्ठ के लिए पूरा हेयूरिस्टिक का भुगतान करता है - वर्गीकृत लागत (~200μs। प्रत्येक बाद में उस होस्ट की ओर से जो संरचनात्मक औठाछाप मिलते हैं, उसका प्रत्येक पृष्ठ कैशित एक्सटेक्टर लेता है। यह CSS का एक हज़ार होता है।
यह औठाछाप एक सामान्यकृत DOM के ऊपर मिनहश स्कैच है।
रेंडर साइड है जहां कुत्ते भोजन लूप मुझे यह अर्जित करने के लिए बना
StyloExtract का पहला संस्करण वर्गीकृत ब्लॉकों और प्रक्षेपण की हिदायत करके मार्कडाउन जारी किया element.TextContent.Trim() आउटपुट में. हर ब्लॉक एक पैराग्राफ बन गया # text regardless of whether it was H1 or H 4. Anchors collapsed to bare text
यह तकनीकी रूप से है "Markdown." यहM SK2s भी बेकार है क्रोम विश्लेषण से बचेंऔर हम इसे पैराग्राफों की एक दीवार देते हैं जहां केवल संकेत कभी-कभी सादा होता है
तो StyloExtract का अगला संस्करण हर वर्गीकृत सामग्री ब्लॉक के DOM चलाता है और वास्तविक GFM :
<h1> के माध्यम से <h6> के माध्यम से 1 बन जाएँ # अक्षर<a href> बन जाता है [text](href)<em> और <strong> अपना ध्यान रखें<code> पीछे टिक रहा है <pre> एक घेरेदार ब्लॉक के साथ बन जाता है language-x चरितार्थ<ul> और <ol> वास्तविक गोली और संख्यांकित सूची जारी करें<blockquote> प्रत्येक लाइन के साथ उपसर्ग > ( और बहुक - अनुच्छेद उद्धरण प्राप्त करता है > body\n>\n> body कन्वेंशन<table> एक WHATWG स्लॉट के माध्यम से पुनर्गठन किया जाता है। grid एल्गोरिथ्म सही कोलस्पैन सहित। क्या वे ऍनलाइन में गद्य या स्टैंडलोन में हैं <figure>वॉकर एक स्ट्रिंग बिल्डर प्रति ब्लॉक है। , एक आंतरिक scratch बफर को सेलों के बीच फिर से प्रयोग किया जाता है।
वॉकर भी वह हिस्सा है जो पहले टूट गया
lucidVIEW एक मार्कडाउन दृश्यकर्ता है मैं StyloExtract के साथ बनाता हूँ. उत्पाद एक ब्राउज़र है- एक बाजू पाठक है जो एक URL लेता है।
जो lucidVIEW मुझे दिया था कि दांतों के साथ कुत्ते भोजन लूप था। मैं. IM SK1m लूप में हूँ।
lucidVIEW एक नीचे की रीडर के लिए मार्कडाउन renders (me, लेकिन पढ़ने वाले विषयवस्तु को पढ़ता है अवयव, उपकरण के रूप में नहीं है।
तो मैं अपनी ब्लॉग इंडेक्स की ओर संकेत करते हुए lucidVIEW खोलता हूँ। [Post title](/blog/post) शैलिटेड क्लिक करने योग्य लिंक के बजाय - अक्षरिक कोष्ठक पाठ
इकाई-test सूट हरे रंग का है। [Post title](/blog/post)मार्कडाउन गलत है वैसे भी
ब्लॉग अनुक्रमणिका Tailwind के साथ बनायी जाती है. tailwind आउटपुट पढ़ने की क्षमता के लिए इन्डेन्ट किया जाता है : प्रत्येक wrapper div अपने मूल से दो स्थानों में आगे बैठता है।
<section class="...">
<div class="container...">
<div class="grid...">
<div class="card...">
<a href="/blog/post-a">Post title</a>
...
walkinger's text AppendEscapedInline, एक एकल खाली स्थान के लिए सफेद जगह के रन को संक्षिप्त करता है prevWs फ्लैग जो क्रमिक सफेद खाली स्थान को दबाता है, निष्काशित करता है।
इन्डेन्टेशन के चार लपेटने वाले [Post title](/blog/post) एक पंक्ति पर उतरता है जो चार जगहों से शुरू होती है
यूनिट परीक्षण पास करता है क्योंकि परीक्षण स्ट्रिंग कोserts [Post title](/blog/post) आउटपुट में कहीं दिखाई देता है
फ़िक्स पंक्ति में दो लाइनें है prevWs = true तो प्रथम प्रत्येक पाठ नोड से अग्रणी श्वेतस्थान उत्तरित के बजाय छोड़ दिया जाता है. आरेखित एचटीएमएल में अग्रणी सफेदस्थान कभी भी आउटपुट तक नहीं पहुंचता
दिलचस्प बात है कि क्या परीक्षण होना चाहिए सतह .Contains() जाँच करता है अक्षर मौजूद हैं. वे थे. वे सिर्फ गलत CommonMark ब्लॉक प्रकार में थे संरचनात्मक त्रुटि सच्ची CommonMark पार्सर के साथ आउटपुट का विश्लेषण करें और अनुच्छेद अनुच्छेदों को अनुच्छेद मानें।
LinkInline AST मेंलांट के दाँत थे साबित करने के लिए, मैंने मूल फ़िक्स को वापस किया और लिंट सूट चलाया।
यह एकल जाँच अब सूट में हर चालक परीक्षण पर चलता है

प्रत्येक उत्पाद में एक चरण है जहां यूनिट परीक्षण हरे हैं और डेमो काम करता है और ऑपरेटर ने सही कॉन्फ़िगरेशन फ्लैग सेट किया है और आप एक रिज़र्व भेजते हैं और एक दिन बाद एक उपयोक्ता एक मुद्दे को खोलता है कहता है '"' यह नहीं करता है ''' वास्तविक सामग्री पर काम नही करता है''
कुत्ता आहार लूप इस जाल से बाहर सबसे सस्ता तरीका है। अलग उत्पादअलग उपयोगकर्ताओं के साथ , अपने उत्पाद सतह के रूप में StyloExtract' आउटपुट का उपयोग करने के लिए होता है. यदि lucidVIEW विच्छेदित मार्कडाउन दिखाता है, तो lucidVIEW के उपयोक्ता lucidView के बारे में शिकायत करते हैं।
यह पृथक्करण महत्वपूर्ण है. यदि lucidVIEW एक StyloExtract परीक्षण फिक्सर होता था, तो मैं इसे sterile सामग्री के साथ लिखा गया था क्योंकि मैं जानता हूँ कि निष्कर्षक क्या पसंद करता है।
बहुत से v1.7.x प्रकाशन इस लूप के पीछे ट्रेस करता है।
पैटर्न'नई नई नहीं है उपभोक्ता उत्पाद आपके साथ समानांतर में अवसंरचना उत्पाद, और उपभोक्ता के माध्यम से अपना मूल संरचना खपत करें वर्ग अवसंरचना परत पर कवरेज हर चीज़ से विस्तार करता है जो उपभोक्ता आप के लिए एक परीक्षण लिखने के लिए नहीं सोचा था
StyloExtract / lucidVIEW एक नमूना का एक उदाहरण है जो मैं प्रत्येक परियोजना पर चलाता हूँ
flowchart LR
PB[visible product<br/>behaviour] --> TR[test/review<br/>loop]
TR --> AP[architectural<br/>primitive]
AP --> RL[reusable<br/>library]
RL --> WE[written<br/>explanation]
WE --> LG[LLM-readable<br/>grammar]
LG --> NP[next<br/>product]
NP --> PB
किसी उत्पाद में एक बग का सतह बनता है।
निर्भरता ग्राफ जो यह उत्पादित करता है मैं चलाने के सभी परियोजनाओं में ,
flowchart TB
LV[lucidVIEW<br/>Avalonia markdown reader]
SB[StyloBot<br/>detection gateway]
SF[StyloFlow<br/>policy + flow runtime]
SE[StyloExtract<br/>HTML → Markdown]
NA[mostlylucid.Naiad<br/>Mermaid renderer fork]
DA[mostlylucid.dagre<br/>graph layout]
EP[mostlylucid.ephemeral<br/>signal + sketch primitives]
UT[Mostlylucid.Avalonia.UITesting<br/>Avalonia UI test framework]
SB --> SF
SB --> SE
LV --> SE
LV --> NA
NA --> DA
SE --> EP
SF --> EP
LV -.tests via.-> UT
Mostlylucid.Avalonia.UITesting डेस्कटॉप साइड पर समतुल्य लूप बंद करता है. StyloExtract.Playwright इसे हेडless पर बन्द करता है- वेब साइड को बंद करता हैं\M SK3 एक ही नमूना, भिन्न सतह\MSC5 एक परीक्षण\MST6\automation harness लेता है कि एजेंटिक लूम वास्तव में उत्पाद व्यवहार सत्यापित करता है यह निश्चित करने के लिए किया गया था
व्यापार वास्तविक है ग्राफ incestuous है mostlylucid.ephemeral StyloExtract और StyloFlow के माध्यम से StyloBot और lucidVIEW में ripples up . कम करने का समय है।
इसका अर्थ यह भी है कि इस लेख को लिखना एक पक्ष नहीं है। StyloExtract का प्रभाव1StyleoExtract का प्रभाव2The writing IS one of the stages.Externalizing the design into prose closes the loop that started with "blog cards render wrong in lucidVIEW"and ends with "The next consumer of Styloextract has a structural lint helper and a documented walker contract
यह मेरे लिए काम करता है क्योंकि बंद लूप है कैसे मैं सोचता हूँ
flowchart LR
URL[URL bar] --> Fetch[HttpClient GET<br/>Accept: text/markdown, text/html]
Fetch --> Sniff{Content-Type}
Sniff -->|text/markdown| Render[LiveMarkdown.Avalonia]
Sniff -->|text/html| Convert[HtmlToMarkdownService]
Convert --> Sparse{< 200 chars +<br/>SPA markers?}
Sparse -->|yes| Stub[Stub: needs JS,<br/>open in browser?]
Sparse -->|no| Render
Stub --> Render
चार पैकेज संदर्भ और एक सेवा
public sealed class HtmlToMarkdownService
{
private readonly IHtmlDomParser _parser = new AngleSharpHtmlDomParser();
private readonly IDomCleaner _cleaner = new DomCleaner();
private readonly IBlockSegmenter _segmenter = new BlockSegmenter();
private readonly IBlockClassifier _classifier =
HeuristicBlockClassifier.LoadFromEmbeddedResources();
private readonly IMarkdownRenderer _renderer = new TypedMarkdownRenderer();
public string Convert(string html, Uri? sourceUri = null)
{
var doc = _parser.Parse(html, sourceUri);
_cleaner.Clean(doc);
var blocks = _classifier.Classify(_segmenter.Segment(doc));
return _renderer.Render(blocks, ExtractionProfile.RagFull);
}
}
कि's यह है। . एक स्थिति। NAME OF TRANSLATORS

flowchart LR
HTML[HTML] --> P[AngleSharpHtmlDomParser]
P --> C[DomCleaner<br/>strip script/style]
C --> S[BlockSegmenter<br/>candidate subtrees]
S --> K[HeuristicBlockClassifier<br/>role + score]
K --> W[DomMarkdownWalker<br/>GFM per block]
W --> R[TypedMarkdownRenderer<br/>profile gate]
R --> MD[Markdown]
विश्लेषक + क्लीनर कोणशॉर्प wrappers हैं
सेगमेंटर शरीर चलाएँ , कोई अर्थात्मक टैग sinkmain/article/section/h1-h6/ul/pre/...) प्लस कोई भी <div>/<section> कि”'s text“-”heavy or has many children“.” Everything else is too small to be content”
public IReadOnlyList<IElement> Segment(IDocument document)
{
if (document.Body is null) return Array.Empty<IElement>();
var result = new List<IElement>();
Walk(document.Body, result);
return result;
}
private static void Walk(IElement element, List<IElement> sink)
{
if (SemanticTags.Contains(element.TagName)) sink.Add(element);
else if (IsBlockyDiv(element)) sink.Add(element);
foreach (var child in element.Children) Walk(child, sink);
}
वर्गीकृत प्रत्येक उम्मीदवार को अंकित करें-,- non चुनें--- overlapping winners- , BlockRole (MainContentM SK1 Heading, NavigationMSC3 BoilerplateMNK4 RepeatedItemMRK5 ...). प्रत्येक चुने गए ब्लॉक को अपने DOM को निर्मित मार्कडाउन में चला जाता है
foreach (var element in selected)
{
var role = ClassifyRole(element);
yield return new ExtractedBlock
{
Role = role,
Text = element.TextContent.Trim(),
Markdown = ShouldRenderMarkdown(role) ? DomMarkdownWalker.Render(element) : "",
Links = ExtractLinks(element),
XPath = XPathBuilder.For(element),
// ...
};
}
वॉकर एक स्ट्रिंग बिल्डर, एक डोम पास <a> केस है जहाँ v1.7.1 बग जीवित था
case "a":
var href = el.GetAttribute("href") ?? "";
if (href.Length == 0) { WriteInlineChildren(dest, el); return; }
dest.Append('[');
WriteInlineChildren(dest, el);
dest.Append("](").Append(href).Append(')');
return;
यह यहाँ नहीं था AppendEscapedInline, जो leading whitespace में भर दिया dest इससे पहले कि इस मामले कभी चला [ CommonMark को एक कोड ब्लॉक के रूप में लाइन का विश्लेषण करता है
रेंडरर प्रोफ़ाइल द्वारा गेट. RagFull अनुच्छेद को रखता है-संtext (BreadcrumbM SK2 संबद्ध लिंकMSC3 और क्रोम ड्रॉप करता है। MainContentOnly सिर्फ शरीर रखता है AgentNavigation सिर्फ Nav रखता है ( crawl के लिए -link discovery):
return p switch
{
ExtractionProfile.RagFull => b.Role is not (BlockRole.Footer or BlockRole.Header
or BlockRole.Advertisement or BlockRole.CookieBanner or BlockRole.Boilerplate
or BlockRole.Unknown or BlockRole.PrimaryNavigation or BlockRole.SecondaryNavigation),
ExtractionProfile.MainContentOnly => b.Role is BlockRole.MainContent or BlockRole.Article
or BlockRole.Heading or BlockRole.Summary or BlockRole.Table or BlockRole.CodeBlock
or BlockRole.RepeatedItem,
ExtractionProfile.AgentNavigation => b.Role is BlockRole.PrimaryNavigation
or BlockRole.SecondaryNavigation or BlockRole.Breadcrumb or BlockRole.Form,
_ => true
};
StyloExtract' its heuristic operates on the static HTML the server returned . That' s fine for SSR sites MSC3 WikipediaM SK4 GitHubMNK5 most news article URLsMRK6 It breaks on SPA shells where the visible content is hydrated clientMST7side from a JSON blobMTSK8 __NEXT_DATA__, __NUXT__, __APOLLO_STATE__स्थिर एचटीएमएल में मेटा टैग हैं
Mostlylucid.StyloExtract.Playwright पाइपलाइन की ऊपरी धारा में प्लग्स IRenderedHtmlFetcherPlaywright के माध्यम से एक हेडレス क्रोमियम ड्राइव करता है
public async Task<RenderedHtmlResult> FetchAsync(
Uri uri, RenderOptions? options = null, CancellationToken cancellationToken = default)
{
var page = await _context.NewPageAsync();
await page.GotoAsync(uri.ToString(), new PageGotoOptions
{
WaitUntil = WaitUntilState.NetworkIdle,
Timeout = options?.NavigationTimeoutMs ?? 15000,
});
var html = await page.ContentAsync();
await page.CloseAsync();
return new RenderedHtmlResult { Html = html, FinalUrl = page.Url };
}
एक ही पार्सर, क्लीनर, खण्डकM SK2 वर्गीकृतकर्ता , वॉकरMSC4 रेंडरर नीचे प्रवाहित है। यह एकमात्र अंतर है कि इनपुट एचटीएमएल अब हाइडिडेड DOM है जो JS उत्पादित करता है।
flowchart LR
URL[URL] --> Choice{Render mode}
Choice -->|static| HTTP[HttpClient]
Choice -->|js-required| PW[PlaywrightHtmlFetcher<br/>headless Chromium]
HTTP --> Pipeline[parse → clean → segment<br/>→ classify → walk → render]
PW --> Pipeline
Pipeline --> MD[Markdown]
यह सही उत्तर है जब एक ऑपरेटर StyloExtract सर्वर चलाता है stylo-extract (AOT, M SK2MB, स्थिर stylo-extract-playwright (~120MB एक बार Playwright's ब्राउज़र पैक भूमि लेता है
lucidVIEW इसका उपयोग नहीं करता है. lucidVIEW एक मार्कडाउन रीडर है।
चार गैर-bugs जो lucidVIEW को आकार देता है
स्पेक जो v1.7.0. चलाता है प्रथम निर्माण उत्सर्जित समतल अनुच्छेद (element.TextContent.Trim() प्रति ब्लॉक). विकिपीडिया पढ़ा नहीं जा सकता था। docs/styloextract-markdown-spec.md क्या खो गया था enumerating what was missing: heading levels, inline runsMSC2 listsM SK3 GFM tables , block images
स्पीए पृष्ठ bbc.com/news अगले है.js: स्थिर एचटीएमएल मेटा टैग है __NEXT_DATA__ JS द्वारा hydrated JSON blob__NEXT_DATA__, __NUXT__, __APOLLO_STATE__, data-reactroot, ng-version=, __REMIX_DATA__sparse आउटपुट पर ) और, चिह्नक यह पृष्ठ {फ्रेमवर्क का उपयोग करता है अनुच्छेद यूआरएल/news/articles/<id>) वास्तविक सेवा <main> और साफ रूपांतरित करें. होम पेज अगला पेज

अर्थशास्त्र example.com नहीं है <main>, नहीं <article>. अनुमान सही रूप से कुछ नहीं लौटता है
सही - मगर - अवश्यक उत्सर्जन . मेरा ब्लॉग'कोटि फ़िल्टर है <select><option>. वॉकर कोई नहीं पाता <a href>विकल्प पाठ को एक अनुच्छेद के रूप में जारी करता है सभी सही (options aren't linksM SK2 but visually awful. A future walker pass could detect <select> और एक परिभाषा सूची जारी करें या [42 categories] सारांश.
इसके अलावा एक गार्डरेल जो स्पष्ट शॉर्टकट के प्रतिरोध से बाहर आया है। <meta> / og: टैग, फिर "ब्राउजर में खोलें ठ̧à¥à¤°à¥à¤ एक ही मूल से एक भिन्न फ़ैच , या हमारे पास पहले से ही है डेटा से संश्लेषण करता है | . | इस के लिए उत्तर |" | यह नहीं |
क्या कुत्ते आहार लूप खोजने में अच्छा है अच्छी पर टूटी आउटपुट है।
मेरे पास एक धुँआ है-- runner अब जो एक दर्जन वास्तविक साइटों को ले आता है। - world sites and dumps the extractor।
अन्य आधा पर - Allbirds | ( |Shopify |), | Notion & #44; ' | marketing page & #39; , | anything built with a custom Tailwind component library | - | the classifier finds कुछ भी नहीं. Zero MainContent blocks. प्रत्येक उम्मीदवार को बॉयलप्लेट में डेमोड किया जाता है क्योंकि पृष्ठ का उपयोग नहीं करता <main> या <article> और वर्ग नाम don't match any of the patterns in the framework
उस JSON फ़ाइल में अधिक प्रविष्टियों को जोड़ना स्पष्ट कदम है।
वास्तविक समाधान एक प्रशिक्षित मॉडल है। Microsoft.ML.OnnxRuntimeएक 45- एक प्रति उम्मीदवार विशेषता सदिश |, | ~10 | प्रत्येक तत्व के अनुमान की μs |मस्क4 | मस्क5 | एमबी मॉडल फ़ाइल |म्स्क6 | AOT | म्स्क7 | क्लेन | मास्क8 | मॉडल ने ह्रासात्मक को बढ़ावा दिया है।
इसके लिए डिजाइन StyloExtract रिपो ( में किया गया हैdocs/ml-classifier-v2-design.mdक्रियान्वयन नहीं है।
अंतरिम में ',' क्या ऑपरेटरों को मिलता है मैनुअल escape hatch: operator -authored YAML templates, one file per hostM SK3 parsed AOTMST4cleanMSC5 hotMSSK6overriding the induction pipeline for that host. An operator notices that weird-shopify-tenant.com रिक्त मार्कडाउन उत्पन्न करता है , इस होस्ट के लिए एक पांच |- |लाइन YAML फ़ाइल लिखता है जो कहता है " |MainContent यह है .product-description-body", इसे डालता है config/templates/, और रनटाइम इसे सेकेंडों के भीतर FileSystemWatcher के माध्यम से उठाता है
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.