new: yew-based front-end
This commit is contained in:
		
							parent
							
								
									abadb2ec7d
								
							
						
					
					
						commit
						d64938e8e5
					
				
					 20 changed files with 680 additions and 6263 deletions
				
			
		
							
								
								
									
										70
									
								
								.github/workflows/ci.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								.github/workflows/ci.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -1,70 +0,0 @@ | |||
| name: ci | ||||
| 
 | ||||
| on: | ||||
|   push: | ||||
|     branches: [ main ] | ||||
|   pull_request: | ||||
|     branches: [ main ] | ||||
| 
 | ||||
| env: | ||||
|   CARGO_TERM_COLOR: always | ||||
| 
 | ||||
| jobs: | ||||
|   test: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - uses: actions/checkout@v2 | ||||
| 
 | ||||
|     - uses: actions/cache@v2 | ||||
|       with: | ||||
|         path: | | ||||
|           ~/.cargo/registry | ||||
|           ~/.cargo/git | ||||
|           target | ||||
|         key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | ||||
| 
 | ||||
|     - name: lint | ||||
|       run: cargo fmt -- --check | ||||
| 
 | ||||
|     - name: install wasm-pack | ||||
|       run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh | ||||
| 
 | ||||
|     - run: cargo check | ||||
| 
 | ||||
|     - run: cargo test | ||||
| 
 | ||||
|     - run: wasm-pack test --headless --firefox | ||||
| 
 | ||||
|     - run: wasm-pack test --headless --chrome | ||||
| 
 | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     needs: test | ||||
|     steps: | ||||
|     - uses: actions/checkout@v2 | ||||
| 
 | ||||
|     - uses: actions/cache@v2 | ||||
|       with: | ||||
|         path: | | ||||
|           ~/.cargo/registry | ||||
|           ~/.cargo/git | ||||
|           target | ||||
|         key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | ||||
| 
 | ||||
|     - name: install wasm-pack | ||||
|       run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh | ||||
| 
 | ||||
|     - name: build | ||||
|       run: | | ||||
|         wasm-pack build | ||||
|         cd www | ||||
|         npm install | ||||
|         npm run build | ||||
| 
 | ||||
|     - name: deploy | ||||
|       uses: peaceiris/actions-gh-pages@v3 | ||||
|       if: github.ref == 'refs/heads/main' | ||||
|       with: | ||||
|         github_token: ${{ secrets.GITHUB_TOKEN }} | ||||
|         publish_dir: www/dist | ||||
|         cname: gpx.thermokar.st | ||||
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,5 +1,6 @@ | |||
| /target | ||||
| **/*.rs.bk | ||||
| bin/ | ||||
| dist/ | ||||
| pkg/ | ||||
| wasm-pack.log | ||||
|  |  | |||
							
								
								
									
										316
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										316
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -1,5 +1,7 @@ | |||
| # This file is automatically @generated by Cargo. | ||||
| # It is not intended for manual editing. | ||||
| version = 3 | ||||
| 
 | ||||
| [[package]] | ||||
| name = "addr2line" | ||||
| version = "0.14.0" | ||||
|  | @ -41,6 +43,12 @@ dependencies = [ | |||
|  "rustc-demangle", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "boolinator" | ||||
| version = "2.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "bumpalo" | ||||
| version = "3.4.0" | ||||
|  | @ -106,6 +114,113 @@ version = "0.23.0" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo" | ||||
| version = "0.4.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "23947965eee55e3e97a5cd142dd4c10631cc349b48cecca0ed230fd296f568cd" | ||||
| dependencies = [ | ||||
|  "gloo-console", | ||||
|  "gloo-dialogs", | ||||
|  "gloo-events", | ||||
|  "gloo-file", | ||||
|  "gloo-render", | ||||
|  "gloo-storage", | ||||
|  "gloo-timers", | ||||
|  "gloo-utils", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-console" | ||||
| version = "0.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3907f786f65bbb4f419e918b0c5674175ef1c231ecda93b2dbd65fd1e8882637" | ||||
| dependencies = [ | ||||
|  "js-sys", | ||||
|  "serde", | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-dialogs" | ||||
| version = "0.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4ffb557a2ea2ed283f1334423d303a336fad55fb8572d51ae488f828b1464b40" | ||||
| dependencies = [ | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-events" | ||||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "088514ec8ef284891c762c88a66b639b3a730134714692ee31829765c5bc814f" | ||||
| dependencies = [ | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-file" | ||||
| version = "0.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d31ba1f51868ae10a0b665c6dccd5ed967486e7c17055d1c889596ee983be493" | ||||
| dependencies = [ | ||||
|  "gloo-events", | ||||
|  "js-sys", | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-render" | ||||
| version = "0.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5b4cda6e149df3bb4a3c6a343873903e5bcc2448a9877d61bb8274806ad67f6e" | ||||
| dependencies = [ | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-storage" | ||||
| version = "0.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1b5057761927af1b1929d02b1f49cf83553dd347a473ee7c8bb08420f2673ffc" | ||||
| dependencies = [ | ||||
|  "gloo-utils", | ||||
|  "js-sys", | ||||
|  "serde", | ||||
|  "serde_json", | ||||
|  "thiserror", | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-timers" | ||||
| version = "0.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" | ||||
| dependencies = [ | ||||
|  "js-sys", | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-utils" | ||||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3d77d28d9a6f7c384d9e40293fa11f05558bf928a993208e12528ee6633cb415" | ||||
| dependencies = [ | ||||
|  "js-sys", | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gpx" | ||||
| version = "0.8.1" | ||||
|  | @ -124,12 +239,37 @@ name = "gpx-web-utils" | |||
| version = "0.0.1" | ||||
| dependencies = [ | ||||
|  "console_error_panic_hook", | ||||
|  "gloo-file", | ||||
|  "gpx", | ||||
|  "js-sys", | ||||
|  "wasm-bindgen", | ||||
|  "wasm-bindgen-test", | ||||
|  "web-sys", | ||||
|  "wee_alloc", | ||||
|  "yew", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "hashbrown" | ||||
| version = "0.11.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "indexmap" | ||||
| version = "1.7.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" | ||||
| dependencies = [ | ||||
|  "autocfg", | ||||
|  "hashbrown", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "itoa" | ||||
| version = "0.4.8" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "js-sys" | ||||
| version = "0.3.45" | ||||
|  | @ -160,6 +300,12 @@ dependencies = [ | |||
|  "cfg-if 0.1.10", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "memory_units" | ||||
| version = "0.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "miniz_oxide" | ||||
| version = "0.4.3" | ||||
|  | @ -195,6 +341,30 @@ version = "0.22.0" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro-error" | ||||
| version = "1.0.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" | ||||
| dependencies = [ | ||||
|  "proc-macro-error-attr", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "version_check", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro-error-attr" | ||||
| version = "1.0.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "version_check", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro2" | ||||
| version = "1.0.24" | ||||
|  | @ -220,10 +390,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "scoped-tls" | ||||
| version = "1.0.0" | ||||
| name = "ryu" | ||||
| version = "1.0.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" | ||||
| checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "scoped-tls-hkt" | ||||
| version = "0.1.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c2e9d7eaddb227e8fbaaa71136ae0e1e913ca159b86c7da82f3e8f0044ad3a63" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "1.0.118" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" | ||||
| dependencies = [ | ||||
|  "serde_derive", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde_derive" | ||||
| version = "1.0.118" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde_json" | ||||
| version = "1.0.72" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" | ||||
| dependencies = [ | ||||
|  "itoa", | ||||
|  "ryu", | ||||
|  "serde", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "slab" | ||||
| version = "0.4.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "syn" | ||||
|  | @ -236,6 +449,26 @@ dependencies = [ | |||
|  "unicode-xid", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "thiserror" | ||||
| version = "1.0.30" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" | ||||
| dependencies = [ | ||||
|  "thiserror-impl", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "thiserror-impl" | ||||
| version = "1.0.30" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "time" | ||||
| version = "0.1.44" | ||||
|  | @ -253,6 +486,12 @@ version = "0.2.1" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "version_check" | ||||
| version = "0.9.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "wasi" | ||||
| version = "0.10.0+wasi-snapshot-preview1" | ||||
|  | @ -266,6 +505,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" | ||||
| dependencies = [ | ||||
|  "cfg-if 0.1.10", | ||||
|  "serde", | ||||
|  "serde_json", | ||||
|  "wasm-bindgen-macro", | ||||
| ] | ||||
| 
 | ||||
|  | @ -325,30 +566,6 @@ version = "0.2.68" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "wasm-bindgen-test" | ||||
| version = "0.3.18" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "34d1cdc8b98a557f24733d50a1199c4b0635e465eecba9c45b214544da197f64" | ||||
| dependencies = [ | ||||
|  "console_error_panic_hook", | ||||
|  "js-sys", | ||||
|  "scoped-tls", | ||||
|  "wasm-bindgen", | ||||
|  "wasm-bindgen-futures", | ||||
|  "wasm-bindgen-test-macro", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "wasm-bindgen-test-macro" | ||||
| version = "0.3.18" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e8fb9c67be7439ee8ab1b7db502a49c05e51e2835b66796c705134d9b8e1a585" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "web-sys" | ||||
| version = "0.3.45" | ||||
|  | @ -359,6 +576,18 @@ dependencies = [ | |||
|  "wasm-bindgen", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "wee_alloc" | ||||
| version = "0.4.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" | ||||
| dependencies = [ | ||||
|  "cfg-if 0.1.10", | ||||
|  "libc", | ||||
|  "memory_units", | ||||
|  "winapi", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "winapi" | ||||
| version = "0.3.9" | ||||
|  | @ -386,3 +615,34 @@ name = "xml-rs" | |||
| version = "0.8.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "yew" | ||||
| version = "0.18.0" | ||||
| source = "git+https://github.com/yewstack/yew.git#996bf5b41ac30d7ada14fdc2f419de7659e94613" | ||||
| dependencies = [ | ||||
|  "console_error_panic_hook", | ||||
|  "gloo", | ||||
|  "gloo-utils", | ||||
|  "indexmap", | ||||
|  "js-sys", | ||||
|  "scoped-tls-hkt", | ||||
|  "slab", | ||||
|  "wasm-bindgen", | ||||
|  "wasm-bindgen-futures", | ||||
|  "web-sys", | ||||
|  "yew-macro", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "yew-macro" | ||||
| version = "0.18.0" | ||||
| source = "git+https://github.com/yewstack/yew.git#996bf5b41ac30d7ada14fdc2f419de7659e94613" | ||||
| dependencies = [ | ||||
|  "boolinator", | ||||
|  "lazy_static", | ||||
|  "proc-macro-error", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
|  |  | |||
							
								
								
									
										24
									
								
								Cargo.toml
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								Cargo.toml
									
										
									
									
									
								
							|  | @ -4,25 +4,25 @@ version = "0.0.1" | |||
| authors = ["Matthew Dillon <matthewrdillon@gmail.com>"] | ||||
| edition = "2018" | ||||
| description = "just some gpx-related tools that i want to use" | ||||
| repository = "https://github.com/thermokarst/gpx-web-utils" | ||||
| repository = "git://pingo.thermokar.st/gpx-web-utils" | ||||
| license = "MIT" | ||||
| 
 | ||||
| [lib] | ||||
| crate-type = ["cdylib", "rlib"] | ||||
| 
 | ||||
| [features] | ||||
| default = ["console_error_panic_hook"] | ||||
| 
 | ||||
| [dependencies] | ||||
| wasm-bindgen = "0.2.63" | ||||
| js-sys = "0.3.45" | ||||
| wasm-bindgen = "0.2" | ||||
| js-sys = "0.3" | ||||
| gpx = "0.8.1" | ||||
| # TODO: still waiting on a public release | ||||
| # yew = "0.19" | ||||
| yew = { git = "https://github.com/yewstack/yew.git" } | ||||
| gloo-file = "0.2" | ||||
| wee_alloc = "0.4" | ||||
| 
 | ||||
| console_error_panic_hook = { version = "0.1.6", optional = true } | ||||
| 
 | ||||
| [dev-dependencies] | ||||
| wasm-bindgen-test = "0.3.13" | ||||
| 
 | ||||
| [profile.release] | ||||
| opt-level = 3 | ||||
| lto = true | ||||
| 
 | ||||
| [dependencies.web-sys] | ||||
| version = "0.3" | ||||
| features = ["File", "Blob", "Element", "MouseEvent", "EventTarget", "Url", "Event"] | ||||
|  |  | |||
							
								
								
									
										24
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								README.md
									
										
									
									
									
								
							|  | @ -1,11 +1,21 @@ | |||
| # gpx-web-utils | ||||
| 
 | ||||
|  | ||||
| ## development | ||||
| 
 | ||||
| ## quickstart | ||||
| ```bash | ||||
| cargo install --locked trunk | ||||
| cargo install wasm-bindgen-cli | ||||
| rustup target add wasm32-unknown-unknown | ||||
| trunk serve | ||||
| ``` | ||||
| 
 | ||||
| 1. install [wasm-pack](https://rustwasm.github.io/wasm-pack/installer/) | ||||
| 2. `wasm-pack build` | ||||
| 3. `cd www` | ||||
| 4. `npm install` | ||||
| 5. `npm run start` | ||||
| ## deployment | ||||
| 
 | ||||
| ```bash | ||||
| trunk build --release | ||||
| git switch deploy | ||||
| rm index-* | ||||
| cp dist/* . | ||||
| git commit -am 'foo' | ||||
| git push <DOKKU INSTANCE> deploy | ||||
| ``` | ||||
|  |  | |||
							
								
								
									
										25
									
								
								index.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								index.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| <!DOCTYPE html> | ||||
| <html> | ||||
|   <head> | ||||
|     <meta charset="utf-8" /> | ||||
|     <title>gpx.thermokar.st</title> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
|     <style> | ||||
|       body { | ||||
|         max-width: 35em; | ||||
|         margin: 0 auto; | ||||
|         line-height: 1.5; | ||||
|         font-family: sans-serif; | ||||
|         font-size: large; | ||||
|       } | ||||
|     </style> | ||||
|   </head> | ||||
|   <body> | ||||
|     <noscript> | ||||
|       <mark> | ||||
|         This page contains webassembly and javascript content, please enable | ||||
|         javascript in your browser to use this tool. | ||||
|       </mark> | ||||
|     </noscript> | ||||
|   </body> | ||||
| </html> | ||||
							
								
								
									
										81
									
								
								src/app.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/app.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,81 @@ | |||
| use super::loader::Loader; | ||||
| 
 | ||||
| use web_sys::Node; | ||||
| use yew::virtual_dom::VNode; | ||||
| use yew::{function_component, html, Html}; | ||||
| 
 | ||||
| #[function_component(App)] | ||||
| pub fn app() -> Html { | ||||
|     html! { | ||||
|         <> | ||||
|             <h1> | ||||
|                 <a href="/"> | ||||
|                     { "gpx.thermokar.st" } | ||||
|                 </a> | ||||
|             </h1> | ||||
| 
 | ||||
|             <p> | ||||
|                 { "a client-side tool for merging " } | ||||
|                 <a href="https://www.topografix.com/gpx.asp"> | ||||
|                     { "gpx files" } | ||||
|                 </a> | ||||
|             </p> | ||||
| 
 | ||||
|             <Loader /> | ||||
| 
 | ||||
|             <hr/> | ||||
| 
 | ||||
|             <Footer /> | ||||
|         </> | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[function_component(Footer)] | ||||
| fn footer() -> Html { | ||||
|     let notes = Vec::from([ | ||||
|         // note 1
 | ||||
|         "this has only been tested on GPX files produced by \ | ||||
|         <a href=\"https://strava.com\" target=\"_blank\">strava</a> and \ | ||||
|         <a href=\"https://garmin.com\" target=\"_blank\">garmin</a>", | ||||
|         // note 2
 | ||||
|         "all third-party extension info \ | ||||
|         <a href=\"https://github.com/georust/gpx/issues/8\" target=\"_blank\">\ | ||||
|         is stripped</a>",
 | ||||
|         // note 3
 | ||||
|         "if the app breaks, try refreshing the page", | ||||
|         "source (public access): git://pingo.thermokar.st/gpx-web-utils", | ||||
|         // note 4
 | ||||
|         "source (mirror): \ | ||||
|         <a href=\"https://github.com/thermokarst/gpx-web-utils\" target=\"_blank\">\ | ||||
|         https://github.com/thermokarst/gpx-web-utils</a>",
 | ||||
|     ]); | ||||
| 
 | ||||
|     html! { | ||||
|         <div> | ||||
|             <ul> | ||||
|                 { for notes.iter().map(|n| inner_html_enabled_li(n)) } | ||||
|             </ul> | ||||
| 
 | ||||
|             <span> | ||||
|                 <small> | ||||
|                     { "\u{000A9} matthew ryan dillon, 2021" } | ||||
|                 </small> | ||||
|             </span> | ||||
|         </div> | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn inner_html_enabled_li(data: &str) -> Html { | ||||
|     let li = web_sys::window() | ||||
|         .unwrap() | ||||
|         .document() | ||||
|         .unwrap() | ||||
|         .create_element("li") | ||||
|         .unwrap(); | ||||
| 
 | ||||
|     li.set_inner_html(data); | ||||
| 
 | ||||
|     let node = Node::from(li); | ||||
| 
 | ||||
|     VNode::VRef(node) | ||||
| } | ||||
							
								
								
									
										88
									
								
								src/gpx.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/gpx.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,88 @@ | |||
| use std::error::Error; | ||||
| use wasm_bindgen::prelude::*; | ||||
| use web_sys::{Blob, MouseEvent, Url}; | ||||
| 
 | ||||
| fn join_gpx_files(files: &[String]) -> Result<gpx::Gpx, Box<dyn Error>> { | ||||
|     let mut merged_gpx: gpx::Gpx = Default::default(); | ||||
|     let mut merged_track: gpx::Track = gpx::Track::new(); | ||||
| 
 | ||||
|     for file in files.iter() { | ||||
|         let buffer = std::io::BufReader::new(file.as_bytes()); | ||||
|         let mut parsed_gpx: gpx::Gpx = gpx::read(buffer)?; | ||||
| 
 | ||||
|         // consolidate all track segements into one single track.
 | ||||
|         for track in parsed_gpx.tracks { | ||||
|             for segment in track.segments { | ||||
|                 merged_track.segments.push(segment); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         merged_gpx.waypoints.append(&mut parsed_gpx.waypoints); | ||||
|     } | ||||
| 
 | ||||
|     merged_gpx.tracks.push(merged_track); | ||||
| 
 | ||||
|     let link = gpx::Link { | ||||
|         href: String::from("https://gpx.thermokar.st"), | ||||
|         ..Default::default() | ||||
|     }; | ||||
|     let author = gpx::Person { | ||||
|         link: Some(link), | ||||
|         ..Default::default() | ||||
|     }; | ||||
|     let metadata = gpx::Metadata { | ||||
|         name: Some(String::from("merged")), | ||||
|         author: Some(author), | ||||
|         ..Default::default() | ||||
|     }; | ||||
|     merged_gpx.metadata = Some(metadata); | ||||
|     merged_gpx.version = gpx::GpxVersion::Gpx11; | ||||
| 
 | ||||
|     Ok(merged_gpx) | ||||
| } | ||||
| fn write_gpx_to_buffer(gpx: gpx::Gpx) -> Result<js_sys::Array, Box<dyn Error>> { | ||||
|     let mut buffer = Vec::new(); | ||||
|     gpx::write(&gpx, &mut buffer)?; | ||||
| 
 | ||||
|     let uint8arr = js_sys::Uint8Array::new(&unsafe { js_sys::Uint8Array::view(&buffer) }.into()); | ||||
|     let array = js_sys::Array::new(); | ||||
|     array.push(&uint8arr.buffer()); | ||||
| 
 | ||||
|     Ok(array) | ||||
| } | ||||
| 
 | ||||
| pub fn merge(files: &[String]) -> Result<Blob, Box<dyn Error>> { | ||||
|     let merged: gpx::Gpx = join_gpx_files(files)?; | ||||
|     let out_vec = write_gpx_to_buffer(merged)?; | ||||
|     let result = Blob::new_with_u8_array_sequence(&out_vec).map_err(|e| e.as_string().unwrap())?; | ||||
| 
 | ||||
|     Ok(result) | ||||
| } | ||||
| 
 | ||||
| pub fn download(merged: Blob) -> Result<(), Box<dyn Error>> { | ||||
|     let window = web_sys::window().ok_or("no global `window` exists")?; | ||||
|     let document = window | ||||
|         .document() | ||||
|         .ok_or("should have a document on window")?; | ||||
| 
 | ||||
|     let err_handler = |e: JsValue| e.as_string().unwrap(); | ||||
|     let anchor_element = document.create_element("a").map_err(err_handler)?; | ||||
|     let url = Url::create_object_url_with_blob(&merged).map_err(err_handler)?; | ||||
| 
 | ||||
|     anchor_element | ||||
|         .set_attribute("href", &url) | ||||
|         .map_err(err_handler)?; | ||||
|     anchor_element | ||||
|         .set_attribute("download", "merged.gpx") | ||||
|         .map_err(err_handler)?; | ||||
| 
 | ||||
|     let event = MouseEvent::new("click").map_err(err_handler)?; | ||||
|     anchor_element.dispatch_event(&event).map_err(err_handler)?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| #[wasm_bindgen] | ||||
| extern "C" { | ||||
|     pub fn alert(s: &str); | ||||
| } | ||||
							
								
								
									
										17
									
								
								src/lib.rs
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								src/lib.rs
									
										
									
									
									
								
							|  | @ -1,17 +0,0 @@ | |||
| mod utils; | ||||
| 
 | ||||
| use wasm_bindgen::prelude::*; | ||||
| 
 | ||||
| #[cfg(feature = "wee_alloc")] | ||||
| #[global_allocator] | ||||
| static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; | ||||
| 
 | ||||
| #[wasm_bindgen] | ||||
| pub fn merge(files: js_sys::Array) -> wasm_bindgen::JsValue { | ||||
|     utils::set_panic_hook(); | ||||
|     let files: Vec<String> = utils::translate_js_to_rust(files); | ||||
|     let merged: gpx::Gpx = utils::join_gpx_files(files); | ||||
|     let out_vec: Vec<u8> = utils::write_gpx_to_buffer(merged); | ||||
| 
 | ||||
|     JsValue::from_str(&String::from_utf8(out_vec).unwrap()) | ||||
| } | ||||
							
								
								
									
										155
									
								
								src/loader.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								src/loader.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,155 @@ | |||
| use std::collections::HashMap; | ||||
| 
 | ||||
| use gloo_file::callbacks::FileReader; | ||||
| use gloo_file::File; | ||||
| use web_sys::{Blob, Event, HtmlInputElement}; | ||||
| use yew::{html, html::TargetCast, Component, Context, Html}; | ||||
| 
 | ||||
| use super::gpx; | ||||
| 
 | ||||
| pub enum Msg { | ||||
|     FileLoaded(String, String), | ||||
|     StartLoad(Vec<File>), | ||||
|     FilesLoaded, | ||||
|     Download(Blob), | ||||
|     Reset, | ||||
| } | ||||
| 
 | ||||
| pub struct Loader { | ||||
|     readers: HashMap<String, FileReader>, | ||||
|     files: Vec<String>, | ||||
|     count: usize, | ||||
|     is_loading: bool, | ||||
|     // This field is to handle resetting the native HTML widget's state on error
 | ||||
|     field_value: &'static str, | ||||
| } | ||||
| 
 | ||||
| impl Component for Loader { | ||||
|     type Message = Msg; | ||||
|     type Properties = (); | ||||
| 
 | ||||
|     fn create(_ctx: &Context<Self>) -> Self { | ||||
|         Self { | ||||
|             readers: HashMap::default(), | ||||
|             files: vec![], | ||||
|             count: 0, | ||||
|             is_loading: false, | ||||
|             field_value: "", | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool { | ||||
|         match msg { | ||||
|             Msg::FileLoaded(filename, data) => { | ||||
|                 self.files.push(data); | ||||
|                 self.readers.remove(&filename); | ||||
|                 if self.files.len() == self.count { | ||||
|                     ctx.link().send_message(Msg::FilesLoaded); | ||||
|                 } | ||||
| 
 | ||||
|                 true | ||||
|             } | ||||
| 
 | ||||
|             Msg::StartLoad(files) => { | ||||
|                 self.count = files.len(); | ||||
|                 if self.count < 2 { | ||||
|                     gpx::alert("must load two or more files"); | ||||
|                     ctx.link().send_message(Msg::Reset); | ||||
|                     return true; | ||||
|                 } | ||||
|                 self.is_loading = true; | ||||
| 
 | ||||
|                 for file in files.into_iter() { | ||||
|                     let file_name = file.name(); | ||||
|                     let task = { | ||||
|                         let file_name = file_name.clone(); | ||||
|                         let link = ctx.link().clone(); | ||||
| 
 | ||||
|                         gloo_file::callbacks::read_as_text(&file, move |res| { | ||||
|                             link.send_message(Msg::FileLoaded( | ||||
|                                 file_name, | ||||
|                                 res.unwrap_or_else(|e| e.to_string()), | ||||
|                             )) | ||||
|                         }) | ||||
|                     }; | ||||
|                     self.readers.insert(file_name, task); | ||||
|                 } | ||||
| 
 | ||||
|                 true | ||||
|             } | ||||
| 
 | ||||
|             Msg::FilesLoaded => { | ||||
|                 let link = ctx.link(); | ||||
| 
 | ||||
|                 let merged = match gpx::merge(&self.files) { | ||||
|                     Ok(result) => result, | ||||
|                     Err(err) => { | ||||
|                         gpx::alert(&err.to_string()); | ||||
|                         link.send_message(Msg::Reset); | ||||
|                         return true; | ||||
|                     } | ||||
|                 }; | ||||
| 
 | ||||
|                 link.send_message(Msg::Download(merged)); | ||||
| 
 | ||||
|                 true | ||||
|             } | ||||
| 
 | ||||
|             Msg::Download(merged) => { | ||||
|                 let link = ctx.link(); | ||||
| 
 | ||||
|                 match gpx::download(merged) { | ||||
|                     Ok(_) => (), | ||||
|                     Err(err) => { | ||||
|                         gpx::alert(&err.to_string()); | ||||
|                         link.send_message(Msg::Reset); | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|                 link.send_message(Msg::Reset); | ||||
| 
 | ||||
|                 true | ||||
|             } | ||||
| 
 | ||||
|             Msg::Reset => { | ||||
|                 self.readers = HashMap::default(); | ||||
|                 self.files = vec![]; | ||||
|                 self.count = 0; | ||||
|                 self.is_loading = false; | ||||
|                 self.field_value = ""; | ||||
| 
 | ||||
|                 true | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn view(&self, ctx: &Context<Self>) -> Html { | ||||
|         let cb = move |e: Event| { | ||||
|             let mut result = Vec::new(); | ||||
|             let input: HtmlInputElement = e.target_unchecked_into(); | ||||
| 
 | ||||
|             if let Some(files) = input.files() { | ||||
|                 let files = js_sys::try_iter(&files) | ||||
|                     .unwrap() | ||||
|                     .unwrap() | ||||
|                     .map(|v| web_sys::File::from(v.unwrap())) | ||||
|                     .map(File::from); | ||||
|                 result.extend(files); | ||||
|             } | ||||
|             Msg::StartLoad(result) | ||||
|         }; | ||||
| 
 | ||||
|         html! { | ||||
|             if self.is_loading { | ||||
|                 <span><strong>{"processing..."}</strong></span> | ||||
|             } else { | ||||
|                 <input | ||||
|                     type="file" | ||||
|                     value={self.field_value} | ||||
|                     multiple=true | ||||
|                     onchange={ctx.link().callback(cb)} | ||||
|                 /> | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										13
									
								
								src/main.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/main.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| extern crate wee_alloc; | ||||
| 
 | ||||
| mod app; | ||||
| mod gpx; | ||||
| mod loader; | ||||
| 
 | ||||
| // Use `wee_alloc` as the global allocator.
 | ||||
| #[global_allocator] | ||||
| static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; | ||||
| 
 | ||||
| fn main() { | ||||
|     yew::start_app::<app::App>(); | ||||
| } | ||||
							
								
								
									
										55
									
								
								src/utils.rs
									
										
									
									
									
								
							
							
						
						
									
										55
									
								
								src/utils.rs
									
										
									
									
									
								
							|  | @ -1,55 +0,0 @@ | |||
| pub fn set_panic_hook() { | ||||
|     #[cfg(feature = "console_error_panic_hook")] | ||||
|     console_error_panic_hook::set_once(); | ||||
| } | ||||
| 
 | ||||
| pub fn translate_js_to_rust(files: js_sys::Array) -> Vec<String> { | ||||
|     // https://github.com/rustwasm/wasm-bindgen/issues/111
 | ||||
|     files.iter().map(|f| f.as_string().unwrap()).collect() | ||||
| } | ||||
| 
 | ||||
| pub fn join_gpx_files(files: Vec<String>) -> gpx::Gpx { | ||||
|     let mut merged_gpx: gpx::Gpx = Default::default(); | ||||
|     let mut merged_track: gpx::Track = gpx::Track::new(); | ||||
| 
 | ||||
|     for file in files.iter() { | ||||
|         let buffer = std::io::BufReader::new(file.as_bytes()); | ||||
|         let mut parsed_gpx: gpx::Gpx = gpx::read(buffer).expect("invalid gpx"); | ||||
| 
 | ||||
|         // consolidate all track segements into one single track.
 | ||||
|         for track in parsed_gpx.tracks { | ||||
|             for segment in track.segments { | ||||
|                 merged_track.segments.push(segment); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         merged_gpx.waypoints.append(&mut parsed_gpx.waypoints); | ||||
|     } | ||||
| 
 | ||||
|     merged_gpx.tracks.push(merged_track); | ||||
| 
 | ||||
|     let link = gpx::Link { | ||||
|         href: String::from("https://gpx.thermokar.st"), | ||||
|         ..Default::default() | ||||
|     }; | ||||
|     let author = gpx::Person { | ||||
|         link: Some(link), | ||||
|         ..Default::default() | ||||
|     }; | ||||
|     let metadata = gpx::Metadata { | ||||
|         name: Some(String::from("merged")), | ||||
|         author: Some(author), | ||||
|         ..Default::default() | ||||
|     }; | ||||
|     merged_gpx.metadata = Some(metadata); | ||||
|     merged_gpx.version = gpx::GpxVersion::Gpx11; | ||||
| 
 | ||||
|     merged_gpx | ||||
| } | ||||
| 
 | ||||
| pub fn write_gpx_to_buffer(gpx: gpx::Gpx) -> Vec<u8> { | ||||
|     let mut buffer = Vec::new(); | ||||
|     gpx::write(&gpx, &mut buffer).unwrap(); | ||||
| 
 | ||||
|     buffer | ||||
| } | ||||
							
								
								
									
										93
									
								
								tests/web.rs
									
										
									
									
									
								
							
							
						
						
									
										93
									
								
								tests/web.rs
									
										
									
									
									
								
							|  | @ -1,93 +0,0 @@ | |||
| //! Test suite for the Web and headless browsers.
 | ||||
| 
 | ||||
| #![cfg(target_arch = "wasm32")] | ||||
| 
 | ||||
| extern crate wasm_bindgen_test; | ||||
| use wasm_bindgen_test::*; | ||||
| 
 | ||||
| wasm_bindgen_test_configure!(run_in_browser); | ||||
| 
 | ||||
| #[wasm_bindgen_test] | ||||
| fn basic_merge() { | ||||
|     // arrange
 | ||||
|     let array: js_sys::Array = js_sys::Array::new(); | ||||
|     let file1 = wasm_bindgen::JsValue::from_str( | ||||
|         "<?xml version='1.0' encoding='utf-8'?>
 | ||||
|          <gpx version='1.0' encoding='UTF-8'> | ||||
|            <trk> | ||||
|              <name>file1 tracks</name> | ||||
|              <type>1</type> | ||||
|              <trkseg> | ||||
|                <trkpt lat='35.466388' lon='-111.640076'> | ||||
|                  <ele>2152.8</ele> | ||||
|                  <time>2020-09-27T15:39:27+00:00</time> | ||||
|                </trkpt> | ||||
|              </trkseg> | ||||
|            </trk> | ||||
|          </gpx>",
 | ||||
|     ); | ||||
|     let file2 = wasm_bindgen::JsValue::from_str( | ||||
|         "<?xml version='1.0' encoding='utf-8'?>
 | ||||
|          <gpx version='1.0' encoding='UTF-8'> | ||||
|            <trk> | ||||
|              <name>file2 tracks</name> | ||||
|              <type>1</type> | ||||
|              <trkseg> | ||||
|                <trkpt lat='35.339854' lon='-111.737165'> | ||||
|                  <ele>2556.8</ele> | ||||
|                  <time>2020-09-26T19:07:14+00:00</time> | ||||
|                </trkpt> | ||||
|              </trkseg> | ||||
|            </trk> | ||||
|          </gpx>",
 | ||||
|     ); | ||||
|     array.push(&file1); | ||||
|     array.push(&file2); | ||||
| 
 | ||||
|     let exp = wasm_bindgen::JsValue::from_str( | ||||
|         "<?xml version=\"1.0\" encoding=\"utf-8\"?>
 | ||||
| <gpx version=\"1.1\" creator=\"https://github.com/georust/gpx\">
 | ||||
|   <metadata> | ||||
|     <name>merged</name> | ||||
|     <author> | ||||
|       <link href=\"https://gpx.thermokar.st\" />
 | ||||
|     </author> | ||||
|   </metadata> | ||||
|   <trk> | ||||
|     <name>file1 tracks</name> | ||||
|     <type>1</type> | ||||
|     <trkseg> | ||||
|       <trkpt lat=\"35.466388\" lon=\"-111.640076\">
 | ||||
|         <ele>2152.8</ele> | ||||
|         <time>2020-09-27T15:39:27+00:00</time> | ||||
|       </trkpt> | ||||
|     </trkseg> | ||||
|   </trk> | ||||
|   <trk> | ||||
|     <name>file2 tracks</name> | ||||
|     <type>1</type> | ||||
|     <trkseg> | ||||
|       <trkpt lat=\"35.339854\" lon=\"-111.737165\">
 | ||||
|         <ele>2556.8</ele> | ||||
|         <time>2020-09-26T19:07:14+00:00</time> | ||||
|       </trkpt> | ||||
|     </trkseg> | ||||
|   </trk> | ||||
|   <rte /> | ||||
| </gpx>",
 | ||||
|     ); | ||||
| 
 | ||||
|     // act
 | ||||
|     let obs = gpx_web_utils::merge(array); | ||||
| 
 | ||||
|     // assert
 | ||||
|     assert_eq!(obs, exp); | ||||
| } | ||||
| 
 | ||||
| // TODO: https://github.com/rustwasm/wasm-bindgen/issues/2286
 | ||||
| // #[wasm_bindgen_test]
 | ||||
| // #[should_panic]
 | ||||
| // fn invalid_inputs() {
 | ||||
| //     let array: js_sys::Array = js_sys::Array::new_with_length(10);
 | ||||
| //     let obs = gpx_web_utils::merge(array);
 | ||||
| // }
 | ||||
							
								
								
									
										2
									
								
								www/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								www/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,2 +0,0 @@ | |||
| node_modules | ||||
| dist | ||||
							
								
								
									
										5
									
								
								www/bootstrap.js
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								www/bootstrap.js
									
										
									
									
										vendored
									
									
								
							|  | @ -1,5 +0,0 @@ | |||
| // A dependency graph that contains any wasm must all be imported
 | ||||
| // asynchronously. This `bootstrap.js` file does the single async import, so
 | ||||
| // that no one else needs to worry about it again.
 | ||||
| import("./index.js") | ||||
|   .catch(e => console.error("Error importing `index.js`:", e)); | ||||
|  | @ -1,46 +0,0 @@ | |||
| <!DOCTYPE html> | ||||
| <html> | ||||
|   <head> | ||||
|     <meta charset="utf-8"> | ||||
|     <title>gpx.thermokar.st</title> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
|     <style> | ||||
|       body { | ||||
|         max-width: 35em; | ||||
|         margin: 0 auto; | ||||
|         line-height: 1.5; | ||||
|         font-family: sans-serif; | ||||
|         font-size: large; | ||||
|       } | ||||
|     </style> | ||||
|   </head> | ||||
|   <body> | ||||
|     <h1> | ||||
|       <a href="https://gpx.thermokar.st">gpx.thermokar.st</a> | ||||
|     </h1> | ||||
|     <noscript> | ||||
|       <mark> | ||||
|         This page contains webassembly and javascript content, please enable | ||||
|         javascript in your browser. | ||||
|       </mark> | ||||
|     </noscript> | ||||
|     <p> | ||||
|       This client-side tool is for merging | ||||
|       <a href="https://www.topografix.com/gpx.asp">GPX files</a>. | ||||
|       Please note, this has only been tested on GPX files produced by | ||||
|       <a href="https://www.garmin.com">Garmin</a> and | ||||
|       <a href="https://www.strava.com">Strava</a> - your mileage may vary. | ||||
|     </p> | ||||
|     <form> | ||||
|       <input id="gpxInput" type="file" multiple accept="text/gpx,.gpx"> | ||||
|     </form> | ||||
|     <hr> | ||||
|     <p> | ||||
|       <small> | ||||
|          <a href="https://github.com/thermokarst/gpx-web-utils"> | ||||
|           https://github.com/thermokarst/gpx-web-utils</a> | ||||
|       </small> | ||||
|     </p> | ||||
|     <script src="./bootstrap.js"></script> | ||||
|   </body> | ||||
| </html> | ||||
							
								
								
									
										37
									
								
								www/index.js
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								www/index.js
									
										
									
									
									
								
							|  | @ -1,37 +0,0 @@ | |||
| import * as gpx from "gpx-web-utils"; | ||||
| 
 | ||||
| const inputElement = document.getElementById("gpxInput"); | ||||
| const loadingElement = document.createElement("span"); | ||||
| 
 | ||||
| loadingElement.innerHTML = "<strong>processing...</strong>"; | ||||
| inputElement.value = ""; | ||||
| inputElement.addEventListener("change", readFiles, false); | ||||
| 
 | ||||
| function readFiles() { | ||||
|   if (inputElement.files.length < 2) { alert("open two or more files"); return; } | ||||
| 
 | ||||
|   inputElement.replaceWith(loadingElement); | ||||
|   const files = Array.from(inputElement.files); | ||||
|   const promises = files.map(f => f.text()); | ||||
| 
 | ||||
|   Promise.all(promises).then(gpxes => { | ||||
|     try { | ||||
|       const merged = gpx.merge(gpxes); | ||||
|       writeOutput(merged); | ||||
|     } catch { | ||||
|       alert("there was a problem, please check the console."); | ||||
|     } finally { | ||||
|       inputElement.value = ""; | ||||
|       loadingElement.replaceWith(inputElement); | ||||
|     } | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| function writeOutput(file) { | ||||
|     const blob = new Blob([file], {type: "text/gpx"}); | ||||
|     const anchorElement = document.createElement("a"); | ||||
|     anchorElement.href = URL.createObjectURL(blob); | ||||
|     anchorElement.download = "merged.gpx"; | ||||
|     anchorElement.click(); | ||||
|     URL.revokeObjectURL(anchorElement.href); | ||||
| } | ||||
							
								
								
									
										5842
									
								
								www/package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										5842
									
								
								www/package-lock.json
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,35 +0,0 @@ | |||
| { | ||||
|   "name": "gpx-web-utils", | ||||
|   "version": "0.0.1", | ||||
|   "description": "just some gpx-related tools that i want to use.", | ||||
|   "main": "index.js", | ||||
|   "scripts": { | ||||
|     "build": "webpack --config webpack.config.js", | ||||
|     "start": "webpack-dev-server" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
|     "url": "git+https://github.com/thermokarst/gpx-web-utils.git" | ||||
|   }, | ||||
|   "keywords": [ | ||||
|     "webassembly", | ||||
|     "wasm", | ||||
|     "rust", | ||||
|     "webpack" | ||||
|   ], | ||||
|   "author": "Matthew Ryan Dillon <matthewrdillon@gmail.com>", | ||||
|   "license": "MIT", | ||||
|   "bugs": { | ||||
|     "url": "https://github.com/thermokarst/gpx-web-utils/issues" | ||||
|   }, | ||||
|   "homepage": "https://github.com/thermokarst/gpx-web-util#readme", | ||||
|   "dependencies": { | ||||
|     "gpx-web-utils": "file:../pkg" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "webpack": "^4.29.3", | ||||
|     "webpack-cli": "^3.1.0", | ||||
|     "webpack-dev-server": "^3.1.5", | ||||
|     "copy-webpack-plugin": "^5.0.0" | ||||
|   } | ||||
| } | ||||
|  | @ -1,14 +0,0 @@ | |||
| const CopyWebpackPlugin = require("copy-webpack-plugin"); | ||||
| const path = require('path'); | ||||
| 
 | ||||
| module.exports = { | ||||
|   entry: "./bootstrap.js", | ||||
|   output: { | ||||
|     path: path.resolve(__dirname, "dist"), | ||||
|     filename: "bootstrap.js", | ||||
|   }, | ||||
|   mode: "development", | ||||
|   plugins: [ | ||||
|     new CopyWebpackPlugin(['index.html']) | ||||
|   ], | ||||
| }; | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue