extra.js 8.8 KB

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