|
| 1 | +var nodemcu = nodemcu || {}; |
| 2 | +(function () { |
| 3 | + 'use strict'; |
| 4 | + //var languageCodeToNameMap = {en: 'English', de: 'Deutsch'}; |
| 5 | + var languageCodeToNameMap = {en: 'English'}; |
| 6 | + var languageNames = values(languageCodeToNameMap); |
| 7 | + var defaultLanguageCode = 'en'; |
| 8 | + |
| 9 | + $(document).ready(function () { |
| 10 | + addToc(); |
| 11 | + fixSearch(); |
| 12 | + hideNavigationForAllButSelectedLanguage(); |
| 13 | + addLanguageSelectorToRtdFlyOutMenu(); |
| 14 | + replaceRelativeLinksWithStaticGitHubUrl(); |
| 15 | + }); |
| 16 | + |
| 17 | + /** |
| 18 | + * Adds a TOC-style table to each page in the 'Modules' section. |
| 19 | + */ |
| 20 | + function addToc() { |
| 21 | + var func, intro, tocHtmlTable; |
| 22 | + if (isModulePage()) { |
| 23 | + tocHtmlTable = '<table class="docutils">'; |
| 24 | + $('h2').each(function (index) { |
| 25 | + // 'slice' cuts off the single permalink character at the end of the text (e.g. '¶') |
| 26 | + func = $(this).text().slice(0, -1); |
| 27 | + // get the first sentence of the paragraph directly below h2 |
| 28 | + intro = $(this).next().text(); |
| 29 | + intro = intro.substring(0, intro.indexOf('.') + 1); |
| 30 | + tocHtmlTable += createTocTableRow(func, intro); |
| 31 | + }); |
| 32 | + tocHtmlTable += '</table>'; |
| 33 | + $(tocHtmlTable).insertBefore($('h2').first()) |
| 34 | + } |
| 35 | + function isModulePage() { |
| 36 | + // if the breadcrumb contains 'Modules »' it must be an API page |
| 37 | + return $("ul.wy-breadcrumbs li:contains('Modules »')").size() > 0; |
| 38 | + } |
| 39 | + function createTocTableRow(func, intro) { |
| 40 | + // fragile attempt to auto-create the in-page anchor |
| 41 | + var href = func.replace(/\.|:/g, '').replace('()', '').replace(' --', '-').replace(/ /g, '-'); |
| 42 | + var link = '<a href="#' + href.toLowerCase() + '">' + func + '</a>'; |
| 43 | + return '<tr><td>' + link + '</td><td>' + intro + '</td></tr>'; |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + /* |
| 48 | + * RTD messes up MkDocs' search feature by tinkering with the search box defined in the theme, see |
| 49 | + * https://github.com/rtfd/readthedocs.org/issues/1088. This function sets up a DOM4 MutationObserver |
| 50 | + * to react to changes to the search form (triggered by RTD on doc ready). It then reverts everything |
| 51 | + * the RTD JS code modified. |
| 52 | + */ |
| 53 | + function fixSearch() { |
| 54 | + var target = document.getElementById('rtd-search-form'); |
| 55 | + var config = {attributes: true, childList: true}; |
| 56 | + |
| 57 | + var observer = new MutationObserver(function(mutations) { |
| 58 | + // if it isn't disconnected it'll loop infinitely because the observed element is modified |
| 59 | + observer.disconnect(); |
| 60 | + var form = $('#rtd-search-form'); |
| 61 | + form.empty(); |
| 62 | + form.attr('action', 'https://' + window.location.hostname + '/en/' + determineSelectedBranch() + '/search.html'); |
| 63 | + $('<input>').attr({ |
| 64 | + type: "text", |
| 65 | + name: "q", |
| 66 | + placeholder: "Search docs" |
| 67 | + }).appendTo(form); |
| 68 | + }); |
| 69 | + |
| 70 | + if (window.location.origin.indexOf('readthedocs') > -1) { |
| 71 | + observer.observe(target, config); |
| 72 | + } |
| 73 | + } |
| 74 | + |
| 75 | + function hideNavigationForAllButSelectedLanguage() { |
| 76 | + var selectedLanguageCode = determineSelectedLanguageCode(); |
| 77 | + var selectedLanguageName = languageCodeToNameMap[selectedLanguageCode]; |
| 78 | + // Finds all subnav elements and hides them if they're /language/ subnavs. Hence, all 'Modules' subnav elements |
| 79 | + // won't be hidden. |
| 80 | + // <ul class="subnav"> |
| 81 | + // <li><span>Modules</span></li> |
| 82 | + // <li class="toctree-l1 "> |
| 83 | + // <a class="" href="EN/modules/node/">node</a> |
| 84 | + // </li> |
| 85 | + $('.subnav li span').not(':contains(' + selectedLanguageName + ')').each(function (index) { |
| 86 | + var spanElement = $(this); |
| 87 | + if ($.inArray(spanElement.text(), languageNames) > -1) { |
| 88 | + spanElement.parent().parent().hide(); |
| 89 | + } |
| 90 | + }); |
| 91 | + } |
| 92 | + |
| 93 | + /** |
| 94 | + * Adds a language selector to the RTD fly-out menu found bottom left. Example: |
| 95 | + * |
| 96 | + * <dl> |
| 97 | + * <dt>Languages</dt> |
| 98 | + * <dd><a href="http://nodemcu.readthedocs.io/en/<branch>/de/">de</a></dd> |
| 99 | + * <strong> |
| 100 | + * <dd><a href="http://nodemcu.readthedocs.io/en/<branch>/en/">en</a></dd> |
| 101 | + * </strong> |
| 102 | + * </dl> |
| 103 | + * |
| 104 | + * UGLY! That fly-out menu is added by RTD with an AJAX call after page load. Hence, we need to |
| 105 | + * react to the subsequent DOM manipulation using a DOM4 MutationObserver. The provided structure |
| 106 | + * is as follows: |
| 107 | + * |
| 108 | + * <div class="rst-other-versions"> |
| 109 | + * <!-- Inserted RTD Footer --> |
| 110 | + * <div class="injected"> |
| 111 | + */ |
| 112 | + function addLanguageSelectorToRtdFlyOutMenu() { |
| 113 | + var flyOutWrapper = $('.rst-other-versions'); |
| 114 | + // only relevant on RTD |
| 115 | + if (flyOutWrapper.size() > 0) { |
| 116 | + var observer = new MutationObserver(function (mutations) { |
| 117 | + // since mutation on the target node was triggered we can safely assume the injected RTD div has now been added |
| 118 | + var injectedDiv = $('.rst-other-versions .injected'); |
| 119 | + var selectedLanguageCode = determineSelectedLanguageCode(); |
| 120 | + var dl = document.createElement('dl'); |
| 121 | + var dt = document.createElement('dt'); |
| 122 | + dl.appendChild(dt); |
| 123 | + dt.appendChild(document.createTextNode('Languages')); |
| 124 | + for (var languageCode in languageCodeToNameMap) { |
| 125 | + dl.appendChild(createLanguageLinkFor(languageCode, selectedLanguageCode === languageCode)); |
| 126 | + } |
| 127 | + injectedDiv.prepend(dl); |
| 128 | + // no need for that observer anymore |
| 129 | + observer.disconnect(); |
| 130 | + }); |
| 131 | + |
| 132 | + // observed target node is the fly-out wrapper, the only event we care about is when children are modified |
| 133 | + observer.observe(flyOutWrapper[0], {childList: true}); |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | + /** |
| 138 | + * The module doc pages contain relative links to artifacts in the GitHub repository. For those links to work both |
| 139 | + * on GitHub (i.e. when the page is viewed on GitHub) and on RTD they are defined with a relative URL. This function |
| 140 | + * replaces the relative path with an absolute path based on the selected branch. |
| 141 | + */ |
| 142 | + function replaceRelativeLinksWithStaticGitHubUrl() { |
| 143 | + var relativePath = "../../../.."; |
| 144 | + var gitHubPath = "https://github.com/nodemcu/nodemcu-firmware/tree/" + determineSelectedBranch(); |
| 145 | + var gitHubLinks = $("a[href^='" + relativePath + "']").each(function (index) { |
| 146 | + var url = $(this).attr('href'); |
| 147 | + $(this).attr('href', url.replace(relativePath, gitHubPath)); |
| 148 | + }); |
| 149 | + } |
| 150 | + |
| 151 | + function createLanguageLinkFor(languageCode, isCurrentlySelected) { |
| 152 | + var strong; |
| 153 | + // split[0] is an '' because the path starts with the separator |
| 154 | + var pathSegments = window.location.pathname.split('/'); |
| 155 | + var dd = document.createElement("dd"); |
| 156 | + var href = document.createElement("a"); |
| 157 | + href.setAttribute('href', '/' + pathSegments[1] + '/' + pathSegments[2] + '/' + languageCode); |
| 158 | + href.appendChild(document.createTextNode(languageCode)); |
| 159 | + dd.appendChild(href); |
| 160 | + if (isCurrentlySelected) { |
| 161 | + strong = document.createElement("strong"); |
| 162 | + strong.appendChild(dd); |
| 163 | + return strong; |
| 164 | + } else { |
| 165 | + return dd; |
| 166 | + } |
| 167 | + } |
| 168 | + |
| 169 | + /** |
| 170 | + * Analyzes the URL of the current page to find out what the selected language is. It's usually |
| 171 | + * part of the location path. The code needs to distinguish between running MkDocs standalone |
| 172 | + * and docs served from RTD. If no valid language could be determined the default language is |
| 173 | + * returned. |
| 174 | + * |
| 175 | + * @returns 2-char language code |
| 176 | + */ |
| 177 | + function determineSelectedLanguageCode() { |
| 178 | + var selectedLanguageCode, path = window.location.pathname; |
| 179 | + if (window.location.origin.indexOf('readthedocs') > -1) { |
| 180 | + // path is like /en/<branch>/<lang>/build/ -> extract 'lang' |
| 181 | + // split[0] is an '' because the path starts with the separator |
| 182 | + selectedLanguageCode = path.split('/')[3]; |
| 183 | + } else { |
| 184 | + // path is like /<lang>/build/ -> extract 'lang' |
| 185 | + selectedLanguageCode = path.substr(1, 2); |
| 186 | + } |
| 187 | + if (!selectedLanguageCode || selectedLanguageCode.length > 2) { |
| 188 | + selectedLanguageCode = defaultLanguageCode; |
| 189 | + } |
| 190 | + return selectedLanguageCode; |
| 191 | + } |
| 192 | + |
| 193 | + /** |
| 194 | + * Analyzes the URL of the current page to find out what the selected GitHub branch is. It's usually |
| 195 | + * part of the location path. The code needs to distinguish between running MkDocs standalone |
| 196 | + * and docs served from RTD. If no valid branch could be determined 'dev' returned. |
| 197 | + * |
| 198 | + * @returns GitHub branch name |
| 199 | + */ |
| 200 | + function determineSelectedBranch() { |
| 201 | + var branch = 'dev', path = window.location.pathname; |
| 202 | + if (window.location.origin.indexOf('readthedocs') > -1) { |
| 203 | + // path is like /en/<branch>/<lang>/build/ -> extract 'lang' |
| 204 | + // split[0] is an '' because the path starts with the separator |
| 205 | + branch = path.split('/')[2]; |
| 206 | + } |
| 207 | + return branch; |
| 208 | + } |
| 209 | + |
| 210 | + function values(associativeArray) { |
| 211 | + var values = []; |
| 212 | + for (var key in associativeArray) { |
| 213 | + if (associativeArray.hasOwnProperty(key)) { |
| 214 | + values.push(associativeArray[key]); |
| 215 | + } |
| 216 | + } |
| 217 | + return values; |
| 218 | + } |
| 219 | +}()); |
0 commit comments