PageSourceSearch

https://urzenia.net/posts/home-assistant-yrno-weather-card/

html urzenia.net collected 2026-09-25 20:42:22 UTC 25,110 bytes, 480 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en" dir="auto" data-theme="auto">
3
4<head><meta charset="utf-8">
5<meta http-equiv="X-UA-Compatible" content="IE=edge">
6<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7<meta name="robots" content="index, follow">
8<title>Home Assistant: Yr.no Weather Card (vibe coded) | It&#39;s my world!</title>
9<meta name="keywords" content="ha, homeassistant, yr.no, hacs, hacs-plugin, vibe-coding, perplexity">
10<meta name="description" content="Od kilku lat moim ulubionym serwisem z którego pobieram prognozy pogody jest Yr.no. Ma całkiem fajny widget na Androida, i tam u mnie zagościł dawno temu. Prognozy pogody jak wiemy, różnie mają się do rzeczywistej pogody ;) Ale tutaj z trafialnością nie jest źle. Mi podpasowało, i przy widgecie z Yr.no zostałem.
11
12Mam też zbudowane odrobinę domowej automatyki (bo przecież nie smart-dom&hellip; w niczym nie jest smart ;) ) z użyciem Home Assistant. Już jakiś czas temu dodałem prostą kartę z prognozą pogody od nich, ale ta co mnie najbardziej interesowała nie miała nawet języka angielskiego, używałem w wersji norweskiej ;) No i wczoraj uznałem, że skoro nikt tego nie zrobił do tej pory, to sobie stworzę plugin do HA.">
13<meta name="author" content="Marcin Sztolcman">
14<link rel="canonical" href="https://urzenia.net/posts/home-assistant-yrno-weather-card/">
15<link crossorigin="anonymous" href="/assets/css/stylesheet.6ff46447b1fa3f8a5cc0bcae48088decc3ae37f5fbc99406a3aefc3bf0e6044a.css" integrity="sha256-b/RkR7H6P4pcwLyuSAiN7MOuN/X7yZQGo678O/DmBEo=" rel="preload stylesheet" as="style">
16<link rel="icon" href="https://urzenia.net/favicon.ico">
17<link rel="icon" type="image/png" sizes="16x16" href="https://urzenia.net/favicon-16x16.png">
18<link rel="icon" type="image/png" sizes="32x32" href="https://urzenia.net/favicon-32x32.png">
19<link rel="apple-touch-icon" href="https://urzenia.net/apple-touch-icon.png">
20<link rel="mask-icon" href="https://urzenia.net/safari-pinned-tab.svg">
21<meta name="theme-color" content="#2e2e33">
22<meta name="msapplication-TileColor" content="#2e2e33">
23<link rel="alternate" hreflang="en" href="https://urzenia.net/posts/home-assistant-yrno-weather-card/">
24<noscript>
25    <style>
26        #theme-toggle,
27        .top-link {
28            display: none;
29        }
30
31    </style>
32    <style>
33        @media (prefers-color-scheme: dark) {
34            :root {
35                --theme: rgb(29, 30, 32);
36                --entry: rgb(46, 46, 51);
37                --primary: rgb(218, 218, 219);
38                --secondary: rgb(155, 156, 157);
39                --tertiary: rgb(65, 66, 68);
40                --content: rgb(196, 196, 197);
41                --code-block-bg: rgb(46, 46, 51);
42                --code-bg: rgb(55, 56, 62);
43                --border: rgb(51, 51, 51);
44                color-scheme: dark;
45            }
46
47            .list {
48                background: var(--theme);
49            }
50
51            .toc {
52                background: var(--entry);
53            }
54        }
55
56    </style>
57</noscript>
58<script>
59    if (localStorage.getItem("pref-theme") === "dark") {
60        document.querySelector("html").dataset.theme = 'dark';
61    } else if (localStorage.getItem("pref-theme") === "light") {
62       document.querySelector("html").dataset.theme = 'light';
63    } else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
64        document.querySelector("html").dataset.theme = 'dark';
65    } else {
66        document.querySelector("html").dataset.theme = 'light';
67    }
68
69</script>
69<meta name="google-site-verification" content="yOVB8-ZNJLmLSploaFftAqs8MymW8YFeBmYufDy-c_M" />
70<meta name="p:domain_verify" content="888fe7e3c88e4bac8233ed5653c4c1ce"/>
71<link rel="me" href="https://101010.pl/@msztolcman" />
72<link rel="me" href="https://pol.social/@msztolcman" />
73<meta property="og:url" content="https://urzenia.net/posts/home-assistant-yrno-weather-card/">
74  <meta property="og:site_name" content="It&#39;s my world!">
75  <meta property="og:title" content="Home Assistant: Yr.no Weather Card (vibe coded)">
76  <meta property="og:description" content="Od kilku lat moim ulubionym serwisem z którego pobieram prognozy pogody jest Yr.no. Ma całkiem fajny widget na Androida, i tam u mnie zagościł dawno temu. Prognozy pogody jak wiemy, różnie mają się do rzeczywistej pogody ;) Ale tutaj z trafialnością nie jest źle. Mi podpasowało, i przy widgecie z Yr.no zostałem.
77Mam też zbudowane odrobinę domowej automatyki (bo przecież nie smart-dom… w niczym nie jest smart ;) ) z użyciem Home Assistant. Już jakiś czas temu dodałem prostą kartę z prognozą pogody od nich, ale ta co mnie najbardziej interesowała nie miała nawet języka angielskiego, używałem w wersji norweskiej ;) No i wczoraj uznałem, że skoro nikt tego nie zrobił do tej pory, to sobie stworzę plugin do HA.">
78  <meta property="og:locale" content="pl_pl">
79  <meta property="og:type" content="article">
80    <meta property="article:section" content="posts">
81    <meta property="article:published_time" content="2026-06-12T11:25:51+02:00">
82    <meta property="article:modified_time" content="2026-06-12T11:25:51+02:00">
83    <meta property="article:tag" content="ha">
84    <meta property="article:tag" content="homeassistant">
85    <meta property="article:tag" content="yr.no">
86    <meta property="article:tag" content="hacs">
87    <meta property="article:tag" content="hacs-plugin">
88    <meta property="article:tag" content="vibe-coding">
89  <meta name="fediverse:creator" content="@[email protected]">
90
91  <meta name="twitter:card" content="summary">
92  <meta name="twitter:title" content="Home Assistant: Yr.no Weather Card (vibe coded)">
93  <meta name="twitter:description" content="Od kilku lat moim ulubionym serwisem z którego pobieram prognozy pogody jest Yr.no. Ma całkiem fajny widget na Androida, i tam u mnie zagościł dawno temu. Prognozy pogody jak wiemy, różnie mają się do rzeczywistej pogody ;) Ale tutaj z trafialnością nie jest źle. Mi podpasowało, i przy widgecie z Yr.no zostałem.
94Mam też zbudowane odrobinę domowej automatyki (bo przecież nie smart-dom… w niczym nie jest smart ;) ) z użyciem Home Assistant. Już jakiś czas temu dodałem prostą kartę z prognozą pogody od nich, ale ta co mnie najbardziej interesowała nie miała nawet języka angielskiego, używałem w wersji norweskiej ;) No i wczoraj uznałem, że skoro nikt tego nie zrobił do tej pory, to sobie stworzę plugin do HA.">
95
96
97<script type="application/ld+json">
98{
99  "@context": "https://schema.org",
100  "@type": "BreadcrumbList",
101  "itemListElement": [
102    {
103      "@type": "ListItem",
104      "position":  1 ,
105      "name": "posts",
106      "item": "https://urzenia.net/posts/"
107    }, 
108    {
109      "@type": "ListItem",
110      "position":  2 ,
111      "name": "Home Assistant: Yr.no Weather Card (vibe coded)",
112      "item": "https://urzenia.net/posts/home-assistant-yrno-weather-card/"
113    }
114  ]
115}
116</script>
vendor: 1 bytes, line 116
116
117<script type="application/ld+json">
118{
119  "@context": "https://schema.org",
120  "@type": "BlogPosting",
121  "headline": "Home Assistant: Yr.no Weather Card (vibe coded)",
122  "name": "Home Assistant: Yr.no Weather Card (vibe coded)",
123  "description": "Od kilku lat moim ulubionym serwisem z którego pobieram prognozy pogody jest Yr.no. Ma całkiem fajny widget na Androida, i tam u mnie zagościł dawno temu. Prognozy pogody jak wiemy, różnie mają się do rzeczywistej pogody ;) Ale tutaj z trafialnością nie jest źle. Mi podpasowało, i przy widgecie z Yr.no zostałem.\nMam też zbudowane odrobinę domowej automatyki (bo przecież nie smart-dom\u0026hellip; w niczym nie jest smart ;) ) z użyciem Home Assistant. Już jakiś czas temu dodałem prostą kartę z prognozą pogody od nich, ale ta co mnie najbardziej interesowała nie miała nawet języka angielskiego, używałem w wersji norweskiej ;) No i wczoraj uznałem, że skoro nikt tego nie zrobił do tej pory, to sobie stworzę plugin do HA.\n",
124  "keywords": [
125    "ha", "homeassistant", "yr.no", "hacs", "hacs-plugin", "vibe-coding", "perplexity"
126  ],
127  "articleBody": "Od kilku lat moim ulubionym serwisem z którego pobieram prognozy pogody jest Yr.no. Ma całkiem fajny widget na Androida, i tam u mnie zagościł dawno temu. Prognozy pogody jak wiemy, różnie mają się do rzeczywistej pogody ;) Ale tutaj z trafialnością nie jest źle. Mi podpasowało, i przy widgecie z Yr.no zostałem.\nMam też zbudowane odrobinę domowej automatyki (bo przecież nie smart-dom… w niczym nie jest smart ;) ) z użyciem Home Assistant. Już jakiś czas temu dodałem prostą kartę z prognozą pogody od nich, ale ta co mnie najbardziej interesowała nie miała nawet języka angielskiego, używałem w wersji norweskiej ;) No i wczoraj uznałem, że skoro nikt tego nie zrobił do tej pory, to sobie stworzę plugin do HA.\nJak pomyślałem, tak zrobiłem. Nie bardzo chce mi się już programować, więc postanowiłem zaprzęc do tego “AI”. W cudzysłowie, bo “I” to tam niewiele. Od kilku miesięcy używam do różnych celów Perplexity które dostałem w jakiejś promocji na rok za darmo. Zasiadłem, pogadałem… znów pogadałem… znów pogadałem… zajęło to kilka godzin, ale powstało :) (a to bardzo prosty plugin, więc jeśli ktoś Wam powie że zbudujecie Onet czy inny WP z użyciem “AI” w godzinę czy dwie, to wiecie… ;) ).\nPlugin jest dostępny na GitHub. Został w całości napisany przez “AI”, więc nie biorę odpowiedzialności za jakoś(ć) ;) Ale działa, i nawet spoko wygląda, więc jak ktoś ma ochotę popróbować to zapraszam :) Sposób instalacji i konfiguracja opisane zostały na stronie projektu.\nPS. Plugin został zgłoszony do dodania do bazy HACS, ale tam w kolejce na review w tej chwili są rzeczy z marca i kwietnia, więc nie spodziewam się akceptacji wcześniej jak pod koniec roku ;)\nA jak wygląda skonfigurowana karta pogody? Ano tak:\n",
128  "wordCount" : "286",
129  "inLanguage": "en",
130  "datePublished": "2026-06-12T11:25:51+02:00",
131  "dateModified": "2026-06-12T11:25:51+02:00",
132  "author":{
133    "@type": "Person",
134    "name": "Marcin Sztolcman"
135  },
136  "mainEntityOfPage": {
137    "@type": "WebPage",
138    "@id": "https://urzenia.net/posts/home-assistant-yrno-weather-card/"
139  },
140  "publisher": {
141    "@type": "Organization",
142    "name": "It's my world!",
143    "logo": {
144      "@type": "ImageObject",
145      "url": "https://urzenia.net/favicon.ico"
146    }
147  }
148}
149</script>
149
150</head>
151<body id="top">
152    <header class="header">
153    <nav class="header-nav">
154        <div class="logo">
155            <a href="https://urzenia.net/" accesskey="h" title="It&#39;s my world! (Alt + H)">It&#39;s my world!</a>
156            <div class="logo-switches">
157                <button id="theme-toggle" class="theme-toggle" accesskey="t" title="(Alt + T)" aria-label="Toggle theme">
158                    <svg class="moon" xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24"
159                        fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
160                        stroke-linejoin="round">
161                        <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
162                    </svg>
163                    <svg class="sun" xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24"
164                        fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
165                        stroke-linejoin="round">
166                        <circle cx="12" cy="12" r="5"></circle>
167                        <line x1="12" y1="1" x2="12" y2="3"></line>
168                        <line x1="12" y1="21" x2="12" y2="23"></line>
169                        <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
170                        <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
171                        <line x1="1" y1="12" x2="3" y2="12"></line>
172                        <line x1="21" y1="12" x2="23" y2="12"></line>
173                        <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
174                        <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
175                    </svg>
176                </button>
177            </div>
178        </div>
179        <ul id="menu" class="menu">
180            <li>
181                <a href="https://urzenia.net/" title="Home">
182                    <span>Home</span>
183                </a>
184            </li>
185            <li>
186                <a href="https://urzenia.net/tags/" title="Tags">
187                    <span>Tags</span>
188                </a>
189            </li>
190            <li>
191                <a href="https://urzenia.net/about/" title="About">
192                    <span>About</span>
193                </a>
194            </li>
195        </ul>
196    </nav>
197</header>
198<main class="main">
199
200<article class="post-single">
201  <header class="post-header">
202    
203    <h1 class="post-title entry-hint-parent">
204      Home Assistant: Yr.no Weather Card (vibe coded)
205    </h1>
206    <div class="post-meta">
207
208<span title='2026-06-12 11:25:51 +0200 CEST'>2026-06-12 11:25:51</span>&nbsp;·&nbsp;<span>2 min</span>&nbsp;·&nbsp;<span>Marcin Sztolcman</span>
209
210</div>
211  </header> 
212  <div class="post-content md-content"><p>Od kilku lat moim ulubionym serwisem z którego pobieram prognozy pogody jest Yr.no. Ma całkiem fajny widget na Androida, i tam u mnie zagościł dawno temu. Prognozy pogody jak wiemy, różnie mają się do rzeczywistej pogody ;) Ale tutaj z trafialnością nie jest źle. Mi podpasowało, i przy widgecie z Yr.no zostałem.</p>
213<p><img alt="Yr.no Android widget" loading="lazy" src="/posts/home-assistant-yrno-weather-card/images/yrno-android-widget.jpg"></p>
214<p>Mam też zbudowane odrobinę domowej automatyki (bo przecież nie smart-dom&hellip; w niczym nie jest smart ;) ) z użyciem <a href="https://www.home-assistant.io/">Home Assistant</a>. Już jakiś czas temu dodałem prostą kartę z prognozą pogody od nich, ale ta co mnie najbardziej interesowała nie miała nawet języka angielskiego, używałem w wersji norweskiej ;) No i wczoraj uznałem, że skoro nikt tego nie zrobił do tej pory, to sobie stworzę plugin do HA.</p>
215<p>Jak pomyślałem, tak zrobiłem. Nie bardzo chce mi się już programować, więc postanowiłem zaprzęc do tego <em>&ldquo;AI&rdquo;</em>. W cudzysłowie, bo <em>&ldquo;I&rdquo;</em> to tam niewiele. Od kilku miesięcy używam do różnych celów <a href="https://www.perplexity.ai/">Perplexity</a> które dostałem w jakiejś promocji na rok za darmo. Zasiadłem, pogadałem&hellip; znów pogadałem&hellip; znów pogadałem&hellip; zajęło to kilka godzin, ale powstało :) (a to bardzo prosty plugin, więc jeśli ktoś Wam powie że zbudujecie Onet czy inny WP z użyciem <em>&ldquo;AI&rdquo;</em> w godzinę czy dwie, to wiecie&hellip; ;) ).</p>
216<p>Plugin jest dostępny na <a href="https://github.com/msztolcman/yrno-weather-card">GitHub</a>. Został w całości napisany przez <em>&ldquo;AI&rdquo;</em>, więc nie biorę odpowiedzialności za jakoś(ć) ;) Ale działa, i nawet spoko wygląda, więc jak ktoś ma ochotę popróbować to zapraszam :) Sposób instalacji i konfiguracja opisane zostały na <a href="https://github.com/msztolcman/yrno-weather-card">stronie projektu</a>.</p>
217<p>PS. Plugin został zgłoszony do dodania do bazy <a href="https://github.com/hacs/default">HACS</a>, ale tam w kolejce na review w tej chwili są rzeczy z marca i kwietnia, więc nie spodziew
217am się akceptacji wcześniej jak pod koniec roku ;)</p>
218<p>A jak wygląda skonfigurowana karta pogody? Ano tak:</p>
219<p><img alt="Yr.no weather card" loading="lazy" src="/posts/home-assistant-yrno-weather-card/images/yrno-weather-card.png"></p>
220
221
222  </div>
223
224  <footer class="post-footer">
225    <ul class="post-tags">
226      <li><a href="https://urzenia.net/tags/ha/">ha</a></li>
227      <li><a href="https://urzenia.net/tags/homeassistant/">homeassistant</a></li>
228      <li><a href="https://urzenia.net/tags/yr.no/">yr.no</a></li>
229      <li><a href="https://urzenia.net/tags/hacs/">hacs</a></li>
230      <li><a href="https://urzenia.net/tags/hacs-plugin/">hacs-plugin</a></li>
231      <li><a href="https://urzenia.net/tags/vibe-coding/">vibe-coding</a></li>
232      <li><a href="https://urzenia.net/tags/perplexity/">perplexity</a></li>
233    </ul>
234  </footer><div id="cusdis_thread"
235  data-host="https://cusdis.com"
236  data-app-id="eabf43fe-cca0-4282-a43e-3cf52d269d62"
237  data-page-id="https://urzenia.net/posts/home-assistant-yrno-weather-card/"
238  data-page-url="https://urzenia.net/posts/home-assistant-yrno-weather-card/"
239  data-page-title="Home Assistant: Yr.no Weather Card (vibe coded)"
240  data-theme="dark"
241></div>
242<script async defer src="https://cusdis.com/js/cusdis.es.js"></script>
242
243
244<div id="cusdis_thread"
245  data-host="https://cusdis.com"
246  data-app-id="eabf43fe-cca0-4282-a43e-3cf52d269d62"
247  data-page-id="https://urzenia.net/posts/home-assistant-yrno-weather-card/"
248  data-page-url="https://urzenia.net/posts/home-assistant-yrno-weather-card/"
249  data-page-title="Home Assistant: Yr.no Weather Card (vibe coded)"
250  data-theme="dark"
251></div>
252<script async defer src="https://cusdis.com/js/cusdis.es.js"></script>
252
253
254<script>
255  const cusdisObserver = new MutationObserver((mutations) => {
256    mutations.forEach((mutation) => {
257      if (mutation.addedNodes.length === 0) return;
258      const iframe = mutation.addedNodes[0];
259      if (!iframe || iframe.tagName !== 'IFRAME') return;
260
261      const customCSS = `
262        /* Tło dopasowane do PaperMod dark */
263        .dark { background: #1d1e20 !important; }
264        #cusdis .dark { background: #1d1e20 !important; }
265
266        /* Teksty */
267        .dark, .dark p, .dark span, .dark label {
268          color: #d4d4d4 !important;
269        }
270
271        /* Pole tekstowe */
272        .dark textarea, .dark input[type="text"], .dark input[type="email"] {
273          background: #2a2b2d !important;
274          border-color: #444 !important;
275          color: #d4d4d4 !important;
276          border-radius: 4px !important;
277        }
278        .dark textarea:focus, .dark input:focus {
279          border-color: #888 !important;
280          outline: none !important;
281        }
282
283        /* Przycisk Send */
284        .dark button[type="submit"] {
285          background: #555 !important;
286          color: #fff !important;
287          border: none !important;
288          border-radius: 4px !important;
289          cursor: pointer !important;
290        }
291        .dark button[type="submit"]:hover {
292          background: #777 !important;
293        }
294
295        /* Pojedynczy komentarz */
296        .dark .comment-container {
297          border-color: #333 !important;
298        }
299
300        /* Nazwa autora */
301        .dark .by-line {
302          color: #aaa !important;
303        }
304      `;
305
306      iframe.srcdoc = iframe.srcdoc.replace('</style>', customCSS + '</style>');
307    });
308  });
309
310  cusdisObserver.observe(document.getElementById('cusdis_thread'), {
311    childList: true,
312    subtree: true
313  });
314
315  document.addEventListener('DOMContentLoaded', function() {
316    var frameObserver = new MutationObserver(function() {
317      var iframe = document.querySelector('#cusdis_thread iframe');
318      if (!iframe) return;
319      frameObserver.disconnect();
320      iframe.setAttribute('scrolling', 'no');
321      iframe.style.overflow = 'hidden';
322      iframe.style.width = '100%';
323
324      function resizeIframe() {
325        try {
326          var height = iframe.contentWindow.document.body.scrollHeight;
327          if (height && height > 50) iframe.style.height = height + 'px';
328        } catch(e) {}
329      }
330      setInterval(resizeIframe, 300);
331
332      iframe.addEventListener('load', function() {
333        iframe.setAttribute('scrolling', 'no');
334        iframe.style.overflow = 'hidden';
335        setTimeout(resizeIframe, 200);
336      });
337
338      window.addEventListener('message', function(e) {
339        if (e.origin !== 'https://cusdis.com') return;
340        var h = e.data && (e.data.height || e.data.scrollHeight || e.data);
341        if (typeof h === 'number' && h > 50) iframe.style.height = h + 'px';
342      });
343    });
344    frameObserver.observe(document.getElementById('cusdis_thread'), { childList: true, subtree: true });
345  });
346</script>
346
347
348
349</article>
350    </main>
351    
352<footer class="footer">
353        <span>&copy; 2026 <a href="https://urzenia.net/">It&#39;s my world!</a></span> · 
354
355    
356    
357    <span>
358        Powered by
359        <a href="https://gohugo.io/?utm_source=papermod" rel="noopener" target="_blank">Hugo</a> &
360        <a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
361    </span>
362</footer>
363<a href="#top" id="top-link" class="top-link hidden" aria-label="go to top" title="Go to Top (Alt + G)" accesskey="g">
364    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
365        stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevrons-up">
366        <polyline points="17 11 12 6 7 11"></polyline>
367        <polyline points="17 18 12 13 7 18"></polyline>
368    </svg>
369</a>
370
371<script>
372    let menu = document.getElementById('menu');
373    if (menu) {
374        
375        const scrollPosition = localStorage.getItem("menu-scroll-position");
376        if (scrollPosition) {
377            menu.scrollLeft = parseInt(scrollPosition, 10);
378        }
379        
380        menu.onscroll = function () {
381            localStorage.setItem("menu-scroll-position", menu.scrollLeft);
382        }
383    }
384
385    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
386        anchor.addEventListener("click", function (e) {
387            e.preventDefault();
388            var id = this.getAttribute("href").substr(1);
389            if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
390                document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
391                    behavior: "smooth"
392                });
393            } else {
394                document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
395            }
396            if (id === "top") {
397                history.replaceState(null, null, " ");
398            } else {
399                history.pushState(null, null, `#${id}`);
400            }
401        });
402    });
403
404</script>
vendor: 1 bytes, line 404
404
405<script>
406    var toplink = document.getElementById("top-link");
407    window.onscroll = function () {
408        const scrollThreshold = window.innerHeight;
409        if (document.body.scrollTop > scrollThreshold || document.documentElement.scrollTop > scrollThreshold) {
410            toplink.classList.remove("hidden");
411        } else {
412            toplink.classList.add("hidden");
413        }
414    };
415
416</script>
vendor: 1 bytes, line 416
416
417<script>
418    document.getElementById("theme-toggle").addEventListener("click", () => {
419        const html = document.querySelector("html");
420        if (html.dataset.theme === "dark") {
421            html.dataset.theme = 'light';
422            localStorage.setItem("pref-theme", 'light');
423        } else {
424            html.dataset.theme = 'dark';
425            localStorage.setItem("pref-theme", 'dark');
426        }
427    })
428
429</script>
vendor: 1 bytes, line 429
429
430<script>
431    document.querySelectorAll('pre > code').forEach((codeblock) => {
432        const container = codeblock.parentNode.parentNode;
433
434        const copybutton = document.createElement('button');
435        copybutton.classList.add('copy-code');
436        copybutton.innerHTML = 'copy';
437
438        function copyingDone() {
439            copybutton.innerHTML = 'copied!';
440            setTimeout(() => {
441                copybutton.innerHTML = 'copy';
442            }, 2000);
443        }
444
445        copybutton.addEventListener('click', (cb) => {
446            if ('clipboard' in navigator) {
447                navigator.clipboard.writeText(codeblock.textContent);
448                copyingDone();
449                return;
450            }
451
452            const range = document.createRange();
453            range.selectNodeContents(codeblock);
454            const selection = window.getSelection();
455            selection.removeAllRanges();
456            selection.addRange(range);
457            try {
458                document.execCommand('copy');
459                copyingDone();
460            } catch (e) { };
461            selection.removeRange(range);
462        });
463
464        if (container.classList.contains("highlight")) {
465            container.appendChild(copybutton);
466        } else if (container.parentNode.firstChild == container) {
467            
468        } else if (codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName == "TABLE") {
469            
470            codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(copybutton);
471        } else {
472            
473            codeblock.parentNode.appendChild(copybutton);
474        }
475    });
476</script>
vendor: 1 bytes, line 476
476
477<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"f532191458864c8084dae4127f6323d4","r":1,"spa":2}' crossorigin="anonymous"></script>
477
478</body>
479
480</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.