index.hbs

  1<!DOCTYPE HTML>
  2<html lang="{{ language }}" dir="{{ text_direction }}">
  3    <head>
  4        <!-- Book generated using mdBook -->
  5        <meta charset="UTF-8">
  6        <style>
  7            @view-transition {
  8                navigation: auto;
  9            }
 10            ::view-transition-old(root),
 11            ::view-transition-new(root) {
 12                animation-duration: 0.05s;
 13            }
 14        </style>
 15        <!-- Theme initialization - must run before any CSS loads to prevent flicker -->
 16        <script>
 17            (function() {
 18                var theme;
 19                try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
 20                if (theme === null || theme === undefined) {
 21                    theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
 22                }
 23                var html = document.documentElement;
 24                html.setAttribute('data-theme', theme);
 25                html.setAttribute('data-color-scheme', theme);
 26                html.className = theme;
 27            })();
 28        </script>
 29        <title>{{ title }}</title>
 30        {{#if is_print }}
 31        <meta name="robots" content="noindex">
 32        {{/if}}
 33        {{#if base_url}}
 34        <base href="{{ base_url }}">
 35        {{/if}}
 36
 37
 38        <!-- Custom HTML head -->
 39        {{> head}}
 40
 41        <meta name="description" content="#description#">
 42        <meta name="viewport" content="width=device-width, initial-scale=1">
 43        <meta name="theme-color" content="#ffffff">
 44
 45        <link rel="shortcut icon" href="{{ path_to_root }}favicon.png">
 46        <link rel="stylesheet" href="{{ path_to_root }}css/variables.css">
 47        <link rel="stylesheet" href="{{ path_to_root }}css/general.css">
 48        <link rel="stylesheet" href="{{ path_to_root }}css/chrome.css">
 49        {{#if print_enable}}
 50        <link rel="stylesheet" href="{{ path_to_root }}css/print.css" media="print">
 51        {{/if}}
 52
 53        <!-- Fonts -->
 54        <link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
 55        {{#if copy_fonts}}
 56        <link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css">
 57        {{/if}}
 58
 59        <!-- Highlight.js Stylesheets -->
 60        <link rel="stylesheet" href="{{ path_to_root }}highlight.css">
 61        <link rel="stylesheet" href="{{ path_to_root }}tomorrow-night.css">
 62        <link rel="stylesheet" href="{{ path_to_root }}ayu-highlight.css">
 63
 64        <!-- Custom theme stylesheets -->
 65        {{#each additional_css}}
 66        <link rel="stylesheet" href="{{ ../path_to_root }}{{ this }}">
 67        {{/each}}
 68
 69        {{#if mathjax_support}}
 70        <!-- MathJax -->
 71        <script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
 72        {{/if}}
 73        <meta name="amplitude-key" content="#amplitude_key#" />
 74        <meta name="consent-io-instance" content="#consent_io_instance#" />
 75    </head>
 76    <body class="no-js">
 77    <div id="body-container">
 78        <div class="noise-pattern" style="background-image: url('https://cdn.zed.dev/images/noise.png');"></div>
 79
 80        <!-- Provide site root to javascript -->
 81        <script>
 82            var path_to_root = "{{ path_to_root }}";
 83            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "{{ preferred_dark_theme }}" : "{{ default_theme }}";
 84            // Mark as JS-enabled
 85            document.body.classList.remove('no-js');
 86            document.body.classList.add('js');
 87        </script>
 88
 89        <header class="header-bar">
 90            <div class="left-container">
 91                <a href="/" class="logo-nav">
 92                    <img src="https://zed.dev/logo_icon.webp" class="icon-logo-img" alt="Zed Industries" style="height: 26px;">
 93                </a>
 94                <button id="sidebar-toggle" class="icon-button ib-hidden-desktop" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar" aria-expanded="false">
 95                    <i class="fa fa-bars"></i>
 96                </button>
 97            </div>
 98            {{#if search_enabled}}
 99            <button id="search-toggle" class="search-button" type="button" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
100                <i class="icon fa fa-search"></i>
101                <span class="search-content-desktop">
102                    <span class="placeholder">Search docs…</span>
103                    <kbd>S</kbd>
104                </span>
105                <span class="search-content-mobile">
106                    <span class="placeholder">Search…</span>
107                </span>
108            </button>
109            {{/if}}
110            <div class="right-container">
111                <button id="theme-toggle" class="icon-button" type="button" title="Change Theme" aria-label="Change Theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
112                    <i class="fa fa-paint-brush"></i>
113                </button>
114
115                <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
116                    <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
117                    <li role="none"><button role="menuitem" class="theme" id="dark">Dark</button></li>
118                </ul>
119
120                <button id="copy-markdown-toggle" class="icon-button ib-hidden-mobile" type="button" title="Copy Page as Markdown" aria-label="Copy page as markdown">
121                    <i class="fa fa-copy"></i>
122                </button>
123
124                <a class="download-button" href="https://zed.dev/download" title="Download Zed" aria-label="Download Zed">
125                    Download
126                </a>
127                {{#if git_repository_url}}
128                <a href="{{git_repository_url}}" title="Git repository" aria-label="Git repository">
129                    <i id="git-repository-button" class="fa {{git_repository_icon}}"></i>
130                </a>
131                {{/if}}
132                {{#if git_repository_edit_url}}
133                <a href="{{git_repository_edit_url}}" title="Suggest an edit" aria-label="Suggest an edit">
134                    <i id="git-edit-button" class="fa fa-edit"></i>
135                </a>
136                {{/if}}
137            </div>
138        </header>
139
140        <div id="page-wrapper" class="page-wrapper">
141
142            {{#if search_enabled}}
143            <div class="search-container">
144                <div id="search-wrapper" class="search-modal hidden">
145                    <form id="searchbar-outer" class="searchbar-outer">
146                        <input type="search" id="searchbar" name="searchbar" placeholder="Search…" aria-controls="searchresults-outer" aria-describedby="searchresults-header">
147                    </form>
148                    <div id="searchresults-outer" class="searchresults-outer">
149                        <div id="searchresults-header" class="searchresults-header"></div>
150                        <ul id="searchresults">
151                        </ul>
152                    </div>
153                </div>
154            </div>
155            {{/if}}
156
157            <nav id="sidebar" class="sidebar" aria-label="Table of contents">
158                <div class="sidebar-scrollbox">
159                    {{#toc}}{{/toc}}
160                </div>
161                <div style="display: none;" id="sidebar-resize-handle" class="sidebar-resize-handle">
162                    <div class="sidebar-resize-indicator"></div>
163                </div>
164            </nav>
165
166            <!-- Mobile sidebar toggle -->
167            <script>
168                (function() {
169                    var sidebarToggle = document.getElementById('sidebar-toggle');
170                    var sidebar = document.getElementById('sidebar');
171
172                    sidebarToggle.addEventListener('click', function() {
173                        var isOpen = document.body.classList.toggle('sidebar-open');
174                        sidebarToggle.setAttribute('aria-expanded', isOpen);
175                        sidebar.setAttribute('aria-hidden', !isOpen);
176                    });
177
178                    // Close sidebar when clicking a link inside it (on mobile)
179                    sidebar.addEventListener('click', function(e) {
180                        if (e.target.tagName === 'A' && window.innerWidth < 620) {
181                            document.body.classList.remove('sidebar-open');
182                            sidebarToggle.setAttribute('aria-expanded', 'false');
183                            sidebar.setAttribute('aria-hidden', 'true');
184                        }
185                    });
186                })();
187            </script>
188
189            <!-- Search backdrop handlers -->
190            <script>
191                (function() {
192                    var searchWrapper = document.getElementById('search-wrapper');
193                    var searchContainer = document.querySelector('.search-container');
194                    var searchResults = document.getElementById('searchresults');
195
196                    if (!searchWrapper || !searchContainer) return;
197
198                    searchContainer.addEventListener('click', function(e) {
199                        if (e.target === searchContainer) {
200                            searchWrapper.classList.add('hidden');
201                        }
202                    });
203
204                    if (searchResults) {
205                        searchResults.addEventListener('click', function(e) {
206                            if (e.target.tagName === 'A' || e.target.closest('a')) {
207                                searchWrapper.classList.add('hidden');
208                            }
209                        });
210                    }
211                })();
212            </script>
213
214            <!-- Insert section spacers and apply collapsed state before scroll restoration to prevent layout shift/flicker -->
215            <script>
216                (function() {
217                    var chapterList = document.querySelector('#sidebar ol.chapter');
218                    if (!chapterList) return;
219
220                    var collapsedSections = [];
221                    try {
222                        var stored = sessionStorage.getItem('sidebar-collapsed-sections');
223                        if (stored) {
224                            collapsedSections = JSON.parse(stored);
225                        }
226                    } catch (e) {}
227
228                    var partTitles = chapterList.querySelectorAll('li.part-title');
229                    var previousPartTitle = null;
230
231                    partTitles.forEach(function(partTitle, index) {
232                        partTitle._sectionName = partTitle.textContent.trim();
233
234                        // Insert a spacer before this part-title (except for the first one)
235                        if (index > 0) {
236                            var spacer = document.createElement('li');
237                            spacer.className = 'section-spacer';
238                            partTitle.parentNode.insertBefore(spacer, partTitle);
239
240                            if (previousPartTitle) {
241                                previousPartTitle._spacerAfter = spacer;
242                            }
243                        }
244
245                        var isCollapsed = collapsedSections.includes(partTitle._sectionName);
246                        if (isCollapsed) {
247                            // Hide all siblings until next part-title
248                            var sibling = partTitle.nextElementSibling;
249                            while (sibling && !sibling.classList.contains('part-title')) {
250                                sibling.classList.add('section-hidden');
251                                sibling = sibling.nextElementSibling;
252                            }
253                            // Hide the spacer after this section (will be set on next iteration)
254                            partTitle._isCollapsed = true;
255                        }
256
257                        // If previous section was collapsed, hide its spacer
258                        if (previousPartTitle && previousPartTitle._isCollapsed && previousPartTitle._spacerAfter) {
259                            previousPartTitle._spacerAfter.classList.add('section-hidden');
260                        }
261
262                        previousPartTitle = partTitle;
263                    });
264
265                    // Handle the last section's spacer if it was collapsed
266                    if (previousPartTitle && previousPartTitle._isCollapsed && previousPartTitle._spacerAfter) {
267                        previousPartTitle._spacerAfter.classList.add('section-hidden');
268                    }
269                })();
270            </script>
271
272            <!-- Track and set sidebar scroll position -->
273            <script>
274                var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
275                sidebarScrollbox.addEventListener('click', function(e) {
276                    if (e.target.tagName === 'A') {
277                        sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
278                    }
279                }, { passive: true });
280                var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
281                sessionStorage.removeItem('sidebar-scroll');
282                if (sidebarScrollTop) {
283                    // preserve sidebar scroll position when navigating via links within sidebar
284                    sidebarScrollbox.scrollTop = sidebarScrollTop;
285                } else {
286                    // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
287                    var activeSection = document.querySelector('#sidebar .active');
288                    if (activeSection) {
289                        activeSection.scrollIntoView({ block: 'center' });
290                    }
291                }
292            </script>
293
294            <div class="page">
295                <div id="content" class="content">
296                    <main>
297                      {{{ content }}}
298                        <div class="footer-buttons">
299                            {{#previous}}
300                            <a rel="prev" href="{{ path_to_root }}{{link}}" class="footer-button" title="{{title}}">
301                                <i class="fa fa-angle-left"></i>
302                                {{title}}
303                            </a>
304                            {{/previous}}
305                            {{#next}}
306                            <a rel="next" href="{{ path_to_root }}{{link}}" class="footer-button" title="{{title}}">
307                                {{title}}
308                                <i class="fa fa-angle-right"></i>
309                            </a>
310                            {{/next}}
311                        </div>
312                        <footer class="footer">
313                            <a href="/" class="logo-nav">
314                                <img
315                                    src="https://zed.dev/logo_icon.webp"
316                                    class="footer-logo"
317                                    alt="Zed Industries"
318                                />
319                            </a>
320                            <span class="footer-separator">•</span>
321                            <a class="footer-link" href="https://zed.dev"
322                                >Back to Site</a
323                            >
324                            <span class="footer-separator">•</span>
325                            <a
326                                class="footer-link"
327                                href="https://zed.dev/releases"
328                                >Releases</a
329                            >
330                            <span class="footer-separator">•</span>
331                            <a
332                                class="footer-link"
333                                href="https://zed.dev/roadmap"
334                                >Roadmap</a
335                            >
336                            <span class="footer-separator">•</span>
337                            <a
338                                class="footer-link"
339                                href="https://github.com/zed-industries/zed"
340                                >GitHub</a
341                            >
342                            <span class="footer-separator">•</span>
343                            <a
344                                class="footer-link"
345                                href="https://zed.dev/blog"
346                                >Blog</a
347                            >
348                            <span class="footer-separator">•</span>
349                            <button
350                                id="c15t-manage-consent-btn"
351                                class="footer-link"
352                            >
353                                Manage Site Cookies
354                            </button>
355                        </footer>
356                    </main>
357                    <div class="toc-container">
358                        <nav class="pagetoc"></nav>
359                    </div>
360                    <!-- Immediately detect if page has headins that are not h1 to prevent flicker -->
361                    <script>
362                        (function() {
363                            var tocContainer = document.querySelector('.toc-container');
364                            var headers = document.querySelectorAll('.header');
365                            var hasNonH1Headers = false;
366                            for (var i = 0; i < headers.length; i++) {
367                                var parent = headers[i].parentElement;
368                                if (parent && !parent.tagName.toLowerCase().startsWith('h1')) {
369                                    hasNonH1Headers = true;
370                                    break;
371                                }
372                            }
373                            if (hasNonH1Headers) {
374                                tocContainer.classList.add('has-toc');
375                            } else {
376                                tocContainer.classList.add('no-toc');
377                            }
378                        })();
379                    </script>
380                </div>
381            </div>
382        </div>
383
384        {{#if live_reload_endpoint}}
385        <!-- Livereload script (if served using the cli tool) -->
386        <script>
387            const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
388            const wsAddress = wsProtocol + "//" + location.host + "/" + "{{{live_reload_endpoint}}}";
389            const socket = new WebSocket(wsAddress);
390            socket.onmessage = function (event) {
391                if (event.data === "reload") {
392                    socket.close();
393                    location.reload();
394                }
395            };
396
397            window.onbeforeunload = function() {
398                socket.close();
399            }
400        </script>
401        {{/if}}
402
403        {{#if playground_line_numbers}}
404        <script>
405            window.playground_line_numbers = true;
406        </script>
407        {{/if}}
408
409        {{#if playground_copyable}}
410        <script>
411            window.playground_copyable = true;
412        </script>
413        {{/if}}
414
415        {{#if playground_js}}
416        <script src="{{ path_to_root }}ace.js"></script>
417        <script src="{{ path_to_root }}editor.js"></script>
418        <script src="{{ path_to_root }}mode-rust.js"></script>
419        <script src="{{ path_to_root }}theme-dawn.js"></script>
420        <script src="{{ path_to_root }}theme-tomorrow_night.js"></script>
421        {{/if}}
422
423        {{#if search_js}}
424        <script src="{{ path_to_root }}elasticlunr.min.js"></script>
425        <script src="{{ path_to_root }}mark.min.js"></script>
426        <script src="{{ path_to_root }}searcher.js"></script>
427        {{/if}}
428
429        <script src="{{ path_to_root }}clipboard.min.js"></script>
430        <script src="{{ path_to_root }}highlight.js"></script>
431        <script src="{{ path_to_root }}book.js"></script>
432
433        <!-- Custom JS scripts -->
434        {{#each additional_js}}
435        <script src="{{ ../path_to_root }}{{this}}"></script>
436        {{/each}}
437
438        {{#if is_print}}
439        {{#if mathjax_support}}
440        <script>
441        window.addEventListener('load', function() {
442            MathJax.Hub.Register.StartupHook('End', function() {
443                window.setTimeout(window.print, 100);
444            });
445        });
446        </script>
447        {{else}}
448        <script>
449        window.addEventListener('load', function() {
450            window.setTimeout(window.print, 100);
451        });
452        </script>
453        {{/if}}
454        {{/if}}
455
456        <!-- c15t Consent Banner -->
457        <div id="c15t-banner" style="display: none;">
458            <div>
459                <p id="c15t-description">
460                    Zed uses cookies to improve your experience and for marketing. Read <a href="https://zed.dev/cookie-policy">our cookie policy</a> for more details.
461                </p>
462            </div>
463            <div id="c15t-configure-section" style="display: none">
464                <div>
465                    <label for="c15t-toggle-necessary"
466                        >Strictly Necessary</label
467                    >
468                    <label class="c15t-switch">
469                        <input
470                            type="checkbox"
471                            id="c15t-toggle-necessary"
472                            checked
473                            disabled
474                        />
475                        <span class="c15t-slider"></span>
476                    </label>
477                </div>
478                <div>
479                    <label for="c15t-toggle-measurement">Analytics</label>
480                    <label class="c15t-switch">
481                        <input
482                            type="checkbox"
483                            id="c15t-toggle-measurement"
484                        />
485                        <span class="c15t-slider"></span>
486                    </label>
487                </div>
488                <div>
489                    <label for="c15t-toggle-marketing">Marketing</label>
490                    <label class="c15t-switch">
491                        <input
492                            type="checkbox"
493                            id="c15t-toggle-marketing"
494                        />
495                        <span class="c15t-slider"></span>
496                    </label>
497                </div>
498            </div>
499            <div id="c15t-footer">
500                <button
501                    id="c15t-configure-btn"
502                    class="c15t-button icon"
503                    title="Configure"
504                >
505                    <svg
506                        xmlns="http://www.w3.org/2000/svg"
507                        width="14"
508                        height="14"
509                        viewBox="0 0 24 24"
510                        fill="none"
511                        stroke="currentColor"
512                        stroke-width="2"
513                        stroke-linecap="round"
514                        stroke-linejoin="round"
515                    >
516                        <path d="M20 7h-9" />
517                        <path d="M14 17H5" />
518                        <circle cx="17" cy="17" r="3" />
519                        <circle cx="7" cy="7" r="3" />
520                    </svg>
521                </button>
522                <div>
523                    <button id="c15t-decline" class="c15t-button">
524                        Reject all
525                    </button>
526                    <button id="c15t-accept" class="c15t-button primary">
527                        Accept all
528                    </button>
529                </div>
530            </div>
531        </div>
532    </div>
533    </body>
534</html>