diff --git a/.github/ISSUE_TEMPLATE/2-bug-report.yml b/.github/ISSUE_TEMPLATE/2-bug-report.yml new file mode 100644 index 0000000..fed15ae --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2-bug-report.yml @@ -0,0 +1,42 @@ +name: πŸ› Bug Report +description: Report an issue that should be fixed +labels: [bug] +body: + - type: markdown + attributes: + value: | + Thank you for submitting a bug report. It helps make meso better. + + Make sure you are running the latest version of meso. + The bug you are experiencing may already have been fixed. + + Please try to include as much information as possible. + + - type: input + attributes: + label: What version of meso is running? + description: Check the version in your Cargo.toml + - type: input + attributes: + label: What platform is your computer? + description: | + For MacOS and Linux: copy the output of `uname -mprs` + For Windows: copy the output of `"$([Environment]::OSVersion | ForEach-Object VersionString) $(if ([Environment]::Is64BitOperatingSystem) { "x64" } else { "x86" })"` in the PowerShell console + - type: textarea + attributes: + label: What steps can reproduce the bug? + description: Explain the bug and provide a code snippet that can reproduce it. + validations: + required: true + - type: textarea + attributes: + label: What is the expected behavior? + description: If possible, please provide text instead of a screenshot. + - type: textarea + attributes: + label: What do you see instead? + description: If possible, please provide text instead of a screenshot. + - type: textarea + attributes: + label: Additional information + description: Is there anything else you think we should know? diff --git a/.github/ISSUE_TEMPLATE/3-feature-request.yml b/.github/ISSUE_TEMPLATE/3-feature-request.yml new file mode 100644 index 0000000..9f2cf78 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3-feature-request.yml @@ -0,0 +1,21 @@ +name: πŸš€ Feature Request +description: Suggest an idea, feature, or enhancement +labels: [enhancement] +body: + - type: markdown + attributes: + value: | + Thank you for submitting an idea. It helps make meso better. + - type: textarea + attributes: + label: What is the problem this feature would solve? + validations: + required: true + - type: textarea + attributes: + label: What is the feature you are proposing to solve the problem? + validations: + required: true + - type: textarea + attributes: + label: What alternatives have you considered? diff --git a/.github/ISSUE_TEMPLATE/4-docs-issue.yml b/.github/ISSUE_TEMPLATE/4-docs-issue.yml new file mode 100644 index 0000000..ffcfb5d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/4-docs-issue.yml @@ -0,0 +1,27 @@ +name: πŸ“— Documentation Issue +description: Tell us if there is missing or incorrect documentation +labels: [docs] +body: + - type: markdown + attributes: + value: | + Thank you for submitting a documentation request. It helps make meso better. + - type: dropdown + attributes: + label: What is the type of issue? + multiple: true + options: + - Documentation is missing + - Documentation is incorrect + - Documentation is confusing + - Example code is not working + - Something else + - type: textarea + attributes: + label: What is the issue? + validations: + required: true + - type: textarea + attributes: + label: Where did you find it? + description: If possible, please provide the URL(s) where you found this issue. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..0086358 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..e8d486a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "cargo" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..30b42b6 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,5 @@ +# What does this PR do? +- [ ] Documentation +- [ ] Code changes + +# How did you verify your code works? diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1e6614e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,101 @@ +name: CI + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - platform: macos-latest + args: "--target aarch64-apple-darwin" + rust_targets: "aarch64-apple-darwin" + label: "macos-arm64" + + - platform: macos-latest + args: "--target x86_64-apple-darwin" + rust_targets: "x86_64-apple-darwin" + label: "macos-intel" + + - platform: windows-latest + args: "" + rust_targets: "" + label: "windows-x64" + + - platform: ubuntu-22.04 + args: "" + rust_targets: "" + label: "linux-x64" + + - platform: ubuntu-24.04 + args: "" + rust_targets: "" + label: "linux-x64" + + runs-on: ${{ matrix.platform}} + + steps: + - uses: actions/checkout@v4 + + - name: install dependencies (ubuntu) + if: matrix.platform == 'ubuntu-22.04' || matrix.platform == 'ubuntu-24.04' + run: | + sudo apt-get update + sudo apt-get install -y \ + libasound2-dev \ + libwebkit2gtk-4.1-dev \ + libayatana-appindicator3-dev \ + libgtk-3-dev \ + librsvg2-dev \ + patchelf + + - name: install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.rust_targets }} + + - name: Install wasm target + trunk + run: | + rustup target add wasm32-unknown-unknown + cargo install --locked trunk + + - name: Rust cache + uses: swatinem/rust-cache@v2 + with: + workspaces: "./src-tauri -> target" + + - name: build (all targets) + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + clippy: + name: Clippy + runs-on: ubuntu-latest + permissions: write-all + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@clippy + - run: cargo install clippy-sarif sarif-fmt + - run: rustup component add --toolchain stable-x86_64-unknown-linux-gnu clippy + - run: cargo clippy + --all-features + --message-format=json + -- -Dclippy::all -Dclippy::pedantic | clippy-sarif | tee rust-clippy-results.sarif | sarif-fmt + continue-on-error: true + - uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: rust-clippy-results.sarif + wait-for-processing: true diff --git a/.github/workflows/gh-page-unstable.yml b/.github/workflows/gh-page-unstable.yml new file mode 100644 index 0000000..d4c2dff --- /dev/null +++ b/.github/workflows/gh-page-unstable.yml @@ -0,0 +1,30 @@ +name: Github Pages (Unstable) + +on: + workflow_dispatch: + push: + branches: + - main + +permissions: + contents: write + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup mdBook + uses: peaceiris/actions-mdbook@v2 + with: + mdbook-version: "latest" + + - run: mdbook build book + + - name: Publish book + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages-unstable + publish_dir: ./book/book diff --git a/.github/workflows/gh-page.yml b/.github/workflows/gh-page.yml new file mode 100644 index 0000000..248585d --- /dev/null +++ b/.github/workflows/gh-page.yml @@ -0,0 +1,29 @@ +name: Github Pages + +on: + workflow_dispatch: + push: + tags: + - "*" + +permissions: + contents: write + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup mdBook + uses: peaceiris/actions-mdbook@v2 + with: + mdbook-version: "latest" + + - run: mdbook build book + + - name: Publish book + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./book/book diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..03df131 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,77 @@ +name: Release + +on: + release: + types: [published] + +permissions: + contents: write + +env: + RUSTFLAGS: -Dwarnings + +jobs: + publish: + strategy: + fail-fast: false + matrix: + include: + - platform: macos-latest + rust_targets: "aarch64-apple-darwin" + args: "--target aarch64-apple-darwin" + + - platform: macos-latest + rust_targets: "x86_64-apple-darwin" + args: "--target x86_64-apple-darwin" + + - platform: windows-latest + rust_targets: "" + args: "" + + - platform: ubuntu-22.04 + rust_targets: "" + args: "" + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v4 + + - name: Install Linux dependencies + if: matrix.platform == 'ubuntu-22.04' + run: | + sudo apt-get update + sudo apt-get install -y \ + libasound2-dev \ + libwebkit2gtk-4.1-dev \ + libayatana-appindicator3-dev \ + libgtk-3-dev \ + librsvg2-dev \ + patchelf + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.rust_targets }} + + - name: Install wasm target + trunk + run: | + rustup target add wasm32-unknown-unknown + cargo install --locked trunk + + - name: Cache Rust + uses: swatinem/rust-cache@v2 + with: + workspaces: "./src-tauri -> target" + + - name: Build & Upload Release Assets + uses: tauri-apps/tauri-action@v0 + with: + tagName: ${{ github.event.release.tag_name }} + releaseName: ${{ github.event.release.name }} + releaseBody: ${{ github.event.release.body }} + releaseDraft: false + prerelease: ${{ github.event.release.prerelease }} + args: ${{ matrix.args }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/book/.gitignore b/book/.gitignore new file mode 100644 index 0000000..7585238 --- /dev/null +++ b/book/.gitignore @@ -0,0 +1 @@ +book diff --git a/book/book.toml b/book/book.toml new file mode 100644 index 0000000..92ead91 --- /dev/null +++ b/book/book.toml @@ -0,0 +1,11 @@ +[book] +authors = ["Cameron Howell"] +language = "en" +src = "src" + +[output.html] +default-theme = "mocha" +preferred-dark-theme = "mocha" +git-repository-url = "https://github.com/crhowell3/meso" +edit-url-template = "https://github.com/crhowell3/meso/edit/main/book/{path}" +additional-css = ["./theme/catppuccin.css"] diff --git a/book/src/README.md b/book/src/README.md new file mode 100644 index 0000000..6d706b9 --- /dev/null +++ b/book/src/README.md @@ -0,0 +1,9 @@ +# meso + +**meso** is an open-source graphical desktop weather dashboard for viewing NWS/SPC +products for a given location. + +## Contributing + +Meso is free and open source. You can find the source code as well as +report issues and create feature requests on [GitHub](https://github.com/crhowell3/meso). diff --git a/book/theme/catppuccin.css b/book/theme/catppuccin.css new file mode 100644 index 0000000..a66b452 --- /dev/null +++ b/book/theme/catppuccin.css @@ -0,0 +1,844 @@ +/* https://highlightjs.readthedocs.io/en/latest/css-classes-reference.html */ +.latte.hljs { + color: #4c4f69; + background: #eff1f5; +} +.latte .hljs-keyword { + color: #8839ef; +} +.latte .hljs-built_in { + color: #d20f39; +} +.latte .hljs-type { + color: #df8e1d; +} +.latte .hljs-literal { + color: #fe640b; +} +.latte .hljs-number { + color: #fe640b; +} +.latte .hljs-operator { + color: #04a5e5; +} +.latte .hljs-punctuation { + color: #5c5f77; +} +.latte .hljs-property { + color: #179299; +} +.latte .hljs-regexp { + color: #ea76cb; +} +.latte .hljs-string { + color: #40a02b; +} +.latte .hljs-char.escape_ { + color: #40a02b; +} +.latte .hljs-subst { + color: #6c6f85; +} +.latte .hljs-symbol { + color: #dd7878; +} +.latte .hljs-variable { + color: #8839ef; +} +.latte .hljs-variable.language_ { + color: #8839ef; +} +.latte .hljs-variable.constant_ { + color: #fe640b; +} +.latte .hljs-title { + color: #1e66f5; +} +.latte .hljs-title.class_ { + color: #df8e1d; +} +.latte .hljs-title.function_ { + color: #1e66f5; +} +.latte .hljs-params { + color: #4c4f69; +} +.latte .hljs-comment { + color: #7c7f93; +} +.latte .hljs-doctag { + color: #d20f39; +} +.latte .hljs-meta { + color: #fe640b; +} +.latte .hljs-section { + color: #1e66f5; +} +.latte .hljs-tag { + color: #179299; +} +.latte .hljs-name { + color: #8839ef; +} +.latte .hljs-attr { + color: #1e66f5; +} +.latte .hljs-attribute { + color: #40a02b; +} +.latte .hljs-bullet { + color: #179299; +} +.latte .hljs-code { + color: #40a02b; +} +.latte .hljs-emphasis { + color: #d20f39; + font-style: italic; +} +.latte .hljs-strong { + color: #d20f39; + font-weight: bold; +} +.latte .hljs-formula { + color: #179299; +} +.latte .hljs-link { + color: #209fb5; + font-style: italic; +} +.latte .hljs-quote { + color: #40a02b; + font-style: italic; +} +.latte .hljs-selector-tag { + color: #df8e1d; +} +.latte .hljs-selector-id { + color: #1e66f5; +} +.latte .hljs-selector-class { + color: #179299; +} +.latte .hljs-selector-attr { + color: #8839ef; +} +.latte .hljs-selector-pseudo { + color: #179299; +} +.latte .hljs-template-tag { + color: #dd7878; +} +.latte .hljs-template-variable { + color: #dd7878; +} +.latte .hljs-addition { + color: #40a02b; + background: rgba(64, 160, 43, 0.15); +} +.latte .hljs-deletion { + color: #d20f39; + background: rgba(210, 15, 57, 0.15); +} +.latte :is(h1, h2, h3, h4, h5, h6) a code { + color: #4c4f69; +} +.latte a code { + color: #1e66f5; +} +.latte code { + color: #4c4f69; + background: #e6e9ef; +} +.latte blockquote blockquote { + border-top: 0.1em solid #acb0be; + border-bottom: 0.1em solid #acb0be; +} +.latte hr { + border-color: #acb0be; + border-style: solid; +} +.latte del { + color: #7c7f93; +} +.latte .ace_gutter { + color: #8c8fa1; + background: #e6e9ef; +} +.latte .ace_gutter-active-line.ace_gutter-cell { + color: #ea76cb; + background: #e6e9ef; +} +.latte .tooltiptext { + background: #e6e9ef; + color: #4c4f69; +} + +.frappe.hljs { + color: #c6d0f5; + background: #303446; +} +.frappe .hljs-keyword { + color: #ca9ee6; +} +.frappe .hljs-built_in { + color: #e78284; +} +.frappe .hljs-type { + color: #e5c890; +} +.frappe .hljs-literal { + color: #ef9f76; +} +.frappe .hljs-number { + color: #ef9f76; +} +.frappe .hljs-operator { + color: #99d1db; +} +.frappe .hljs-punctuation { + color: #b5bfe2; +} +.frappe .hljs-property { + color: #81c8be; +} +.frappe .hljs-regexp { + color: #f4b8e4; +} +.frappe .hljs-string { + color: #a6d189; +} +.frappe .hljs-char.escape_ { + color: #a6d189; +} +.frappe .hljs-subst { + color: #a5adce; +} +.frappe .hljs-symbol { + color: #eebebe; +} +.frappe .hljs-variable { + color: #ca9ee6; +} +.frappe .hljs-variable.language_ { + color: #ca9ee6; +} +.frappe .hljs-variable.constant_ { + color: #ef9f76; +} +.frappe .hljs-title { + color: #8caaee; +} +.frappe .hljs-title.class_ { + color: #e5c890; +} +.frappe .hljs-title.function_ { + color: #8caaee; +} +.frappe .hljs-params { + color: #c6d0f5; +} +.frappe .hljs-comment { + color: #949cbb; +} +.frappe .hljs-doctag { + color: #e78284; +} +.frappe .hljs-meta { + color: #ef9f76; +} +.frappe .hljs-section { + color: #8caaee; +} +.frappe .hljs-tag { + color: #81c8be; +} +.frappe .hljs-name { + color: #ca9ee6; +} +.frappe .hljs-attr { + color: #8caaee; +} +.frappe .hljs-attribute { + color: #a6d189; +} +.frappe .hljs-bullet { + color: #81c8be; +} +.frappe .hljs-code { + color: #a6d189; +} +.frappe .hljs-emphasis { + color: #e78284; + font-style: italic; +} +.frappe .hljs-strong { + color: #e78284; + font-weight: bold; +} +.frappe .hljs-formula { + color: #81c8be; +} +.frappe .hljs-link { + color: #85c1dc; + font-style: italic; +} +.frappe .hljs-quote { + color: #a6d189; + font-style: italic; +} +.frappe .hljs-selector-tag { + color: #e5c890; +} +.frappe .hljs-selector-id { + color: #8caaee; +} +.frappe .hljs-selector-class { + color: #81c8be; +} +.frappe .hljs-selector-attr { + color: #ca9ee6; +} +.frappe .hljs-selector-pseudo { + color: #81c8be; +} +.frappe .hljs-template-tag { + color: #eebebe; +} +.frappe .hljs-template-variable { + color: #eebebe; +} +.frappe .hljs-addition { + color: #a6d189; + background: rgba(166, 209, 137, 0.15); +} +.frappe .hljs-deletion { + color: #e78284; + background: rgba(231, 130, 132, 0.15); +} +.frappe :is(h1, h2, h3, h4, h5, h6) a code { + color: #c6d0f5; +} +.frappe a code { + color: #8caaee; +} +.frappe code { + color: #c6d0f5; + background: #292c3c; +} +.frappe blockquote blockquote { + border-top: 0.1em solid #626880; + border-bottom: 0.1em solid #626880; +} +.frappe hr { + border-color: #626880; + border-style: solid; +} +.frappe del { + color: #949cbb; +} +.frappe .ace_gutter { + color: #838ba7; + background: #292c3c; +} +.frappe .ace_gutter-active-line.ace_gutter-cell { + color: #f4b8e4; + background: #292c3c; +} +.frappe .tooltiptext { + background: #292c3c; + color: #c6d0f5; +} + +.macchiato.hljs { + color: #cad3f5; + background: #24273a; +} +.macchiato .hljs-keyword { + color: #c6a0f6; +} +.macchiato .hljs-built_in { + color: #ed8796; +} +.macchiato .hljs-type { + color: #eed49f; +} +.macchiato .hljs-literal { + color: #f5a97f; +} +.macchiato .hljs-number { + color: #f5a97f; +} +.macchiato .hljs-operator { + color: #91d7e3; +} +.macchiato .hljs-punctuation { + color: #b8c0e0; +} +.macchiato .hljs-property { + color: #8bd5ca; +} +.macchiato .hljs-regexp { + color: #f5bde6; +} +.macchiato .hljs-string { + color: #a6da95; +} +.macchiato .hljs-char.escape_ { + color: #a6da95; +} +.macchiato .hljs-subst { + color: #a5adcb; +} +.macchiato .hljs-symbol { + color: #f0c6c6; +} +.macchiato .hljs-variable { + color: #c6a0f6; +} +.macchiato .hljs-variable.language_ { + color: #c6a0f6; +} +.macchiato .hljs-variable.constant_ { + color: #f5a97f; +} +.macchiato .hljs-title { + color: #8aadf4; +} +.macchiato .hljs-title.class_ { + color: #eed49f; +} +.macchiato .hljs-title.function_ { + color: #8aadf4; +} +.macchiato .hljs-params { + color: #cad3f5; +} +.macchiato .hljs-comment { + color: #939ab7; +} +.macchiato .hljs-doctag { + color: #ed8796; +} +.macchiato .hljs-meta { + color: #f5a97f; +} +.macchiato .hljs-section { + color: #8aadf4; +} +.macchiato .hljs-tag { + color: #8bd5ca; +} +.macchiato .hljs-name { + color: #c6a0f6; +} +.macchiato .hljs-attr { + color: #8aadf4; +} +.macchiato .hljs-attribute { + color: #a6da95; +} +.macchiato .hljs-bullet { + color: #8bd5ca; +} +.macchiato .hljs-code { + color: #a6da95; +} +.macchiato .hljs-emphasis { + color: #ed8796; + font-style: italic; +} +.macchiato .hljs-strong { + color: #ed8796; + font-weight: bold; +} +.macchiato .hljs-formula { + color: #8bd5ca; +} +.macchiato .hljs-link { + color: #7dc4e4; + font-style: italic; +} +.macchiato .hljs-quote { + color: #a6da95; + font-style: italic; +} +.macchiato .hljs-selector-tag { + color: #eed49f; +} +.macchiato .hljs-selector-id { + color: #8aadf4; +} +.macchiato .hljs-selector-class { + color: #8bd5ca; +} +.macchiato .hljs-selector-attr { + color: #c6a0f6; +} +.macchiato .hljs-selector-pseudo { + color: #8bd5ca; +} +.macchiato .hljs-template-tag { + color: #f0c6c6; +} +.macchiato .hljs-template-variable { + color: #f0c6c6; +} +.macchiato .hljs-addition { + color: #a6da95; + background: rgba(166, 218, 149, 0.15); +} +.macchiato .hljs-deletion { + color: #ed8796; + background: rgba(237, 135, 150, 0.15); +} +.macchiato :is(h1, h2, h3, h4, h5, h6) a code { + color: #cad3f5; +} +.macchiato a code { + color: #8aadf4; +} +.macchiato code { + color: #cad3f5; + background: #1e2030; +} +.macchiato blockquote blockquote { + border-top: 0.1em solid #5b6078; + border-bottom: 0.1em solid #5b6078; +} +.macchiato hr { + border-color: #5b6078; + border-style: solid; +} +.macchiato del { + color: #939ab7; +} +.macchiato .ace_gutter { + color: #8087a2; + background: #1e2030; +} +.macchiato .ace_gutter-active-line.ace_gutter-cell { + color: #f5bde6; + background: #1e2030; +} +.macchiato .tooltiptext { + background: #1e2030; + color: #cad3f5; +} + +.mocha.hljs { + color: #cdd6f4; + background: #1e1e2e; +} +.mocha .hljs-keyword { + color: #cba6f7; +} +.mocha .hljs-built_in { + color: #f38ba8; +} +.mocha .hljs-type { + color: #f9e2af; +} +.mocha .hljs-literal { + color: #fab387; +} +.mocha .hljs-number { + color: #fab387; +} +.mocha .hljs-operator { + color: #89dceb; +} +.mocha .hljs-punctuation { + color: #bac2de; +} +.mocha .hljs-property { + color: #94e2d5; +} +.mocha .hljs-regexp { + color: #f5c2e7; +} +.mocha .hljs-string { + color: #a6e3a1; +} +.mocha .hljs-char.escape_ { + color: #a6e3a1; +} +.mocha .hljs-subst { + color: #a6adc8; +} +.mocha .hljs-symbol { + color: #f2cdcd; +} +.mocha .hljs-variable { + color: #cba6f7; +} +.mocha .hljs-variable.language_ { + color: #cba6f7; +} +.mocha .hljs-variable.constant_ { + color: #fab387; +} +.mocha .hljs-title { + color: #89b4fa; +} +.mocha .hljs-title.class_ { + color: #f9e2af; +} +.mocha .hljs-title.function_ { + color: #89b4fa; +} +.mocha .hljs-params { + color: #cdd6f4; +} +.mocha .hljs-comment { + color: #9399b2; +} +.mocha .hljs-doctag { + color: #f38ba8; +} +.mocha .hljs-meta { + color: #fab387; +} +.mocha .hljs-section { + color: #89b4fa; +} +.mocha .hljs-tag { + color: #94e2d5; +} +.mocha .hljs-name { + color: #cba6f7; +} +.mocha .hljs-attr { + color: #89b4fa; +} +.mocha .hljs-attribute { + color: #a6e3a1; +} +.mocha .hljs-bullet { + color: #94e2d5; +} +.mocha .hljs-code { + color: #a6e3a1; +} +.mocha .hljs-emphasis { + color: #f38ba8; + font-style: italic; +} +.mocha .hljs-strong { + color: #f38ba8; + font-weight: bold; +} +.mocha .hljs-formula { + color: #94e2d5; +} +.mocha .hljs-link { + color: #74c7ec; + font-style: italic; +} +.mocha .hljs-quote { + color: #a6e3a1; + font-style: italic; +} +.mocha .hljs-selector-tag { + color: #f9e2af; +} +.mocha .hljs-selector-id { + color: #89b4fa; +} +.mocha .hljs-selector-class { + color: #94e2d5; +} +.mocha .hljs-selector-attr { + color: #cba6f7; +} +.mocha .hljs-selector-pseudo { + color: #94e2d5; +} +.mocha .hljs-template-tag { + color: #f2cdcd; +} +.mocha .hljs-template-variable { + color: #f2cdcd; +} +.mocha .hljs-addition { + color: #a6e3a1; + background: rgba(166, 227, 161, 0.15); +} +.mocha .hljs-deletion { + color: #f38ba8; + background: rgba(243, 139, 168, 0.15); +} +.mocha :is(h1, h2, h3, h4, h5, h6) a code { + color: #cdd6f4; +} +.mocha a code { + color: #89b4fa; +} +.mocha code { + color: #cdd6f4; + background: #181825; +} +.mocha blockquote blockquote { + border-top: 0.1em solid #585b70; + border-bottom: 0.1em solid #585b70; +} +.mocha hr { + border-color: #585b70; + border-style: solid; +} +.mocha del { + color: #9399b2; +} +.mocha .ace_gutter { + color: #7f849c; + background: #181825; +} +.mocha .ace_gutter-active-line.ace_gutter-cell { + color: #f5c2e7; + background: #181825; +} +.mocha .tooltiptext { + background: #181825; + color: #cdd6f4; +} + +.latte { + --bg: #eff1f5; + --fg: #4c4f69; + --sidebar-bg: #e6e9ef; + --sidebar-fg: #4c4f69; + --sidebar-non-existant: #9ca0b0; + --sidebar-active: #1e66f5; + --sidebar-spacer: #9ca0b0; + --scrollbar: #9ca0b0; + --icons: #9ca0b0; + --icons-hover: #7c7f93; + --links: #1e66f5; + --inline-code-color: #fe640b; + --theme-popup-bg: #e6e9ef; + --theme-popup-border: #9ca0b0; + --theme-hover: #ccd0da; + --quote-bg: #e6e9ef; + --quote-border: #dce0e8; + --table-border-color: #ccd0da; + --table-header-bg: #e6e9ef; + --table-alternate-bg: #e6e9ef; + --searchbar-border-color: #ccd0da; + --searchbar-bg: #e6e9ef; + --searchbar-fg: #4c4f69; + --searchbar-shadow-color: #dce0e8; + --searchresults-header-fg: #4c4f69; + --searchresults-border-color: #ccd0da; + --searchresults-li-bg: #eff1f5; + --search-mark-bg: #fe640b; + --warning-border: #fe640b; + --color-scheme: light; + --copy-button-filter: brightness(0) saturate(100%) invert(47%) sepia(6%) saturate(1263%) hue-rotate(195deg) brightness(90%) contrast(81%); + --copy-button-filter-hover: brightness(0) saturate(100%) invert(30%) sepia(80%) saturate(1850%) hue-rotate(209deg) brightness(94%) contrast(105%); +} + +.frappe { + --bg: #303446; + --fg: #c6d0f5; + --sidebar-bg: #292c3c; + --sidebar-fg: #c6d0f5; + --sidebar-non-existant: #737994; + --sidebar-active: #8caaee; + --sidebar-spacer: #737994; + --scrollbar: #737994; + --icons: #737994; + --icons-hover: #949cbb; + --links: #8caaee; + --inline-code-color: #ef9f76; + --theme-popup-bg: #292c3c; + --theme-popup-border: #737994; + --theme-hover: #414559; + --quote-bg: #292c3c; + --quote-border: #232634; + --table-border-color: #414559; + --table-header-bg: #292c3c; + --table-alternate-bg: #292c3c; + --searchbar-border-color: #414559; + --searchbar-bg: #292c3c; + --searchbar-fg: #c6d0f5; + --searchbar-shadow-color: #232634; + --searchresults-header-fg: #c6d0f5; + --searchresults-border-color: #414559; + --searchresults-li-bg: #303446; + --search-mark-bg: #ef9f76; + --warning-border: #ef9f76; + --color-scheme: dark; + --copy-button-filter: brightness(0) saturate(100%) invert(82%) sepia(6%) saturate(1287%) hue-rotate(192deg) brightness(86%) contrast(85%); + --copy-button-filter-hover: brightness(0) saturate(100%) invert(68%) sepia(16%) saturate(1070%) hue-rotate(185deg) brightness(96%) contrast(95%); +} + +.macchiato { + --bg: #24273a; + --fg: #cad3f5; + --sidebar-bg: #1e2030; + --sidebar-fg: #cad3f5; + --sidebar-non-existant: #6e738d; + --sidebar-active: #8aadf4; + --sidebar-spacer: #6e738d; + --scrollbar: #6e738d; + --icons: #6e738d; + --icons-hover: #939ab7; + --links: #8aadf4; + --inline-code-color: #f5a97f; + --theme-popup-bg: #1e2030; + --theme-popup-border: #6e738d; + --theme-hover: #363a4f; + --quote-bg: #1e2030; + --quote-border: #181926; + --table-border-color: #363a4f; + --table-header-bg: #1e2030; + --table-alternate-bg: #1e2030; + --searchbar-border-color: #363a4f; + --searchbar-bg: #1e2030; + --searchbar-fg: #cad3f5; + --searchbar-shadow-color: #181926; + --searchresults-header-fg: #cad3f5; + --searchresults-border-color: #363a4f; + --searchresults-li-bg: #24273a; + --search-mark-bg: #f5a97f; + --warning-border: #f5a97f; + --color-scheme: dark; + --copy-button-filter: brightness(0) saturate(100%) invert(75%) sepia(18%) saturate(361%) hue-rotate(190deg) brightness(91%) contrast(86%); + --copy-button-filter-hover: brightness(0) saturate(100%) invert(67%) sepia(17%) saturate(1007%) hue-rotate(183deg) brightness(99%) contrast(94%); +} + +.mocha { + --bg: #1e1e2e; + --fg: #cdd6f4; + --sidebar-bg: #181825; + --sidebar-fg: #cdd6f4; + --sidebar-non-existant: #6c7086; + --sidebar-active: #89b4fa; + --sidebar-spacer: #6c7086; + --scrollbar: #6c7086; + --icons: #6c7086; + --icons-hover: #9399b2; + --links: #89b4fa; + --inline-code-color: #fab387; + --theme-popup-bg: #181825; + --theme-popup-border: #6c7086; + --theme-hover: #313244; + --quote-bg: #181825; + --quote-border: #11111b; + --table-border-color: #313244; + --table-header-bg: #181825; + --table-alternate-bg: #181825; + --searchbar-border-color: #313244; + --searchbar-bg: #181825; + --searchbar-fg: #cdd6f4; + --searchbar-shadow-color: #11111b; + --searchresults-header-fg: #cdd6f4; + --searchresults-border-color: #313244; + --searchresults-li-bg: #1e1e2e; + --search-mark-bg: #fab387; + --warning-border: #fab387; + --color-scheme: dark; + --copy-button-filter: brightness(0) saturate(100%) invert(84%) sepia(9%) saturate(767%) hue-rotate(192deg) brightness(84%) contrast(84%); + --copy-button-filter-hover: brightness(0) saturate(100%) invert(68%) sepia(18%) saturate(951%) hue-rotate(180deg) brightness(98%) contrast(100%); +} diff --git a/book/theme/index.hbs b/book/theme/index.hbs new file mode 100644 index 0000000..ecc9306 --- /dev/null +++ b/book/theme/index.hbs @@ -0,0 +1,366 @@ + + + + + + {{ title }} + {{#if is_print }} + + {{/if}} + {{#if base_url}} + + {{/if}} + + + + {{> head}} + + + + + + {{#if favicon_svg}} + + {{/if}} + {{#if favicon_png}} + + {{/if}} + + + + {{#if print_enable}} + + {{/if}} + + + + + + + + + + + {{#each additional_css}} + + {{/each}} + + {{#if mathjax_support}} + + + {{/if}} + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press ← or β†’ to navigate between chapters

+ {{#if search_enabled}} +

Press S or / to search in the book

+ {{/if}} +

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+ {{> header}} +
+ + + {{#if search_enabled}} + + {{/if}} + + + + + +
+ + + +
+ + + + + + + + {{#if live_reload_endpoint}} + + + {{/if}} + + {{#if playground_line_numbers}} + + {{/if}} + + {{#if playground_copyable}} + + {{/if}} + + {{#if playground_js}} + + + + + + {{/if}} + + {{#if search_js}} + + + + {{/if}} + + + + + + + {{#each additional_js}} + + {{/each}} + + {{#if is_print}} + {{#if mathjax_support}} + + {{else}} + + {{/if}} + {{/if}} + + {{#if fragment_map}} + + {{/if}} + +
+ + diff --git a/src/app.rs b/src/app.rs index 0bcb559..f87c0b1 100755 --- a/src/app.rs +++ b/src/app.rs @@ -1,8 +1,8 @@ -use serde::{Deserialize}; -use wasm_bindgen::prelude::*; -use yew::prelude::*; use gloo_net::http::Request; +use serde::Deserialize; use std::fmt; +use wasm_bindgen::prelude::*; +use yew::prelude::*; #[wasm_bindgen] extern "C" { @@ -10,7 +10,8 @@ extern "C" { async fn invoke(cmd: &str, args: JsValue) -> JsValue; } -const ARCGIS_BASE_URL: &str = "https://mapservices.weather.noaa.gov/vector/rest/services/outlooks/SPC_wx_outlks/MapServer/"; +const ARCGIS_BASE_URL: &str = + "https://mapservices.weather.noaa.gov/vector/rest/services/outlooks/SPC_wx_outlks/MapServer/"; // These will be removed in the future in favor of configurability // Currently hardcoded to Huntsville, AL @@ -25,6 +26,46 @@ enum MapServer { Day1Wind = 7, } +#[derive(Debug, PartialEq, Copy, Clone)] +enum Categories { + NoThunder = 0, + Thunderstorms = 2, + Marginal = 3, + Slight = 4, + Enhanced = 5, + Moderate = 6, + High = 7, +} + +impl Categories { + fn from_i32(value: i32) -> Option { + match value { + 0 => Some(Self::NoThunder), + 2 => Some(Self::Thunderstorms), + 3 => Some(Self::Marginal), + 4 => Some(Self::Slight), + 5 => Some(Self::Enhanced), + 6 => Some(Self::Moderate), + 7 => Some(Self::High), + _ => None, + } + } +} + +impl fmt::Display for Categories { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::NoThunder => write!(f, "none"), + Self::Thunderstorms => write!(f, "thunderstorms"), + Self::Marginal => write!(f, "marginal"), + Self::Slight => write!(f, "slight"), + Self::Enhanced => write!(f, "enhanced"), + Self::Moderate => write!(f, "moderate"), + Self::High => write!(f, "high"), + } + } +} + impl MapServer { fn get_common_name(&self) -> String { match self { @@ -74,8 +115,10 @@ struct Attributes { async fn fetch_risk(map_server: MapServer) -> Result { let dn = map_server.get_dn(); - let url = format!("{ARCGIS_BASE_URL}/{dn}/query?f=json&geometry={LONGITUDE},{LATITUDE}&geometryType=esriGeometryPoint\ - &inSR=4326&spatialRel=esriSpatialRelIntersects&outFields=*"); + let url = format!( + "{ARCGIS_BASE_URL}/{dn}/query?f=json&geometry={LONGITUDE},{LATITUDE}&geometryType=esriGeometryPoint\ + &inSR=4326&spatialRel=esriSpatialRelIntersects&outFields=*" + ); let response: ArcGisResponse = Request::get(&url) .send() @@ -143,7 +186,10 @@ fn GetRisk(MapServerProps { map_server }: &MapServerProps) -> Html { if *r == 0 { html! { {"NO THUNDER"} } } else { - let caps = r.to_string().to_uppercase(); + let category = Categories::from_i32(*r).unwrap_or(Categories::NoThunder); + let cat_name = category.to_string(); + let color = format!("categorical-{cat_name}"); + let caps = cat_name.to_uppercase(); html! { {format!("{caps}")} } } } else {