forked from extern/jq_offline
feature: first draft version
This commit is contained in:
parent
e7aef5e4ec
commit
0d2b7a8150
68
README.md
68
README.md
@ -1,67 +1,3 @@
|
||||
![Build Status](https://gitlab.com/pages/plain-html/badges/master/build.svg)
|
||||
# Jq Offline (WASM)
|
||||
|
||||
---
|
||||
|
||||
Example plain HTML site using GitLab Pages.
|
||||
|
||||
Learn more about GitLab Pages at https://pages.gitlab.io and the official
|
||||
documentation https://docs.gitlab.com/ce/user/project/pages/.
|
||||
|
||||
---
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
||||
|
||||
- [GitLab CI](#gitlab-ci)
|
||||
- [GitLab User or Group Pages](#gitlab-user-or-group-pages)
|
||||
- [Did you fork this project?](#did-you-fork-this-project)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
## GitLab CI
|
||||
|
||||
This project's static Pages are built by [GitLab CI][ci], following the steps
|
||||
defined in [`.gitlab-ci.yml`](.gitlab-ci.yml):
|
||||
|
||||
```
|
||||
image: alpine:latest
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
script:
|
||||
- echo 'Nothing to do...'
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- master
|
||||
```
|
||||
|
||||
The above example expects to put all your HTML files in the `public/` directory.
|
||||
|
||||
## GitLab User or Group Pages
|
||||
|
||||
To use this project as your user/group website, you will need one additional
|
||||
step: just rename your project to `namespace.gitlab.io`, where `namespace` is
|
||||
your `username` or `groupname`. This can be done by navigating to your
|
||||
project's **Settings**.
|
||||
|
||||
Read more about [user/group Pages][userpages] and [project Pages][projpages].
|
||||
|
||||
## Did you fork this project?
|
||||
|
||||
If you forked this project for your own use, please go to your project's
|
||||
**Settings** and remove the forking relationship, which won't be necessary
|
||||
unless you want to contribute back to the upstream project.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. CSS is missing! That means that you have wrongly set up the CSS URL in your
|
||||
HTML files. Have a look at the [index.html] for an example.
|
||||
|
||||
[ci]: https://about.gitlab.com/gitlab-ci/
|
||||
[index.html]: https://gitlab.com/pages/plain-html/blob/master/public/index.html
|
||||
[userpages]: https://docs.gitlab.com/ce/user/project/pages/introduction.html#user-or-group-pages
|
||||
[projpages]: https://docs.gitlab.com/ce/user/project/pages/introduction.html#project-pages
|
||||
TODO
|
110
public/index.html
Normal file → Executable file
110
public/index.html
Normal file → Executable file
@ -1,23 +1,101 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="GitLab Pages">
|
||||
<title>Plain HTML site using GitLab Pages</title>
|
||||
<title>Jq Play Offline</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar">
|
||||
<a href="https://pages.gitlab.io/plain-html/">Plain HTML Example</a>
|
||||
<a href="https://gitlab.com/pages/plain-html/">Repository</a>
|
||||
<a href="https://gitlab.com/pages/">Other Examples</a>
|
||||
<!-- <script defer src="https://cdn.biowasm.com/v2/aioli/latest/aioli.js"></script> -->
|
||||
<script defer src="./js/aioli.js"></script>
|
||||
<script defer type="module">
|
||||
// let CLI = await new Aioli("jq/1.6");
|
||||
let CLI = await new Aioli({
|
||||
tool: "jq",
|
||||
version: "1.6",
|
||||
urlPrefix: "./wasm/",
|
||||
loading: "eager",
|
||||
}, {
|
||||
urlAioli: "./js/aioli.worker.js",
|
||||
});
|
||||
|
||||
async function jq() {
|
||||
let data = document.getElementById("input-json").value;
|
||||
let query = document.getElementById("filter").value;
|
||||
let compactOutput = document.getElementById("compact-output").checked;
|
||||
let sortKeys = document.getElementById("sort-keys").checked;
|
||||
|
||||
let options = ["--monochrome-output"];
|
||||
if (compactOutput) {
|
||||
options.push("--compact-output");
|
||||
}
|
||||
if (sortKeys) {
|
||||
options.push("--sort-keys");
|
||||
}
|
||||
|
||||
// Create mock JSON file
|
||||
await CLI.fs.writeFile("test.json", data);
|
||||
|
||||
options.push(query);
|
||||
options.push("test.json");
|
||||
|
||||
let output = await CLI.exec("jq", options);
|
||||
document.getElementById("output-json").value = output;
|
||||
}
|
||||
|
||||
// buffer and call the callback only after no activity for "interval": aka debounce
|
||||
// This reduces load on the browser by avoiding jq evaluation while the user is typing
|
||||
function debounce(callback, interval) {
|
||||
let debounceTimeoutId;
|
||||
|
||||
return function(...args) {
|
||||
clearTimeout(debounceTimeoutId);
|
||||
debounceTimeoutId = setTimeout(() => callback.apply(this, args), interval);
|
||||
};
|
||||
}
|
||||
|
||||
let delayedJq = debounce(jq, 400);
|
||||
|
||||
document.getElementById("filter").addEventListener('input', delayedJq);
|
||||
document.getElementById("input-json").addEventListener('input', delayedJq);
|
||||
document.getElementById("compact-output").addEventListener('input', jq);
|
||||
document.getElementById("sort-keys").addEventListener('input', jq);
|
||||
|
||||
// Call jq the first time without any changes
|
||||
jq()
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="top">
|
||||
<h1>Jq Play Offline</h1>
|
||||
<a href="https://stedolan.github.io/jq/manual/v1.6/">1.6 - Web Assembly Version</a>
|
||||
</div>
|
||||
<div id="content">
|
||||
<div id="query">
|
||||
<label id="filter-label" for="filter">Query</label>
|
||||
<input id="filter" type="text" name="filter" />
|
||||
<ul id="options">
|
||||
<p>Options</p>
|
||||
<li>
|
||||
<input type="checkbox" id="compact-output" name="co">
|
||||
<label for="co">Compact Output</label>
|
||||
</li>
|
||||
<li>
|
||||
<input type="checkbox" id="sort-keys" name="sk">
|
||||
<label for="sk">Sort Keys</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="input">
|
||||
<label id="input-label" for="input-json">Input</label>
|
||||
<textarea id="input-json" name="input" placeholder="Paste your input json here"></textarea>
|
||||
</div>
|
||||
|
||||
<h1>Hello World!</h1>
|
||||
<div id="output">
|
||||
<label id="output-label" for="output-json">Result</label>
|
||||
<textarea id="output-json">Output</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<p>
|
||||
This is a simple plain-HTML website on GitLab Pages, without any fancy static site generator.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
1
public/js/aioli.js
Normal file
1
public/js/aioli.js
Normal file
@ -0,0 +1 @@
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Aioli=t()}(this,(function(){"use strict";var e="2.3.0";const t=Symbol("Comlink.proxy"),n=Symbol("Comlink.endpoint"),r=Symbol("Comlink.releaseProxy"),a=Symbol("Comlink.thrown"),o=e=>"object"==typeof e&&null!==e||"function"==typeof e,i=new Map([["proxy",{canHandle:e=>o(e)&&e[t],serialize(e){const{port1:t,port2:n}=new MessageChannel;return s(e,t),[n,[n]]},deserialize:e=>(e.start(),l(e))}],["throw",{canHandle:e=>o(e)&&a in e,serialize({value:e}){let t;return t=e instanceof Error?{isError:!0,value:{message:e.message,name:e.name,stack:e.stack}}:{isError:!1,value:e},[t,[]]},deserialize(e){if(e.isError)throw Object.assign(new Error(e.value.message),e.value);throw e.value}}]]);function s(e,n=self){n.addEventListener("message",(function r(o){if(!o||!o.data)return;const{id:i,type:l,path:u}=Object.assign({path:[]},o.data),p=(o.data.argumentList||[]).map(g);let d;try{const n=u.slice(0,-1).reduce(((e,t)=>e[t]),e),r=u.reduce(((e,t)=>e[t]),e);switch(l){case"GET":d=r;break;case"SET":n[u.slice(-1)[0]]=g(o.data.value),d=!0;break;case"APPLY":d=r.apply(n,p);break;case"CONSTRUCT":d=function(e){return Object.assign(e,{[t]:!0})}(new r(...p));break;case"ENDPOINT":{const{port1:t,port2:n}=new MessageChannel;s(e,n),d=function(e,t){return f.set(e,t),e}(t,[t])}break;case"RELEASE":d=void 0;break;default:return}}catch(e){d={value:e,[a]:0}}Promise.resolve(d).catch((e=>({value:e,[a]:0}))).then((e=>{const[t,a]=h(e);n.postMessage(Object.assign(Object.assign({},t),{id:i}),a),"RELEASE"===l&&(n.removeEventListener("message",r),c(n))}))})),n.start&&n.start()}function c(e){(function(e){return"MessagePort"===e.constructor.name})(e)&&e.close()}function l(e,t){return p(e,[],t)}function u(e){if(e)throw new Error("Proxy has been released and is not useable")}function p(e,t=[],a=function(){}){let o=!1;const i=new Proxy(a,{get(n,a){if(u(o),a===r)return()=>m(e,{type:"RELEASE",path:t.map((e=>e.toString()))}).then((()=>{c(e),o=!0}));if("then"===a){if(0===t.length)return{then:()=>i};const n=m(e,{type:"GET",path:t.map((e=>e.toString()))}).then(g);return n.then.bind(n)}return p(e,[...t,a])},set(n,r,a){u(o);const[i,s]=h(a);return m(e,{type:"SET",path:[...t,r].map((e=>e.toString())),value:i},s).then(g)},apply(r,a,i){u(o);const s=t[t.length-1];if(s===n)return m(e,{type:"ENDPOINT"}).then(g);if("bind"===s)return p(e,t.slice(0,-1));const[c,l]=d(i);return m(e,{type:"APPLY",path:t.map((e=>e.toString())),argumentList:c},l).then(g)},construct(n,r){u(o);const[a,i]=d(r);return m(e,{type:"CONSTRUCT",path:t.map((e=>e.toString())),argumentList:a},i).then(g)}});return i}function d(e){const t=e.map(h);return[t.map((e=>e[0])),(n=t.map((e=>e[1])),Array.prototype.concat.apply([],n))];var n}const f=new WeakMap;function h(e){for(const[t,n]of i)if(n.canHandle(e)){const[r,a]=n.serialize(e);return[{type:"HANDLER",name:t,value:r},a]}return[{type:"RAW",value:e},f.get(e)||[]]}function g(e){switch(e.type){case"HANDLER":return i.get(e.name).deserialize(e.value);case"RAW":return e.value}}function m(e,t,n){return new Promise((r=>{const a=new Array(4).fill(0).map((()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16))).join("-");e.addEventListener("message",(function t(n){n.data&&n.data.id&&n.data.id===a&&(e.removeEventListener("message",t),r(n.data))})),e.start&&e.start(),e.postMessage(Object.assign({id:a},t),n)}))}const y="https://cdn.biowasm.com/v2",b={urlCDN:y,urlAioli:`${y}/aioli/${e}/aioli.worker.js`,urlBaseModule:null,dirShared:"/shared",dirMounted:"/mnt",dirData:"/data",printInterleaved:!0,callback:null,debug:!1,env:"prd"};return class{constructor(t,n={}){if(null==t)throw"Expecting array of tools as input to Aioli constructor.";return Array.isArray(t)||(t=[t]),n=Object.assign({},b,n),t=t.map(this._parseTool),"prd"!=n.env&&(n.urlCDN=n.urlCDN.replace("cdn",`cdn-${n.env}`),n.urlAioli=n.urlAioli.replace("cdn",`cdn-${n.env}`)),t=[{tool:"base",version:e,urlPrefix:n.urlBaseModule},...t],this.tools=t,this.config=n,null!=this.config.callback&&(this.callback=this.config.callback),delete this.config.callback,this.init()}async init(){const e=await(await fetch(this.config.urlAioli)).text(),t=new Blob([e],{type:"application/javascript"}),n=new Worker(URL.createObjectURL(t));this.callback&&(n.onmessage=e=>{"biowasm"==e.data.type&&this.callback(e.data.value)});const r=l(n);return r.tools=this.tools,r.config=this.config,await r.init(),r}_parseTool(e){if("string"!=typeof e)return e;const t=e.split("/");if(2!=t.length&&3!=t.length)throw"Expecting '<tool>/<version>' or '<tool>/<program>/<version>'";return{tool:t[0],program:3==t.length?t[1]:t[0],version:t[t.length-1]}}}}));
|
1
public/js/aioli.worker.js
Normal file
1
public/js/aioli.worker.js
Normal file
File diff suppressed because one or more lines are too long
143
public/style.css
Normal file → Executable file
143
public/style.css
Normal file → Executable file
@ -1,24 +1,137 @@
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background-color: #313236;
|
||||
border-radius: 2px;
|
||||
max-width: 800px;
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-variant: small-caps;
|
||||
}
|
||||
|
||||
.navbar a {
|
||||
color: #aaa;
|
||||
display: inline-block;
|
||||
font-size: 15px;
|
||||
padding: 10px;
|
||||
text-decoration: none;
|
||||
#top {
|
||||
color: #bfbdb6;
|
||||
background-color: #222222;
|
||||
height: 4em;
|
||||
|
||||
display:flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.navbar a:hover {
|
||||
color: #ffffff;
|
||||
#top a {
|
||||
position: fixed;
|
||||
right: 2em;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
#top a:visited {
|
||||
color: #bfbdb6;
|
||||
}
|
||||
|
||||
#content {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"query query query query"
|
||||
"input input output output";
|
||||
gap: 1em;
|
||||
grid-template-rows: auto 1fr;
|
||||
|
||||
padding: 1em;
|
||||
height: 80vh;
|
||||
}
|
||||
|
||||
textarea {
|
||||
font-family: "Fira Code", monospace;
|
||||
border: none;
|
||||
border-radius: .3em;
|
||||
padding: .5em;
|
||||
background: #e8e8e8;
|
||||
|
||||
resize: none;
|
||||
}
|
||||
|
||||
#content label {
|
||||
font-size: 1.3em;
|
||||
font-weight: bold;
|
||||
height: 1.5em;
|
||||
}
|
||||
|
||||
#query {
|
||||
grid-area: query;
|
||||
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"label"
|
||||
"filter"
|
||||
"options";
|
||||
}
|
||||
|
||||
#filter-label {
|
||||
grid-area: label;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#filter {
|
||||
grid-area: filter;
|
||||
height: 2em;
|
||||
font-size: 1.1em;
|
||||
|
||||
background: #e8e8e8;
|
||||
border: none;
|
||||
border-radius: .3em;
|
||||
padding-left: .5em;
|
||||
}
|
||||
|
||||
#options {
|
||||
grid-area: options;
|
||||
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-left: .5em;
|
||||
}
|
||||
|
||||
#options li {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
margin-left: 1em;
|
||||
font-size: .7em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#input {
|
||||
grid-area: input;
|
||||
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"input-label"
|
||||
"input-json";
|
||||
grid-template-rows: auto 1fr;
|
||||
}
|
||||
|
||||
#input-label {
|
||||
grid-area: input-label;
|
||||
}
|
||||
|
||||
#input-json {
|
||||
grid-area: input-json;
|
||||
}
|
||||
|
||||
#output {
|
||||
grid-area: output;
|
||||
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"output-label"
|
||||
"output-json";
|
||||
grid-template-rows: auto 1fr;
|
||||
}
|
||||
|
||||
#output-label {
|
||||
grid-area: output-label;
|
||||
}
|
||||
|
||||
#output-json {
|
||||
grid-area: output-json;
|
||||
}
|
22
public/wasm/base.js
Normal file
22
public/wasm/base.js
Normal file
File diff suppressed because one or more lines are too long
1
public/wasm/base.wasm
Normal file
1
public/wasm/base.wasm
Normal file
@ -0,0 +1 @@
|
||||
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
|
1
public/wasm/config.json
Normal file
1
public/wasm/config.json
Normal file
@ -0,0 +1 @@
|
||||
{"wasm-features":[]}
|
22
public/wasm/jq.js
Normal file
22
public/wasm/jq.js
Normal file
File diff suppressed because one or more lines are too long
1
public/wasm/jq.wasm
Normal file
1
public/wasm/jq.wasm
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user