sphinx-thebe.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /**
  2. * Add attributes to Thebe blocks to initialize thebe properly
  3. */
  4. var configureThebe = () => {
  5. // Load thebe config in case we want to update it as some point
  6. console.log("[sphinx-thebe]: Loading thebe config...");
  7. thebe_config = $('script[type="text/x-thebe-config"]')[0];
  8. // If we already detect a Thebe cell, don't re-run
  9. if (document.querySelectorAll("div.thebe-cell").length > 0) {
  10. return;
  11. }
  12. // Update thebe buttons with loading message
  13. $(".thebe-launch-button").each((ii, button) => {
  14. button.innerHTML = `
  15. <div class="spinner">
  16. <div class="rect1"></div>
  17. <div class="rect2"></div>
  18. <div class="rect3"></div>
  19. <div class="rect4"></div>
  20. </div>
  21. <span class="loading-text"></span>`;
  22. });
  23. // Set thebe event hooks
  24. var thebeStatus;
  25. thebelab.on("status", function (evt, data) {
  26. console.log("Status changed:", data.status, data.message);
  27. $(".thebe-launch-button ")
  28. .removeClass("thebe-status-" + thebeStatus)
  29. .addClass("thebe-status-" + data.status)
  30. .find(".loading-text")
  31. .html(
  32. "<span class='launch_msg'>Launching from mybinder.org: </span><span class='status'>" +
  33. data.status +
  34. "</span>"
  35. );
  36. // Now update our thebe status
  37. thebeStatus = data.status;
  38. // Find any cells with an initialization tag and ask thebe to run them when ready
  39. if (data.status === "ready") {
  40. var thebeInitCells = document.querySelectorAll(
  41. ".thebe-init, .tag_thebe-init"
  42. );
  43. thebeInitCells.forEach((cell) => {
  44. console.log("Initializing Thebe with cell: " + cell.id);
  45. cell.querySelector(".thebelab-run-button").click();
  46. });
  47. }
  48. });
  49. };
  50. /**
  51. * Update the page DOM to use Thebe elements
  52. */
  53. var modifyDOMForThebe = () => {
  54. // Find all code cells, replace with Thebe interactive code cells
  55. const codeCells = document.querySelectorAll(thebe_selector);
  56. codeCells.forEach((codeCell, index) => {
  57. const codeCellId = (index) => `codecell${index}`;
  58. codeCell.id = codeCellId(index);
  59. codeCellText = codeCell.querySelector(thebe_selector_input);
  60. codeCellOutput = codeCell.querySelector(thebe_selector_output);
  61. // Clean up the language to make it work w/ CodeMirror and add it to the cell
  62. dataLanguage = detectLanguage(kernelName);
  63. // Re-arrange the cell and add metadata
  64. if (codeCellText) {
  65. codeCellText.setAttribute("data-language", dataLanguage);
  66. codeCellText.setAttribute("data-executable", "true");
  67. // If we had an output, insert it just after the `pre` cell
  68. if (codeCellOutput) {
  69. $(codeCellOutput).attr("data-output", "");
  70. $(codeCellOutput).insertAfter(codeCellText);
  71. }
  72. }
  73. // Remove sphinx-copybutton blocks, which are common in Sphinx
  74. codeCell.querySelectorAll("button.copybtn").forEach((el) => {
  75. el.remove();
  76. });
  77. });
  78. };
  79. var initThebe = () => {
  80. // Load thebe dynamically if it's not already loaded
  81. if (typeof thebelab === "undefined") {
  82. console.log("[sphinx-thebe]: Loading thebe from CDN...");
  83. $(".thebe-launch-button ").text("Loading thebe from CDN...");
  84. const script = document.createElement("script");
  85. script.src = `${THEBE_JS_URL}`;
  86. document.head.appendChild(script);
  87. // Runs once the script has finished loading
  88. script.addEventListener("load", () => {
  89. console.log("[sphinx-thebe]: Finished loading thebe from CDN...");
  90. configureThebe();
  91. modifyDOMForThebe();
  92. thebelab.bootstrap();
  93. });
  94. } else {
  95. console.log(
  96. "[sphinx-thebe]: thebe already loaded, not loading from CDN..."
  97. );
  98. configureThebe();
  99. modifyDOMForThebe();
  100. thebelab.bootstrap();
  101. }
  102. };
  103. // Helper function to munge the language name
  104. var detectLanguage = (language) => {
  105. if (language.indexOf("python") > -1) {
  106. language = "python";
  107. } else if (language === "ir") {
  108. language = "r";
  109. }
  110. return language;
  111. };