index.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import init, { setup_panic_hook, Numbat, FormatType } from "./pkg/numbat_wasm.js";
  2. async function fetch_exchange_rates() {
  3. try {
  4. const response = await fetch("https://numbat.dev/ecb-exchange-rates.php");
  5. if (!response.ok) {
  6. return;
  7. }
  8. const xml_content = await response.text();
  9. numbat.set_exchange_rates(xml_content);
  10. } catch (error) {
  11. console.error("Failed to load currency exchange rates from the European Central Bank");
  12. return;
  13. }
  14. }
  15. function create_numbat_instance() {
  16. return Numbat.new(true, true, FormatType.JqueryTerminal);
  17. }
  18. function updateUrlQuery(query) {
  19. let url = new URL(window.location);
  20. if (query == null) {
  21. url.searchParams.delete('q');
  22. } else {
  23. url.searchParams.set('q', query);
  24. }
  25. history.replaceState(null, null, url);
  26. }
  27. function interpret(input) {
  28. // Skip empty lines or comments
  29. var input_trimmed = input.trim();
  30. if (input_trimmed === "" || (input_trimmed[0] === "#" && input_trimmed.indexOf("\n") == -1)) {
  31. return;
  32. }
  33. if (input_trimmed == "clear") {
  34. this.clear();
  35. var output = "";
  36. } else if (input_trimmed == "reset") {
  37. numbat = create_numbat_instance();
  38. numbat.interpret("use units::currencies");
  39. combined_input = "";
  40. updateUrlQuery(null);
  41. this.clear();
  42. } else if (input_trimmed == "list") {
  43. output = numbat.print_environment();
  44. } else if (input_trimmed == "list functions") {
  45. output = numbat.print_functions();
  46. } else if (input_trimmed == "list dimensions") {
  47. output = numbat.print_dimensions();
  48. } else if (input_trimmed == "list variables") {
  49. output = numbat.print_variables();
  50. } else if (input_trimmed == "list units") {
  51. output = numbat.print_units();
  52. } else if (input_trimmed == "help" || input_trimmed == "?") {
  53. output = numbat.help();
  54. } else {
  55. var result = { is_error: false };
  56. if (input_trimmed.startsWith("info ")) {
  57. var keyword = input_trimmed.substring(4).trim();
  58. output = numbat.print_info(keyword);
  59. } else {
  60. result = numbat.interpret(input);
  61. output = result.output;
  62. }
  63. if (!result.is_error) {
  64. combined_input += input.trim() + "⏎";
  65. updateUrlQuery(combined_input);
  66. }
  67. }
  68. return output;
  69. }
  70. const parsedTerminalHeightInPixels = parseInt(
  71. getComputedStyle(document.documentElement).getPropertyValue(
  72. "--terminal-height"
  73. ),
  74. 10
  75. );
  76. function setup() {
  77. $(document).ready(function () {
  78. var term = $('#terminal').terminal(interpret, {
  79. greetings: false,
  80. name: "terminal",
  81. height: parsedTerminalHeightInPixels,
  82. prompt: "[[;;;prompt]>>> ]",
  83. checkArity: false,
  84. historySize: 200,
  85. historyFilter(line) {
  86. return line.trim() !== "";
  87. },
  88. completion(inp, cb) {
  89. cb(numbat.get_completions_for(inp));
  90. }
  91. });
  92. // Swap out the skeleton loader with the terminal to prevent layout shifting.
  93. document.getElementById("skeleton-loader").classList.add("hidden");
  94. document.getElementById("terminal").classList.remove("hidden");
  95. // evaluate expression in query string if supplied (via opensearch)
  96. if (location.search) {
  97. var queryParams = new URLSearchParams(location.search);
  98. if (queryParams.has("q")) {
  99. // feed in the query line by line, as if the user typed it in
  100. for (const line of queryParams.get("q").split("⏎")) {
  101. if (line.trim().length > 0) {
  102. term.exec(line.trim() + "\n");
  103. }
  104. }
  105. }
  106. }
  107. });
  108. }
  109. var numbat;
  110. var combined_input = "";
  111. async function main() {
  112. await init();
  113. setup_panic_hook();
  114. numbat = create_numbat_instance();
  115. combined_input = "";
  116. // Load KeyboardEvent polyfill for old browsers
  117. keyboardeventKeyPolyfill.polyfill();
  118. fetch_exchange_rates().then(setup);
  119. }
  120. main();