index.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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" || input_trimmed == "ls") {
  43. output = numbat.print_environment();
  44. } else if (input_trimmed == "list functions" || input_trimmed == "ls functions") {
  45. output = numbat.print_functions();
  46. } else if (input_trimmed == "list dimensions" || input_trimmed == "ls dimensions") {
  47. output = numbat.print_dimensions();
  48. } else if (input_trimmed == "list variables" || input_trimmed == "ls variables") {
  49. output = numbat.print_variables();
  50. } else if (input_trimmed == "list units" || input_trimmed == "ls 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. function setup() {
  71. $(document).ready(function() {
  72. var term = $('#terminal').terminal(interpret, {
  73. greetings: false,
  74. name: "terminal",
  75. height: 550,
  76. prompt: "[[;;;prompt]>>> ]",
  77. checkArity: false,
  78. historySize: 200,
  79. historyFilter(line) {
  80. return line.trim() !== "";
  81. },
  82. completion(inp, cb) {
  83. cb(numbat.get_completions_for(inp));
  84. }
  85. });
  86. // Swap out the skeleton loader with the terminal, preventing a layout shift.
  87. document.getElementById("skeleton-loader").classList.add("hidden");
  88. document.getElementById("terminal").classList.remove("hidden");
  89. // evaluate expression in query string if supplied (via opensearch)
  90. if (location.search) {
  91. var queryParams = new URLSearchParams(location.search);
  92. if (queryParams.has("q")) {
  93. // feed in the query line by line, as if the user typed it in
  94. for (const line of queryParams.get("q").split("⏎")) {
  95. if (line.trim().length > 0) {
  96. term.exec(line.trim() + "\n");
  97. }
  98. }
  99. }
  100. }
  101. });
  102. }
  103. var numbat;
  104. var combined_input = "";
  105. async function main() {
  106. await init();
  107. setup_panic_hook();
  108. numbat = create_numbat_instance();
  109. combined_input = "";
  110. // Load KeyboardEvent polyfill for old browsers
  111. keyboardeventKeyPolyfill.polyfill();
  112. fetch_exchange_rates().then(setup);
  113. }
  114. main();