1<!DOCTYPE html> 2<html lang="en" class="h-100"> 3 4 5 6<head> 7 <meta charset="utf-8"> 8 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 9 10 <!-- Allow pinning of website on windows --> 11 <meta name="application-name" content="Erlang.org"> 12 <meta name="msapplication-tooltip" content="The official home of the Erlang Programming Language"> 13 <meta name="msapplication-starturl" content="/" > 14 15 <!-- Make the site look nicer on facebook --> 16 <meta property="og:type" content="website"> 17 <meta property="og:site_name" content="Erlang.org"> 18 <meta property="og:title" content="Index - Erlang/OTP"> 19 <meta property="og:description" content="The official home of the Erlang Programming Language"> 20 <meta property="og:image" content="https://www.erlang.org/assets/img/erlang-228x200.png"> 21 <meta property="og:image:secure_url" content="https://www.erlang.org/assets/img/erlang-228x200.png"> 22 <meta property="og:url" content="https://www.erlang.org/"> 23 24 <!-- Rich data for google search --> 25
25<script type="application/ld+json"> 26{"@type":"WebSite","url":"https://erlang.org/","headline":"Index - Erlang/OTP","name":"Erlang.org","sameAs":["https://github.com/erlang/otp"],"@context":"https://schema.org"}</script>
26 27 28 <title>Index - Erlang/OTP</title> 29 30 31
31<script> 32 (function() { 33 try { 34 var s = JSON.parse(localStorage.getItem("ex_doc:settings") || "{}"); 35 var t = s.theme; 36 var dark = t === "dark" || (t !== "light" && window.matchMedia && 37 window.matchMedia("(prefers-color-scheme: dark)").matches); 38 if (dark) { 39 document.documentElement.classList.add("dark"); 40 document.documentElement.setAttribute("data-bs-theme", "dark"); 41 } 42 } catch (e) { /* localStorage may be unavailable; just skip */ } 43 })(); 44 </script>
44 45 46 <meta name="viewport" content="width=device-width, initial-scale=1"> 47 <!-- tells iOS browsers to not show telephone numbers as links --> 48 <meta name="format-detection" content="telephone=no"> 49 50 <meta name="application-name" content="Erlang.org"> 51 <meta name="description" content="The official home of the Erlang Programming Language"> 52 <!-- https://www.rssboard.org/rss-autodiscovery --> 53 <link rel="alternate" type="application/atom+xml" title="News Atom Feed" href="https://www.erlang.org/news.xml" /> 54 <link rel="alternate" type="application/atom+xml" title="Blog Atom Feed" href="https://www.erlang.org/blog.xml" /> 55 <link rel="icon" href="/favicon.ico" /> 56 57 <link rel="stylesheet" href="/assets/css/index.css"> 58</head> 59 60<body class="d-flex flex-column h-100"> 61 <header class="navbar navbar-expand-lg navbar-light bg-body"> 62 <nav class="container"> 63 <button class="navbar-toggler" type="button" data-toggle="collapse" data-bs-toggle="collapse" 64 data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" 65 aria-label="Toggle navigation"> 66 <span class="navbar-toggler-icon"></span> 67 </button> 68 <a class="navbar-brand" href="/"><img 69 src="/assets/img/erlang-logo.svg" width="60" alt="Erlang.org main page"/></a> 70 <div class="collapse navbar-collapse fw-bold" id="navbarSupportedContent"> 71 <ul class="navbar-nav text-uppercase me-auto mb-2 mb-lg-0"> 72 <li class="nav-item"><a class="nav-link" href="/downloads">Download</a></li> 73 <li class="nav-item"><a class="nav-link" href="/docs">Documentation</a></li> 74 <li class="nav-item"><a class="nav-link" href="/community">Community</a></li> 75 <li class="nav-item"><a class="nav-link" href="/news">News</a></li> 76 <li class="nav-item"><a class="nav-link" href="/blog">Blog</a></li> 77 <li class="nav-item"><a class="nav-link" href="/security">Security</a></li> 78 <li class="nav-item"><a class="nav-link" href="/eep">EEP</a></li> 79 <li class="nav-item"><a class="nav-link" href="/about">About</a></li> 80 </ul> 81 <form class="d-flex" role="search" method="get" action="https://duckduckgo.com/"> 82 <input type="hidden" name="sites" value="erlang.org"> 83 <input class="form-control me-2" id="searchfield" name="q" type="search" placeholder="Search erlang.org" 84 aria-label="Search"> 85 <button class="btn btn-outline-primary" type="submit">Search</button> 86 </form> 87 </div> 88 </nav> 89 </header> 90 <div class="flex-shrink-0 border-top-dark"> 91 <div class="bg-erlang-grey"> 92 <div class="container banner px-0 px-md-2"> 93 <div class="slogan text-center"> 94 <h1 class="h4 px-4 pt-4 text-light"> 95 Practical functional programming<br /> for a parallel world 96 </h1> 97 <!-- <h4 class="px-4 pt-4 text-light"> 98 Build massively scalable soft real-time systems 99 </h4> --> 100 </div> 101 <div class="download text-center"> 102 <!-- We hide the download button on small screens as most likely it is a mobile 103 and no one want to workload Erlang on a mobile --> 104 <div class="btn-group"> 105 106 <a href="/downloads" 107 class="btn btn-success d-inline-flex align-items-center gap-1"> 108 Get Erlang/OTP 29 109 <svg width="20" height="20" > 110 111 <use xlink:href="#download"></use> 112</svg> 113 114 </a> 115 </div> 116 </div> 117 <!-- We have two different examples that are shown 118 depending on the size of the viewport --> 119 <div class="example"> 120 121 122 <div class="large">
123 <div id="large-example-carousel" class="h-100 carousel slide" data-bs-ride="carousel"> 124 <div class="carousel-inner h-100"> 125 126 127 128 <div class="h-100 carousel-item active" data-bs-interval="10000"> 129 <div class="h-100 d-flex flex-column"> 130 <div class="flex-grow-1 mx-auto"> 131 <!-- This file has to be 15 lines long --> 132<pre><code class="language-erlang">fact(0) -> 1; %% Pattern matching for control-flow 133fact(N) -> N * fact(N-1). %% Recursion to create loops 134 135> example:fact(10). %% Interactive shell for fast iterations 1363628800 137> [{I, example:fact(I)} || I <- lists:seq(1,10)]. 138[{1, 1}, {2, 2}, {3, 6}, {4, 24}, {5, 120}, {6, 720}, 139 {7, 5040}, {8, 40320}, {9, 362880}, {10, 3628800}] 140</code></pre> 141 142 </div> 143 <div class="text-light text-center"> 144 <p>Functional programming</p> 145 </div> 146 </div> 147 </div> 148 149 150 151 152 153 154 <div class="h-100 carousel-item " data-bs-interval="10000"> 155 <div class="h-100 d-flex flex-column"> 156 <div class="flex-grow-1 mx-auto"> 157 <!-- This file has to be 15 lines long --> 158<pre><code class="language-erlang">> Fruits = ["banana","monkey","jungle"]. %% Immutable variables 159["banana","monkey","jungle"] 160> lists:map(fun string:uppercase/1, Fruits). %% Map values using stdlib functions 161["BANANA","MONKEY","JUNGLE"] 162%% Fold over lists using custom functions 163> lists:foldl(fun(Str, Cnt) -> string:length(Str) + Cnt end, 0, Fruits). 16418 165 166</code></pre> 167 168 </div> 169 <div class="text-light text-center"> 170 <p>Higher-order functions</p> 171 </div> 172 </div> 173 </div> 174 175 176 177 178 179 180 <div class="h-100 carousel-item " data-bs-interval="10000"> 181 <div class="h-100 d-flex flex-column"> 182 <div class="flex-grow-1 mx-auto"> 183 <!-- This file has to be 15 lines long --> 184<pre><code class="language-erlang">> Parent = self(). %% Get own process id 185<0.376.0> 186> Child = spawn(fun() -> receive go -> Parent ! lists:seq(1,100) end end). 187<0.930.0> 188> Child ! go. %% Send message to child 189go 190> receive Reply -> Reply end. %% Receive response from child 191[1,2,3,4,5,6,7,8,9,10,11|...] 192</code></pre> 193 194 </div> 195 <div class="text-light text-center"> 196 <p>Lightweight processes</p> 197 </div> 198 </div> 199 </div> 200 201 202 203 204 205 206 207 208 <div class="h-100 carousel-item " data-bs-interval="10000"> 209 <div class="h-100 d-flex flex-column"> 210 <div class="flex-grow-1 mx-auto"> 211 <!-- This file has to be 15 lines long --> 212<pre><code class="language-erlang">-spec even(list(integer())) -> list(integer()). 213even(Numbers) -> 214 mapreduce(Numbers, fun(Number) -> Number rem 2 == 0 end). 215mapreduce(Numbers, Function) -> 216 Parent = self(), 217 [spawn(fun() -> Parent ! {Number, Function(Number)} end) || Number <- Numbers], 218 lists:flatten( 219 [receive {Number, true} -> Number; _ -> [] end || Number <- Numbers]). 220</code></pre> 221 222 </div> 223 <div class="text-light text-center"> 224 <p>Parallel map-reduce to find even numbers</p> 225 </div> 226 </div> 227 </div> 228 229 230 231 </div> 232 <button class="carousel-control-prev" type="button" data-bs-target="#large-example-carou
232sel" 233 data-bs-slide="prev"> 234 <span class="carousel-control-prev-icon" aria-hidden="true"></span> 235 <span class="visually-hidden">Previous</span> 236 </button> 237 <button class="carousel-control-next" type="button" data-bs-target="#large-example-carousel" 238 data-bs-slide="next"> 239 <span class="carousel-control-next-icon" aria-hidden="true"></span> 240 <span class="visually-hidden">Next</span> 241 </button> 242 </div> 243 </div> 244 245 <div class="small"> 246 <div id="small-example-carousel" class="h-100 carousel slide" data-bs-ride="carousel"> 247 <div class="carousel-inner h-100"> 248 249 250 251 252 253 <div class="h-100 carousel-item active" data-bs-interval="10000"> 254 <div class="h-100 d-flex flex-column"> 255 <div class="flex-grow-1 mx-auto"> 256 <!-- This file has to be 13 lines long --> 257<pre><code class="language-erlang">%% Return factorial for N 258fact(0) -> 1; 259fact(N) -> N * fact(N-1). 260 261> example:fact(10). 2623628800 263</code></pre> 264 265 </div> 266 <div class="text-light text-center"> 267 <p>Functional programming</p> 268 </div> 269 </div> 270 </div> 271 272 273 274 275 276 277 <div class="h-100 carousel-item " data-bs-interval="10000"> 278 <div class="h-100 d-flex flex-column"> 279 <div class="flex-grow-1 mx-auto"> 280 <!-- This file has to be 13 lines long --> 281<pre><code class="language-erlang">> Fruits = ["banana","monkey"]. 282["banana","monkey"] 283> lists:map( 284 fun string:uppercase/1, 285 Fruits). 286["BANANA","MONKEY"] 287</code></pre> 288 289 </div> 290 <div class="text-light text-center"> 291 <p>Higher-order functions</p> 292 </div> 293 </div> 294 </div> 295 296 297 298 299 300 301 <div class="h-100 carousel-item " data-bs-interval="10000"> 302 <div class="h-100 d-flex flex-column"> 303 <div class="flex-grow-1 mx-auto"> 304 <!-- This file has to be 13 lines long --> 305<pre><code class="language-erlang">> Me = self(). 306<0.376.0> %% Send msg using ! 307> spawn(fun() -> Me!lists:seq(1,10) end). 308<0.930.0> 309> receive Reply -> Reply end. 310[1,2,3,4,5,6,7,8,9,10] 311</code></pre> 312 313 </div> 314 <div class="text-light text-center"> 315 <p>Light-weight processes</p> 316 </div> 317 </div> 318 </div> 319 320 321 322 323 <div class="h-100 carousel-item " data-bs-interval="10000"> 324 <div class="h-100 d-flex flex-column"> 325 <div class="flex-grow-1 mx-auto"> 326 <pre><code class="language-erlang">-spec even(In) -> Out 327 when In :: list(integer()), 328 Out :: list(integer()). 329even(Numbers) -> 330 [Number || Number <- Numbers, 331 Number rem 2 == 0]. 332</code></pre> 333 334 </div> 335 <div class="text-light text-center"> 336 <p>Find even numbers</p> 337 </div> 338 </div> 339 </div> 340 341 342 343 344 345 </div> 346 <button class="carousel-control-prev" type="button" data-bs-target="#small-example-carou
346sel" 347 data-bs-slide="prev"> 348 <span class="carousel-control-prev-icon" aria-hidden="true"></span> 349 <span class="visually-hidden">Previous</span> 350 </button> 351 <button class="carousel-control-next" type="button" data-bs-target="#small-example-carousel" 352 data-bs-slide="next"> 353 <span class="carousel-control-next-icon" aria-hidden="true"></span> 354 <span class="visually-hidden">Next</span> 355 </button> 356 </div> 357 </div> 358 359 360 </div> 361 </div> 362</div> 363<main class="content container"> 364 <div class="what-is-erlang"> 365 <h2 class="h4">What is Erlang?</h2> 366 <p class="ps-3">Erlang is a programming language used to build massively scalable soft real-time 367 systems with requirements on high availability. Some of its uses are in telecoms, banking, 368 e-commerce, computer telep
368hony and instant messaging. Erlang's runtime system has built-in 369 support for concurrency, distribution and fault tolerance.</p> 370 <a href="/doc/getting_started/intro.html" role="button" 371 class="btn btn-primary float-end d-inline-flex align-items-center"> 372 Erlang Quickstart 373 <svg width="24" height="24" > 374 375 <use xlink:href="#arrow-right"></use> 376</svg> 377 378 </a> 379 </div> 380 <div class="what-is-otp"> 381 <h2 class="h4">What is OTP?</h2> 382 <p class="ps-3">OTP is set of Erlang libraries and design principles providing middle-ware to 383 develop these systems. It includes its own distributed database, applications to interface 384 towards other languages, debugging and release handling tools.</p> 385 <a href="/doc/design_principles/des_princ.html" role="button" 386 class="btn btn-primary float-end d-inline-flex align-items-center"> 387 Getting Started with OTP 388 <svg width="24" height="24" > 389 390 <use xlink:href="#arrow-right"></use> 391</svg> 392 393 </a> 394 </div> 395 <div class="news"> 396 <h2 class="h4">News</h2> 397 <dl class="ps-3"> 398 399 400 401 402 403 <dt> 404 <h3 class="h5"><a href="/news/191">Erlang/OTP 29.1 Release</a></h3> 405 <small class="ps-2">September 16, 2026 by Henrik Nord</small> 406 </dt> 407 <dd class="px-3 py-1"> 408 Erlang/OTP 29.1 is the first maintenance patch package for OTP 29, with mostly bug fixes. 409 </dd> 410 411 412 413 414 <dt> 415 <h3 class="h5"><a href="/news/190">Björn on BEAM on the BEAM There, Done That Podcast</a></h3> 416 <small class="ps-2">June 26, 2026 by Björn Gustavsson</small> 417 </dt> 418 <dd class="px-3 py-1"> 419 Björn on BEAM on the BEAM There, Done That Podcast 420 </dd> 421 422 423 424 425 <dt> 426 <h3 class="h5"><a href="/news/189">Native Records on the Podcast BEAM There, Done That</a></h3> 427 <small class="ps-2">May 28, 2026 by Björn Gustavsson</small> 428 </dt> 429 <dd class="px-3 py-1"> 430 Native Records on the Podcast BEAM There, Done That 431 </dd> 432 433 </dl> 434 </div> 435 <div class="participate"> 436 <h2 class="h4">Participate</h2> 437 <p class="ps-3"> 438 <a href="https://erlef.org"><img alt="Join the Erlang Ecosystem Foundation" 439 src="/assets/img/eef.png" class="eef-logo" width="174"></a> 440 </p> 441 </div> 442</main>
443<script src="/assets/js/prismjs/prism.js"></script>
vendor: 1 bytes, line 443
443
444<script src="/assets/js/prismjs/components/prism-erlang.js"></script>
444 445 446 </div> 447 <footer class="container-fluid footer mt-auto text-center border-top border-bottom"> 448 <div> 449 <a href="/downloads.html" title="DOWNLOAD"> 450 <svg width="36" height="24" role="img"> 451 452 <title>Download Erlang/OTP</title> 453 454 <use xlink:href="#download-cloud"></use> 455</svg> 456 457 </a> 458 </div> 459 <div> 460 <a href="http://www.github.com/erlang/otp"> 461 <svg width="32" height="32" role="img"> 462 463 <title>Erlang/OTP on Github</title> 464 465 <use xlink:href="#github"></use> 466</svg> 467 468 </a> 469 </div> 470 471 <div> 472 <button type="button" id="theme-toggle" class="theme-toggle" 473 aria-label="Toggle theme" title="Toggle theme (light / dark / system)"> 474 <svg width="20" height="20" class="icon-theme-light"> 475 476 <use xlink:href="#theme-light"></use> 477</svg> 478 479 <svg width="20" height="20" class="icon-theme-dark"> 480 481 <use xlink:href="#theme-dark"></use> 482</svg> 483 484 <svg width="20" height="20" class="icon-theme-system"> 485 486 <use xlink:href="#theme-system"></use> 487</svg> 488 489 </button> 490 </div> 491 </footer> 492 <!-- SVG icons --> 493 <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
494 <symbol id="download-cloud" viewBox="0 0 36 24"> 495 <path fill="currentColor" d="M30.096 10.54S30.76 1.59 22.56.568c-7.03-.718-9.168 5.814-9.168 5.814s-2.117-2.035-4.99-.372c-2.57 1.587-2.116 4.492-2.116 4.492s-5.709 1.11-5.709 6.93c.128 5.812 6.2 5.87 6.2 5.87h11.621l-5.12-5.119h3.072V12.04h4.096v6.143h3.071l-5.119 5.12h10.716s5.652.005 6.446-5.524c.377-6.047-5.464-7.239-5.464-7.239Z"/> 496 </symbol> 497 <symbol id="download" viewBox="0 0 20 20"> 498 <path fill="currentColor" d="M10.75 2.75a.75.75 0 0 0-1.5 0v8.614L6.295 8.235a.75.75 0 1 0-1.09 1.03l4.25 4.5a.75.75 0 0 0 1.09 0l4.25-4.5a.75.75 0 0 0-1.09-1.03l-2.955 3.129V2.75Z" /> 499 <path fill="currentColor" d="M3.5 12.75a.75.75 0 0 0-1.5 0v2.5A2.75 2.75 0 0 0 4.75 18h10.5A2.75 2.75 0 0 0 18 15.25v-2.5a.75.75 0 0 0-1.5 0v2.5c0 .69-.56 1.25-1.25 1.25H4.75c-.69 0-1.25-.56-1.25-1.25v-2.5Z" /> 500 </symbol> 501 <symbol id="arrow-right" viewBox="0 0 20 20"> 502 <path fill="currentColor" fill-rule="evenodd" d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /> 503 </symbol> 504 <symbol id="theme-light" viewBox="0 0 24 24"> 505 <path fill="currentColor" d="M12 17a5 5 0 1 1 0-10 5 5 0 0 1 0 10Zm0-2a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM12 2a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V3a1 1 0 0 1 1-1Zm0 17a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0v-2a1 1 0 0 1 1-1ZM2 12a1 1 0 0 1 1-1h2a1 1 0 1 1 0 2H3a1 1 0 0 1-1-1Zm17 0a1 1 0 0 1 1-1h2a1 1 0 1 1 0 2h-2a1 1 0 0 1-1-1ZM4.93 4.93a1 1 0 0 1 1.41 0l1.42 1.42A1 1 0 1 1 6.34 7.76L4.93 6.34a1 1 0 0 1 0-1.41Zm11.31 11.31a1 1 0 0 1 1.41 0l1.42 1.42a1 1 0 0 1-1.41 1.41l-1.42-1.42a1 1 0 0 1 0-1.41ZM19.07 4.93a1 1 0 0 1 0 1.41l-1.42 1.42a1 1 0 0 1-1.41-1.41l1.42-1.42a1 1 0 0 1 1.41 0ZM7.76 16.24a1 1 0 0 1 0 1.41l-1.42 1.42a1 1 0 0 1-1.41-1.41l1.42-1.42a1 1 0 0 1 1.41 0Z"/> 506 </symbol> 507 <symbol id="theme-dark" viewBox="0 0 24 24"> 508 <path fill="currentColor" d="M20 14.6A8 8 0 0 1 9.4 4a8.001 8.001 0 1 0 10.6 10.6Z"/> 509 </symbol> 510 <symbol id="theme-system" viewBox="0 0 24 24"> 511 <path fill="currentColor" fill-rule="evenodd" d="M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18Zm0 16V5a7 7 0 0 1 0 14Z" clip-rule="evenodd"/> 512 </symbol> 513 <symbol id="github" viewBox="0 0 32 32"> 514 <path fill="currentColor" fill-rule="evenodd" d="M16 0c8.837 0 16 7.344 16 16.405 0 7.246-4.58 13.393-10.933 15.565-.811.161-1.099-.35-1.099-.788 0-.54.02-2.307.02-4.502 0-1.53-.513-2.528-1.087-3.037 3.563-.406 7.307-1.793 7.307-8.094 0-1.792-.62-3.255-1.648-4.403.166-.415.715-2.084-.157-4.343 0 0-1.34-.44-4.395 1.682A15.034 15.034 0 0 0 16 7.933a15 15 0 0 0-4.005.552C8.938 6.363 7.594 6.803 7.594 6.803c-.87 2.26-.32 3.928-.156 4.343-1.022 1.148-1.648 2.61-1.648 4.403 0 6.285 3.736 7.693 7.29 8.107-.458.41-.872 1.133-1.016 2.194-.912.419-3.229 1.144-4.656-1.364 0 0-.846-1.576-2.453-1.69 0 0-1.56-.022-.109.996 0 0 1.048.504 1.776 2.4 0 0 .94 2.928 5.39 1.936.009 1.371.023 2.664.023 3.054 0 .434-.294.941-1.093.79C4.584 29.802 0 23.651 0 16.404 0 7.344 7.165 0 16 0Z" clip-rule="evenodd"/> 515 </symbol> 516 <symbol id="twitter" viewBox="0 0 32 27"> 517 <path fill="#00AAEC" fill-rule="evenodd" d="M32 3.157a12.822 12.822 0 0 1-3.77 1.06A6.717 6.717 0 0 0 31.115.493a12.93 12.93 0 0 1-4.171 1.632A6.472 6.472 0 0 0 22.153 0c-3.623 0-6.562 3.014-6.562 6.732 0 .527.056 1.04.169 1.533-5.457-.282-10.294-2.958-13.534-7.037a6.854 6.854 0 0 0-.887 3.389 6.778 6.778 0 0 0 2.92 5.603 6.446 6.446 0 0 1-2.974-.84v.083c0 3.262 2.263 5.984 5.268 6.6-.562.16-1.145.24-1.73.238-.422 0-.836-.041-1.236-.12.836 2.673 3.259 4.621 6.133 4.673a12.963 12.963 0 0 1-8.153 2.883c-.53 0-1.054-.031-1.567-.092a18.278 18.278 0 0 0 10.063 3.022c12.077 0 18.68-10.257 18.68-19.154 0-.292-.006-.585-.018-.872 1.29-.957 2.4-2.137 3.274-3.484Z" clip-rule="evenodd"/> 518 </symbol> 519 </svg> 520
520<script src="/assets/js/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
520 521
521<script> 522 // Theme toggle: cycles light -> dark -> system. Persists into the 523 // same `ex_doc:settings` localStorage entry that ExDoc uses, so 524 // the choice flows between Jekyll-rendered pages and the 525 // ExDoc-generated docs without a separate switch. 526 (function () { 527 var KEY = "ex_doc:settings"; 528 var btn = document.getElementById("theme-toggle"); 529 if (!btn) return; 530 531 function loadSettings() { 532 try { return JSON.parse(localStorage.getItem(KEY) || "{}"); } 533 catch (_) { return {}; } 534 } 535 function saveSettings(s) { 536 try { localStorage.setItem(KEY, JSON.stringify(s)); } catch (_) {} 537 } 538 function effectiveDark(theme) { 539 if (theme === "dark") return true; 540 if (theme === "light") return false; 541 return window.matchMedia && 542 window.matchMedia("(prefers-color-scheme: dark)").matches; 543 } 544 function apply(theme) { 545 var dark = effectiveDark(theme); 546 document.documentElement.classList.toggle("dark", dark); 547 document.documentElement.setAttribute( 548 "data-bs-theme", dark ? "dark" : "light"); 549 btn.setAttribute("data-theme", theme || "system"); 550 } 551 552 // Initial: reflect the current saved choice on the button. 553 var current = loadSettings().theme || "system"; 554 apply(current); 555 556 btn.addEventListener("click", function () { 557 var order = ["light", "dark", "system"]; 558 var next = order[(order.indexOf(current) + 1) % order.length]; 559 current = next; 560 var s = loadSettings(); 561 if (next === "system") delete s.theme; else s.theme = next; 562 saveSettings(s); 563 apply(next); 564 }); 565 566 // When in system mode, react to OS theme changes live. 567 if (window.matchMedia) { 568 var mq = window.matchMedia("(prefers-color-scheme: dark)"); 569 var listener = function () { if (current === "system") apply("system"); }; 570 if (mq.addEventListener) mq.addEventListener("change", listener); 571 else if (mq.addListener) mq.addListener(listener); // Safari < 14 572 } 573 })(); 574 </script>
574 575</body> 576 577</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.