Compare commits
31 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
fc5498ef29 |
|||
|
1efe2d4859 |
|||
|
b3c210dc47 |
|||
| 3494ba71e6 | |||
| 3d7dbe5622 | |||
| f8708f2500 | |||
| 1aef9d6ee6 | |||
| 0987269307 | |||
| a38d93ba2a | |||
| 26ba5c90e6 | |||
| 4d7ae2e729 | |||
| 297030696e | |||
| 2a01b9ac4c | |||
| 83d7b7e7aa | |||
| 47f8530487 | |||
| e0a5eaaf2f | |||
| c2de0283fd | |||
| 8649169bae | |||
| 70bdba50c8 | |||
| 88fdd3084e | |||
| 1d801dce06 | |||
| ab9b587018 | |||
| 0d48291d5f | |||
| 8100b1ba10 | |||
| d0ca4e6cb3 | |||
| 29c2beb3ed | |||
| aab419a18a | |||
| c18b656125 | |||
| 5bfd23925b | |||
| d881f0bd58 | |||
| cad3213dad |
37 changed files with 1611 additions and 802 deletions
|
|
@ -3,3 +3,4 @@ allow-expect-in-tests = true
|
||||||
single-char-binding-names-threshold = 2
|
single-char-binding-names-threshold = 2
|
||||||
upper-case-acronyms-aggressive = true
|
upper-case-acronyms-aggressive = true
|
||||||
allow-indexing-slicing-in-tests = true
|
allow-indexing-slicing-in-tests = true
|
||||||
|
check-incompatible-msrv-in-tests = true
|
||||||
|
|
|
||||||
|
|
@ -2,44 +2,80 @@ on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- 'v*'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
upload:
|
||||||
|
description: 'Upload built assets to the git.jutty.dev package registry'
|
||||||
|
type: boolean
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
linux:
|
||||||
|
description: 'Build Linux binaries'
|
||||||
|
type: boolean
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
windows:
|
||||||
|
description: 'Build Windows binary'
|
||||||
|
type: boolean
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
if: ${{ inputs.linux }}
|
||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
container:
|
container:
|
||||||
image: rust:slim
|
image: rust:slim
|
||||||
steps:
|
steps:
|
||||||
- name: Install action dependencies
|
- name: Install action dependencies
|
||||||
run: |
|
run: apt-get install --no-install-recommends --update -y nodejs curl git
|
||||||
apt-get install --no-install-recommends --update -y nodejs curl git
|
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-tags: true
|
fetch-tags: true
|
||||||
|
|
||||||
- name: Setup Rust toolchain
|
- name: Set up Rust toolchain
|
||||||
run: |
|
run: |
|
||||||
rustup component add llvm-tools-preview
|
rustup component add llvm-tools
|
||||||
rustup component add --toolchain nightly rustfmt clippy
|
rustup component add --toolchain nightly rustfmt clippy
|
||||||
|
rustup target add x86_64-unknown-linux-gnu
|
||||||
rustup target add x86_64-unknown-linux-musl
|
rustup target add x86_64-unknown-linux-musl
|
||||||
|
|
||||||
- name: Setup additional tooling
|
- name: Set up additional tooling
|
||||||
run: .forgejo/workflows/setup-tools.sh
|
run: .forgejo/workflows/setup-tools.sh
|
||||||
|
|
||||||
|
- name: Set up CI user
|
||||||
|
run: |
|
||||||
|
useradd -m ci && chown -R ci:ci .
|
||||||
|
git config --global --add safe.directory "$PWD"
|
||||||
|
|
||||||
- name: Run all assessments
|
- name: Run all assessments
|
||||||
run: just verify
|
run: just ci verify
|
||||||
|
|
||||||
- name: Build x64 glibc release binary
|
- name: Build x64 Linux glibc release binary
|
||||||
run: just release-build x86_64-unknown-linux-gnu
|
run: just release-build-gnu
|
||||||
|
|
||||||
- name: Build x64 musl release binary
|
- name: Build x64 Linux musl release binary
|
||||||
run: just release-build x86_64-unknown-linux-musl
|
run: just release-build-musl
|
||||||
|
|
||||||
- name: Calculate SHA-256 hashes
|
- name: Calculate SHA-256 hashes
|
||||||
run: just shasum
|
run: just shasum
|
||||||
|
|
||||||
- name: Publish x64 glibc binary to git.jutty.dev registry
|
- name: Publish x64 Linux musl binary to git.jutty.dev registry
|
||||||
|
if: ${{ inputs.upload }}
|
||||||
|
run: |
|
||||||
|
version=$(./target/x86_64-unknown-linux-musl/release/en --version)
|
||||||
|
api_root=https://git.jutty.dev/api
|
||||||
|
url=$api_root/packages/jutty/generic/en/$version/en-x64-linux-musl
|
||||||
|
|
||||||
|
curl -fsSL \
|
||||||
|
--user jutty:${{ secrets.GJD_REGISTRY_TOKEN }} \
|
||||||
|
--upload-file target/x86_64-unknown-linux-musl/release/en $url
|
||||||
|
|
||||||
|
- name: Publish x64 Linux glibc binary to git.jutty.dev registry
|
||||||
|
if: ${{ inputs.upload }}
|
||||||
run: |
|
run: |
|
||||||
version=$(./target/x86_64-unknown-linux-gnu/release/en --version)
|
version=$(./target/x86_64-unknown-linux-gnu/release/en --version)
|
||||||
api_root=https://git.jutty.dev/api
|
api_root=https://git.jutty.dev/api
|
||||||
|
|
@ -49,12 +85,60 @@ jobs:
|
||||||
--user jutty:${{ secrets.GJD_REGISTRY_TOKEN }} \
|
--user jutty:${{ secrets.GJD_REGISTRY_TOKEN }} \
|
||||||
--upload-file target/x86_64-unknown-linux-gnu/release/en $url
|
--upload-file target/x86_64-unknown-linux-gnu/release/en $url
|
||||||
|
|
||||||
- name: Publish x64 musl binary to git.jutty.dev registry
|
publish-windows:
|
||||||
|
runs-on: docker
|
||||||
|
if: ${{ inputs.windows }}
|
||||||
|
timeout-minutes: 20
|
||||||
|
container:
|
||||||
|
image: messense/cargo-xwin
|
||||||
|
env:
|
||||||
|
XWIN_CACHE_DIR: /tmp
|
||||||
|
steps:
|
||||||
|
- name: Install action dependencies
|
||||||
|
run: apt-get install --no-install-recommends --update -y nodejs curl git
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-tags: true
|
||||||
|
|
||||||
|
- name: Set up Rust toolchain
|
||||||
run: |
|
run: |
|
||||||
version=$(./target/x86_64-unknown-linux-musl/release/en --version)
|
version=$(cat Cargo.toml | grep '^rust-version' | cut -d \" -f 2)
|
||||||
|
rustup set auto-self-update disable
|
||||||
|
rustup toolchain install "$version-x86_64-unknown-linux-gnu"
|
||||||
|
rustup default "$version-x86_64-unknown-linux-gnu"
|
||||||
|
rustup target add x86_64-pc-windows-msvc
|
||||||
|
|
||||||
|
- name: Set up additional tooling
|
||||||
|
run: .forgejo/workflows/setup-tools.sh
|
||||||
|
|
||||||
|
- name: Cache MSVC CRT and SDK
|
||||||
|
run: cargo-xwin cache xwin
|
||||||
|
|
||||||
|
- name: Set up CI user
|
||||||
|
run: |
|
||||||
|
useradd -m ci && chown -R ci:ci .
|
||||||
|
git config --global --add safe.directory "$PWD"
|
||||||
|
|
||||||
|
- name: Run Windows tests
|
||||||
|
run: just ci test-windows
|
||||||
|
|
||||||
|
- name: Build x64 Windows MSVC release binary
|
||||||
|
run: |
|
||||||
|
rm -v /usr/bin/clang
|
||||||
|
just release-build-msvc
|
||||||
|
|
||||||
|
- name: Calculate SHA-256 hashes
|
||||||
|
run: just shasum
|
||||||
|
|
||||||
|
- name: Publish x64 Windows MSVC binary to git.jutty.dev registry
|
||||||
|
if: ${{ inputs.upload }}
|
||||||
|
run: |
|
||||||
|
version=$(grep '^version' Cargo.toml | cut -d '"' -f 2)
|
||||||
api_root=https://git.jutty.dev/api
|
api_root=https://git.jutty.dev/api
|
||||||
url=$api_root/packages/jutty/generic/en/$version/en-x64-linux-musl
|
url=$api_root/packages/jutty/generic/en/$version/en-x64-windows-msvc
|
||||||
|
|
||||||
curl -fsSL \
|
curl -fsSL \
|
||||||
--user jutty:${{ secrets.GJD_REGISTRY_TOKEN }} \
|
--user jutty:${{ secrets.GJD_REGISTRY_TOKEN }} \
|
||||||
--upload-file target/x86_64-unknown-linux-musl/release/en $url
|
--upload-file target/x86_64-pc-windows-msvc/release/en.exe $url
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,38 @@
|
||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
JUST_VERSION="1.47.1"
|
TRIPLE="x86_64-unknown-linux-musl"
|
||||||
JUST_SHA256SUM="3cb931ae25860f261ee373f32ede3b772ac91f14f588e4071576d3ffcf1a16fd"
|
TRIPLE_GNU="x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
JUST_VERSION="1.51.0"
|
||||||
|
JUST_SHA256SUM="c8f085ca3e885723c341d06243fc291b5abfdc8bbe3b2c076b117de490387b59"
|
||||||
|
|
||||||
CARGO_LLVM_COV_VERSION="0.6.21"
|
CARGO_LLVM_COV_VERSION="0.6.21"
|
||||||
CARGO_LLVM_COV_SHA256SUM="57f491aedf7cdb261538ceb49cbb1ee9d27df7ca205a5e1a009caaf5cb911afb"
|
CARGO_LLVM_COV_SHA256SUM="57f491aedf7cdb261538ceb49cbb1ee9d27df7ca205a5e1a009caaf5cb911afb"
|
||||||
|
|
||||||
CARGO_AUDIT_VERSION="0.22.1"
|
CARGO_AUDIT_VERSION="0.22.1"
|
||||||
CARGO_AUDIT_TAG="cargo-audit%2Fv$CARGO_AUDIT_VERSION"
|
CARGO_AUDIT_TAG="cargo-audit%2Fv$CARGO_AUDIT_VERSION"
|
||||||
CARGO_AUDIT_SHA256SUM="1890badd5f15831a9af4b074399fcd21e6f7c0fe42c84e9254cdffc9f813765c"
|
CARGO_AUDIT_SHA256SUM="1890badd5f15831a9af4b074399fcd21e6f7c0fe42c84e9254cdffc9f813765c"
|
||||||
|
|
||||||
TRIPLE="x86_64-unknown-linux-gnu"
|
TAPLO_VERSION="0.10.0"
|
||||||
TRIPLE_MUSL="x86_64-unknown-linux-musl"
|
TAPLO_SHA256SUM="8fe196b894ccf9072f98d4e1013a180306e17d244830b03986ee5e8eabeb6156"
|
||||||
|
|
||||||
|
TYPOS_VERSION="1.47.2"
|
||||||
|
TYPOS_SHA256SUM="7aef58932fc123b4cf4b40d86468e89a3297d80169051d7cfd13a235e05fc426"
|
||||||
|
|
||||||
|
CARGO_DENY_VERSION="0.19.8"
|
||||||
|
CARGO_DENY_SHA256SUM="70e769ae3872e34d45132b17040859175e11401dc12dddb0303e0b8c7d088f3f"
|
||||||
|
|
||||||
|
CARGO_MSRV_VERSION="0.19.3"
|
||||||
|
CARGO_MSRV_SHA256SUM="6f9a0011ca8ad959d304185b9090390fd1ad87e2d764007fbb0abe043afa9ff5"
|
||||||
|
|
||||||
fetch() {
|
fetch() {
|
||||||
repo="$1"; tag="$2"; filename="$3"; digest="$4"; binary="$5"
|
repo="$1"
|
||||||
|
tag="$2"
|
||||||
|
filename="$3"
|
||||||
|
digest="$4"
|
||||||
|
binary="$5"
|
||||||
|
renamed_binary="${6:-$binary}"
|
||||||
|
|
||||||
[ -d /tmp/tools ] || mkdir -p /tmp/tools
|
[ -d /tmp/tools ] || mkdir -p /tmp/tools
|
||||||
|
|
||||||
|
|
@ -24,19 +43,45 @@ fetch() {
|
||||||
|
|
||||||
printf '%s %s\n' "$digest" "/tmp/$filename" > /tmp/digest
|
printf '%s %s\n' "$digest" "/tmp/$filename" > /tmp/digest
|
||||||
sha256sum --check /tmp/digest
|
sha256sum --check /tmp/digest
|
||||||
tar xf "/tmp/$filename" -C /tmp/tools
|
|
||||||
find /tmp/tools -type f -executable -name "$binary" \
|
if printf '%s' "$filename" | grep -qE '\.tar\.|\.tgz$'; then
|
||||||
-exec mv -v '{}' /usr/local/bin ';'
|
tar xf "/tmp/$filename" -C /tmp/tools
|
||||||
|
elif printf '%s' "$filename" | grep -q '\.gz$'; then
|
||||||
|
gunzip -c "/tmp/$filename" > "/tmp/tools/$binary"
|
||||||
|
else
|
||||||
|
echo "Fatal: can't determine how to unpack $filename"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
find /tmp/tools -type f -name "$binary" \
|
||||||
|
-exec mv -v '{}' "/usr/local/bin/$renamed_binary" ';'
|
||||||
|
chmod +x "/usr/local/bin/$renamed_binary"
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch casey/just "$JUST_VERSION" \
|
fetch casey/just "$JUST_VERSION" \
|
||||||
"just-$JUST_VERSION-$TRIPLE_MUSL.tar.gz" \
|
"just-$JUST_VERSION-$TRIPLE.tar.gz" \
|
||||||
"$JUST_SHA256SUM" just
|
"$JUST_SHA256SUM" just
|
||||||
|
|
||||||
fetch taiki-e/cargo-llvm-cov "v$CARGO_LLVM_COV_VERSION" \
|
fetch taiki-e/cargo-llvm-cov "v$CARGO_LLVM_COV_VERSION" \
|
||||||
"cargo-llvm-cov-$TRIPLE.tar.gz" \
|
"cargo-llvm-cov-$TRIPLE_GNU.tar.gz" \
|
||||||
"$CARGO_LLVM_COV_SHA256SUM" cargo-llvm-cov
|
"$CARGO_LLVM_COV_SHA256SUM" cargo-llvm-cov
|
||||||
|
|
||||||
fetch rustsec/rustsec "$CARGO_AUDIT_TAG" \
|
fetch rustsec/rustsec "$CARGO_AUDIT_TAG" \
|
||||||
"cargo-audit-$TRIPLE-v$CARGO_AUDIT_VERSION.tgz" \
|
"cargo-audit-$TRIPLE_GNU-v$CARGO_AUDIT_VERSION.tgz" \
|
||||||
"$CARGO_AUDIT_SHA256SUM" cargo-audit
|
"$CARGO_AUDIT_SHA256SUM" cargo-audit
|
||||||
|
|
||||||
|
fetch tamasfe/taplo "$TAPLO_VERSION" \
|
||||||
|
"taplo-linux-x86_64.gz" \
|
||||||
|
"$TAPLO_SHA256SUM" taplo-linux-x86_64 taplo
|
||||||
|
|
||||||
|
fetch crate-ci/typos "v$TYPOS_VERSION" \
|
||||||
|
"typos-v$TYPOS_VERSION-$TRIPLE.tar.gz" \
|
||||||
|
"$TYPOS_SHA256SUM" typos
|
||||||
|
|
||||||
|
fetch EmbarkStudios/cargo-deny "$CARGO_DENY_VERSION" \
|
||||||
|
"cargo-deny-$CARGO_DENY_VERSION-$TRIPLE.tar.gz" \
|
||||||
|
"$CARGO_DENY_SHA256SUM" cargo-deny
|
||||||
|
|
||||||
|
fetch foresterre/cargo-msrv "v$CARGO_MSRV_VERSION" \
|
||||||
|
"cargo-msrv-$TRIPLE_GNU-v$CARGO_MSRV_VERSION.tgz" \
|
||||||
|
"$CARGO_MSRV_SHA256SUM" cargo-msrv
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,13 @@ on:
|
||||||
- '*'
|
- '*'
|
||||||
paths:
|
paths:
|
||||||
- src/**
|
- src/**
|
||||||
- tests/**
|
- static/graph*
|
||||||
- static/graph.toml
|
- static/welcome.toml
|
||||||
- .forgejo/**
|
- .forgejo/**
|
||||||
|
- .justfile
|
||||||
- Cargo.toml
|
- Cargo.toml
|
||||||
- Cargo.lock
|
- Cargo.lock
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
verify:
|
verify:
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
|
@ -24,32 +26,37 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-tags: true
|
fetch-tags: true
|
||||||
|
|
||||||
- name: Setup Rust toolchain
|
- name: Set up Rust toolchain
|
||||||
run: |
|
run: |
|
||||||
rustup component add llvm-tools-preview
|
rustup component add llvm-tools
|
||||||
rustup component add --toolchain nightly rustfmt clippy
|
rustup component add --toolchain nightly rustfmt clippy
|
||||||
rustup target add x86_64-unknown-linux-gnu
|
rustup target add x86_64-unknown-linux-gnu
|
||||||
rustup target add x86_64-unknown-linux-musl
|
rustup target add x86_64-unknown-linux-musl
|
||||||
|
|
||||||
- name: Setup additional tooling
|
- name: Set up additional tooling
|
||||||
run: .forgejo/workflows/setup-tools.sh
|
run: .forgejo/workflows/setup-tools.sh
|
||||||
|
|
||||||
- name: Setup CI user
|
- name: Set up CI user
|
||||||
run: |
|
run: |
|
||||||
useradd -m ci && chown -R ci:ci .
|
useradd -m ci && chown -R ci:ci .
|
||||||
git config --global --add safe.directory "$PWD"
|
git config --global --add safe.directory "$PWD"
|
||||||
|
|
||||||
- name: Build
|
- name: Text matches
|
||||||
run: just ci build
|
run: just ci todos-assess version-assess spell
|
||||||
|
- name: Schema lint
|
||||||
|
run: just ci schema-lint
|
||||||
|
- name: Deny
|
||||||
|
run: just ci deny
|
||||||
- name: Format
|
- name: Format
|
||||||
run: just ci format-assess
|
run: just ci format-assess
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: just ci lint-assess
|
run: just ci lint-assess
|
||||||
|
- name: MSRV
|
||||||
|
run: just ci msrv-assess
|
||||||
- name: Cargo check
|
- name: Cargo check
|
||||||
run: just ci check
|
run: just ci check
|
||||||
- name: Test
|
- name: Test
|
||||||
run: just ci test
|
run: just ci test
|
||||||
- name: Assess test coverage
|
- name: Coverage
|
||||||
run: just ci cover-assess
|
run: just ci cover-assess
|
||||||
|
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
/result
|
||||||
|
|
|
||||||
165
.justfile
165
.justfile
|
|
@ -51,7 +51,7 @@ alias wc := run-watch-containerized
|
||||||
|
|
||||||
[private]
|
[private]
|
||||||
assess-quick:
|
assess-quick:
|
||||||
{{ just_cmd }} lint check test-cover-quick
|
{{ just_cmd }} lint check test-cover-quick spell schema-lint
|
||||||
|
|
||||||
[private]
|
[private]
|
||||||
assess-run-quick:
|
assess-run-quick:
|
||||||
|
|
@ -72,6 +72,17 @@ assess-run-watch-quick:
|
||||||
|
|
||||||
alias rq := assess-run-watch-quick
|
alias rq := assess-run-watch-quick
|
||||||
|
|
||||||
|
# Determine the Minimum Supported Rust Version
|
||||||
|
[group: 'develop']
|
||||||
|
msrv-find:
|
||||||
|
@{{ make_msrv("find", musl_target) }}
|
||||||
|
@{{ make_msrv("find", glibc_target) }}
|
||||||
|
@{{ make_msrv("find", msvc_target) }}
|
||||||
|
|
||||||
|
make_msrv(command, target) := f"printf '{{ target }}: '; " + \
|
||||||
|
f"cargo msrv {{ command }} --target {{ target }} --output-format minimal " \
|
||||||
|
+ f"-- {{ maybe_xwin(target) }} build --ignore-rust-version"
|
||||||
|
|
||||||
[private]
|
[private]
|
||||||
test-cover-quick:
|
test-cover-quick:
|
||||||
{{ cover_cmd }} --no-report -- --test 'serial_tests::' --test-threads 1
|
{{ cover_cmd }} --no-report -- --test 'serial_tests::' --test-threads 1
|
||||||
|
|
@ -198,11 +209,29 @@ cover-open:
|
||||||
|
|
||||||
alias oo := cover-open
|
alias oo := cover-open
|
||||||
|
|
||||||
|
# Perform mutation testing
|
||||||
|
[group: 'develop']
|
||||||
|
mutate:
|
||||||
|
-just mutate-single -- --test-threads=1 serial_tests::
|
||||||
|
-just mutate-single -- --skip serial_tests::
|
||||||
|
|
||||||
|
alias m := mutate
|
||||||
|
|
||||||
|
[private]
|
||||||
|
mutate-single *cargo_test_args:
|
||||||
|
cargo mutants --iterate \
|
||||||
|
-E '<impl Debug<' \
|
||||||
|
-E '<impl From<' \
|
||||||
|
-E '<impl std::fmt::Display for ' \
|
||||||
|
-E 'print_help -> bool' \
|
||||||
|
--output target/mutants \
|
||||||
|
-- {{ cargo_test_args }}
|
||||||
|
|
||||||
# Tag HEAD with version from Cargo.toml
|
# Tag HEAD with version from Cargo.toml
|
||||||
[script, group: 'assess']
|
[script, group: 'assess']
|
||||||
tag commit="HEAD": update
|
tag commit="HEAD": update
|
||||||
if [ "{{ last_tag }}" = "{{ manifest_version }}" ]; then
|
if [ "{{ last_local_tag }}" = "{{ manifest_version }}" ]; then
|
||||||
echo "Last tag {{ last_tag }} and manifest ({{ manifest_version }}) already match"
|
echo "Last tag {{ last_local_tag }} and manifest ({{ manifest_version }}) already match"
|
||||||
exit
|
exit
|
||||||
elif [ "{{ manifest_version }}" != "{{ lockfile_version }}" ]; then
|
elif [ "{{ manifest_version }}" != "{{ lockfile_version }}" ]; then
|
||||||
echo "Manifest and lockfile versions don't match: update failed?"
|
echo "Manifest and lockfile versions don't match: update failed?"
|
||||||
|
|
@ -213,15 +242,15 @@ tag commit="HEAD": update
|
||||||
{{ just_cmd }} version-assess
|
{{ just_cmd }} version-assess
|
||||||
|
|
||||||
# Verify and push
|
# Verify and push
|
||||||
[group: 'develop']
|
[group: 'develop', env("JUST", "1")]
|
||||||
push: verify
|
push: verify && (version-assess "true")
|
||||||
git push
|
git push
|
||||||
git push --tags
|
git push --tags
|
||||||
|
|
||||||
alias p := push
|
alias p := push
|
||||||
|
|
||||||
# Push without verifying
|
# Push without verifying
|
||||||
[group: 'develop']
|
[group: 'develop', env("JUST", "1")]
|
||||||
push-unsafe:
|
push-unsafe:
|
||||||
git push --no-verify
|
git push --no-verify
|
||||||
git push --tags --no-verify
|
git push --tags --no-verify
|
||||||
|
|
@ -283,13 +312,28 @@ alias c := check
|
||||||
# Run tests
|
# Run tests
|
||||||
[group: 'assess']
|
[group: 'assess']
|
||||||
test pattern="":
|
test pattern="":
|
||||||
cargo test {{ pattern}} --timings -- --test-threads=1 'serial_tests::'
|
cargo test {{ pattern }} --timings -- --test-threads=1 'serial_tests::'
|
||||||
cargo test {{ pattern}} --timings --bin en
|
cargo test {{ pattern }} --timings --bin en
|
||||||
cargo test {{ pattern}} --timings --doc
|
cargo test {{ pattern }} --timings --doc
|
||||||
cargo test {{ pattern}} --timings --lib -- --skip 'serial_tests::'
|
cargo test {{ pattern }} --timings --lib -- --skip 'serial_tests::'
|
||||||
|
{{ if which("wine") == "" {
|
||||||
|
"echo Skipping Windows tests: wine not found"
|
||||||
|
} else {
|
||||||
|
just_cmd + " test-windows"
|
||||||
|
} }}
|
||||||
|
|
||||||
alias t := test
|
alias t := test
|
||||||
|
|
||||||
|
# Run Windows tests using wine
|
||||||
|
[group: 'assess']
|
||||||
|
test-windows pattern="":
|
||||||
|
-{{ xwin_test(pattern) }} --timings -- --test-threads=1 'serial_tests::'
|
||||||
|
-{{ xwin_test(pattern) }} --timings --bin en
|
||||||
|
-{{ xwin_test(pattern) }} --timings --doc
|
||||||
|
-{{ xwin_test(pattern) }} --timings --lib -- --skip 'serial_tests::'
|
||||||
|
|
||||||
|
xwin_test(pattern) := f"cargo-xwin test {{ pattern }} --target {{ msvc_target }}"
|
||||||
|
|
||||||
# Run tests with unfiltered output
|
# Run tests with unfiltered output
|
||||||
[group: 'assess']
|
[group: 'assess']
|
||||||
test-output pattern="":
|
test-output pattern="":
|
||||||
|
|
@ -329,41 +373,65 @@ verify:
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
{{ just_cmd }} \
|
{{ just_cmd }} \
|
||||||
todos-assess version-assess \
|
todos-assess version-assess spell schema-lint deny \
|
||||||
security-assess \
|
format-assess lint-assess msrv-assess check \
|
||||||
format-assess lint-assess check \
|
|
||||||
test "" cover-assess
|
test "" cover-assess
|
||||||
|
|
||||||
alias v := verify
|
alias v := verify
|
||||||
|
|
||||||
# Check tag-manifest consistency
|
# Check tag-manifest consistency
|
||||||
[script, group: 'assess']
|
[script, group: 'assess']
|
||||||
version-assess: update
|
[arg("remote", long="remote", short="r", value="true")]
|
||||||
if
|
version-assess remote="false": update
|
||||||
[ "{{ last_tag }}" != "{{ lockfile_version }}" ] \
|
last_remote_tag=$(
|
||||||
|| [ "{{ last_tag }}" != "{{ lockfile_version }}" ]
|
git ls-remote --tags --sort=-creatordate origin |
|
||||||
then
|
head -n 1 | tr -d v | cut -d / -f 3
|
||||||
printf 'Last tag: %s\nManifest: %s\nLockfile: %s\n' \
|
)
|
||||||
"{{ last_tag }}" \
|
printf 'Local: %s\nRemote: %s\nManifest: %s\nLockfile: %s\n' \
|
||||||
"{{ manifest_version }}" \
|
"{{ last_local_tag }}" \
|
||||||
"{{ lockfile_version }}"
|
"$last_remote_tag" \
|
||||||
exit 1
|
"{{ manifest_version }}" \
|
||||||
|
"{{ lockfile_version }}"
|
||||||
|
test "{{ last_local_tag }}" = "{{ lockfile_version }}"
|
||||||
|
test "{{ last_local_tag }}" = "{{ manifest_version }}"
|
||||||
|
if {{ if remote == "true" { "true" } else { "false" } }}; then
|
||||||
|
test "{{ last_local_tag }}" = "$last_remote_tag"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
alias va := version-assess
|
alias va := version-assess
|
||||||
|
|
||||||
# Audit security advisories
|
# Assess if the current Minimum Supported Rust Version is accurate
|
||||||
security-assess:
|
[group: 'assess']
|
||||||
cargo audit --deny warnings
|
msrv-assess:
|
||||||
alias sa := security-assess
|
{{ make_msrv("verify", musl_target) }}
|
||||||
|
{{ make_msrv("verify", glibc_target) }}
|
||||||
|
if rustup toolchain list | grep -q {{ msvc_target }}; then \
|
||||||
|
{{ make_msrv("verify", msvc_target) }}; \
|
||||||
|
fi
|
||||||
|
|
||||||
# Find TODOs
|
# Find TODOs
|
||||||
[group: 'assess']
|
[group: 'assess']
|
||||||
todos-assess:
|
todos-assess:
|
||||||
! rg -M 200 --max-columns-preview TODO src
|
! grep -rn TODO src
|
||||||
|
|
||||||
alias ta := todos-assess
|
alias ta := todos-assess
|
||||||
|
|
||||||
|
# Check for security advisories, unexpected licenses, allowed registries
|
||||||
|
[group: 'assess']
|
||||||
|
deny:
|
||||||
|
cargo-deny check
|
||||||
|
|
||||||
|
# Check for spelling mistakes
|
||||||
|
[group: 'assess']
|
||||||
|
spell:
|
||||||
|
typos
|
||||||
|
|
||||||
|
# Lint the default and builtin graphs against the schema
|
||||||
|
[group: 'assess']
|
||||||
|
schema-lint:
|
||||||
|
test -z "$(grep -LF '#:schema ./graph-schema.json' static/*.toml)"
|
||||||
|
taplo lint static/*.toml
|
||||||
|
|
||||||
# BUILD
|
# BUILD
|
||||||
|
|
||||||
# Cleanup build artifacts
|
# Cleanup build artifacts
|
||||||
|
|
@ -398,8 +466,12 @@ alias bm := build-musl
|
||||||
# Release build
|
# Release build
|
||||||
[group: 'build']
|
[group: 'build']
|
||||||
release-build target=default_target:
|
release-build target=default_target:
|
||||||
cargo build --timings --target {{ target }} --locked --release
|
{{ maybe_xwin(target) }} build \
|
||||||
du -h target/{{ target }}/release/en
|
--timings --target {{ target }} --locked --release
|
||||||
|
du -h target/{{ target }}/release/{{ with_suffix("en", target) }}
|
||||||
|
|
||||||
|
maybe_xwin(target) := if target == msvc_target { "cargo-xwin" } else { "cargo" }
|
||||||
|
with_suffix(file, target) := if target == msvc_target { f"{{ file }}.exe" } else { file }
|
||||||
|
|
||||||
alias rb := release-build
|
alias rb := release-build
|
||||||
|
|
||||||
|
|
@ -417,15 +489,29 @@ release-build-musl:
|
||||||
|
|
||||||
alias rbm := release-build-musl
|
alias rbm := release-build-musl
|
||||||
|
|
||||||
|
# MSVC release build
|
||||||
|
[group: 'build']
|
||||||
|
release-build-msvc:
|
||||||
|
{{ just_cmd }} release-build {{ msvc_target }}
|
||||||
|
|
||||||
|
alias rbw := release-build-msvc
|
||||||
|
|
||||||
# Calculate SHA 256 hashes for release binaries
|
# Calculate SHA 256 hashes for release binaries
|
||||||
[group: 'build']
|
[group: 'build']
|
||||||
|
[script]
|
||||||
shasum:
|
shasum:
|
||||||
find target -type d -name 'release' \
|
binaries=$(find target -type d -name 'release' \
|
||||||
-exec find '{}' -maxdepth 1 -type f -name en -executable ';' \
|
-exec find '{}' -maxdepth 1 -type f \
|
||||||
| xargs sha256sum
|
-regex '.*/en\(\.exe\)?$' -executable ';' \
|
||||||
|
)
|
||||||
|
if [ -n "$binaries" ]; then
|
||||||
|
printf '%s\n' "$binaries" | xargs sha256sum
|
||||||
|
else
|
||||||
|
echo "Can't generate SHA-256 hashes: No release binaries found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
## META
|
## META
|
||||||
|
|
||||||
[default, private]
|
[default, private]
|
||||||
default:
|
default:
|
||||||
@just --list --unsorted --justfile {{justfile()}}
|
@just --list --unsorted --justfile {{justfile()}}
|
||||||
|
|
@ -435,25 +521,25 @@ choose:
|
||||||
|
|
||||||
alias ch := choose
|
alias ch := choose
|
||||||
|
|
||||||
[script, private]
|
[script, private, env("CARGO_HOME", "$HOME/.cargo")]
|
||||||
ci recipe:
|
ci recipe:
|
||||||
su ci -c "just {{ recipe }}"
|
su ci -c "just {{ recipe }}"
|
||||||
|
|
||||||
## VARIABLES
|
## VARIABLES
|
||||||
|
|
||||||
export CARGO_TERM_COLOR := 'always'
|
export CARGO_TERM_COLOR := 'always'
|
||||||
|
|
||||||
musl_target := "x86_64-unknown-linux-musl"
|
musl_target := "x86_64-unknown-linux-musl"
|
||||||
glibc_target := "x86_64-unknown-linux-gnu"
|
glibc_target := "x86_64-unknown-linux-gnu"
|
||||||
|
msvc_target := "x86_64-pc-windows-msvc"
|
||||||
default_target := musl_target
|
default_target := musl_target
|
||||||
|
|
||||||
debug_vars := 'DEBUG=${DEBUG:-} DEBUG_FILTER=${DEBUG_FILTER:-} RUST_BACKTRACE=${RUST_BACKTRACE:-} RUSTFLAGS=${RUSTFLAGS:-}'
|
debug_vars := 'DEBUG=${DEBUG:-} DEBUG_FILTER=${DEBUG_FILTER:-} RUST_BACKTRACE=${RUST_BACKTRACE:-} RUSTFLAGS=${RUSTFLAGS:-}'
|
||||||
just_cmd := 'just --timestamp --explain --command-color green'
|
just_cmd := 'just --timestamp --command-color green'
|
||||||
just_cmd_no_ts := 'just --explain --command-color green'
|
just_cmd_no_ts := 'just --explain --command-color green'
|
||||||
watch_cmd := "watchexec -qc -r -e rs,toml,html --color always -- "
|
watch_cmd := "watchexec -qc -r -e rs,toml,html,css --color always -- "
|
||||||
cover_cmd := 'cargo llvm-cov --color always --ignore-filename-regex "main\.rs|log\.rs"'
|
cover_cmd := 'cargo llvm-cov --color always --ignore-filename-regex "main\.rs|log\.rs"'
|
||||||
|
|
||||||
last_tag := `git tag --sort=-creatordate | head -1 | tr -d v`
|
last_local_tag := `git tag --sort=-creatordate | head -n 1 | tr -d v`
|
||||||
manifest_version := `grep "^version" Cargo.toml | cut -d \" -f 2`
|
manifest_version := `grep "^version" Cargo.toml | cut -d \" -f 2`
|
||||||
lockfile_version := ```
|
lockfile_version := ```
|
||||||
grep -A 1 'name = "en"' Cargo.lock \
|
grep -A 1 'name = "en"' Cargo.lock \
|
||||||
|
|
@ -461,6 +547,5 @@ lockfile_version := ```
|
||||||
```
|
```
|
||||||
|
|
||||||
## OPTIONS
|
## OPTIONS
|
||||||
|
|
||||||
set unstable
|
set unstable
|
||||||
set lazy
|
set lazy
|
||||||
|
|
|
||||||
412
Cargo.lock
generated
412
Cargo.lock
generated
|
|
@ -2,12 +2,6 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "adler2"
|
|
||||||
version = "2.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.4"
|
version = "1.1.4"
|
||||||
|
|
@ -34,15 +28,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.5.0"
|
version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum"
|
name = "axum"
|
||||||
version = "0.8.8"
|
version = "0.8.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
|
checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum-core",
|
"axum-core",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
|
@ -90,17 +84,11 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base64"
|
|
||||||
version = "0.22.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.11.0"
|
version = "2.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
|
|
@ -123,21 +111,21 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.20.2"
|
version = "3.20.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
|
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.11.1"
|
version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.57"
|
version = "1.2.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423"
|
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
"shlex",
|
"shlex",
|
||||||
|
|
@ -151,9 +139,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.44"
|
version = "0.4.45"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
|
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
|
@ -197,15 +185,6 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crc32fast"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.6"
|
version = "0.8.6"
|
||||||
|
|
@ -268,7 +247,6 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
"tower",
|
"tower",
|
||||||
"ureq",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -283,16 +261,6 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "flate2"
|
|
||||||
version = "1.1.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
|
|
||||||
dependencies = [
|
|
||||||
"crc32fast",
|
|
||||||
"miniz_oxide",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
|
|
@ -382,15 +350,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.16.1"
|
version = "0.17.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "1.4.0"
|
version = "1.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
|
checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"itoa",
|
"itoa",
|
||||||
|
|
@ -442,9 +410,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.8.1"
|
version = "1.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11"
|
checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
|
@ -456,7 +424,6 @@ dependencies = [
|
||||||
"httpdate",
|
"httpdate",
|
||||||
"itoa",
|
"itoa",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"pin-utils",
|
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
@ -502,9 +469,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
version = "0.4.25"
|
version = "0.4.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a"
|
checksum = "b915661dd01db3f05050265b2477bcc6527b3792388e2749b41623cc592be67d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-deque",
|
"crossbeam-deque",
|
||||||
"globset",
|
"globset",
|
||||||
|
|
@ -518,9 +485,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.13.0"
|
version = "2.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
|
|
@ -534,11 +501,12 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.91"
|
version = "0.3.102"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c"
|
checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"cfg-if",
|
||||||
|
"futures-util",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -550,9 +518,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.183"
|
version = "0.2.186"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libm"
|
name = "libm"
|
||||||
|
|
@ -562,9 +530,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.29"
|
version = "0.4.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchit"
|
name = "matchit"
|
||||||
|
|
@ -574,9 +542,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.8.0"
|
version = "2.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
|
|
@ -584,25 +552,15 @@ version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "miniz_oxide"
|
|
||||||
version = "0.8.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
|
||||||
dependencies = [
|
|
||||||
"adler2",
|
|
||||||
"simd-adler32",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "1.1.1"
|
version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
|
checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -722,12 +680,6 @@ version = "0.2.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pin-utils"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
|
|
@ -757,9 +709,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha",
|
"rand_chacha",
|
||||||
|
|
@ -787,9 +739,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.12.3"
|
version = "1.12.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
|
checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
@ -810,58 +762,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.10"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
|
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ring"
|
|
||||||
version = "0.17.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"cfg-if",
|
|
||||||
"getrandom",
|
|
||||||
"libc",
|
|
||||||
"untrusted",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustls"
|
|
||||||
version = "0.23.37"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
"once_cell",
|
|
||||||
"ring",
|
|
||||||
"rustls-pki-types",
|
|
||||||
"rustls-webpki",
|
|
||||||
"subtle",
|
|
||||||
"zeroize",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustls-pki-types"
|
|
||||||
version = "1.14.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
|
|
||||||
dependencies = [
|
|
||||||
"zeroize",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustls-webpki"
|
|
||||||
version = "0.103.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef"
|
|
||||||
dependencies = [
|
|
||||||
"ring",
|
|
||||||
"rustls-pki-types",
|
|
||||||
"untrusted",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
|
|
@ -916,9 +819,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.149"
|
version = "1.0.150"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
@ -940,9 +843,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_spanned"
|
name = "serde_spanned"
|
||||||
version = "1.0.4"
|
version = "1.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
|
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
@ -972,21 +875,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "simd-adler32"
|
|
||||||
version = "0.3.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "siphasher"
|
name = "siphasher"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
|
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
|
|
@ -1006,31 +903,25 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.15.1"
|
version = "1.15.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.6.3"
|
version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
|
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "subtle"
|
|
||||||
version = "2.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.117"
|
version = "2.0.118"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -1067,23 +958,23 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.50.0"
|
version = "1.52.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
|
checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "2.6.1"
|
version = "2.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c"
|
checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -1116,18 +1007,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_parser"
|
name = "toml_parser"
|
||||||
version = "1.0.10+spec-1.1.0"
|
version = "1.1.2+spec-1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7df25b4befd31c4816df190124375d5a20c6b6921e2cad937316de3fccd63420"
|
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winnow 1.0.0",
|
"winnow 1.0.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_writer"
|
name = "toml_writer"
|
||||||
version = "1.0.7+spec-1.1.0"
|
version = "1.1.1+spec-1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f17aaa1c6e3dc22b1da4b6bba97d066e354c7945cac2f7852d4e4e7ca7a6b56d"
|
checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower"
|
name = "tower"
|
||||||
|
|
@ -1179,9 +1070,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.19.0"
|
version = "1.20.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ucd-trie"
|
name = "ucd-trie"
|
||||||
|
|
@ -1197,50 +1088,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.12.0"
|
version = "1.13.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "untrusted"
|
|
||||||
version = "0.9.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ureq"
|
|
||||||
version = "3.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0"
|
|
||||||
dependencies = [
|
|
||||||
"base64",
|
|
||||||
"flate2",
|
|
||||||
"log",
|
|
||||||
"percent-encoding",
|
|
||||||
"rustls",
|
|
||||||
"rustls-pki-types",
|
|
||||||
"ureq-proto",
|
|
||||||
"utf8-zero",
|
|
||||||
"webpki-roots",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ureq-proto"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c"
|
|
||||||
dependencies = [
|
|
||||||
"base64",
|
|
||||||
"http",
|
|
||||||
"httparse",
|
|
||||||
"log",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "utf8-zero"
|
|
||||||
version = "0.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
|
|
@ -1266,9 +1116,9 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.114"
|
version = "0.2.125"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e"
|
checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
@ -1279,9 +1129,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.114"
|
version = "0.2.125"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6"
|
checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
|
|
@ -1289,9 +1139,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.114"
|
version = "0.2.125"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3"
|
checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
|
@ -1302,29 +1152,20 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.114"
|
version = "0.2.125"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16"
|
checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "webpki-roots"
|
|
||||||
version = "1.0.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed"
|
|
||||||
dependencies = [
|
|
||||||
"rustls-pki-types",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-util"
|
name = "winapi-util"
|
||||||
version = "0.1.11"
|
version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1386,15 +1227,6 @@ dependencies = [
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.52.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.61.2"
|
version = "0.61.2"
|
||||||
|
|
@ -1404,70 +1236,6 @@ dependencies = [
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-targets"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
|
||||||
dependencies = [
|
|
||||||
"windows_aarch64_gnullvm",
|
|
||||||
"windows_aarch64_msvc",
|
|
||||||
"windows_i686_gnu",
|
|
||||||
"windows_i686_gnullvm",
|
|
||||||
"windows_i686_msvc",
|
|
||||||
"windows_x86_64_gnu",
|
|
||||||
"windows_x86_64_gnullvm",
|
|
||||||
"windows_x86_64_msvc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.7.15"
|
version = "0.7.15"
|
||||||
|
|
@ -1476,36 +1244,30 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "1.0.0"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8"
|
checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.47"
|
version = "0.8.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87"
|
checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.8.47"
|
version = "0.8.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89"
|
checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zeroize"
|
|
||||||
version = "1.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zmij"
|
name = "zmij"
|
||||||
version = "1.0.21"
|
version = "1.0.21"
|
||||||
|
|
|
||||||
34
Cargo.toml
34
Cargo.toml
|
|
@ -23,7 +23,6 @@ serde = { version = "1.0.228", features = ["derive"] }
|
||||||
toml = "0.9.8"
|
toml = "0.9.8"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
ureq = "3"
|
|
||||||
tower = { version = "0.5.2", features = ["util"] }
|
tower = { version = "0.5.2", features = ["util"] }
|
||||||
|
|
||||||
[lints.rust]
|
[lints.rust]
|
||||||
|
|
@ -55,6 +54,7 @@ cast_sign_loss = "warn"
|
||||||
checked_conversions = "warn"
|
checked_conversions = "warn"
|
||||||
clear_with_drain = "warn"
|
clear_with_drain = "warn"
|
||||||
cloned_instead_of_copied = "warn"
|
cloned_instead_of_copied = "warn"
|
||||||
|
cmp_owned = "warn"
|
||||||
coerce_container_to_any = "warn"
|
coerce_container_to_any = "warn"
|
||||||
collapsible_else_if = "allow"
|
collapsible_else_if = "allow"
|
||||||
collapsible_if = "allow"
|
collapsible_if = "allow"
|
||||||
|
|
@ -71,6 +71,7 @@ doc_link_code = "warn"
|
||||||
doc_link_with_quotes = "warn"
|
doc_link_with_quotes = "warn"
|
||||||
doc_markdown = "warn"
|
doc_markdown = "warn"
|
||||||
doc_paragraphs_missing_punctuation = "warn"
|
doc_paragraphs_missing_punctuation = "warn"
|
||||||
|
double_must_use = "warn"
|
||||||
duration_suboptimal_units = "warn"
|
duration_suboptimal_units = "warn"
|
||||||
empty_drop = "warn"
|
empty_drop = "warn"
|
||||||
empty_enum_variants_with_brackets = "warn"
|
empty_enum_variants_with_brackets = "warn"
|
||||||
|
|
@ -81,6 +82,7 @@ error_impl_error = "warn"
|
||||||
exit = "warn"
|
exit = "warn"
|
||||||
expect_used = "warn"
|
expect_used = "warn"
|
||||||
expl_impl_clone_on_copy = "warn"
|
expl_impl_clone_on_copy = "warn"
|
||||||
|
explicit_counter_loop = "warn"
|
||||||
explicit_deref_methods = "warn"
|
explicit_deref_methods = "warn"
|
||||||
explicit_into_iter_loop = "warn"
|
explicit_into_iter_loop = "warn"
|
||||||
explicit_iter_loop = "warn"
|
explicit_iter_loop = "warn"
|
||||||
|
|
@ -94,7 +96,6 @@ float_cmp_const = "warn"
|
||||||
fn_to_numeric_cast_any = "warn"
|
fn_to_numeric_cast_any = "warn"
|
||||||
format_collect = "warn"
|
format_collect = "warn"
|
||||||
format_push_string = "warn"
|
format_push_string = "warn"
|
||||||
from_iter_instead_of_collect = "warn"
|
|
||||||
get_unwrap = "warn"
|
get_unwrap = "warn"
|
||||||
if_not_else = "warn"
|
if_not_else = "warn"
|
||||||
if_then_some_else_none = "warn"
|
if_then_some_else_none = "warn"
|
||||||
|
|
@ -103,11 +104,13 @@ ignored_unit_patterns = "warn"
|
||||||
implicit_clone = "warn"
|
implicit_clone = "warn"
|
||||||
implicit_hasher = "warn"
|
implicit_hasher = "warn"
|
||||||
imprecise_flops = "warn"
|
imprecise_flops = "warn"
|
||||||
|
incompatible_msrv = "warn"
|
||||||
inconsistent_struct_constructor = "warn"
|
inconsistent_struct_constructor = "warn"
|
||||||
index_refutable_slice = "warn"
|
index_refutable_slice = "warn"
|
||||||
indexing_slicing = "warn"
|
indexing_slicing = "warn"
|
||||||
inefficient_to_string = "warn"
|
inefficient_to_string = "warn"
|
||||||
infinite_loop = "warn"
|
infinite_loop = "warn"
|
||||||
|
int_plus_one = "warn"
|
||||||
integer_division = "warn"
|
integer_division = "warn"
|
||||||
integer_division_remainder_used = "warn"
|
integer_division_remainder_used = "warn"
|
||||||
into_iter_without_iter = "warn"
|
into_iter_without_iter = "warn"
|
||||||
|
|
@ -115,6 +118,7 @@ invalid_upcast_comparisons = "warn"
|
||||||
ip_constant = "warn"
|
ip_constant = "warn"
|
||||||
iter_filter_is_ok = "warn"
|
iter_filter_is_ok = "warn"
|
||||||
iter_filter_is_some = "warn"
|
iter_filter_is_some = "warn"
|
||||||
|
iter_kv_map = "warn"
|
||||||
iter_not_returning_iterator = "warn"
|
iter_not_returning_iterator = "warn"
|
||||||
iter_on_empty_collections = "warn"
|
iter_on_empty_collections = "warn"
|
||||||
iter_on_single_items = "warn"
|
iter_on_single_items = "warn"
|
||||||
|
|
@ -130,14 +134,19 @@ literal_string_with_formatting_args = "warn"
|
||||||
lossy_float_literal = "warn"
|
lossy_float_literal = "warn"
|
||||||
macro_use_imports = "warn"
|
macro_use_imports = "warn"
|
||||||
manual_assert = "warn"
|
manual_assert = "warn"
|
||||||
|
manual_checked_ops = "warn"
|
||||||
manual_ilog2 = "warn"
|
manual_ilog2 = "warn"
|
||||||
manual_instant_elapsed = "warn"
|
manual_instant_elapsed = "warn"
|
||||||
|
manual_is_multiple_of = "warn"
|
||||||
manual_is_power_of_two = "warn"
|
manual_is_power_of_two = "warn"
|
||||||
manual_is_variant_and = "warn"
|
manual_is_variant_and = "warn"
|
||||||
manual_let_else = "warn"
|
manual_let_else = "warn"
|
||||||
manual_midpoint = "warn"
|
manual_midpoint = "warn"
|
||||||
manual_non_exhaustive = "allow"
|
manual_non_exhaustive = "allow"
|
||||||
|
manual_option_zip = "warn"
|
||||||
|
manual_pop_if = "warn"
|
||||||
manual_string_new = "warn"
|
manual_string_new = "warn"
|
||||||
|
manual_take = "warn"
|
||||||
many_single_char_names = "warn"
|
many_single_char_names = "warn"
|
||||||
map_err_ignore = "warn"
|
map_err_ignore = "warn"
|
||||||
map_with_unused_argument_over_ranges = "warn"
|
map_with_unused_argument_over_ranges = "warn"
|
||||||
|
|
@ -180,15 +189,19 @@ option_option = "warn"
|
||||||
panic_in_result_fn = "warn"
|
panic_in_result_fn = "warn"
|
||||||
path_buf_push_overwrite = "warn"
|
path_buf_push_overwrite = "warn"
|
||||||
pathbuf_init_then_push = "warn"
|
pathbuf_init_then_push = "warn"
|
||||||
|
possible_missing_else = "warn"
|
||||||
pub_underscore_fields = "warn"
|
pub_underscore_fields = "warn"
|
||||||
pub_without_shorthand = "warn"
|
pub_without_shorthand = "warn"
|
||||||
|
question_mark = "warn"
|
||||||
range_minus_one = "warn"
|
range_minus_one = "warn"
|
||||||
range_plus_one = "warn"
|
range_plus_one = "warn"
|
||||||
rc_buffer = "warn"
|
rc_buffer = "warn"
|
||||||
rc_mutex = "warn"
|
rc_mutex = "warn"
|
||||||
read_zero_byte_vec = "warn"
|
read_zero_byte_vec = "warn"
|
||||||
redundant_clone = "warn"
|
redundant_clone = "warn"
|
||||||
|
redundant_closure = "warn"
|
||||||
redundant_closure_for_method_calls = "warn"
|
redundant_closure_for_method_calls = "warn"
|
||||||
|
redundant_iter_cloned = "warn"
|
||||||
redundant_pub_crate = "warn"
|
redundant_pub_crate = "warn"
|
||||||
redundant_test_prefix = "warn"
|
redundant_test_prefix = "warn"
|
||||||
redundant_type_annotations = "warn"
|
redundant_type_annotations = "warn"
|
||||||
|
|
@ -196,6 +209,7 @@ ref_binding_to_reference = "warn"
|
||||||
ref_option = "warn"
|
ref_option = "warn"
|
||||||
ref_option_ref = "warn"
|
ref_option_ref = "warn"
|
||||||
renamed_function_params = "warn"
|
renamed_function_params = "warn"
|
||||||
|
replace_box = "warn"
|
||||||
rest_pat_in_fully_bound_structs = "warn"
|
rest_pat_in_fully_bound_structs = "warn"
|
||||||
return_and_then = "warn"
|
return_and_then = "warn"
|
||||||
return_self_not_must_use = "warn"
|
return_self_not_must_use = "warn"
|
||||||
|
|
@ -236,12 +250,17 @@ unchecked_time_subtraction = "warn"
|
||||||
unicode_not_nfc = "warn"
|
unicode_not_nfc = "warn"
|
||||||
uninlined_format_args = "warn"
|
uninlined_format_args = "warn"
|
||||||
unnecessary_box_returns = "warn"
|
unnecessary_box_returns = "warn"
|
||||||
|
unnecessary_cast = "warn"
|
||||||
unnecessary_debug_formatting = "warn"
|
unnecessary_debug_formatting = "warn"
|
||||||
|
unnecessary_fold = "warn"
|
||||||
unnecessary_join = "warn"
|
unnecessary_join = "warn"
|
||||||
unnecessary_literal_bound = "warn"
|
unnecessary_literal_bound = "warn"
|
||||||
|
unnecessary_option_map_or_else = "warn"
|
||||||
|
unnecessary_result_map_or_else = "warn"
|
||||||
unnecessary_self_imports = "warn"
|
unnecessary_self_imports = "warn"
|
||||||
unnecessary_semicolon = "warn"
|
unnecessary_semicolon = "warn"
|
||||||
unnecessary_struct_initialization = "warn"
|
unnecessary_struct_initialization = "warn"
|
||||||
|
unnecessary_trailing_comma = "warn"
|
||||||
unnecessary_wraps = "warn"
|
unnecessary_wraps = "warn"
|
||||||
unneeded_field_pattern = "warn"
|
unneeded_field_pattern = "warn"
|
||||||
unnested_or_patterns = "warn"
|
unnested_or_patterns = "warn"
|
||||||
|
|
@ -258,6 +277,8 @@ unwrap_in_result = "warn"
|
||||||
unwrap_used = "warn"
|
unwrap_used = "warn"
|
||||||
used_underscore_binding = "warn"
|
used_underscore_binding = "warn"
|
||||||
used_underscore_items = "warn"
|
used_underscore_items = "warn"
|
||||||
|
useless_concat = "warn"
|
||||||
|
useless_conversion = "warn"
|
||||||
useless_let_if_seq = "warn"
|
useless_let_if_seq = "warn"
|
||||||
verbose_file_reads = "warn"
|
verbose_file_reads = "warn"
|
||||||
volatile_composites = "warn"
|
volatile_composites = "warn"
|
||||||
|
|
@ -269,3 +290,12 @@ zero_sized_map_values = "warn"
|
||||||
negative_feature_names = "warn"
|
negative_feature_names = "warn"
|
||||||
redundant_feature_names = "warn"
|
redundant_feature_names = "warn"
|
||||||
wildcard_dependencies = "warn"
|
wildcard_dependencies = "warn"
|
||||||
|
|
||||||
|
[package.metadata.typos.default]
|
||||||
|
extend-ignore-re = [
|
||||||
|
"oficial do Brasil",
|
||||||
|
"Creative Commons ND",
|
||||||
|
"Creative Commons BY-ND",
|
||||||
|
"CC_BY_ND_",
|
||||||
|
"(?ms)^mod tests \\{.*^\\}",
|
||||||
|
]
|
||||||
|
|
|
||||||
13
README.md
13
README.md
|
|
@ -10,17 +10,10 @@ You can learn more and see what en looks like by visiting the [homepage](https:/
|
||||||
|
|
||||||
## Install and run
|
## Install and run
|
||||||
|
|
||||||
See the [Documentation](https://en.jutty.dev/node/Documentation) page for instructions and how to install and start using en.
|
See the [Get Started](https://en.jutty.dev/node/GetStarted) page for instructions and how to install and start using en.
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
On a high-level, here are some things that en intends to achieve at some point:
|
For a high-level view of what's in the future for en, see the [What's ahead section](https://en.jutty.dev/node/Introduction#What's) of the docs Introduction.
|
||||||
|
|
||||||
1. Separate 'en' the server from 'en' the source-to-source translator. This would allow using en's markup syntax as a standalone compile-to-HTML language, effectively creating an "en cli" that should also have options to make it more practical to manipulate a graph, such as adding new nodes or querying your graph
|
For a more detailed outline of what's planned, along with what's already been completed, see the [roadmap](https://en.jutty.dev/node/Roadmap).
|
||||||
3. Multifile graphs, with _optional_ TOML frontmatter
|
|
||||||
2. Make en more fitting to the 'note taking' use case
|
|
||||||
3. Multigraph, with the server being capable to let the user choose which graph to render and with inter-graph connections
|
|
||||||
4. Different rendering modes such as to a static website, to PDF or EPUB (with paper-friendly metadata)
|
|
||||||
5. Stateful and stateless online graph editing with 'export to TOML'
|
|
||||||
|
|
||||||
For a more detailed outline of what's planned for the future of en, along with what's already been completed, see the [roadmap](https://en.jutty.dev/node/Roadmap).
|
|
||||||
|
|
|
||||||
243
deny.toml
Normal file
243
deny.toml
Normal file
|
|
@ -0,0 +1,243 @@
|
||||||
|
# This template contains all of the possible sections and their default values
|
||||||
|
|
||||||
|
# Note that all fields that take a lint level have these possible values:
|
||||||
|
# * deny - An error will be produced and the check will fail
|
||||||
|
# * warn - A warning will be produced, but the check will not fail
|
||||||
|
# * allow - No warning or error will be produced, though in some cases a note
|
||||||
|
# will be
|
||||||
|
|
||||||
|
# The values provided in this template are the default values that will be used
|
||||||
|
# when any section or field is not specified in your own configuration
|
||||||
|
|
||||||
|
# Root options
|
||||||
|
|
||||||
|
# The graph table configures how the dependency graph is constructed and thus
|
||||||
|
# which crates the checks are performed against
|
||||||
|
[graph]
|
||||||
|
# If 1 or more target triples (and optionally, target_features) are specified,
|
||||||
|
# only the specified targets will be checked when running `cargo deny check`.
|
||||||
|
# This means, if a particular package is only ever used as a target specific
|
||||||
|
# dependency, such as, for example, the `nix` crate only being used via the
|
||||||
|
# `target_family = "unix"` configuration, that only having windows targets in
|
||||||
|
# this list would mean the nix crate, as well as any of its exclusive
|
||||||
|
# dependencies not shared by any other crates, would be ignored, as the target
|
||||||
|
# list here is effectively saying which targets you are building for.
|
||||||
|
targets = [
|
||||||
|
# The triple can be any string, but only the target triples built in to
|
||||||
|
# rustc (as of 1.40) can be checked against actual config expressions
|
||||||
|
#"x86_64-unknown-linux-musl",
|
||||||
|
# You can also specify which target_features you promise are enabled for a
|
||||||
|
# particular target. target_features are currently not validated against
|
||||||
|
# the actual valid features supported by the target architecture.
|
||||||
|
#{ triple = "wasm32-unknown-unknown", features = ["atomics"] },
|
||||||
|
]
|
||||||
|
# When creating the dependency graph used as the source of truth when checks are
|
||||||
|
# executed, this field can be used to prune crates from the graph, removing them
|
||||||
|
# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate
|
||||||
|
# is pruned from the graph, all of its dependencies will also be pruned unless
|
||||||
|
# they are connected to another crate in the graph that hasn't been pruned,
|
||||||
|
# so it should be used with care. The identifiers are [Package ID Specifications]
|
||||||
|
# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html)
|
||||||
|
#exclude = []
|
||||||
|
# If true, metadata will be collected with `--all-features`. Note that this can't
|
||||||
|
# be toggled off if true, if you want to conditionally enable `--all-features` it
|
||||||
|
# is recommended to pass `--all-features` on the cmd line instead
|
||||||
|
all-features = false
|
||||||
|
# If true, metadata will be collected with `--no-default-features`. The same
|
||||||
|
# caveat with `all-features` applies
|
||||||
|
no-default-features = false
|
||||||
|
# If set, these feature will be enabled when collecting metadata. If `--features`
|
||||||
|
# is specified on the cmd line they will take precedence over this option.
|
||||||
|
#features = []
|
||||||
|
|
||||||
|
# The output table provides options for how/if diagnostics are outputted
|
||||||
|
[output]
|
||||||
|
# When outputting inclusion graphs in diagnostics that include features, this
|
||||||
|
# option can be used to specify the depth at which feature edges will be added.
|
||||||
|
# This option is included since the graphs can be quite large and the addition
|
||||||
|
# of features from the crate(s) to all of the graph roots can be far too verbose.
|
||||||
|
# This option can be overridden via `--feature-depth` on the cmd line
|
||||||
|
feature-depth = 1
|
||||||
|
|
||||||
|
# This section is considered when running `cargo deny check advisories`
|
||||||
|
# More documentation for the advisories section can be found here:
|
||||||
|
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
|
||||||
|
[advisories]
|
||||||
|
# The path where the advisory databases are cloned/fetched into
|
||||||
|
#db-path = "$CARGO_HOME/advisory-dbs"
|
||||||
|
# The url(s) of the advisory databases to use
|
||||||
|
#db-urls = ["https://github.com/rustsec/advisory-db"]
|
||||||
|
# A list of advisory IDs to ignore. Note that ignored advisories will still
|
||||||
|
# output a note when they are encountered.
|
||||||
|
ignore = [
|
||||||
|
#"RUSTSEC-0000-0000",
|
||||||
|
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
|
||||||
|
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
|
||||||
|
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" },
|
||||||
|
]
|
||||||
|
# If this is true, then cargo deny will use the git executable to fetch advisory database.
|
||||||
|
# If this is false, then it uses a built-in git library.
|
||||||
|
# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support.
|
||||||
|
# See Git Authentication for more information about setting up git authentication.
|
||||||
|
#git-fetch-with-cli = true
|
||||||
|
|
||||||
|
# This section is considered when running `cargo deny check licenses`
|
||||||
|
# More documentation for the licenses section can be found here:
|
||||||
|
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
|
||||||
|
[licenses]
|
||||||
|
# List of explicitly allowed licenses
|
||||||
|
# See https://spdx.org/licenses/ for list of possible licenses
|
||||||
|
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
||||||
|
allow = [
|
||||||
|
"MIT",
|
||||||
|
"BSD-2-Clause",
|
||||||
|
"BSD-3-Clause",
|
||||||
|
"Apache-2.0",
|
||||||
|
"Apache-2.0 WITH LLVM-exception",
|
||||||
|
"AGPL-3.0-only",
|
||||||
|
"Unicode-3.0",
|
||||||
|
]
|
||||||
|
# The confidence threshold for detecting a license from license text.
|
||||||
|
# The higher the value, the more closely the license text must be to the
|
||||||
|
# canonical license text of a valid SPDX license file.
|
||||||
|
# [possible values: any between 0.0 and 1.0].
|
||||||
|
confidence-threshold = 0.8
|
||||||
|
# Allow 1 or more licenses on a per-crate basis, so that particular licenses
|
||||||
|
# aren't accepted for every possible crate as with the normal allow list
|
||||||
|
exceptions = [
|
||||||
|
# Each entry is the crate and version constraint, and its specific allow
|
||||||
|
# list
|
||||||
|
#{ allow = ["Zlib"], crate = "adler32" },
|
||||||
|
]
|
||||||
|
|
||||||
|
# Some crates don't have (easily) machine readable licensing information,
|
||||||
|
# adding a clarification entry for it allows you to manually specify the
|
||||||
|
# licensing information
|
||||||
|
#[[licenses.clarify]]
|
||||||
|
# The package spec the clarification applies to
|
||||||
|
#crate = "ring"
|
||||||
|
# The SPDX expression for the license requirements of the crate
|
||||||
|
#expression = "MIT AND ISC AND OpenSSL"
|
||||||
|
# One or more files in the crate's source used as the "source of truth" for
|
||||||
|
# the license expression. If the contents match, the clarification will be used
|
||||||
|
# when running the license check, otherwise the clarification will be ignored
|
||||||
|
# and the crate will be checked normally, which may produce warnings or errors
|
||||||
|
# depending on the rest of your configuration
|
||||||
|
#license-files = [
|
||||||
|
# Each entry is a crate relative path, and the (opaque) hash of its contents
|
||||||
|
#{ path = "LICENSE", hash = 0xbd0eed23 }
|
||||||
|
#]
|
||||||
|
|
||||||
|
[licenses.private]
|
||||||
|
# If true, ignores workspace crates that aren't published, or are only
|
||||||
|
# published to private registries.
|
||||||
|
# To see how to mark a crate as unpublished (to the official registry),
|
||||||
|
# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field.
|
||||||
|
ignore = false
|
||||||
|
# One or more private registries that you might publish crates to, if a crate
|
||||||
|
# is only published to private registries, and ignore is true, the crate will
|
||||||
|
# not have its license(s) checked
|
||||||
|
registries = [
|
||||||
|
#"https://sekretz.com/registry
|
||||||
|
]
|
||||||
|
|
||||||
|
# This section is considered when running `cargo deny check bans`.
|
||||||
|
# More documentation about the 'bans' section can be found here:
|
||||||
|
# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html
|
||||||
|
[bans]
|
||||||
|
# Lint level for when multiple versions of the same crate are detected
|
||||||
|
multiple-versions = "warn"
|
||||||
|
# Lint level for when a crate version requirement is `*`
|
||||||
|
wildcards = "allow"
|
||||||
|
# The graph highlighting used when creating dotgraphs for crates
|
||||||
|
# with multiple versions
|
||||||
|
# * lowest-version - The path to the lowest versioned duplicate is highlighted
|
||||||
|
# * simplest-path - The path to the version with the fewest edges is highlighted
|
||||||
|
# * all - Both lowest-version and simplest-path are used
|
||||||
|
highlight = "all"
|
||||||
|
# The default lint level for `default` features for crates that are members of
|
||||||
|
# the workspace that is being checked. This can be overridden by allowing/denying
|
||||||
|
# `default` on a crate-by-crate basis if desired.
|
||||||
|
workspace-default-features = "allow"
|
||||||
|
# The default lint level for `default` features for external crates that are not
|
||||||
|
# members of the workspace. This can be overridden by allowing/denying `default`
|
||||||
|
# on a crate-by-crate basis if desired.
|
||||||
|
external-default-features = "allow"
|
||||||
|
# List of crates that are allowed. Use with care!
|
||||||
|
allow = [
|
||||||
|
#"ansi_term@0.11.0",
|
||||||
|
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" },
|
||||||
|
]
|
||||||
|
# If true, workspace members are automatically allowed even when using deny-by-default
|
||||||
|
# This is useful for organizations that want to deny all external dependencies by default
|
||||||
|
# but allow their own workspace crates without having to explicitly list them
|
||||||
|
allow-workspace = false
|
||||||
|
# List of crates to deny
|
||||||
|
deny = [
|
||||||
|
#"ansi_term@0.11.0",
|
||||||
|
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" },
|
||||||
|
# Wrapper crates can optionally be specified to allow the crate when it
|
||||||
|
# is a direct dependency of the otherwise banned crate
|
||||||
|
#{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] },
|
||||||
|
]
|
||||||
|
|
||||||
|
# List of features to allow/deny
|
||||||
|
# Each entry the name of a crate and a version range. If version is
|
||||||
|
# not specified, all versions will be matched.
|
||||||
|
#[[bans.features]]
|
||||||
|
#crate = "reqwest"
|
||||||
|
# Features to not allow
|
||||||
|
#deny = ["json"]
|
||||||
|
# Features to allow
|
||||||
|
#allow = [
|
||||||
|
# "rustls",
|
||||||
|
# "__rustls",
|
||||||
|
# "__tls",
|
||||||
|
# "hyper-rustls",
|
||||||
|
# "rustls",
|
||||||
|
# "rustls-pemfile",
|
||||||
|
# "rustls-tls-webpki-roots",
|
||||||
|
# "tokio-rustls",
|
||||||
|
# "webpki-roots",
|
||||||
|
#]
|
||||||
|
# If true, the allowed features must exactly match the enabled feature set. If
|
||||||
|
# this is set there is no point setting `deny`
|
||||||
|
#exact = true
|
||||||
|
|
||||||
|
# Certain crates/versions that will be skipped when doing duplicate detection.
|
||||||
|
skip = [
|
||||||
|
#"ansi_term@0.11.0",
|
||||||
|
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" },
|
||||||
|
]
|
||||||
|
# Similarly to `skip` allows you to skip certain crates during duplicate
|
||||||
|
# detection. Unlike skip, it also includes the entire tree of transitive
|
||||||
|
# dependencies starting at the specified crate, up to a certain depth, which is
|
||||||
|
# by default infinite.
|
||||||
|
skip-tree = [
|
||||||
|
#"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies
|
||||||
|
#{ crate = "ansi_term@0.11.0", depth = 20 },
|
||||||
|
]
|
||||||
|
|
||||||
|
# This section is considered when running `cargo deny check sources`.
|
||||||
|
# More documentation about the 'sources' section can be found here:
|
||||||
|
# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html
|
||||||
|
[sources]
|
||||||
|
# Lint level for what to happen when a crate from a crate registry that is not
|
||||||
|
# in the allow list is encountered
|
||||||
|
unknown-registry = "warn"
|
||||||
|
# Lint level for what to happen when a crate from a git repository that is not
|
||||||
|
# in the allow list is encountered
|
||||||
|
unknown-git = "warn"
|
||||||
|
# List of URLs for allowed crate registries. Defaults to the crates.io index
|
||||||
|
# if not specified. If it is specified but empty, no registries are allowed.
|
||||||
|
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
|
||||||
|
# List of URLs for allowed Git repositories
|
||||||
|
allow-git = []
|
||||||
|
|
||||||
|
[sources.allow-org]
|
||||||
|
# github.com organizations to allow git sources for
|
||||||
|
github = []
|
||||||
|
# gitlab.com organizations to allow git sources for
|
||||||
|
gitlab = []
|
||||||
|
# bitbucket.org organizations to allow git sources for
|
||||||
|
bitbucket = []
|
||||||
26
flake.lock
generated
Normal file
26
flake.lock
generated
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1780453794,
|
||||||
|
"narHash": "sha256-bXMRa9VTsHSPXL4Cw8R6JJLQeY3Y/IP4+YJCYVmQ7FY=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "6b316287bae2ee04c9b93c8c858d930fd07d7338",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-26.05",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
99
flake.nix
Normal file
99
flake.nix
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
# Note this is just a draft, not properly tested or documented yet
|
||||||
|
|
||||||
|
{
|
||||||
|
description = "A non-linear writing instrument.";
|
||||||
|
inputs.nixpkgs.url = "nixpkgs/nixos-26.05";
|
||||||
|
|
||||||
|
outputs = { nixpkgs, self }: let
|
||||||
|
name = "en";
|
||||||
|
version = "0.4.0-alpha";
|
||||||
|
|
||||||
|
supportedSystems = [
|
||||||
|
"x86_64-linux"
|
||||||
|
];
|
||||||
|
|
||||||
|
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||||
|
nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; });
|
||||||
|
|
||||||
|
in {
|
||||||
|
packages = forAllSystems (system: let pkgs = nixpkgsFor.${system};
|
||||||
|
in {
|
||||||
|
default = pkgs.rustPlatform.buildRustPackage {
|
||||||
|
inherit name version;
|
||||||
|
src = ./.;
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
just
|
||||||
|
];
|
||||||
|
dontUseJustInstall = true;
|
||||||
|
dontUseJustBuild = true;
|
||||||
|
cargoHash =
|
||||||
|
"sha256-U6jf48KmqcdCBYKyZhYPpiv5qj98SjlNqw8Ii2mJn0I=";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
devShells = forAllSystems (system:
|
||||||
|
let
|
||||||
|
pkgs = nixpkgsFor.${system};
|
||||||
|
base = with pkgs; [
|
||||||
|
rustup
|
||||||
|
just
|
||||||
|
watchexec
|
||||||
|
cargo-deny
|
||||||
|
cargo-llvm-cov
|
||||||
|
cargo-mutants
|
||||||
|
cargo-msrv
|
||||||
|
typos
|
||||||
|
taplo
|
||||||
|
];
|
||||||
|
in {
|
||||||
|
default = pkgs.mkShell { buildInputs = base; };
|
||||||
|
cross = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; base ++ [
|
||||||
|
cargo-xwin
|
||||||
|
wine
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
nixosModules.en = { config, lib, system, ... }:
|
||||||
|
{
|
||||||
|
options.within.services.en = {
|
||||||
|
enable = lib.mkEnableOption "enable en server";
|
||||||
|
port = lib.mkOption {
|
||||||
|
description = "Port to serve your graph on";
|
||||||
|
defaultText = "A random port chosen by the OS";
|
||||||
|
type = lib.types.port;
|
||||||
|
};
|
||||||
|
host = lib.mkOption {
|
||||||
|
description = "Address or hostname to serve your graph on";
|
||||||
|
default = "0.0.0.0";
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
graph = lib.mkOption {
|
||||||
|
description = "File path pointing to your graph file";
|
||||||
|
default = "./static/graph.toml";
|
||||||
|
type = lib.types.path;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config =
|
||||||
|
lib.mkIf config.within.services.en.enable {
|
||||||
|
systemd.services.en = {
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Restart = "always";
|
||||||
|
ExecStart = let
|
||||||
|
user_opts = config.within.services.en;
|
||||||
|
in
|
||||||
|
"${self.packages.${system}.default}/bin/en"
|
||||||
|
+ " --port ${user_opts.port}"
|
||||||
|
+ " --host ${user_opts.host}"
|
||||||
|
+ " --graph ${user_opts.graph}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -396,7 +396,7 @@ impl Graph {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if let Some(destination) = anchor.destination()
|
if let Some(destination) = anchor.destination()
|
||||||
&& !anchor.external()
|
&& !anchor.absolute()
|
||||||
{
|
{
|
||||||
let trimmed_destination = destination
|
let trimmed_destination = destination
|
||||||
.trim_start_matches("/node/")
|
.trim_start_matches("/node/")
|
||||||
|
|
@ -665,7 +665,7 @@ mod tests {
|
||||||
"title": "JSON",
|
"title": "JSON",
|
||||||
"links": [],
|
"links": [],
|
||||||
"id": "JSON",
|
"id": "JSON",
|
||||||
"hidden": false,
|
"listed": true,
|
||||||
"connections": {}
|
"connections": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ pub struct Node {
|
||||||
pub links: Vec<String>,
|
pub links: Vec<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub redirect: String,
|
pub redirect: String,
|
||||||
#[serde(default)]
|
#[serde(default = "mktrue")]
|
||||||
pub hidden: bool,
|
pub listed: bool,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub connections: HashMap<String, Edge>,
|
pub connections: HashMap<String, Edge>,
|
||||||
|
|
@ -28,6 +28,9 @@ pub struct Node {
|
||||||
pub stats: Stats,
|
pub stats: Stats,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See: https://github.com/serde-rs/serde/issues/368
|
||||||
|
const fn mktrue() -> bool { true }
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Default, Eq, PartialEq, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Default, Eq, PartialEq, Debug)]
|
||||||
pub struct Stats {
|
pub struct Stats {
|
||||||
pub outgoing: u32,
|
pub outgoing: u32,
|
||||||
|
|
@ -46,7 +49,7 @@ impl Node {
|
||||||
connections: HashMap::default(),
|
connections: HashMap::default(),
|
||||||
links: vec![],
|
links: vec![],
|
||||||
redirect: String::default(),
|
redirect: String::default(),
|
||||||
hidden: false,
|
listed: true,
|
||||||
summary: String::default(),
|
summary: String::default(),
|
||||||
stats: Stats::default(),
|
stats: Stats::default(),
|
||||||
}
|
}
|
||||||
|
|
@ -78,8 +81,8 @@ impl std::fmt::Display for Node {
|
||||||
meta_elements.push(format!("links:{links}"));
|
meta_elements.push(format!("links:{links}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.hidden {
|
if !self.listed {
|
||||||
meta_elements.push(String::from("hidden"));
|
meta_elements.push(String::from("unlisted"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let meta = meta_elements.join(" ");
|
let meta = meta_elements.join(" ");
|
||||||
|
|
@ -143,7 +146,7 @@ mod tests {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
node.hidden = true;
|
node.listed = false;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{node}"),
|
format!("{node}"),
|
||||||
|
|
@ -153,7 +156,7 @@ mod tests {
|
||||||
text:15l summary:{} \
|
text:15l summary:{} \
|
||||||
redirect:{redirect} \
|
redirect:{redirect} \
|
||||||
links:{} \
|
links:{} \
|
||||||
hidden\
|
unlisted\
|
||||||
]",
|
]",
|
||||||
summary.len(),
|
summary.len(),
|
||||||
node.links.len(),
|
node.links.len(),
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ impl Asset {
|
||||||
///
|
///
|
||||||
/// Defaults are found in the `fixed::DEFAULTS` map.
|
/// Defaults are found in the `fixed::DEFAULTS` map.
|
||||||
///
|
///
|
||||||
/// Returns a `FallbackError` if neither is found or an I/O error ocurred.
|
/// Returns a `FallbackError` if neither is found or an I/O error occurred.
|
||||||
fn fallback(path: &str, graph: &Graph) -> Result<Asset, AssetError> {
|
fn fallback(path: &str, graph: &Graph) -> Result<Asset, AssetError> {
|
||||||
let target = format!("static/public/assets/{path}");
|
let target = format!("static/public/assets/{path}");
|
||||||
let defaults: HashMap<&str, &str> = TEXTS.iter().copied().collect();
|
let defaults: HashMap<&str, &str> = TEXTS.iter().copied().collect();
|
||||||
|
|
@ -292,7 +292,7 @@ pub async fn file(
|
||||||
} else {
|
} else {
|
||||||
String::from(
|
String::from(
|
||||||
"The requested file exists, but the server lacks \
|
"The requested file exists, but the server lacks \
|
||||||
permission to access it or another I/O error ocurred.",
|
permission to access it or another I/O error occurred.",
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
if log::env_level() >= DEBUG {
|
if log::env_level() >= DEBUG {
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn docs_redirect() {
|
async fn docs_redirect() {
|
||||||
let response = wrap_node("docs").await;
|
let response = wrap_node("RedirectTest").await;
|
||||||
assert_eq!(response.status(), StatusCode::PERMANENT_REDIRECT);
|
assert_eq!(response.status(), StatusCode::PERMANENT_REDIRECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
use crate::syntax::content::parser::{
|
use crate::syntax::content::parser::{
|
||||||
State, Token,
|
State, Token,
|
||||||
token::{Header, Paragraph, PreFormat, Verse},
|
token::{Header, Paragraph, Verse},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod anchor;
|
pub mod anchor;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod inline;
|
pub mod inline;
|
||||||
pub mod list;
|
pub mod list;
|
||||||
|
pub mod preformat;
|
||||||
pub mod quote;
|
pub mod quote;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
|
|
||||||
|
|
@ -38,30 +39,32 @@ pub enum Inline {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// Panics if there is an open header or list at end of input.
|
/// Panics if there is an open token at end of input that can't be easily
|
||||||
|
/// closed by simply adding a matching closing token. This normally is handled
|
||||||
|
/// by context parsers and probably indicates an error in one of them.
|
||||||
pub fn close(state: &State, tokens: &mut Vec<Token>) {
|
pub fn close(state: &State, tokens: &mut Vec<Token>) {
|
||||||
match state.context.block {
|
match state.context.block {
|
||||||
Block::PreFormat => {
|
|
||||||
tokens.push(Token::PreFormat(PreFormat::new(false)));
|
|
||||||
},
|
|
||||||
Block::Paragraph => {
|
Block::Paragraph => {
|
||||||
tokens.push(Token::Paragraph(Paragraph::new(false)));
|
tokens.push(Token::Paragraph(Paragraph::new(false)));
|
||||||
},
|
},
|
||||||
Block::List => {
|
|
||||||
panic!("End of input with open list")
|
|
||||||
},
|
|
||||||
Block::Header(level) => {
|
Block::Header(level) => {
|
||||||
tokens.push(Token::Header(Header::from_u8(level, false, None)));
|
tokens.push(Token::Header(Header::from_u8(level, false, None)));
|
||||||
},
|
},
|
||||||
Block::Quote => {
|
|
||||||
panic!("End of input with open quote")
|
|
||||||
},
|
|
||||||
Block::Table => {
|
|
||||||
panic!("End of input with open table")
|
|
||||||
},
|
|
||||||
Block::Verse => {
|
Block::Verse => {
|
||||||
tokens.push(Token::Verse(Verse::new(false)));
|
tokens.push(Token::Verse(Verse::new(false)));
|
||||||
},
|
},
|
||||||
|
Block::PreFormat => {
|
||||||
|
panic!("End of input with open preformat: {tokens:#?}")
|
||||||
|
},
|
||||||
|
Block::List => {
|
||||||
|
panic!("End of input with open list: {tokens:#?}")
|
||||||
|
},
|
||||||
|
Block::Quote => {
|
||||||
|
panic!("End of input with open quote: {tokens:#?}")
|
||||||
|
},
|
||||||
|
Block::Table => {
|
||||||
|
panic!("End of input with open table: {tokens:#?}")
|
||||||
|
},
|
||||||
Block::None => (),
|
Block::None => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,9 @@ pub fn parse(
|
||||||
log!(VERBOSE, "End: Next lexeme is a pipe");
|
log!(VERBOSE, "End: Next lexeme is a pipe");
|
||||||
buffer.text.push_str(&lexeme.text());
|
buffer.text.push_str(&lexeme.text());
|
||||||
candidate.set_text(&buffer.text.clone());
|
candidate.set_text(&buffer.text.clone());
|
||||||
|
if buffer.text.starts_with('/') {
|
||||||
|
candidate.set_absolute(true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log!(
|
log!(
|
||||||
VERBOSE,
|
VERBOSE,
|
||||||
|
|
@ -84,6 +87,13 @@ pub fn parse(
|
||||||
"State: Found a pipe, but no boundary: destination follows"
|
"State: Found a pipe, but no boundary: destination follows"
|
||||||
);
|
);
|
||||||
candidate.set_balanced(true);
|
candidate.set_balanced(true);
|
||||||
|
if lexeme.match_next_first_char('/') {
|
||||||
|
log!(
|
||||||
|
VERBOSE,
|
||||||
|
"State: Destination starts with a dash, marking as absolute"
|
||||||
|
);
|
||||||
|
candidate.set_absolute(true);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if lexeme.match_char(':') {
|
} else if lexeme.match_char(':') {
|
||||||
log!(VERBOSE, "State: Found a colon, marking anchor as external");
|
log!(VERBOSE, "State: Found a colon, marking anchor as external");
|
||||||
|
|
@ -205,8 +215,10 @@ mod tests {
|
||||||
fn needless_three_pipe_anchor() {
|
fn needless_three_pipe_anchor() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
read("|Node|Destination|"),
|
read("|Node|Destination|"),
|
||||||
concat!(r#"<p><a class="detached" title="" "#,
|
concat!(
|
||||||
r#"href="/node/Destination">Node</a></p>"#)
|
r#"<p><a class="detached" title="" "#,
|
||||||
|
r#"href="/node/Destination">Node</a></p>"#
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,9 +237,11 @@ mod tests {
|
||||||
fn anchor_to_node_s() {
|
fn anchor_to_node_s() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
read("The |letter s|s|'s node: |s|!"),
|
read("The |letter s|s|'s node: |s|!"),
|
||||||
concat!(r#"<p>The <a class="detached" title="" "#,
|
concat!(
|
||||||
|
r#"<p>The <a class="detached" title="" "#,
|
||||||
r#"href="/node/s">letter s</a>'s node: "#,
|
r#"href="/node/s">letter s</a>'s node: "#,
|
||||||
r#"<a class="detached" title="" href="/node/s">s</a>!</p>"#)
|
r#"<a class="detached" title="" href="/node/s">s</a>!</p>"#
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,9 +260,11 @@ mod tests {
|
||||||
fn leading_plural_anchor() {
|
fn leading_plural_anchor() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
read("Interfaces are |element|s of |system|s."),
|
read("Interfaces are |element|s of |system|s."),
|
||||||
concat!(r#"<p>Interfaces are <a class="detached" title="" "#,
|
concat!(
|
||||||
|
r#"<p>Interfaces are <a class="detached" title="" "#,
|
||||||
r#"href="/node/element">elements</a> of <a class="detached" "#,
|
r#"href="/node/element">elements</a> of <a class="detached" "#,
|
||||||
r#"title="" href="/node/system">systems</a>.</p>"#)
|
r#"title="" href="/node/system">systems</a>.</p>"#
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,9 +284,11 @@ mod tests {
|
||||||
fn explicit_end_of_destination() {
|
fn explicit_end_of_destination() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
read("interactions are |basic elements|BasicElements| of systems"),
|
read("interactions are |basic elements|BasicElements| of systems"),
|
||||||
concat!(r#"<p>interactions are <a class="detached" title="" "#,
|
concat!(
|
||||||
|
r#"<p>interactions are <a class="detached" title="" "#,
|
||||||
r#"href="/node/BasicElements">basic elements</a> of "#,
|
r#"href="/node/BasicElements">basic elements</a> of "#,
|
||||||
r#"systems</p>"#)
|
r#"systems</p>"#
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -327,6 +345,21 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn absolute_anchor() {
|
||||||
|
let parse_result =
|
||||||
|
parser::rich_read("see the |raw endpoints|/data|.", &Graph::load());
|
||||||
|
println!("Parsed tokens: {:#?}", parse_result.tokens);
|
||||||
|
assert_eq!(
|
||||||
|
parse_result.text.unwrap(),
|
||||||
|
concat!(
|
||||||
|
r#"<p>see the <a class="absolute" title="" "#,
|
||||||
|
r#"href="/data">"#,
|
||||||
|
r#"raw endpoints</a>.</p>"#,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn http_external_anchor() {
|
fn http_external_anchor() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,17 @@ use crate::{
|
||||||
syntax::content::{
|
syntax::content::{
|
||||||
Parseable as _,
|
Parseable as _,
|
||||||
parser::{
|
parser::{
|
||||||
Block, Lexeme, State, Token,
|
Block, Lexeme, State, Token, context,
|
||||||
token::{
|
token::{
|
||||||
Header, LineBreak, List, Literal, Paragraph, PreFormat, Quote,
|
Header, LineBreak, List, Paragraph, PreFormat, Quote, Table,
|
||||||
Table, Verse,
|
Verse,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A return of `true` will trigger a `continue` on the outer parser, causing
|
||||||
|
/// no more subsequent parsing of the current lexeme.
|
||||||
pub fn parse(
|
pub fn parse(
|
||||||
lexeme: &Lexeme,
|
lexeme: &Lexeme,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
|
|
@ -27,8 +29,7 @@ pub fn parse(
|
||||||
if PreFormat::probe(lexeme) {
|
if PreFormat::probe(lexeme) {
|
||||||
log!(VERBOSE, "Block Context: None -> PreFormat on {lexeme}");
|
log!(VERBOSE, "Block Context: None -> PreFormat on {lexeme}");
|
||||||
state.context.block = Block::PreFormat;
|
state.context.block = Block::PreFormat;
|
||||||
tokens.push(Token::PreFormat(PreFormat::new(true)));
|
return true
|
||||||
return true;
|
|
||||||
} else if Header::probe(lexeme) {
|
} else if Header::probe(lexeme) {
|
||||||
let mut header = Header::lex(lexeme);
|
let mut header = Header::lex(lexeme);
|
||||||
header.dom_id = Some(Header::make_id(
|
header.dom_id = Some(Header::make_id(
|
||||||
|
|
@ -44,7 +45,7 @@ pub fn parse(
|
||||||
log!(VERBOSE, "Block Context: None -> List on {lexeme}");
|
log!(VERBOSE, "Block Context: None -> List on {lexeme}");
|
||||||
state.context.block = Block::List;
|
state.context.block = Block::List;
|
||||||
state.buffers.list.candidate.ordered = lexeme.match_char('+');
|
state.buffers.list.candidate.ordered = lexeme.match_char('+');
|
||||||
return super::list::parse(
|
return context::list::parse(
|
||||||
lexeme, state, tokens, iterator, graph,
|
lexeme, state, tokens, iterator, graph,
|
||||||
);
|
);
|
||||||
} else if Quote::probe(lexeme) {
|
} else if Quote::probe(lexeme) {
|
||||||
|
|
@ -71,14 +72,7 @@ pub fn parse(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Block::PreFormat => {
|
Block::PreFormat => {
|
||||||
if PreFormat::probe(lexeme) {
|
return context::preformat::parse(lexeme, state, tokens, iterator);
|
||||||
tokens.push(Token::PreFormat(PreFormat::new(false)));
|
|
||||||
log!(VERBOSE, "Block Context: PreFormat -> None on {lexeme}");
|
|
||||||
state.context.block = Block::None;
|
|
||||||
} else {
|
|
||||||
tokens.push(Token::Literal(Literal::lex(lexeme)));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
Block::Paragraph => {
|
Block::Paragraph => {
|
||||||
if Paragraph::probe_end(lexeme) {
|
if Paragraph::probe_end(lexeme) {
|
||||||
|
|
@ -95,13 +89,17 @@ pub fn parse(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Block::List => {
|
Block::List => {
|
||||||
return super::list::parse(lexeme, state, tokens, iterator, graph);
|
return context::list::parse(lexeme, state, tokens, iterator, graph);
|
||||||
},
|
},
|
||||||
Block::Quote => {
|
Block::Quote => {
|
||||||
return super::quote::parse(lexeme, state, tokens, iterator, graph);
|
return context::quote::parse(
|
||||||
|
lexeme, state, tokens, iterator, graph,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
Block::Table => {
|
Block::Table => {
|
||||||
return super::table::parse(lexeme, state, tokens, iterator, graph);
|
return context::table::parse(
|
||||||
|
lexeme, state, tokens, iterator, graph,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
Block::Verse => {
|
Block::Verse => {
|
||||||
if Verse::probe_end(lexeme) {
|
if Verse::probe_end(lexeme) {
|
||||||
|
|
@ -127,7 +125,7 @@ mod tests {
|
||||||
graph::Graph,
|
graph::Graph,
|
||||||
syntax::content::parser::{
|
syntax::content::parser::{
|
||||||
self, Block, State, Token, context,
|
self, Block, State, Token, context,
|
||||||
token::{Header, PreFormat, header::Level},
|
token::{Header, header::Level},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -161,16 +159,6 @@ mod tests {
|
||||||
assert_eq!(vec, vec![Token::Header(Header::from_u8(1, false, None))]);
|
assert_eq!(vec, vec![Token::Header(Header::from_u8(1, false, None))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn end_with_open_preformat() {
|
|
||||||
let mut state = State::default();
|
|
||||||
state.context.block = Block::PreFormat;
|
|
||||||
|
|
||||||
let mut vec: Vec<Token> = vec![];
|
|
||||||
context::close(&state, &mut vec);
|
|
||||||
assert_eq!(vec, vec![Token::PreFormat(PreFormat::new(false))]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn truncated_header_level() {
|
fn truncated_header_level() {
|
||||||
let u: usize = 999;
|
let u: usize = 999;
|
||||||
|
|
|
||||||
61
src/syntax/content/parser/context/preformat.rs
Normal file
61
src/syntax/content/parser/context/preformat.rs
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
use std::{iter::Peekable, slice::Iter};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
prelude::*,
|
||||||
|
syntax::content::{
|
||||||
|
Parseable as _,
|
||||||
|
parser::{Lexeme, State, Token, context::Block, token::PreFormat},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Handles open `PreFormat` contexts until a block is fully parsed.
|
||||||
|
///
|
||||||
|
/// A return of `true` will trigger a continue in the outer parser,
|
||||||
|
/// skipping any further parsing of the current lexeme.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// This parser can handle only the List context, and will panic if passed an
|
||||||
|
/// unrelated context since it has no knowledge on how to handle them.
|
||||||
|
pub fn parse(
|
||||||
|
lexeme: &Lexeme,
|
||||||
|
state: &mut State,
|
||||||
|
tokens: &mut Vec<Token>,
|
||||||
|
iterator: &mut Peekable<Iter<'_, Lexeme>>,
|
||||||
|
) -> bool {
|
||||||
|
let buffer = &mut state.buffers.preformat;
|
||||||
|
let candidate = &mut buffer.candidate;
|
||||||
|
|
||||||
|
#[expect(clippy::wildcard_enum_match_arm)]
|
||||||
|
match state.context.block {
|
||||||
|
Block::PreFormat => {
|
||||||
|
if lexeme.match_first_char('<') {
|
||||||
|
candidate.text.push_str("<");
|
||||||
|
candidate.text.push_str(
|
||||||
|
lexeme.text().strip_prefix('<').unwrap_or(&lexeme.text()),
|
||||||
|
);
|
||||||
|
} else if lexeme.match_last_char('>') {
|
||||||
|
candidate.text.push_str(
|
||||||
|
lexeme.text().strip_suffix('>').unwrap_or(&lexeme.text()),
|
||||||
|
);
|
||||||
|
candidate.text.push_str(">");
|
||||||
|
} else if lexeme.match_char('\\') {
|
||||||
|
candidate.text.push_str(lexeme.next().as_str());
|
||||||
|
iterator.next();
|
||||||
|
return true;
|
||||||
|
} else if PreFormat::probe(lexeme) {
|
||||||
|
// found end of block, push it and reset state
|
||||||
|
log!(VERBOSE, "Accepting preformat candidate {candidate}");
|
||||||
|
tokens.push(Token::PreFormat(candidate.clone()));
|
||||||
|
state.context.block = Block::None;
|
||||||
|
*candidate = PreFormat::default();
|
||||||
|
} else {
|
||||||
|
// anything else is pushed into the candidate preformat's text
|
||||||
|
candidate.text.push_str(&lexeme.text());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
panic!("PreFormat context parser called for {:?}", state.context)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
@ -32,6 +32,8 @@ impl Lexeme {
|
||||||
|
|
||||||
pub fn mutate_text(&mut self, new: &str) { self.text = new.to_string(); }
|
pub fn mutate_text(&mut self, new: &str) { self.text = new.to_string(); }
|
||||||
|
|
||||||
|
/// Returns an Option containing the character if the raw lexeme text
|
||||||
|
/// is composed of a single character, None if it has multiple characters.
|
||||||
pub fn as_char(&self) -> Option<char> {
|
pub fn as_char(&self) -> Option<char> {
|
||||||
if self.text.chars().count() == 1 {
|
if self.text.chars().count() == 1 {
|
||||||
self.text.chars().nth(0)
|
self.text.chars().nth(0)
|
||||||
|
|
@ -56,6 +58,7 @@ impl Lexeme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the raw lexeme text is a single matching character.
|
||||||
pub fn match_char(&self, c: char) -> bool {
|
pub fn match_char(&self, c: char) -> bool {
|
||||||
self.as_char().is_some_and(|as_char| as_char == c)
|
self.as_char().is_some_and(|as_char| as_char == c)
|
||||||
}
|
}
|
||||||
|
|
@ -86,6 +89,8 @@ impl Lexeme {
|
||||||
&& self.match_third_char(c3)
|
&& self.match_third_char(c3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the lexeme raw text is composed of a single character
|
||||||
|
/// and this character is in the provided slice.
|
||||||
pub fn match_char_in(&self, slice: &[char]) -> bool {
|
pub fn match_char_in(&self, slice: &[char]) -> bool {
|
||||||
self.as_char().is_some_and(|c| slice.contains(&c))
|
self.as_char().is_some_and(|c| slice.contains(&c))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,9 @@ pub(super) fn lex(
|
||||||
|
|
||||||
let mut iterator = lexemes.iter().peekable();
|
let mut iterator = lexemes.iter().peekable();
|
||||||
while let Some(lexeme) = iterator.next() {
|
while let Some(lexeme) = iterator.next() {
|
||||||
if lexeme.match_char('\\') {
|
if lexeme.match_char('\\')
|
||||||
|
&& !matches!(state.context.block, context::Block::PreFormat)
|
||||||
|
{
|
||||||
if let Some(next) = iterator.next() {
|
if let Some(next) = iterator.next() {
|
||||||
tokens.push(Token::Literal(Literal::lex(next)));
|
tokens.push(Token::Literal(Literal::lex(next)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||||
use crate::syntax::content::parser::{
|
use crate::syntax::content::parser::{
|
||||||
Token,
|
Token,
|
||||||
context::Context,
|
context::Context,
|
||||||
token::{Anchor, Item, List, Quote, Table},
|
token::{Anchor, Item, List, PreFormat, Quote, Table},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug)]
|
#[derive(Clone, Default, Debug)]
|
||||||
|
|
@ -29,6 +29,7 @@ pub struct Buffers {
|
||||||
pub list: ListBuffer,
|
pub list: ListBuffer,
|
||||||
pub quote: QuoteBuffer,
|
pub quote: QuoteBuffer,
|
||||||
pub table: TableBuffer,
|
pub table: TableBuffer,
|
||||||
|
pub preformat: PreFormatBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug)]
|
#[derive(Default, Clone, Debug)]
|
||||||
|
|
@ -59,6 +60,11 @@ pub struct TableBuffer {
|
||||||
pub in_header: bool,
|
pub in_header: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Debug)]
|
||||||
|
pub struct PreFormatBuffer {
|
||||||
|
pub candidate: PreFormat,
|
||||||
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for AnchorBuffer {
|
impl std::fmt::Display for AnchorBuffer {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
let display_text = if self.text.is_empty() {
|
let display_text = if self.text.is_empty() {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ pub struct Anchor {
|
||||||
node: Option<Node>,
|
node: Option<Node>,
|
||||||
leading: bool,
|
leading: bool,
|
||||||
balanced: bool,
|
balanced: bool,
|
||||||
|
absolute: bool,
|
||||||
external: bool,
|
external: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,10 +35,17 @@ impl Anchor {
|
||||||
self.balanced = balanced;
|
self.balanced = balanced;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn absolute(&self) -> bool { self.absolute }
|
||||||
|
|
||||||
|
pub const fn set_absolute(&mut self, absolute: bool) {
|
||||||
|
self.absolute = absolute;
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn external(&self) -> bool { self.external }
|
pub const fn external(&self) -> bool { self.external }
|
||||||
|
|
||||||
pub const fn set_external(&mut self, external: bool) {
|
pub const fn set_external(&mut self, external: bool) {
|
||||||
self.external = external;
|
self.external = external;
|
||||||
|
self.absolute = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn set_leading(&mut self, leading: bool) {
|
pub const fn set_leading(&mut self, leading: bool) {
|
||||||
|
|
@ -58,21 +66,28 @@ impl Anchor {
|
||||||
|
|
||||||
fn route(&mut self) {
|
fn route(&mut self) {
|
||||||
self.destination = if let Some(destination) = self.destination.clone() {
|
self.destination = if let Some(destination) = self.destination.clone() {
|
||||||
if destination.contains(':') || destination.contains('/') {
|
if destination.contains(':') || destination.starts_with('/') {
|
||||||
Some(destination)
|
Some(destination)
|
||||||
} else if destination.is_empty() && self.text.is_empty() {
|
} else if destination.is_empty() && self.text.is_empty() {
|
||||||
None
|
None
|
||||||
} else if destination.is_empty() {
|
} else if destination.is_empty() {
|
||||||
self.node_id = Some(self.text.clone());
|
self.node_id = Some(Self::strip_fragment(&self.text));
|
||||||
Some(format!("/node/{}", self.text))
|
Some(format!("/node/{}", self.text))
|
||||||
} else {
|
} else {
|
||||||
self.node_id = self.destination.clone();
|
self.node_id = self
|
||||||
|
.destination
|
||||||
|
.clone()
|
||||||
|
.map(|d| Anchor::strip_fragment(&d));
|
||||||
Some(format!("/node/{destination}"))
|
Some(format!("/node/{destination}"))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn strip_fragment(target: &str) -> String {
|
||||||
|
target.split('#').next().unwrap_or(target).to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parseable for Anchor {
|
impl Parseable for Anchor {
|
||||||
|
|
@ -100,19 +115,31 @@ impl Parseable for Anchor {
|
||||||
String::default()
|
String::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let classes = if self.node.is_some() {
|
let classes = if self.external {
|
||||||
String::from(r#"class="attached""#)
|
|
||||||
} else if !self.external {
|
|
||||||
String::from(r#"class="detached""#)
|
|
||||||
} else if self.external {
|
|
||||||
String::from(r#"class="external""#)
|
String::from(r#"class="external""#)
|
||||||
|
} else if self.absolute {
|
||||||
|
String::from(r#"class="absolute""#)
|
||||||
|
} else if self.node.is_some() {
|
||||||
|
String::from(r#"class="attached""#)
|
||||||
} else {
|
} else {
|
||||||
String::default()
|
String::from(r#"class="detached""#)
|
||||||
|
};
|
||||||
|
|
||||||
|
let text = if destination.contains('#')
|
||||||
|
&& !self.absolute
|
||||||
|
&& destination == &format!("/node/{}", self.text)
|
||||||
|
{
|
||||||
|
self.text
|
||||||
|
.split('#')
|
||||||
|
.next()
|
||||||
|
.unwrap_or(&self.text)
|
||||||
|
.to_string()
|
||||||
|
} else {
|
||||||
|
self.text.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
r#"<a {classes} title="{summary}" href="{}">{}</a>"#,
|
r#"<a {classes} title="{summary}" href="{destination}">{text}</a>"#
|
||||||
destination, self.text,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,42 @@
|
||||||
use crate::syntax::content::{Lexeme, Parseable};
|
use crate::syntax::content::{Lexeme, Parseable};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Default, Clone, Eq, PartialEq)]
|
||||||
pub struct PreFormat {
|
pub struct PreFormat {
|
||||||
open: Option<bool>,
|
pub text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreFormat {
|
impl PreFormat {
|
||||||
pub const fn new(open: bool) -> PreFormat { PreFormat { open: Some(open) } }
|
pub fn new(text: &str) -> PreFormat {
|
||||||
|
PreFormat {
|
||||||
|
text: String::from(text),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for PreFormat {
|
impl std::fmt::Display for PreFormat {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
let display_open_state = if let Some(open_state) = self.open {
|
let character_count = self.text.chars().count();
|
||||||
if open_state { "open" } else { "closed" }
|
let is_whitespace = self.text.trim_ascii().is_empty();
|
||||||
|
let summary = if is_whitespace {
|
||||||
|
"empty"
|
||||||
} else {
|
} else {
|
||||||
"unknown"
|
&format!("{character_count} chars")
|
||||||
};
|
};
|
||||||
write!(f, "PreFormat [{display_open_state}]")
|
write!(f, "PreFormat [{summary}]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parseable for PreFormat {
|
impl Parseable for PreFormat {
|
||||||
fn probe(lexeme: &Lexeme) -> bool {
|
fn probe(lexeme: &Lexeme) -> bool {
|
||||||
lexeme.match_first_char('`') && (lexeme.next() == "\n" || lexeme.last())
|
lexeme.match_char('`') && (lexeme.next() == "\n" || lexeme.last())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lex(_lexeme: &Lexeme) -> PreFormat { PreFormat { open: None } }
|
fn lex(_lexeme: &Lexeme) -> PreFormat {
|
||||||
|
panic!("Attempt to lex a preformat directly from a lexeme")
|
||||||
fn render(&self) -> String {
|
|
||||||
if let Some(o) = self.open {
|
|
||||||
if o {
|
|
||||||
"<pre>".to_owned()
|
|
||||||
} else {
|
|
||||||
"</pre>".to_owned()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!(
|
|
||||||
"Attempt to render a preformat tag while open state is unknown"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render(&self) -> String { format!("<pre>{}</pre>", self.text) }
|
||||||
|
|
||||||
fn flatten(&self) -> String { String::default() }
|
fn flatten(&self) -> String { String::default() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,49 +46,39 @@ mod tests {
|
||||||
use crate::syntax::content::parser::Token;
|
use crate::syntax::content::parser::Token;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[should_panic(
|
||||||
|
expected = "Attempt to lex a preformat directly from a lexeme"
|
||||||
|
)]
|
||||||
fn lex() {
|
fn lex() {
|
||||||
let from_empty_lexeme = PreFormat::lex(&Lexeme::default());
|
let lexeme = Lexeme::new("a", "b", "c");
|
||||||
assert!(from_empty_lexeme.open.is_none());
|
PreFormat::lex(&lexeme);
|
||||||
|
|
||||||
let from_non_empty_lexeme = PreFormat::lex(&Lexeme::default());
|
|
||||||
assert!(from_non_empty_lexeme.open.is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "Attempt to render a preformat tag while \
|
|
||||||
open state is unknown")]
|
|
||||||
fn render() {
|
|
||||||
let from_empty_lexeme = PreFormat::lex(&Lexeme::default());
|
|
||||||
from_empty_lexeme.render();
|
|
||||||
|
|
||||||
let from_non_empty_lexeme = PreFormat::lex(&Lexeme::default());
|
|
||||||
from_non_empty_lexeme.render();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn token_display() {
|
fn token_display() {
|
||||||
let mut preformat = PreFormat::new(true);
|
let mut preformat = PreFormat::new("");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{}", Token::PreFormat(preformat.clone())),
|
format!("{}", Token::PreFormat(preformat.clone())),
|
||||||
"Tk:PreFormat [open]"
|
"Tk:PreFormat [empty]"
|
||||||
);
|
);
|
||||||
|
|
||||||
preformat.open = Some(false);
|
preformat.text = "\n ".to_string();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{}", Token::PreFormat(preformat.clone())),
|
format!("{}", Token::PreFormat(preformat.clone())),
|
||||||
"Tk:PreFormat [closed]"
|
"Tk:PreFormat [empty]"
|
||||||
);
|
);
|
||||||
|
|
||||||
preformat.open = None;
|
preformat.text = "text".to_string();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{}", Token::PreFormat(preformat)),
|
format!("{}", Token::PreFormat(preformat)),
|
||||||
"Tk:PreFormat [unknown]"
|
"Tk:PreFormat [4 chars]"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn flatten() {
|
fn flatten() {
|
||||||
let preformat = PreFormat::new(false);
|
let preformat = PreFormat::new("");
|
||||||
assert_eq!(preformat.flatten(), "");
|
assert_eq!(preformat.flatten(), "");
|
||||||
|
|
||||||
let token = Token::PreFormat(preformat);
|
let token = Token::PreFormat(preformat);
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ impl Parseable for Quote {
|
||||||
let content = if let Some(citation) = &self.citation {
|
let content = if let Some(citation) = &self.citation {
|
||||||
format!(
|
format!(
|
||||||
r#"{}<br/><cite class="quote-citation">{citation}</cite>"#,
|
r#"{}<br/><cite class="quote-citation">{citation}</cite>"#,
|
||||||
&self.text
|
self.text
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
String::from(&self.text)
|
String::from(&self.text)
|
||||||
|
|
|
||||||
|
|
@ -122,8 +122,8 @@ mod tests {
|
||||||
table.add_header("C");
|
table.add_header("C");
|
||||||
|
|
||||||
let table_token = Token::Table(table.clone());
|
let table_token = Token::Table(table.clone());
|
||||||
assert_eq!(format!("{table}"), format!("Table [+3 headers]"));
|
assert_eq!(format!("{table}"), "Table [+3 headers]");
|
||||||
assert_eq!(format!("{table_token}"), format!("Tk:Table [+3 headers]"));
|
assert_eq!(format!("{table_token}"), "Tk:Table [+3 headers]");
|
||||||
|
|
||||||
table.add_row(
|
table.add_row(
|
||||||
["1", "2", "3"]
|
["1", "2", "3"]
|
||||||
|
|
|
||||||
80
static/graph-schema.json
Normal file
80
static/graph-schema.json
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
{
|
||||||
|
"$id": "https://git.jutty.dev/jutty/en/raw/branch/main/static/graph-schema.json",
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"title": "Graph",
|
||||||
|
"description": "An en graph file",
|
||||||
|
"type": "object",
|
||||||
|
"$defs": {
|
||||||
|
"node": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "Node",
|
||||||
|
"description": "A node object.",
|
||||||
|
"example": "[nodes.Earth]\ntext = \"Earth is a planet of the solar system.\"",
|
||||||
|
"default": null,
|
||||||
|
"properties": {
|
||||||
|
"text": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The text content of this node."
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The node display title, useful to make it distinct from the ID.",
|
||||||
|
"default": "The node's ID."
|
||||||
|
},
|
||||||
|
"listed": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether this node is shown in listing pages.",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"redirect": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A node ID to where any requests for this node will be redirected.",
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"root_node": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Root node ID",
|
||||||
|
"description": "The ID of node highlighted in the homepage as the graph root.",
|
||||||
|
"example": "MyNode",
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"nodes": {
|
||||||
|
"title": "Nodes",
|
||||||
|
"description": "The graph's nodes.",
|
||||||
|
"default": null,
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"$ref": "#/$defs/node"
|
||||||
|
},
|
||||||
|
"propertyNames": {
|
||||||
|
"pattern": "^[^-][^!@#$%^&*;:/~| \\]\\[()\\\\]*$"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"config": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"content_language": { "type": "string" },
|
||||||
|
"footer_credits": { "type": "boolean" },
|
||||||
|
"error_poem": { "type": "boolean" },
|
||||||
|
"node_selector": { "type": "boolean" },
|
||||||
|
"navbar_search": { "type": "boolean" },
|
||||||
|
"about": { "type": "boolean" },
|
||||||
|
"footer_text": { "type": "string" },
|
||||||
|
"acknowledgments": { "type": "string" }
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -34,6 +34,7 @@ p:not(.quote-citation), section li {
|
||||||
|
|
||||||
section p {
|
section p {
|
||||||
line-height: 2;
|
line-height: 2;
|
||||||
|
margin: 4px 0 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
|
|
@ -46,30 +47,25 @@ pre {
|
||||||
transition: 1000ms;
|
transition: 1000ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre:hover {
|
|
||||||
box-shadow: 1px 1px 3px 2.5px #00777777;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
code {
|
||||||
padding: 3px 6px;
|
padding: 3px 6px;
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-size: calc(var(--base-font-size) * 0.8);
|
|
||||||
box-shadow: 1px 1px 1px 1px #00000077;
|
|
||||||
transition: 1000ms;
|
transition: 1000ms;
|
||||||
}
|
box-shadow: 1px 1px 0.5px 0.5px #00000077;
|
||||||
|
|
||||||
code:hover {
|
|
||||||
box-shadow: 1px 1px 1px 1px #00777799;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pre, code {
|
pre, code {
|
||||||
background: light-dark(#e0e0e0, #333);
|
background: light-dark(#e0e0e0, #333);
|
||||||
font-family: mono, monospace;
|
font-family: mono, monospace;
|
||||||
border: solid 2px light-dark(#d0d0d0, #434343);
|
border: solid 1px light-dark(#d0d0d0, #434343);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1 , h2 , h3 , h4 , h5 , h6 {
|
||||||
|
code { font-size: calc(var(--base-font-size) * 0.6); }
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: light-dark(#0f6366, #1dd7d7);
|
color: light-dark(#0f6366, #1dd7d7);
|
||||||
text-decoration: underline dotted #159b9b;
|
text-decoration: underline dotted #159b9b;
|
||||||
|
|
@ -100,8 +96,20 @@ a.external {
|
||||||
}
|
}
|
||||||
|
|
||||||
a.external:hover {
|
a.external:hover {
|
||||||
color: light-dark(#0393b2, #74e5ff);
|
color: light-dark(#037cb2, #74e5ff);
|
||||||
text-decoration-color: light-dark(#1ed4f1, #aeffff);
|
transition: 1500ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.absolute {
|
||||||
|
color: light-dark(#196719, #2fe471);
|
||||||
|
text-decoration-color: light-dark(#196719, #2fe471);
|
||||||
|
text-decoration-style: solid;
|
||||||
|
text-decoration-thickness: 1.5px;
|
||||||
|
transition: 1500ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.absolute:hover {
|
||||||
|
filter: brightness(1.25);
|
||||||
transition: 1500ms;
|
transition: 1500ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,7 +158,7 @@ span.id-label {
|
||||||
border: solid 1px light-dark(#d0d0d0, #666);
|
border: solid 1px light-dark(#d0d0d0, #666);
|
||||||
}
|
}
|
||||||
|
|
||||||
span.hidden-label {
|
span.unlisted-label {
|
||||||
background: light-dark(#888, #000);
|
background: light-dark(#888, #000);
|
||||||
color: light-dark(#eee, #969696);
|
color: light-dark(#eee, #969696);
|
||||||
border: solid 1px light-dark(#d0d0d0, #555);
|
border: solid 1px light-dark(#d0d0d0, #555);
|
||||||
|
|
@ -171,7 +179,7 @@ main h2 {
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
font-weight: 1;
|
font-weight: 1;
|
||||||
margin: 10px 0;
|
margin: 10px 0 5px;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
#:schema ./graph-schema.json
|
||||||
|
|
||||||
[nodes.GettingStarted]
|
[nodes.GettingStarted]
|
||||||
title = "Getting Started"
|
title = "Getting Started"
|
||||||
text = """
|
text = """
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,17 @@
|
||||||
{% if graph.meta.config.about_text %}
|
{% if graph.meta.config.about_text %}
|
||||||
{{ graph.meta.config.about_text | safe }}
|
{{ graph.meta.config.about_text | safe }}
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>en is a program to create a connected collection of texts.</p>
|
<p>en is a writing instrument to create a connected collection of texts.</p>
|
||||||
|
|
||||||
<p>You define your graph using a plain-text configuration file, en reads this file and generates a website like the one you are browsing right now.</p>
|
<p>You define your graph using plain-text files, en reads these files and generates a website like the one you are browsing right now.</p>
|
||||||
|
|
||||||
<p>If you'd like to learn more:</p>
|
<p>If you'd like to learn more:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://en.jutty.dev">Website</a></li>
|
<li><a href="https://en.jutty.dev/node/Introduction">More about en</a></li>
|
||||||
<li><a href="https://en.jutty.dev/node/en">More about en</a></li>
|
<li><a href="https://en.jutty.dev/node/GetStarted">Get Started</a></li>
|
||||||
<li><a href="https://en.jutty.dev/node/Documentation">Documentation</a></li>
|
<li><a href="https://en.jutty.dev">Documentation</a></li>
|
||||||
<li><a href="https://codeberg.org/jutty/en">Source code repository</a></li>
|
<li><a href="https://codeberg.org/jutty/en">Code repository</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,8 @@
|
||||||
<select class="node-selector" name="node">
|
<select class="node-selector" name="node">
|
||||||
<option value="">Nodes</option>
|
<option value="">Nodes</option>
|
||||||
{% for _, node in graph.nodes %}
|
{% for _, node in graph.nodes %}
|
||||||
{% if node.hidden or node.redirect %}{% continue %}{% endif %}
|
{% if not node.listed or node.redirect %}{% continue %}{% endif %}
|
||||||
{% if not node.hidden and not node.redirect %}
|
{% if node.listed and not node.redirect %}
|
||||||
<option value="{{node.id}}">{{node.title}}</option>
|
<option value="{{node.id}}">{{node.title}}</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,16 @@
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="#detached-edges">Detached edges</a>
|
<a href="#detached-connections">Detached connections</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="#detached-edges:~:text=Anchors">{{ detached_count }}</a>
|
<a href="#detached-connections:~:text=Anchors">{{ detached_count }}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h3 id="detached-edges">Detached edges</h3>
|
<h3 id="detached-connections">Detached connections</h3>
|
||||||
|
<p>These are the destinations to which connections exist, but the target node doesn't.</p>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Expand to see all detached edges.</summary>
|
<summary>Expand to see all detached edges.</summary>
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
{% if loop.index > graph.meta.config.index_node_count %}
|
{% if loop.index > graph.meta.config.index_node_count %}
|
||||||
{% break %}
|
{% break %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if node.id != graph.root_node and not node.hidden and not node.redirect %}
|
{% if node.id != graph.root_node and node.listed and not node.redirect %}
|
||||||
<li><a href="/node/{{node.id}}">{{node.title}}</a></li>
|
<li><a href="/node/{{node.id}}">{{node.title}}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<h1 class="node-title">{{ node.title }}</h1>
|
<h1 class="node-title">{{ node.title }}</h1>
|
||||||
<div class="labels">
|
<div class="labels">
|
||||||
{% if node.title != node.id %}<span class="label id-label">ID: {{ node.id }}</span>{% endif %}
|
{% if node.title != node.id %}<span class="label id-label">ID: {{ node.id }}</span>{% endif %}
|
||||||
{% if node.hidden %}<span class="label hidden-label">Hidden</span>{% endif %}
|
{% if not node.listed %}<span class="label unlisted-label">Unlisted</span>{% endif %}
|
||||||
{% if node.id == graph.root_node %}<span class="label root-label">Root</span>{% endif %}
|
{% if node.id == graph.root_node %}<span class="label root-label">Root</span>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
{% if graph.nodes or root_node %}
|
{% if graph.nodes or root_node %}
|
||||||
<h1>Tree</h1>
|
<h1>Tree</h1>
|
||||||
<ul>
|
<ul>
|
||||||
{% if root_node and not root_node.hidden %}
|
{% if root_node and root_node.listed %}
|
||||||
<li>
|
<li>
|
||||||
<a href="/node/{{root_node.id}}">{{root_node.title}}</a>
|
<a href="/node/{{root_node.id}}">{{root_node.title}}</a>
|
||||||
<span class="label root-label">Root</span>
|
<span class="label root-label">Root</span>
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if graph.nodes %}
|
{% if graph.nodes %}
|
||||||
{% for id, node in graph.nodes %}
|
{% for id, node in graph.nodes %}
|
||||||
{% if node.hidden or (root_node and node.id == root_node.id ) %}{% continue %}{% endif %}
|
{% if not node.listed or (root_node and node.id == root_node.id ) %}{% continue %}{% endif %}
|
||||||
<li>
|
<li>
|
||||||
<a href="/node/{{node.id}}">{{node.title}}</a>
|
<a href="/node/{{node.id}}">{{node.title}}</a>
|
||||||
{% if node.connections or graph.meta.config.tree_node_summary %}
|
{% if node.connections or graph.meta.config.tree_node_summary %}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue