diff --git a/.dockerignore b/.dockerignore index e9b893a..8c37bb0 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,6 @@ /.git /.github +/dist /tools /wasm /web diff --git a/.github/workflows/deploy_website.yml b/.github/workflows/deploy_website.yml index 54af910..88361a0 100644 --- a/.github/workflows/deploy_website.yml +++ b/.github/workflows/deploy_website.yml @@ -28,6 +28,8 @@ jobs: mdbook-version: "latest" - name: Install static-sitemap-cli run: npm install static-sitemap-cli + - name: Install Tailwind CSS CLI + run: npm install tailwindcss @tailwindcss/cli - name: Build Website run: make website - name: Setup Pages diff --git a/.gitignore b/.gitignore index 75b5c73..18e3634 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ go.work.sum # Build files dist/ www/ +web/online/output.css # WebAssembly file -web/wasm/overscry.wasm +web/online/overscry.wasm diff --git a/Makefile b/Makefile index 9c173e5..fe7b8c0 100644 --- a/Makefile +++ b/Makefile @@ -8,16 +8,17 @@ cli-docker: wasm: GOOS=js GOARCH=wasm go build -o dist/overscry.wasm -ldflags '-s -w' ./wasm - cp dist/overscry.wasm web/wasm - cp "$(shell go env GOROOT)/lib/wasm/wasm_exec.js" web/wasm + cp dist/overscry.wasm web/online + cp "$(shell go env GOROOT)/lib/wasm/wasm_exec.js" web/online website: $(MAKE) wasm -mkdir www cd web/book && mdbook build --dest-dir ../../www - -mkdir www/wasm - cp web/wasm/* www/wasm + -mkdir www/online + cp web/online/* www/online cd www && npx sscli --no-clean --base https://overscry.krypton.ninja + cd www/online && npx @tailwindcss/cli -i input.css -o output.css && rm input.css install: go install . diff --git a/README.md b/README.md index c4101da..e0c9471 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,10 @@ OverScry is a tool designed to simplify the process of generating Overpass queri ## Getting Started +> [!TIP] +> There is a **web version** of the tool available, no installation required, just your browser. +> Check it out [here](https://overscry.krypton.ninja/online/) + ### Installation Installing the tool can currently only be done via Go and Docker. @@ -35,12 +39,6 @@ You need to have [Go](https://go.dev/dl/) installed. You can then install using: go install github.com/kkrypt0nn/overscry@latest ``` -You can then generate a query with the basic examples in the [examples](_examples) folder with - -```bash -overscry gen --settings _examples/housenumber.yml -``` - #### Docker You can run the tool from the published [Docker image](https://hub.docker.com/r/kkrypt0nn/overscry) using: @@ -59,22 +57,43 @@ overscry --help This will give you the list of commands and their respective flags. +You can then simply generate a query with + +```bash +overscry gen --settings _examples/housenumber.yml +``` + ## Settings YML File The YML file for the settings has the following example structure ```yml -version: 0.0.1-dev -author: Krypton (@kkrypt0nn) -description: A query to get every house with number 1337 +version: 0.0.7-dev +author: "Krypton (@kkrypt0nn)" +description: "A query to get apartments with 2 levels" node: - addr: - housenumber: - value: 1337 - match: equals + building: + value: apartments + levels: + value: 2 ``` -A lot of work is put into so that more arguments and features/tags are supported. Please be patient for upcoming changes. +More details about the supported fields is available [here](https://overscry.krypton.ninja/settings/introduction.html). + + +> [!NOTE] +> A lot of work is put into so that more arguments and features/tags are supported. Please be patient for upcoming changes. + +## Supported Platforms + +OverScry works on the following platforms: + +- **Linux** +- **macOS** +- **Windows** +- **Browser (via WebAssembly)** - See https://overscry.krypton.ninja/online/ +- **Docker** +- **Android** ## Troubleshooting diff --git a/_examples/building.yml b/_examples/building.yml index 235ffd0..dea3818 100644 --- a/_examples/building.yml +++ b/_examples/building.yml @@ -1,6 +1,6 @@ version: 0.0.7-dev -author: Krypton (@kkrypt0nn) -description: A query to get apartments with 2 levels +author: "Krypton (@kkrypt0nn)" +description: "A query to get apartments with 2 levels" node: building: value: apartments diff --git a/_examples/housenumber.yml b/_examples/housenumber.yml index e00f783..b472d43 100644 --- a/_examples/housenumber.yml +++ b/_examples/housenumber.yml @@ -1,6 +1,6 @@ version: 0.0.1-dev -author: Krypton (@kkrypt0nn) -description: A query to get every house with number 1337 +author: "Krypton (@kkrypt0nn)" +description: "A query to get every house with number 1337" node: addr: housenumber: diff --git a/core/constants.go b/core/constants.go index acc2b65..4595098 100644 --- a/core/constants.go +++ b/core/constants.go @@ -2,7 +2,7 @@ package core const ( Name = "OverScry" - Version = "0.0.10-dev" + Version = "0.0.11-dev" Author = "Krypton (root@krypton.ninja)" Website = "https://overscry.krypton.ninja" ) diff --git a/wasm/main.go b/wasm/main.go index ec3f121..fb6876f 100644 --- a/wasm/main.go +++ b/wasm/main.go @@ -6,11 +6,12 @@ import ( "fmt" "syscall/js" + "github.com/kkrypt0nn/overscry/core" "github.com/kkrypt0nn/overscry/models" "github.com/kkrypt0nn/overscry/settings" ) -func parseYAML(this js.Value, args []js.Value) any { +func convertYAMLToOQL(this js.Value, args []js.Value) any { if len(args) < 1 { return js.ValueOf("Missing YAML input") } @@ -26,7 +27,12 @@ func parseYAML(this js.Value, args []js.Value) any { return js.ValueOf(res) } +func getVersion(this js.Value, args []js.Value) any { + return js.ValueOf(core.Version) +} + func main() { - js.Global().Set("parseYAMLToOQL", js.FuncOf(parseYAML)) + js.Global().Set("convertYAMLToOQL", js.FuncOf(convertYAMLToOQL)) + js.Global().Set("getVersion", js.FuncOf(getVersion)) select {} } diff --git a/web/book/src/assets/android.svg b/web/book/src/assets/android.svg new file mode 100644 index 0000000..a014a0f --- /dev/null +++ b/web/book/src/assets/android.svg @@ -0,0 +1 @@ + diff --git a/web/book/src/assets/apple.svg b/web/book/src/assets/apple.svg new file mode 100644 index 0000000..8ae918b --- /dev/null +++ b/web/book/src/assets/apple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/book/src/assets/docker.svg b/web/book/src/assets/docker.svg new file mode 100644 index 0000000..b209965 --- /dev/null +++ b/web/book/src/assets/docker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/book/src/assets/linux.svg b/web/book/src/assets/linux.svg new file mode 100644 index 0000000..1dff15d --- /dev/null +++ b/web/book/src/assets/linux.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/book/src/assets/wasm.svg b/web/book/src/assets/wasm.svg new file mode 100644 index 0000000..63f6c4b --- /dev/null +++ b/web/book/src/assets/wasm.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/web/book/src/assets/windows.svg b/web/book/src/assets/windows.svg new file mode 100644 index 0000000..94c4ddf --- /dev/null +++ b/web/book/src/assets/windows.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/book/src/introduction.md b/web/book/src/introduction.md index 00f67f2..9642577 100644 --- a/web/book/src/introduction.md +++ b/web/book/src/introduction.md @@ -8,4 +8,19 @@ OverScry is a tool designed to simplify the process of generating Overpass queries from a YML structure file. By taking a structured YML input that defines specific geographical data and search parameters, OverScry automatically converts it into a valid Overpass query. Overall it makes it easier for both beginners and experts to leverage Overpass API capabilities without needing to understand how to write complex raw queries. +--- + +## Test the online version of the tool [here](/online/) + +#### Supports + +
+ Linux + macOS + Windows + WebAssembly + Docker + Android +
+ diff --git a/web/book/src/settings/introduction.md b/web/book/src/settings/introduction.md index 8349dd5..a77671f 100644 --- a/web/book/src/settings/introduction.md +++ b/web/book/src/settings/introduction.md @@ -9,14 +9,14 @@ A lot of work is put into so that more arguments and features/tags are supported An example YML file looks like ```yml -version: 0.0.1-dev -author: Krypton (@kkrypt0nn) -description: A query to get every house with number 1337 +version: 0.0.7-dev +author: "Krypton (@kkrypt0nn)" +description: "A query to get apartments with 2 levels" node: - addr: - housenumber: - value: 1337 - match: equals + building: + value: apartments + levels: + value: 2 ``` The following fields are allowed diff --git a/web/online/ace_editor.js b/web/online/ace_editor.js new file mode 100644 index 0000000..0a4d604 --- /dev/null +++ b/web/online/ace_editor.js @@ -0,0 +1,21 @@ +var editor = ace.edit("editor"); +editor.setTheme("ace/theme/twilight"); +editor.getSession().setMode("ace/mode/yaml"); +editor.getSession().setValue(`version: 0.0.7-dev +author: "Krypton (@kkrypt0nn)" +description: "A query to get apartments with 2 levels" +node: + building: + value: apartments + levels: + value: 2`); + +var output = ace.edit("output"); +output.setTheme("ace/theme/twilight"); +output.setOptions({ + readOnly: true, + showLineNumbers: false, + showGutter: false, +}); +output.container.style.color = "gray"; +output.getSession().setValue("// The generated query will appear here"); diff --git a/web/online/app.js b/web/online/app.js new file mode 100644 index 0000000..8e0a734 --- /dev/null +++ b/web/online/app.js @@ -0,0 +1,163 @@ +function saveToFile() { + const content = output.getValue(); + if ( + content !== "" && + content !== "// The generated query will appear here" && + content !== + "// Sending request to Overpass, this can take some time depending on the query..." + ) { + const mode = output.getSession().getMode().$id; + const fileName = `result.${mode === "ace/mode/json" ? "json" : "txt"}`; + const theFile = new Blob([content], { + type: `${mode === "ace/mode/json" ? "application/json" : "text/plain"}`, + }); + const element = document.createElement("a"); + element.setAttribute("href", window.URL.createObjectURL(theFile)); + element.setAttribute("download", fileName); + element.style.display = "none"; + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); + } +} + +function copyOutput() { + const content = output.getValue(); + if ( + content !== "" && + content !== "// The generated query will appear here" && + content !== + "// Sending request to Overpass, this can take some time depending on the query..." + ) { + navigator.clipboard.writeText(content); + document.getElementById("copy").innerText = "Copied"; + document.getElementById("copy-icon").classList.add("hidden"); + document.getElementById("copied-icon").classList.remove("hidden"); + + setTimeout(() => { + document.getElementById("copy").innerText = "Copy"; + document.getElementById("copied-icon").classList.add("hidden"); + document.getElementById("copy-icon").classList.remove("hidden"); + }, 2000); + } +} + +function editButtons(enable) { + const buttons = [ + document.getElementById("save-btn"), + document.getElementById("copy-btn"), + ]; + + for (btn of buttons) { + switch (enable) { + case true: + btn.classList.add("hover:bg-gray-700", "hover:cursor-pointer"); + btn.classList.remove("opacity-50", "cursor-not-allowed"); + btn.disabled = false; + break; + case false: + btn.classList.remove("hover:bg-gray-700", "hover:cursor-pointer"); + btn.classList.add("opacity-50", "cursor-not-allowed"); + btn.disabled = true; + break; + } + } +} + +const go = new Go(); + +async function execute() { + const input = editor.getValue(); + let result = ""; + let query = await window.convertYAMLToOQL(input); + if (query.startsWith("Error parsing YAML: ")) { + output.container.style.color = "#eb2a2a"; + query = query.replace("Error parsing YAML: ", ""); + let match = query.match(/\(allowed: ([^)]+)\)/); + if (match) { + let list = match[1]; + let items = list.split(", "); + let possibleValues = items.join("\n* "); + query = query.replace(` ${match[0]}`, `, allowed:\n* ${possibleValues}`); + } + query = query.charAt(0).toUpperCase() + query.slice(1); + result = query; + editButtons(false); + } else { + output.container.style.color = "gray"; + result = "// Sending request to Overpass, this can take some time..."; + let formData = new FormData(); + formData.append("data", query); + fetch("https://overpass-api.de/api/interpreter", { + body: new URLSearchParams(formData), + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }) + .then((r) => { + return r.json(); + }) + .then((r) => { + output.container.style.color = "white"; + output.getSession().setMode("ace/mode/json"); + output.getSession().setValue(JSON.stringify(r.elements, null, " ")); + editButtons(true); + }) + .catch((e) => { + output.container.style.color = "#eb2a2a"; + output.getSession().setMode("ace/mode/text"); + output.getSession().setValue(e.toString()); + editButtons(false); + }); + } + + editButtons(false); + output.getSession().setMode("ace/mode/text"); + output.getSession().setValue(result); +} + +async function generate() { + const input = editor.getValue(); + let result = await window.convertYAMLToOQL(input); + if (result.startsWith("Error parsing YAML: ")) { + output.container.style.color = "#eb2a2a"; + result = result.replace("Error parsing YAML: ", ""); + let match = result.match(/\(allowed: ([^)]+)\)/); + if (match) { + let list = match[1]; + let items = list.split(", "); + let possibleValues = items.join("\n* "); + result = result.replace( + ` ${match[0]}`, + `, allowed:\n* ${possibleValues}`, + ); + } + result = result.charAt(0).toUpperCase() + result.slice(1); + editButtons(false); + } else { + output.container.style.color = "white"; + editButtons(true); + } + + output.getSession().setMode("ace/mode/text"); + output.getSession().setValue(result); +} + +async function renderApp() { + const result = await window.getVersion(); + document.getElementById("version").innerText = `(v${result})`; + document.getElementById("app").classList.remove("hidden"); + editButtons(false); +} + +WebAssembly.instantiateStreaming(fetch("overscry.wasm"), go.importObject) + .then((result) => { + go.run(result.instance); + document.getElementById("loading").classList.add("hidden"); + renderApp(); + }) + .catch((e) => { + document.getElementById("loading").classList.add("hidden"); + document.getElementById("error-loading").classList.remove("hidden"); + }); diff --git a/web/online/index.html b/web/online/index.html new file mode 100644 index 0000000..a4fbce4 --- /dev/null +++ b/web/online/index.html @@ -0,0 +1,157 @@ + + + + + + + OverScry Online + + + + + + + + +
+
+
+ +

OverScry

+
+ +
+
+ +
+

+ Welcome to OverScry's online version! For more detailed + instructions and examples, check out the + documentation. +

+

+ The generated queries can then be executed on + Overpass Turbo +

+
+ +
+

+ Loading WebAssembly module... +

+
+ + + + +
+
+ + + + + + + + + + + + + + diff --git a/web/online/input.css b/web/online/input.css new file mode 100644 index 0000000..f1d8c73 --- /dev/null +++ b/web/online/input.css @@ -0,0 +1 @@ +@import "tailwindcss"; diff --git a/web/wasm/wasm_exec.js b/web/online/wasm_exec.js similarity index 100% rename from web/wasm/wasm_exec.js rename to web/online/wasm_exec.js diff --git a/web/wasm/index.html b/web/wasm/index.html deleted file mode 100644 index fe1fa39..0000000 --- a/web/wasm/index.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - OverScry WebAssembly - - -

OverScry WebAssembly

- - - - -

-
-        
-        
-    
-