123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- <!DOCTYPE HTML>
- <html lang="en" class="sidebar-visible no-js light">
- <head>
- <!-- Book generated using mdBook -->
- <meta charset="UTF-8">
- <title>Dynamic Rendering</title>
- <!-- Custom HTML head -->
-
- <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
- <meta name="description" content="">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <meta name="theme-color" content="#ffffff" />
- <link rel="icon" href="../favicon.svg">
- <link rel="shortcut icon" href="../favicon.png">
- <link rel="stylesheet" href="../css/variables.css">
- <link rel="stylesheet" href="../css/general.css">
- <link rel="stylesheet" href="../css/chrome.css">
- <link rel="stylesheet" href="../css/print.css" media="print">
- <!-- Fonts -->
- <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
- <link rel="stylesheet" href="../fonts/fonts.css">
- <!-- Highlight.js Stylesheets -->
- <link rel="stylesheet" href="../highlight.css">
- <link rel="stylesheet" href="../tomorrow-night.css">
- <link rel="stylesheet" href="../ayu-highlight.css">
- <!-- Custom theme stylesheets -->
- <!-- MathJax -->
- <script async type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
- </head>
- <body>
- <!-- Provide site root to javascript -->
- <script type="text/javascript">
- var path_to_root = "../";
- var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
- </script>
- <!-- Work around some values being stored in localStorage wrapped in quotes -->
- <script type="text/javascript">
- try {
- var theme = localStorage.getItem('mdbook-theme');
- var sidebar = localStorage.getItem('mdbook-sidebar');
- if (theme.startsWith('"') && theme.endsWith('"')) {
- localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
- }
- if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
- localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
- }
- } catch (e) { }
- </script>
- <!-- Set the theme before any content is loaded, prevents flash -->
- <script type="text/javascript">
- var theme;
- try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
- if (theme === null || theme === undefined) { theme = default_theme; }
- var html = document.querySelector('html');
- html.classList.remove('no-js')
- html.classList.remove('light')
- html.classList.add(theme);
- html.classList.add('js');
- </script>
- <!-- Hide / unhide sidebar before it is displayed -->
- <script type="text/javascript">
- var html = document.querySelector('html');
- var sidebar = 'hidden';
- if (document.body.clientWidth >= 1080) {
- try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
- sidebar = sidebar || 'visible';
- }
- html.classList.remove('sidebar-visible');
- html.classList.add("sidebar-" + sidebar);
- </script>
- <nav id="sidebar" class="sidebar" aria-label="Table of contents">
- <div class="sidebar-scrollbox">
- <ol class="chapter"><li class="chapter-item expanded affix "><a href="../index.html">Introduction</a></li><li class="chapter-item expanded "><a href="../getting_started/index.html"><strong aria-hidden="true">1.</strong> Getting Started</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../getting_started/desktop.html"><strong aria-hidden="true">1.1.</strong> Desktop</a></li><li class="chapter-item expanded "><a href="../getting_started/web.html"><strong aria-hidden="true">1.2.</strong> Web</a></li><li class="chapter-item expanded "><a href="../getting_started/ssr.html"><strong aria-hidden="true">1.3.</strong> Server-Side Rendering</a></li><li class="chapter-item expanded "><a href="../getting_started/fullstack.html"><strong aria-hidden="true">1.4.</strong> Fullstack</a></li><li class="chapter-item expanded "><a href="../getting_started/liveview.html"><strong aria-hidden="true">1.5.</strong> Liveview</a></li><li class="chapter-item expanded "><a href="../getting_started/tui.html"><strong aria-hidden="true">1.6.</strong> Terminal UI</a></li><li class="chapter-item expanded "><a href="../getting_started/mobile.html"><strong aria-hidden="true">1.7.</strong> Mobile</a></li><li class="chapter-item expanded "><a href="../getting_started/hot_reload.html"><strong aria-hidden="true">1.8.</strong> Hot Reloading</a></li></ol></li><li class="chapter-item expanded "><a href="../describing_ui/index.html"><strong aria-hidden="true">2.</strong> Describing the UI</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../describing_ui/special_attributes.html"><strong aria-hidden="true">2.1.</strong> Special Attributes</a></li><li class="chapter-item expanded "><a href="../describing_ui/components.html"><strong aria-hidden="true">2.2.</strong> Components</a></li><li class="chapter-item expanded "><a href="../describing_ui/component_props.html"><strong aria-hidden="true">2.3.</strong> Props</a></li><li class="chapter-item expanded "><a href="../describing_ui/component_children.html"><strong aria-hidden="true">2.4.</strong> Component Children</a></li></ol></li><li class="chapter-item expanded "><a href="../interactivity/index.html"><strong aria-hidden="true">3.</strong> Interactivity</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../interactivity/event_handlers.html"><strong aria-hidden="true">3.1.</strong> Event Listeners</a></li><li class="chapter-item expanded "><a href="../interactivity/hooks.html"><strong aria-hidden="true">3.2.</strong> Hooks & Component State</a></li><li class="chapter-item expanded "><a href="../interactivity/user_input.html"><strong aria-hidden="true">3.3.</strong> User Input</a></li><li class="chapter-item expanded "><a href="../interactivity/sharing_state.html"><strong aria-hidden="true">3.4.</strong> Sharing State</a></li><li class="chapter-item expanded "><a href="../interactivity/custom_hooks.html"><strong aria-hidden="true">3.5.</strong> Custom Hooks</a></li><li class="chapter-item expanded "><a href="../interactivity/dynamic_rendering.html" class="active"><strong aria-hidden="true">3.6.</strong> Dynamic Rendering</a></li><li class="chapter-item expanded "><a href="../interactivity/router.html"><strong aria-hidden="true">3.7.</strong> Routing</a></li></ol></li><li class="chapter-item expanded "><a href="../async/index.html"><strong aria-hidden="true">4.</strong> Async</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../async/use_future.html"><strong aria-hidden="true">4.1.</strong> UseFuture</a></li><li class="chapter-item expanded "><a href="../async/use_coroutine.html"><strong aria-hidden="true">4.2.</strong> UseCoroutine</a></li><li class="chapter-item expanded "><a href="../async/spawn.html"><strong aria-hidden="true">4.3.</strong> Spawning Futures</a></li></ol></li><li class="chapter-item expanded "><a href="../best_practices/index.html"><strong aria-hidden="true">5.</strong> Best Practices</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../best_practices/error_handling.html"><strong aria-hidden="true">5.1.</strong> Error Handling</a></li><li class="chapter-item expanded "><a href="../best_practices/antipatterns.html"><strong aria-hidden="true">5.2.</strong> Antipatterns</a></li></ol></li><li class="chapter-item expanded "><a href="../publishing/index.html"><strong aria-hidden="true">6.</strong> Publishing</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../publishing/desktop.html"><strong aria-hidden="true">6.1.</strong> Desktop</a></li><li class="chapter-item expanded "><a href="../publishing/web.html"><strong aria-hidden="true">6.2.</strong> Web</a></li><li class="spacer"></li></ol></li><li class="chapter-item expanded "><a href="../fullstack/index.html"><strong aria-hidden="true">7.</strong> Fullstack</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../fullstack/getting_started.html"><strong aria-hidden="true">7.1.</strong> Getting Started</a></li><li class="chapter-item expanded "><a href="../fullstack/server_functions.html"><strong aria-hidden="true">7.2.</strong> Communicating with the Server</a></li><li class="spacer"></li></ol></li><li class="chapter-item expanded "><a href="../custom_renderer/index.html"><strong aria-hidden="true">8.</strong> Custom Renderer</a></li><li class="spacer"></li><li class="chapter-item expanded "><a href="../contributing/index.html"><strong aria-hidden="true">9.</strong> Contributing</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../contributing/project_structure.html"><strong aria-hidden="true">9.1.</strong> Project Structure</a></li><li class="chapter-item expanded "><a href="../contributing/walkthrough_readme.html"><strong aria-hidden="true">9.2.</strong> Walkthrough of Internals</a></li><li class="chapter-item expanded "><a href="../contributing/guiding_principles.html"><strong aria-hidden="true">9.3.</strong> Guiding Principles</a></li><li class="chapter-item expanded "><a href="../contributing/roadmap.html"><strong aria-hidden="true">9.4.</strong> Roadmap</a></li></ol></li></ol>
- </div>
- <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
- </nav>
- <div id="page-wrapper" class="page-wrapper">
- <div class="page">
- <div id="menu-bar-hover-placeholder"></div>
- <div id="menu-bar" class="menu-bar sticky bordered">
- <div class="left-buttons">
- <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
- <i class="fa fa-bars"></i>
- </button>
- <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">
- <i class="fa fa-paint-brush"></i>
- </button>
- <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
- <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
- <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
- <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
- <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
- <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
- </ul>
- <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
- <i class="fa fa-search"></i>
- </button>
- <button id="language-toggle" class="icon-button" type="button" title="Select language" aria-label="Select language" aria-haspopup="true" aria-expanded="false" aria-controls="language-list">
- <i class="fa fa-globe"></i>
- </button>
- <ul id="language-list" class="language-popup" aria-label="Languages" role="menu">
- <li role="none"><a href="../../en/interactivity/dynamic_rendering.html"><button role="menuitem" class="language" id="light">English</button></a></li>
- <li role="none"><a href="../../pt-br/interactivity/dynamic_rendering.html"><button role="menuitem" class="language" id="light">Português Brasileiro</button></a></li>
- </ul>
- </div>
- <h1 class="menu-title"></h1>
- <div class="right-buttons">
- <a href="../print.html" title="Print this book" aria-label="Print this book">
- <i id="print-button" class="fa fa-print"></i>
- </a>
- <a href="https://github.com/DioxusLabs/dioxus/edit/master/docs/guide" title="Git repository" aria-label="Git repository">
- <i id="git-repository-button" class="fa fa-github"></i>
- </a>
- <a href="https://github.com/DioxusLabs/dioxus/edit/master/docs/guide/src/interactivity/dynamic_rendering.md" title="Suggest an edit" aria-label="Suggest an edit">
- <i id="git-edit-button" class="fa fa-edit"></i>
- </a>
- </div>
- </div>
- <div id="search-wrapper" class="hidden">
- <form id="searchbar-outer" class="searchbar-outer">
- <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
- </form>
- <div id="searchresults-outer" class="searchresults-outer hidden">
- <div id="searchresults-header" class="searchresults-header"></div>
- <ul id="searchresults">
- </ul>
- </div>
- </div>
- <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
- <script type="text/javascript">
- document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
- document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
- Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
- link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
- });
- </script>
- <div id="content" class="content">
- <main>
- <h1 id="dynamic-rendering"><a class="header" href="#dynamic-rendering">Dynamic Rendering</a></h1>
- <p>Sometimes you want to render different things depending on the state/props. With Dioxus, just describe what you want to see using Rust control flow – the framework will take care of making the necessary changes on the fly if the state or props change!</p>
- <h2 id="conditional-rendering"><a class="header" href="#conditional-rendering">Conditional Rendering</a></h2>
- <p>To render different elements based on a condition, you could use an <code>if-else</code> statement:</p>
- <pre><pre class="playground"><code class="language-rust edition2018">
- <span class="boring">#![allow(unused)]
- </span><span class="boring">fn main() {
- </span>if *is_logged_in {
- cx.render(rsx! {
- "Welcome!"
- button {
- onclick: move |_| on_log_out.call(()),
- "Log Out",
- }
- })
- } else {
- cx.render(rsx! {
- button {
- onclick: move |_| on_log_in.call(()),
- "Log In",
- }
- })
- }
- <span class="boring">}
- </span></code></pre></pre>
- <blockquote>
- <p>You could also use <code>match</code> statements, or any Rust function to conditionally render different things.</p>
- </blockquote>
- <h3 id="improving-the-if-else-example"><a class="header" href="#improving-the-if-else-example">Improving the <code>if-else</code> Example</a></h3>
- <p>You may have noticed some repeated code in the <code>if-else</code> example above. Repeating code like this is both bad for maintainability and performance. Dioxus will skip diffing static elements like the button, but when switching between multiple <code>rsx</code> calls it cannot perform this optimization. For this example either approach is fine, but for components with large parts that are reused between conditionals, it can be more of an issue.</p>
- <p>We can improve this example by splitting up the dynamic parts and inserting them where they are needed.</p>
- <pre><pre class="playground"><code class="language-rust edition2018">
- <span class="boring">#![allow(unused)]
- </span><span class="boring">fn main() {
- </span>cx.render(rsx! {
- // We only render the welcome message if we are logged in
- // You can use if statements in the middle of a render block to conditionally render elements
- if *is_logged_in {
- // Notice the body of this if statment is rsx code, not an expression
- "Welcome!"
- }
- button {
- // depending on the value of `is_logged_in`, we will call a different event handler
- onclick: move |_| if *is_logged_in {
- on_log_in.call(())
- }
- else{
- on_log_out.call(())
- },
- if *is_logged_in {
- // if we are logged in, the button should say "Log Out"
- "Log Out"
- } else {
- // if we are not logged in, the button should say "Log In"
- "Log In"
- }
- }
- })
- <span class="boring">}
- </span></code></pre></pre>
- <h3 id="inspecting-element-props"><a class="header" href="#inspecting-element-props">Inspecting <code>Element</code> props</a></h3>
- <p>Since <code>Element</code> is a <code>Option<VNode></code>, components accepting <code>Element</code> as a prop can inspect its contents, and render different things based on that. Example:</p>
- <pre><pre class="playground"><code class="language-rust edition2018">
- <span class="boring">#![allow(unused)]
- </span><span class="boring">fn main() {
- </span>fn Clickable<'a>(cx: Scope<'a, ClickableProps<'a>>) -> Element {
- match cx.props.children {
- Some(VNode { dynamic_nodes, .. }) => {
- todo!("render some stuff")
- }
- _ => {
- todo!("render some other stuff")
- }
- }
- }
- <span class="boring">}
- </span></code></pre></pre>
- <p>You can't mutate the <code>Element</code>, but if you need a modified version of it, you can construct a new one based on its attributes/children/etc.</p>
- <h2 id="rendering-nothing"><a class="header" href="#rendering-nothing">Rendering Nothing</a></h2>
- <p>To render nothing, you can return <code>None</code> from a component. This is useful if you want to conditionally hide something:</p>
- <pre><pre class="playground"><code class="language-rust edition2018">
- <span class="boring">#![allow(unused)]
- </span><span class="boring">fn main() {
- </span>if *is_logged_in {
- return None;
- }
- cx.render(rsx! {
- a {
- "You must be logged in to comment"
- }
- })
- <span class="boring">}
- </span></code></pre></pre>
- <p>This works because the <code>Element</code> type is just an alias for <code>Option<VNode></code></p>
- <blockquote>
- <p>Again, you may use a different method to conditionally return <code>None</code>. For example the boolean's <a href="https://doc.rust-lang.org/std/primitive.bool.html#method.then"><code>then()</code></a> function could be used.</p>
- </blockquote>
- <h2 id="rendering-lists"><a class="header" href="#rendering-lists">Rendering Lists</a></h2>
- <p>Often, you'll want to render a collection of components. For example, you might want to render a list of all comments on a post.</p>
- <p>For this, Dioxus accepts iterators that produce <code>Element</code>s. So we need to:</p>
- <ul>
- <li>Get an iterator over all of our items (e.g., if you have a <code>Vec</code> of comments, iterate over it with <code>iter()</code>)</li>
- <li><code>.map</code> the iterator to convert each item into a <code>LazyNode</code> using <code>rsx!(...)</code>
- <ul>
- <li>Add a unique <code>key</code> attribute to each iterator item</li>
- </ul>
- </li>
- <li>Include this iterator in the final RSX (or use it inline)</li>
- </ul>
- <p>Example: suppose you have a list of comments you want to render. Then, you can render them like this:</p>
- <pre><pre class="playground"><code class="language-rust edition2018">
- <span class="boring">#![allow(unused)]
- </span><span class="boring">fn main() {
- </span>let comment_field = use_state(cx, String::new);
- let mut next_id = use_state(cx, || 0);
- let comments = use_ref(cx, Vec::<Comment>::new);
- let comments_lock = comments.read();
- let comments_rendered = comments_lock.iter().map(|comment| {
- rsx!(CommentComponent {
- key: "{comment.id}",
- comment: comment.clone(),
- })
- });
- cx.render(rsx!(
- form {
- onsubmit: move |_| {
- comments.write().push(Comment {
- content: comment_field.get().clone(),
- id: *next_id.get(),
- });
- next_id += 1;
- comment_field.set(String::new());
- },
- input {
- value: "{comment_field}",
- oninput: |event| comment_field.set(event.value.clone()),
- }
- input {
- r#type: "submit",
- }
- },
- comments_rendered,
- ))
- <span class="boring">}
- </span></code></pre></pre>
- <h3 id="inline-for-loops"><a class="header" href="#inline-for-loops">Inline for loops</a></h3>
- <p>Because of how common it is to render a list of items, Dioxus provides a shorthand for this. Instead of using <code>.iter, </code>.map<code>, and </code>rsx<code>, you can use a </code>for` loop with a body of rsx code:</p>
- <pre><pre class="playground"><code class="language-rust edition2018">
- <span class="boring">#![allow(unused)]
- </span><span class="boring">fn main() {
- </span>let comment_field = use_state(cx, String::new);
- let mut next_id = use_state(cx, || 0);
- let comments = use_ref(cx, Vec::<Comment>::new);
- cx.render(rsx!(
- form {
- onsubmit: move |_| {
- comments.write().push(Comment {
- content: comment_field.get().clone(),
- id: *next_id.get(),
- });
- next_id += 1;
- comment_field.set(String::new());
- },
- input {
- value: "{comment_field}",
- oninput: |event| comment_field.set(event.value.clone()),
- }
- input {
- r#type: "submit",
- }
- },
- for comment in &*comments.read() {
- // Notice the body of this for loop is rsx code, not an expression
- CommentComponent {
- key: "{comment.id}",
- comment: comment.clone(),
- }
- }
- ))
- <span class="boring">}
- </span></code></pre></pre>
- <h3 id="the-key-attribute"><a class="header" href="#the-key-attribute">The <code>key</code> Attribute</a></h3>
- <p>Every time you re-render your list, Dioxus needs to keep track of which items go where to determine what updates need to be made to the UI.</p>
- <p>For example, suppose the <code>CommentComponent</code> had some state – e.g. a field where the user typed in a reply. If the order of comments suddenly changes, Dioxus needs to correctly associate that state with the same comment – otherwise, the user will end up replying to a different comment!</p>
- <p>To help Dioxus keep track of list items, we need to associate each item with a unique key. In the example above, we dynamically generated the unique key. In real applications, it's more likely that the key will come from e.g. a database ID. It doesn't matter where you get the key from, as long as it meets the requirements:</p>
- <ul>
- <li>Keys must be unique in a list</li>
- <li>The same item should always get associated with the same key</li>
- <li>Keys should be relatively small (i.e. converting the entire Comment structure to a String would be a pretty bad key) so they can be compared efficiently</li>
- </ul>
- <p>You might be tempted to use an item's index in the list as its key. That’s what Dioxus will use if you don’t specify a key at all. This is only acceptable if you can guarantee that the list is constant – i.e., no re-ordering, additions, or deletions.</p>
- <blockquote>
- <p>Note that if you pass the key to a component you've made, it won't receive the key as a prop. It’s only used as a hint by Dioxus itself. If your component needs an ID, you have to pass it as a separate prop.</p>
- </blockquote>
- </main>
- <nav class="nav-wrapper" aria-label="Page navigation">
- <!-- Mobile navigation buttons -->
- <a rel="prev" href="../interactivity/custom_hooks.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
- <i class="fa fa-angle-left"></i>
- </a>
- <a rel="next" href="../interactivity/router.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
- <i class="fa fa-angle-right"></i>
- </a>
- <div style="clear: both"></div>
- </nav>
- </div>
- </div>
- <nav class="nav-wide-wrapper" aria-label="Page navigation">
- <a rel="prev" href="../interactivity/custom_hooks.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
- <i class="fa fa-angle-left"></i>
- </a>
- <a rel="next" href="../interactivity/router.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
- <i class="fa fa-angle-right"></i>
- </a>
- </nav>
- </div>
- <script type="text/javascript">
- window.playground_line_numbers = true;
- </script>
- <script type="text/javascript">
- window.playground_copyable = true;
- </script>
- <script src="../ace.js" type="text/javascript" charset="utf-8"></script>
- <script src="../editor.js" type="text/javascript" charset="utf-8"></script>
- <script src="../mode-rust.js" type="text/javascript" charset="utf-8"></script>
- <script src="../theme-dawn.js" type="text/javascript" charset="utf-8"></script>
- <script src="../theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
- <script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
- <script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
- <script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
- <script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
- <script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
- <script src="../book.js" type="text/javascript" charset="utf-8"></script>
- <!-- Custom JS scripts -->
- </body>
- </html>
|