mirror of
				https://github.com/ArthurSonzogni/FTXUI.git
				synced 2025-11-04 05:28:15 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			174 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!DOCTYPE html> <html lang="en">
 | 
						|
  <head>
 | 
						|
    <meta charset="utf-8">
 | 
						|
    <title>FTXUI examples WebAssembly</title>
 | 
						|
    <script src="https://cdn.jsdelivr.net/npm/xterm@4.18.0/lib/xterm.min.js"></script>
 | 
						|
    <script src="https://cdn.jsdelivr.net/npm/xterm-addon-webgl@0.11.4/lib/xterm-addon-webgl.min.js"></script>
 | 
						|
    <script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.min.js"></script>
 | 
						|
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@4.11.0/css/xterm.css"></link>
 | 
						|
    <!--Add COOP/COEP via a ServiceWorker to use SharedArrayBuffer-->
 | 
						|
    <script>
 | 
						|
      if ("serviceWorker" in navigator && !window.crossOriginIsolated) {
 | 
						|
        navigator.serviceWorker.register(new URL("./sw.js", location.href)).then(
 | 
						|
          registration => {
 | 
						|
            if (registration.active && !navigator.serviceWorker.controller) {
 | 
						|
              window.location.reload();
 | 
						|
            }
 | 
						|
          },
 | 
						|
        );
 | 
						|
      } 
 | 
						|
    </script>
 | 
						|
  </head>
 | 
						|
  <body>
 | 
						|
    <script id="example_script"></script>
 | 
						|
    <div class="page">
 | 
						|
      <h1>FTXUI WebAssembly Example </h1>
 | 
						|
      <p>
 | 
						|
        <a href="https://github.com/ArthurSonzogni/FTXUI">FTXUI</a> is a single
 | 
						|
        C++ library for terminal user interface.
 | 
						|
      </p>
 | 
						|
      <p>
 | 
						|
        On this page, you can try all the examples contained in: <a
 | 
						|
        href="https://github.com/ArthurSonzogni/FTXUI/tree/master/examples">./example/</a>
 | 
						|
        Those are compiled using WebAssembly.
 | 
						|
      </p>
 | 
						|
      <select id="selectExample"></select>
 | 
						|
      <div id="terminal"></div>
 | 
						|
    </div>
 | 
						|
  </body>
 | 
						|
  <script>
 | 
						|
    const example_list = "@EXAMPLES@".split(";");
 | 
						|
 | 
						|
    const url_search_params = new URLSearchParams(window.location.search);
 | 
						|
    const example = url_search_params.get("file") || "dom/color_gallery";
 | 
						|
    const select = document.getElementById("selectExample"); 
 | 
						|
 | 
						|
    for(var i = 0; i < example_list.length; i++) {
 | 
						|
        var opt = example_list[i];
 | 
						|
        var el = document.createElement("option");
 | 
						|
        el.textContent = opt;
 | 
						|
        el.value = opt;
 | 
						|
        select.appendChild(el);
 | 
						|
    }
 | 
						|
    select.selectedIndex = example_list.findIndex(path => path == example) || 0;
 | 
						|
    select.addEventListener("change", () => {
 | 
						|
      location.href = (location.href).split('?')[0] + "?file=" +
 | 
						|
            example_list[select.selectedIndex];
 | 
						|
    });
 | 
						|
 | 
						|
    let stdin_buffer = [];
 | 
						|
    const stdin = () => {
 | 
						|
      return stdin_buffer.shift() || 0;
 | 
						|
    }
 | 
						|
 | 
						|
    let stdout_buffer = [];
 | 
						|
    const stdout = code => {
 | 
						|
      if (code == 0) {
 | 
						|
        term.write(new Uint8Array(stdout_buffer));
 | 
						|
        stdout_buffer = [];
 | 
						|
      } else {
 | 
						|
        stdout_buffer.push(code)
 | 
						|
      }
 | 
						|
    }
 | 
						|
    let stderrbuffer = [];
 | 
						|
    const stderr = code => {
 | 
						|
      if (code == 0 || code == 10) {
 | 
						|
        console.error(String.fromCodePoint(...stderrbuffer));
 | 
						|
        stderrbuffer = [];
 | 
						|
      } else {
 | 
						|
        stderrbuffer.push(code)
 | 
						|
      }
 | 
						|
    }
 | 
						|
    const term = new Terminal();
 | 
						|
    const term_element = document.querySelector('#terminal');
 | 
						|
    term.open(term_element);
 | 
						|
 | 
						|
    const webgl_addon = new (WebglAddon.WebglAddon)();
 | 
						|
    term.loadAddon(webgl_addon);
 | 
						|
 | 
						|
    const onBinary = e => {
 | 
						|
      for(c of e)
 | 
						|
        stdin_buffer.push(c.charCodeAt(0));
 | 
						|
    }
 | 
						|
    term.onBinary(onBinary);
 | 
						|
    term.onData(onBinary)
 | 
						|
    term.resize(140,43);
 | 
						|
    window.Module = {
 | 
						|
      preRun: () => {
 | 
						|
        FS.init(stdin, stdout, stderr);
 | 
						|
      },
 | 
						|
      postRun: [],
 | 
						|
      onRuntimeInitialized: () => {
 | 
						|
        if (window.Module._ftxui_on_resize == undefined)
 | 
						|
          return;
 | 
						|
 | 
						|
        const fit_addon = new (FitAddon.FitAddon)();
 | 
						|
        term.loadAddon(fit_addon);
 | 
						|
        fit_addon.fit();
 | 
						|
        const resize_handler = () => {
 | 
						|
          const {cols, rows} = fit_addon.proposeDimensions();
 | 
						|
          term.resize(cols, rows);
 | 
						|
          window.Module._ftxui_on_resize(cols, rows);
 | 
						|
        };
 | 
						|
        const resize_observer = new ResizeObserver(resize_handler);
 | 
						|
        resize_observer.observe(term_element);
 | 
						|
        resize_handler();
 | 
						|
 | 
						|
        // Disable scrollbar
 | 
						|
        term.write('\x1b[?47h')
 | 
						|
      },
 | 
						|
    };
 | 
						|
 | 
						|
    const words = example.split('/')
 | 
						|
    words[1] = "ftxui_example_" + words[1] + ".js"
 | 
						|
    document.querySelector("#example_script").src = words.join('/');
 | 
						|
  </script>
 | 
						|
 | 
						|
  <style>
 | 
						|
 | 
						|
    body {
 | 
						|
      background-color:#EEE;
 | 
						|
      padding:20px;
 | 
						|
      font-family: Helvetica, sans-serif;
 | 
						|
      font-size: 130%;
 | 
						|
    }
 | 
						|
 | 
						|
    .page {
 | 
						|
      max-width:1300px;
 | 
						|
      margin: auto;
 | 
						|
    }
 | 
						|
 | 
						|
    h1 {
 | 
						|
      text-decoration: underline;
 | 
						|
    }
 | 
						|
 | 
						|
    select {
 | 
						|
      display:block;
 | 
						|
      padding: .6em 1.4em .5em .8em;
 | 
						|
      border-radius: 20px 20px 0px 0px;
 | 
						|
      font-size: 16px;
 | 
						|
      font-family: sans-serif;
 | 
						|
      font-weight: 700;
 | 
						|
 | 
						|
      color: #444;
 | 
						|
      line-height: 1.3;
 | 
						|
      background-color:black;
 | 
						|
      border:0px;
 | 
						|
      color:white;
 | 
						|
      transition: color 0.2s linear;
 | 
						|
      transition: background-color 0.2s linear;
 | 
						|
    }
 | 
						|
 | 
						|
    #terminal {
 | 
						|
      width:100%;
 | 
						|
      height: 500px;
 | 
						|
      height: calc(clamp(200px, 100vh - 300px, 900px));
 | 
						|
      overflow: hidden;
 | 
						|
      border:none;
 | 
						|
      padding:auto;
 | 
						|
    }
 | 
						|
 | 
						|
  </style>
 | 
						|
 | 
						|
</html>
 |