From 2e6274d2a75432c1bfbceaeb0e6880263d399641 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Sun, 28 Dec 2025 07:59:05 +0100 Subject: [PATCH 1/8] Create reactive-analysis.mdx --- markdown-pages/blog/reactive-analysis.mdx | 113 ++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 markdown-pages/blog/reactive-analysis.mdx diff --git a/markdown-pages/blog/reactive-analysis.mdx b/markdown-pages/blog/reactive-analysis.mdx new file mode 100644 index 000000000..32d76d967 --- /dev/null +++ b/markdown-pages/blog/reactive-analysis.mdx @@ -0,0 +1,113 @@ +--- +author: cristiano +date: "2025-01-02" +title: "Real-Time Analysis is Coming to ReScript" +badge: roadmap +description: | + ReScript's static analyzer is going reactive. Dead code detection that updates instantly as you edit, powered by novel reactive combinators. +--- + +## Introduction + +Imagine editing a ReScript file and seeing dead code warnings appear and disappear _instantly_ as you type. No waiting for a build. No running a separate analysis command. Just immediate, continuous feedback about which parts of your code are actually used. + +This is what we're bringing to ReScript. + +The static analyzer that powers dead code detection is being rebuilt on a **reactive foundation**. When you add a reference to a function, the "unused" warning vanishes immediately. When you remove the last use of a module, the dead code warning appears right away. The analysis stays in sync with your code, updating in real time. + +## Why This Matters + +Traditional static analyzers work in batch mode: gather all files, analyze everything, report results. This works fine when you run analysis as a CI check or a manual command. But it's not what you want when you're actively editing code. + +Batch analysis has an awkward tradeoff: + +- **Run it rarely** and feedback comes too late to be useful +- **Run it often** and you're constantly waiting + +What developers actually want is _continuous_ feedback that keeps up with their typing speed. That's exactly what reactive analysis provides. + +## The Reactive Approach + +Instead of re-analyzing your entire project on every change, the reactive analyzer represents the analysis as a **computation graph**. Each piece of data—declarations, references, liveness information—flows through this graph. When a file changes, only the affected parts of the graph recompute. + +The result: analysis that completes in milliseconds for typical edits, even in large codebases. + +### A Glimpse Under the Hood + +The technology behind this comes from [Skip Labs](https://skiplabs.io), whose reactive programming primitives were designed for exactly this kind of incremental computation. + +The analysis pipeline is built from composable operators: + +- **Sources** hold the raw data from your `.cmt` files +- **FlatMap** transforms and extracts declarations and references +- **Join** connects references to their target declarations +- **Union** combines data from different sources +- **Fixpoint** computes transitive closures—which functions call which + +That last one, **fixpoint**, is particularly interesting. Dead code detection needs to know which declarations are _reachable_ from your entry points. This is a classic graph traversal—but doing it incrementally is hard. When you add one edge to a graph, how do you efficiently update the set of reachable nodes without recomputing from scratch? + +The reactive fixpoint operator solves exactly this problem. It maintains the reachable set incrementally, handling both additions and removals efficiently. This is what makes the analysis fast enough for real-time use. + +### Glitch-Free by Design + +There's a subtle correctness issue with reactive systems: **glitches**. If node A depends on both B and C, and both B and C update, node A might briefly see an inconsistent state—B's new value with C's old value, or vice versa. + +For analysis, glitches mean incorrect results. A function might briefly appear dead because the reference to it hasn't propagated yet, even though it's actually used. + +The reactive scheduler prevents this with a simple principle: **accumulate, then propagate**. All updates at each level of the graph are collected before any downstream nodes run. Nodes process in topological order, wave by wave. The analysis never sees partial updates. + +## What's Shipping + +The reactive analysis infrastructure is landing now. Here's what it enables: + +### For Developers + +- **Editor integration** (coming soon): Dead code warnings that update as you type +- **Faster CI analysis**: Incremental runs are dramatically faster than full runs +- **Immediate feedback loop**: See the impact of your changes instantly + +### For Tooling Authors + +The reactive primitives are general-purpose. The same infrastructure that powers dead code detection can express other analyses: + +- Dependency graph visualization +- Unused export detection +- Reference counting and hotspot identification +- Custom project-specific checks + +## The Road Ahead + +This is the beginning of a larger shift. The same reactive foundation will extend to other parts of the editor experience: + +- **Type checking**: Incremental type feedback without waiting for builds +- **Navigation**: Jump-to-definition that stays accurate as files change +- **Refactoring**: Real-time previews of rename and move operations + +The goal is an editor experience where the tooling _keeps up with you_—no waiting, no stale results, just continuous assistance. + +## Try It Today + +The reactive analyzer is available now in the development builds: + +```bash +# Clone and build +git clone https://github.com/rescript-lang/rescript +cd rescript +make lib + +# Run with timing info +cd your-project +path/to/rescript-editor-analysis reanalyze -dce -config -reactive -timing +``` + +The `-timing` flag shows how much work the reactive system avoided on subsequent runs. You can also use `-runs N` to benchmark multiple iterations. + +## Acknowledgments + +The reactive primitives are based on work by [Skip Labs](https://skiplabs.io). Their reactive collections library provides the foundation for glitch-free, incremental computation that makes real-time analysis possible. + +--- + +We're excited to bring this to the ReScript community. Static analysis that runs continuously, in the background, without you having to think about it—that's the experience we're building toward. + +Stay tuned for editor integration updates. And as always, we welcome feedback on [GitHub](https://github.com/rescript-lang/rescript) and [Discord](https://discord.gg/rescriptlang). From 71bdd02816c428a9db011803b83bd3068ea7fe9a Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Sun, 28 Dec 2025 08:30:14 +0100 Subject: [PATCH 2/8] Update reactive-analysis.mdx --- markdown-pages/blog/reactive-analysis.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/markdown-pages/blog/reactive-analysis.mdx b/markdown-pages/blog/reactive-analysis.mdx index 32d76d967..a6366f745 100644 --- a/markdown-pages/blog/reactive-analysis.mdx +++ b/markdown-pages/blog/reactive-analysis.mdx @@ -1,6 +1,6 @@ --- -author: cristiano -date: "2025-01-02" +author: rescript-team +date: "2025-12-28" title: "Real-Time Analysis is Coming to ReScript" badge: roadmap description: | From 9aa154ea0a025e7a5a3e4159fb0a39322c570920 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Mon, 29 Dec 2025 11:04:41 +0100 Subject: [PATCH 3/8] fix reactive analysis post metadata/links Add reactive-analysis.mdx and align metadata with blog conventions (author/date, links). --- markdown-pages/blog/reactive-analysis.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/markdown-pages/blog/reactive-analysis.mdx b/markdown-pages/blog/reactive-analysis.mdx index a6366f745..71924ea22 100644 --- a/markdown-pages/blog/reactive-analysis.mdx +++ b/markdown-pages/blog/reactive-analysis.mdx @@ -34,7 +34,7 @@ The result: analysis that completes in milliseconds for typical edits, even in l ### A Glimpse Under the Hood -The technology behind this comes from [Skip Labs](https://skiplabs.io), whose reactive programming primitives were designed for exactly this kind of incremental computation. +The technology behind this comes from [SkipLabs](https://skiplabs.io), whose reactive programming primitives were designed for exactly this kind of incremental computation. The analysis pipeline is built from composable operators: @@ -104,10 +104,10 @@ The `-timing` flag shows how much work the reactive system avoided on subsequent ## Acknowledgments -The reactive primitives are based on work by [Skip Labs](https://skiplabs.io). Their reactive collections library provides the foundation for glitch-free, incremental computation that makes real-time analysis possible. +The reactive primitives are based on work by [SkipLabs](https://skiplabs.io). Their reactive collections library provides the foundation for glitch-free, incremental computation that makes real-time analysis possible. --- We're excited to bring this to the ReScript community. Static analysis that runs continuously, in the background, without you having to think about it—that's the experience we're building toward. -Stay tuned for editor integration updates. And as always, we welcome feedback on [GitHub](https://github.com/rescript-lang/rescript) and [Discord](https://discord.gg/rescriptlang). +Stay tuned for editor integration updates. And as always, we welcome feedback on [GitHub](https://github.com/rescript-lang/rescript) and on the [forum](https://forum.rescript-lang.org). From 969c9f7bd59890fdcd55cf154044d10322e6936b Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Wed, 28 Jan 2026 09:59:37 +0100 Subject: [PATCH 4/8] Update reactive analysis post with monorepo support and simplified instructions - Add monorepo support bullet point under "For Developers" - Rewrite "Try It Today" section with version requirements and simple editor workflow - Add link to Dead Code Analysis documentation Co-Authored-By: Claude Opus 4.5 --- markdown-pages/blog/reactive-analysis.mdx | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/markdown-pages/blog/reactive-analysis.mdx b/markdown-pages/blog/reactive-analysis.mdx index 71924ea22..6fdd3925e 100644 --- a/markdown-pages/blog/reactive-analysis.mdx +++ b/markdown-pages/blog/reactive-analysis.mdx @@ -63,6 +63,7 @@ The reactive analysis infrastructure is landing now. Here's what it enables: ### For Developers - **Editor integration** (coming soon): Dead code warnings that update as you type +- **Monorepo support**: The analyzer now works correctly in monorepo setups, running from the workspace root with proper binary lookup - **Faster CI analysis**: Incremental runs are dramatically faster than full runs - **Immediate feedback loop**: See the impact of your changes instantly @@ -87,20 +88,15 @@ The goal is an editor experience where the tooling _keeps up with you_—no wait ## Try It Today -The reactive analyzer is available now in the development builds: +**Requirements:** -```bash -# Clone and build -git clone https://github.com/rescript-lang/rescript -cd rescript -make lib +- ReScript compiler >= 12.1.0 +- VSCode or Cursor with rescript-vscode extension >= 1.74.0 (upcoming release) -# Run with timing info -cd your-project -path/to/rescript-editor-analysis reanalyze -dce -config -reactive -timing -``` +1. Start the build watcher (accept the prompt when opening a ReScript file, or run **"ReScript: Start Build"**) +2. Run **"ReScript: Start Code Analyzer"** -The `-timing` flag shows how much work the reactive system avoided on subsequent runs. You can also use `-runs N` to benchmark multiple iterations. +Dead code warnings will appear in your editor and update automatically as you save files. For configuration options and usage details, see the [Dead Code Analysis guide](../docs/manual/editor-code-analysis.mdx). ## Acknowledgments From 56a94ce79621d021a59017c94f38b2fb98f1560f Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Sat, 31 Jan 2026 17:21:49 +0100 Subject: [PATCH 5/8] extension released Co-Authored-By: Claude Opus 4.5 --- markdown-pages/blog/reactive-analysis.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdown-pages/blog/reactive-analysis.mdx b/markdown-pages/blog/reactive-analysis.mdx index 6fdd3925e..6f16b37cf 100644 --- a/markdown-pages/blog/reactive-analysis.mdx +++ b/markdown-pages/blog/reactive-analysis.mdx @@ -91,7 +91,7 @@ The goal is an editor experience where the tooling _keeps up with you_—no wait **Requirements:** - ReScript compiler >= 12.1.0 -- VSCode or Cursor with rescript-vscode extension >= 1.74.0 (upcoming release) +- VSCode or Cursor with rescript-vscode extension >= 1.73.9 (pre-release) 1. Start the build watcher (accept the prompt when opening a ReScript file, or run **"ReScript: Start Build"**) 2. Run **"ReScript: Start Code Analyzer"** From 73ea8614255941683eb6fea55bca9d2849047504 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Sat, 7 Feb 2026 09:05:52 +0100 Subject: [PATCH 6/8] Clarify reactive analysis availability and version gating --- markdown-pages/blog/reactive-analysis.mdx | 10 ++++++---- markdown-pages/docs/manual/editor-code-analysis.mdx | 4 ++++ markdown-pages/docs/manual/editor-plugins.mdx | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/markdown-pages/blog/reactive-analysis.mdx b/markdown-pages/blog/reactive-analysis.mdx index 6f16b37cf..61fb28e0d 100644 --- a/markdown-pages/blog/reactive-analysis.mdx +++ b/markdown-pages/blog/reactive-analysis.mdx @@ -9,7 +9,7 @@ description: | ## Introduction -Imagine editing a ReScript file and seeing dead code warnings appear and disappear _instantly_ as you type. No waiting for a build. No running a separate analysis command. Just immediate, continuous feedback about which parts of your code are actually used. +Imagine editing a ReScript file and seeing dead code warnings update almost immediately as you work. No waiting for a full re-analysis command. Just continuous feedback about which parts of your code are actually used. This is what we're bringing to ReScript. @@ -62,7 +62,7 @@ The reactive analysis infrastructure is landing now. Here's what it enables: ### For Developers -- **Editor integration** (coming soon): Dead code warnings that update as you type +- **Editor integration**: Available now in the latest extension, with reactive dead code updates during active development - **Monorepo support**: The analyzer now works correctly in monorepo setups, running from the workspace root with proper binary lookup - **Faster CI analysis**: Incremental runs are dramatically faster than full runs - **Immediate feedback loop**: See the impact of your changes instantly @@ -90,13 +90,15 @@ The goal is an editor experience where the tooling _keeps up with you_—no wait **Requirements:** +Reactive analysis is a newer capability of Editor Code Analysis and requires a newer extension version. + - ReScript compiler >= 12.1.0 - VSCode or Cursor with rescript-vscode extension >= 1.73.9 (pre-release) 1. Start the build watcher (accept the prompt when opening a ReScript file, or run **"ReScript: Start Build"**) 2. Run **"ReScript: Start Code Analyzer"** -Dead code warnings will appear in your editor and update automatically as you save files. For configuration options and usage details, see the [Dead Code Analysis guide](../docs/manual/editor-code-analysis.mdx). +Dead code warnings appear in your editor and update reactively while you develop (currently driven by save/build updates). For configuration options and usage details, see the [Dead Code Analysis guide](../docs/manual/editor-code-analysis.mdx). ## Acknowledgments @@ -106,4 +108,4 @@ The reactive primitives are based on work by [SkipLabs](https://skiplabs.io). Th We're excited to bring this to the ReScript community. Static analysis that runs continuously, in the background, without you having to think about it—that's the experience we're building toward. -Stay tuned for editor integration updates. And as always, we welcome feedback on [GitHub](https://github.com/rescript-lang/rescript) and on the [forum](https://forum.rescript-lang.org). +Stay tuned for broader reactive tooling updates. And as always, we welcome feedback on [GitHub](https://github.com/rescript-lang/rescript) and on the [forum](https://forum.rescript-lang.org). diff --git a/markdown-pages/docs/manual/editor-code-analysis.mdx b/markdown-pages/docs/manual/editor-code-analysis.mdx index c4d18d059..9a1a5bca4 100644 --- a/markdown-pages/docs/manual/editor-code-analysis.mdx +++ b/markdown-pages/docs/manual/editor-code-analysis.mdx @@ -37,6 +37,10 @@ ReScript’s language design allows for accurate and efficient dead code analysi - The “Problems” pane populates with dead code warnings and suggestions. +### Reactive Updates (New) + +Reactive dead code updates are a newer enhancement of Editor Code Analysis and require ReScript VSCode extension v1.73.9 or higher (pre-release). + ## Real-World Use Cases ### 1. **Unused Record Fields** diff --git a/markdown-pages/docs/manual/editor-plugins.mdx b/markdown-pages/docs/manual/editor-plugins.mdx index d6593695d..97c5bb884 100644 --- a/markdown-pages/docs/manual/editor-plugins.mdx +++ b/markdown-pages/docs/manual/editor-plugins.mdx @@ -120,7 +120,7 @@ Look - [Editor Code Analysis](./editor-code-analysis.mdx) for a more detailed gu ### Caveats -- Doesn't support cross-package dead code analysis in monorepos. Run it per package instead. +- For older extension versions, cross-package dead code analysis in monorepos may be limited. ## Editor features From 5b58cc3eeb7bf32bdde81782faaf1108b0746f77 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Sat, 7 Feb 2026 10:04:38 +0100 Subject: [PATCH 7/8] Refine reactive analysis blog narrative and diagrams --- markdown-pages/blog/reactive-analysis.mdx | 33 +++++++++++++++---- public/blog/reactive-analysis/fixpoint.mmd | 20 +++++++++++ public/blog/reactive-analysis/fixpoint.svg | 1 + .../reactive-pipeline-simple.mmd | 24 ++++++++++++++ .../reactive-pipeline-simple.svg | 1 + 5 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 public/blog/reactive-analysis/fixpoint.mmd create mode 100644 public/blog/reactive-analysis/fixpoint.svg create mode 100644 public/blog/reactive-analysis/reactive-pipeline-simple.mmd create mode 100644 public/blog/reactive-analysis/reactive-pipeline-simple.svg diff --git a/markdown-pages/blog/reactive-analysis.mdx b/markdown-pages/blog/reactive-analysis.mdx index 61fb28e0d..3cff7c05f 100644 --- a/markdown-pages/blog/reactive-analysis.mdx +++ b/markdown-pages/blog/reactive-analysis.mdx @@ -13,7 +13,7 @@ Imagine editing a ReScript file and seeing dead code warnings update almost imme This is what we're bringing to ReScript. -The static analyzer that powers dead code detection is being rebuilt on a **reactive foundation**. When you add a reference to a function, the "unused" warning vanishes immediately. When you remove the last use of a module, the dead code warning appears right away. The analysis stays in sync with your code, updating in real time. +The static analyzer that powers dead code detection is being rebuilt on a **reactive foundation**. When you add a reference to a function, the "unused" warning vanishes quickly. When you remove the last use of a module, the dead code warning appears right away. The analysis stays in sync with your code, updating in real time. ## Why This Matters @@ -32,21 +32,40 @@ Instead of re-analyzing your entire project on every change, the reactive analyz The result: analysis that completes in milliseconds for typical edits, even in large codebases. +### A Concrete Update Flow + +Suppose you have a call graph where `main` calls `helper`, and `helper` calls `format` and `validate`. In your edit, `validate` starts calling `old`. + +With batch analysis, the analyzer scans everything again. With reactive analysis: + +1. The edited `.cmt` updates — **FlatMap** extracts the new reference. The compiler already resolved it: the ref knows its target (`old`) and its source location (inside `validate`) +2. **Join** maps that source position to its containing declaration, producing a new graph edge: _validate → old_ +3. **Fixpoint** propagates reachability from roots (`main`) along edges — `old` now becomes reachable and enters the live set +4. A final **Classify** step (a join of declarations with the live set) marks `old` as live — so its dead-code warning disappears + +The rest of the project graph stays untouched. + ### A Glimpse Under the Hood -The technology behind this comes from [SkipLabs](https://skiplabs.io), whose reactive programming primitives were designed for exactly this kind of incremental computation. +Here is a simplified view of the reactive dead code pipeline: + +![Simplified reactive dead code pipeline](/blog/reactive-analysis/reactive-pipeline-simple.svg) The analysis pipeline is built from composable operators: - **Sources** hold the raw data from your `.cmt` files -- **FlatMap** transforms and extracts declarations and references -- **Join** connects references to their target declarations -- **Union** combines data from different sources -- **Fixpoint** computes transitive closures—which functions call which +- **FlatMap** extracts declarations, references, and annotations from each file's data +- **Union** merges collections — for example, combining value references, type references, and exception references into a unified set +- **Join** maps data across collections — for example, mapping each reference to the declaration that contains it, or partitioning declarations into dead and live using the fixpoint result +- **Fixpoint** computes transitive reachability — starting from root declarations (entry points, annotated `@live`, or externally referenced), following edges to find everything that's live That last one, **fixpoint**, is particularly interesting. Dead code detection needs to know which declarations are _reachable_ from your entry points. This is a classic graph traversal—but doing it incrementally is hard. When you add one edge to a graph, how do you efficiently update the set of reachable nodes without recomputing from scratch? -The reactive fixpoint operator solves exactly this problem. It maintains the reachable set incrementally, handling both additions and removals efficiently. This is what makes the analysis fast enough for real-time use. +In the running example above, only one new edge (`validate → old`) is added, and fixpoint propagates liveness from that delta. + +![Fixpoint: incremental reachability](/blog/reactive-analysis/fixpoint.svg) + +The reactive fixpoint operator solves exactly this problem. It takes a set of roots and a set of edges, and maintains the full reachable set. In this example, once `old` becomes reachable through `validate`, fixpoint only propagates through neighbors affected by that new edge, without revisiting unrelated parts of the graph. This is what makes the analysis fast enough for real-time use. ### Glitch-Free by Design diff --git a/public/blog/reactive-analysis/fixpoint.mmd b/public/blog/reactive-analysis/fixpoint.mmd new file mode 100644 index 000000000..8387dcd08 --- /dev/null +++ b/public/blog/reactive-analysis/fixpoint.mmd @@ -0,0 +1,20 @@ +%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#e8f5e9', 'primaryTextColor': '#102a43', 'primaryBorderColor': '#4caf50', 'lineColor': '#486581'}}}%% +flowchart LR + A_main["main
root"] + A_helper["helper"] + A_format["format"] + A_validate["validate"] + A_old["old"] + + A_main -- "wave 1" --> A_helper + A_helper -- "wave 2" --> A_format + A_helper -- "wave 2" --> A_validate + A_validate -. "new edge: validate → old" .-> A_old + + classDef rootNode fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px,color:#102a43 + classDef liveNode fill:#e8f5e9,stroke:#4caf50,stroke-width:2px,color:#102a43 + classDef newlyLive fill:#fff9c4,stroke:#f9a825,stroke-width:2.5px,color:#102a43 + + class A_main rootNode + class A_helper,A_format,A_validate liveNode + class A_old newlyLive diff --git a/public/blog/reactive-analysis/fixpoint.svg b/public/blog/reactive-analysis/fixpoint.svg new file mode 100644 index 000000000..bdb3e9225 --- /dev/null +++ b/public/blog/reactive-analysis/fixpoint.svg @@ -0,0 +1 @@ +

wave 1

wave 2

wave 2

new edge: validate → old

main
root

helper

format

validate

old

\ No newline at end of file diff --git a/public/blog/reactive-analysis/reactive-pipeline-simple.mmd b/public/blog/reactive-analysis/reactive-pipeline-simple.mmd new file mode 100644 index 000000000..2a2db3299 --- /dev/null +++ b/public/blog/reactive-analysis/reactive-pipeline-simple.mmd @@ -0,0 +1,24 @@ +%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#eef6ff', 'primaryTextColor': '#102a43', 'primaryBorderColor': '#4a90d9', 'lineColor': '#486581', 'secondaryColor': '#fff1f1', 'tertiaryColor': '#fff5e6'}}}%% +flowchart LR + sources["Sources"] + flatmap["FlatMap"] + edges["Edges"] + roots["Roots"] + fixpoint["Fixpoint"] + classify["Classify"] + issues["Issues"] + + sources --> flatmap + flatmap -- "refs, decls" --> edges + flatmap -- "refs, decls, ann." --> roots + edges --> fixpoint + roots --> fixpoint + flatmap -. "decls" .-> classify + fixpoint -- "live" --> classify + classify -- "dead" --> issues + + classDef coreBox fill:#eef6ff,stroke:#4a90d9,stroke-width:2px,color:#102a43 + classDef solveBox fill:#fff1f1,stroke:#cc6666,stroke-width:2px,color:#102a43 + + class sources,flatmap,edges,roots coreBox + class fixpoint,classify,issues solveBox diff --git a/public/blog/reactive-analysis/reactive-pipeline-simple.svg b/public/blog/reactive-analysis/reactive-pipeline-simple.svg new file mode 100644 index 000000000..f66bd8104 --- /dev/null +++ b/public/blog/reactive-analysis/reactive-pipeline-simple.svg @@ -0,0 +1 @@ +

refs, decls

refs, decls, ann.

decls

live

dead

Sources

FlatMap

Edges

Roots

Fixpoint

Classify

Issues

\ No newline at end of file From 3ba27c7eb3444157251264616a63532b24afce21 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Sun, 8 Feb 2026 08:01:11 +0100 Subject: [PATCH 8/8] Fix link checker false positives for SVG diagrams in blog post The reactive analysis blog post references SVG diagrams via absolute paths (/blog/reactive-analysis/*.svg). The link validator resolves these relative to the markdown file and reports them as missing. Check whether warned-about files exist in public/ before reporting, since Vite serves public/ assets at root. Co-Authored-By: Claude Opus 4.6 --- scripts/test-hrefs.mjs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/scripts/test-hrefs.mjs b/scripts/test-hrefs.mjs index 285fc920a..4cab81c03 100644 --- a/scripts/test-hrefs.mjs +++ b/scripts/test-hrefs.mjs @@ -26,8 +26,27 @@ for (const file of files) { const warningMessage = log.replace(file, ""); + // Skip warnings about files that exist in public/ (served at root by Vite) + const missingFileMatches = [ + ...warningMessage.matchAll(/`\.\.\/\.\.\/(.*?)`/g), + ]; + let allMissingExistInPublic = false; + if (missingFileMatches.length > 0) { + allMissingExistInPublic = ( + await Promise.all( + missingFileMatches.map(([, p]) => + fs.access("public/" + p).then( + () => true, + () => false, + ), + ), + ) + ).every(Boolean); + } + if ( log && + !allMissingExistInPublic && !warningMessage.includes("api/") && // When running on CI it fails to ignore the link directly to the blog root // https://github.com/rescript-lang/rescript-lang.org/actions/runs/19520461368/job/55882556586?pr=1115#step:6:338