♻️ 使用 Actix RS 重构 #8
@ -5,24 +5,24 @@ on:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build-docker:
|
||||
runs-on: edge
|
||||
build-image:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_REGISTRY_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: xsheep2010/roadsign:nightly
|
||||
file: ./Dockerfile
|
||||
tags: xsheep2010/roadsign:sigma
|
490
Cargo.lock
generated
490
Cargo.lock
generated
@ -2,6 +2,240 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "actix-codec"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-files"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf0bdd6ff79de7c9a021f5d9ea79ce23e108d8bfc9b49b5b4a2cf6fad5a35212"
|
||||
dependencies = [
|
||||
"actix-http",
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"actix-web",
|
||||
"bitflags 2.4.1",
|
||||
"bytes",
|
||||
"derive_more",
|
||||
"futures-core",
|
||||
"http-range",
|
||||
"log",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"v_htmlescape",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-http"
|
||||
version = "3.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d223b13fd481fc0d1f83bb12659ae774d9e3601814c68a0bc539731698cca743"
|
||||
dependencies = [
|
||||
"actix-codec",
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"ahash 0.8.8",
|
||||
"base64 0.21.7",
|
||||
"bitflags 2.4.1",
|
||||
"brotli",
|
||||
"bytes",
|
||||
"bytestring",
|
||||
"derive_more",
|
||||
"encoding_rs",
|
||||
"flate2",
|
||||
"futures-core",
|
||||
"h2 0.3.24",
|
||||
"http 0.2.11",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"language-tags",
|
||||
"local-channel",
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rand",
|
||||
"sha1",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-macros"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-proxy"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3eb1ba1258bd79835d602dffb79f62aae42da7569036c67929e21961e2b3693c"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"awc",
|
||||
"openssl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-router"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d22475596539443685426b6bdadb926ad0ecaefdfc5fb05e5e3441f15463c511"
|
||||
dependencies = [
|
||||
"bytestring",
|
||||
"http 0.2.11",
|
||||
"regex",
|
||||
"serde",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-rt"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-server"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4"
|
||||
dependencies = [
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"mio",
|
||||
"socket2",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-service"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"paste",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-tls"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4cce60a2f2b477bc72e5cde0af1812a6e82d8fd85b5570a5dcf2a5bf2c5be5f"
|
||||
dependencies = [
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"futures-core",
|
||||
"http 0.2.11",
|
||||
"http 1.0.0",
|
||||
"impl-more",
|
||||
"openssl",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-openssl",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-utils"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8"
|
||||
dependencies = [
|
||||
"local-waker",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-web"
|
||||
version = "4.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a6556ddebb638c2358714d853257ed226ece6023ef9364f23f0c70737ea984"
|
||||
dependencies = [
|
||||
"actix-codec",
|
||||
"actix-http",
|
||||
"actix-macros",
|
||||
"actix-router",
|
||||
"actix-rt",
|
||||
"actix-server",
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"actix-web-codegen",
|
||||
"ahash 0.8.8",
|
||||
"bytes",
|
||||
"bytestring",
|
||||
"cfg-if",
|
||||
"cookie 0.16.2",
|
||||
"derive_more",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"itoa",
|
||||
"language-tags",
|
||||
"log",
|
||||
"mime",
|
||||
"once_cell",
|
||||
"pin-project-lite",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"smallvec",
|
||||
"socket2",
|
||||
"time",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-web-codegen"
|
||||
version = "4.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb1f50ebbb30eca122b188319a4398b3f7bb4a8cdf50ecfb73bfc6a3c3ce54f5"
|
||||
dependencies = [
|
||||
"actix-router",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.21.0"
|
||||
@ -63,6 +297,19 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
@ -72,6 +319,21 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloc-no-stdlib"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
|
||||
|
||||
[[package]]
|
||||
name = "alloc-stdlib"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
@ -104,6 +366,40 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "awc"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68c09cc97310b926f01621faee652f3d1b0962545a3cec6c9ac07def9ea36c2c"
|
||||
dependencies = [
|
||||
"actix-codec",
|
||||
"actix-http",
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-tls",
|
||||
"actix-utils",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"cfg-if",
|
||||
"cookie 0.16.2",
|
||||
"derive_more",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2 0.3.24",
|
||||
"http 0.2.11",
|
||||
"itoa",
|
||||
"log",
|
||||
"mime",
|
||||
"openssl",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.69"
|
||||
@ -152,6 +448,27 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
"brotli-decompressor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli-decompressor"
|
||||
version = "2.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.14.0"
|
||||
@ -170,12 +487,22 @@ version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||
|
||||
[[package]]
|
||||
name = "bytestring"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -232,6 +559,17 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
"time",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.17.0"
|
||||
@ -275,6 +613,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
@ -406,6 +753,16 @@ version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@ -528,9 +885,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.23"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b553656127a00601c8ae5590fcfdc118e4083a7924b6cf4ffc1ea4b99dc429d7"
|
||||
checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
@ -570,7 +927,7 @@ version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"ahash 0.7.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -683,6 +1040,12 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-range"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.8.0"
|
||||
@ -705,7 +1068,7 @@ dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2 0.3.23",
|
||||
"h2 0.3.24",
|
||||
"http 0.2.11",
|
||||
"http-body 0.4.6",
|
||||
"httparse",
|
||||
@ -814,6 +1177,12 @@ dependencies = [
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "impl-more"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "206ca75c9c03ba3d4ace2460e57b189f39f43de612c2f85836e65c929701bb2d"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.1.0"
|
||||
@ -845,6 +1214,15 @@ version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.67"
|
||||
@ -865,6 +1243,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "language-tags"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
@ -889,6 +1273,23 @@ version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
|
||||
|
||||
[[package]]
|
||||
name = "local-channel"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"local-waker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "local-waker"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.11"
|
||||
@ -949,6 +1350,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
@ -1144,6 +1546,12 @@ dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||
|
||||
[[package]]
|
||||
name = "pathdiff"
|
||||
version = "0.2.1"
|
||||
@ -1249,7 +1657,7 @@ dependencies = [
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"cookie",
|
||||
"cookie 0.17.0",
|
||||
"futures-util",
|
||||
"headers",
|
||||
"http 1.0.0",
|
||||
@ -1495,7 +1903,7 @@ dependencies = [
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2 0.3.23",
|
||||
"h2 0.3.24",
|
||||
"http 0.2.11",
|
||||
"http-body 0.4.6",
|
||||
"hyper 0.14.28",
|
||||
@ -1571,6 +1979,10 @@ dependencies = [
|
||||
name = "roadsign"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"actix-files",
|
||||
"actix-proxy",
|
||||
"actix-web",
|
||||
"awc",
|
||||
"config",
|
||||
"futures-util",
|
||||
"http 1.0.0",
|
||||
@ -2032,6 +2444,18 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-openssl"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ffab79df67727f6acf57f1ff743091873c24c579b1e2ce4d8f53e47ded4d63d"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"openssl",
|
||||
"openssl-sys",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.14"
|
||||
@ -2318,6 +2742,12 @@ version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "v_htmlescape"
|
||||
version = "0.15.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c"
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.0"
|
||||
@ -2623,3 +3053,51 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||
dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110"
|
||||
dependencies = [
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-safe"
|
||||
version = "7.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e"
|
||||
dependencies = [
|
||||
"zstd-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.9+zstd.1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
@ -6,6 +6,10 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
actix-files = "0.6.5"
|
||||
actix-proxy = "0.2.0"
|
||||
actix-web = "4.5.1"
|
||||
awc = "3.4.0"
|
||||
config = { version = "0.13.4", features = ["toml"] }
|
||||
futures-util = "0.3.30"
|
||||
http = "1.0.0"
|
||||
|
98
certs/fullchain.pem
Normal file
98
certs/fullchain.pem
Normal file
@ -0,0 +1,98 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGITCCBQmgAwIBAgISBPa2ahmRa5l0SrbR75K29TlqMA0GCSqGSIb3DQEBCwUA
|
||||
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
|
||||
EwJSMzAeFw0yNDAxMjgxNjM1MzZaFw0yNDA0MjcxNjM1MzVaMBwxGjAYBgNVBAMT
|
||||
EXNtYXJ0c2hlZXAuc3R1ZGlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
|
||||
AgEAumtDoEkBHiqBGNl9JUbt3Nw1a/iLa2JHZvCmUuilvafAj0k1UPEu457iJVjh
|
||||
nxlTl/tgpCooRNviboB0lMAecwiKb5PIZzInY2/gb+rceL7rycalDAjWnwZZg8Tl
|
||||
3JWJaU0D3+jeBQ9p7xkRPTcRpkGxFX9hRdInRqFGmCK4/OXrBwI3FkoP9Z8Nvgzc
|
||||
RyIhmMEafOi2AaLJSXZQE508djHpcxlwoxvVmFIYsjTMJiq+zdqCZDTjDqt7bZC+
|
||||
mp3n/DFLL0sTzIBLuHnPkrjwlE4w/XTLkMLgrGPvEJVHn4kOvnJSWJb95d3sRZqB
|
||||
PLrekQGDtcb0dpFx8ctWycVp0qhBTpuLAoN+AK6cJ3IkxOcGm7sKzYwRINjAblMe
|
||||
n1Y6as6JKL4zSZBt1jxua1NGIRQ1c4ReA78NniTMrFIk1mFL4kNT9ppgDsWGNTJx
|
||||
FqC76rr3TdKXKzD/c8h57j3CPTF9lGB4Vmlkrq/zA++br0IG7Ki/+1n04Q1UDN0E
|
||||
8z/vgUsT+pMItrmUhpnhb+4QWLQHTWOg1CyWT9xSm77ArkuNSdzNFGjpSbYZEPlh
|
||||
pmAYTz+kWvnyg7T3Lt7fmSPCBnnIWhi9CJofvyomICWfcKEfwc0msJquXMyJBayA
|
||||
K91VMoudbveI+CX8Zuc5u4uCOk/Dr6JJWnYkIDK7cW+tFh0CAwEAAaOCAkUwggJB
|
||||
MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
|
||||
DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUPabqUNdBFv+3fEpgh2seAHvPQFgwHwYD
|
||||
VR0jBBgwFoAUFC6zF7dYVsuuUAlA5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEG
|
||||
CCsGAQUFBzABhhVodHRwOi8vcjMuby5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0
|
||||
dHA6Ly9yMy5pLmxlbmNyLm9yZy8wTQYDVR0RBEYwRIIaKi5wbGF5bWMuc21hcnRz
|
||||
aGVlcC5zdHVkaW+CEyouc21hcnRzaGVlcC5zdHVkaW+CEXNtYXJ0c2hlZXAuc3R1
|
||||
ZGlvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMIIBBQYKKwYBBAHWeQIEAgSB9gSB8wDx
|
||||
AHcAO1N3dT4tuYBOizBbBv5AO2fYT8P0x70ADS1yb+H61BcAAAGNUSQZ5gAABAMA
|
||||
SDBGAiEA9i8QVPKh68OY9Ug+KqZ1aWSx5SVUvPKVyp8KkI/RMssCIQD0JsqwhLFx
|
||||
SQFVROa1yhbZIdIHs9NMuW7lHbOWOU4F+AB2AO7N0GTV2xrOxVy3nbTNE6Iyh0Z8
|
||||
vOzew1FIWUZxH7WbAAABjVEkGesAAAQDAEcwRQIhAKXGxcDa/aGK50QyhOXAdlKl
|
||||
VCk0Yo9wYzw2sB48BF1TAiBsW2R+CJXhnCBzcRRh8GQuj+aBcYIzHBaRvsanC9nx
|
||||
9zANBgkqhkiG9w0BAQsFAAOCAQEAgYR8uizQZkkvlEyI5dsz/tGJ0Vuejnd6yfoE
|
||||
OT6BaNF45UtdMfSoJRLwgW6SM1hsuwmPjoUVS9VZ83NAhnWQqSeR9P4m7aMfhaeK
|
||||
qPlDDcGh/SZOvgeja8AsUhCq+9csUzR+FEfk7xJXFflcG1FNGzRglzmqrSvFHKhE
|
||||
EyJQuk6Oa/UiL0ICdKiLxh75gTJvTB/7wznTP7NGsayzqkBj4nxqHIwCGh7hPe2c
|
||||
2xMEbcFA9aArInJEg2PzlYRy1C9qtuhU2hJUhLjEix4WVCHUyAV/X6kwjqIaUEOz
|
||||
NdUrFCahGkWDVZZcPgl/FdFSPfSL/pnT8jOotELnhj0AiX2SNQ==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
|
||||
WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||
RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
|
||||
R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
|
||||
sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
|
||||
NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
|
||||
Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
|
||||
/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
|
||||
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
|
||||
Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
|
||||
FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
|
||||
AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
|
||||
Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
|
||||
gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
|
||||
PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
|
||||
ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
|
||||
CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
|
||||
lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
|
||||
avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
|
||||
yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
|
||||
yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
|
||||
hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
|
||||
HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
|
||||
MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
|
||||
nLRbwHOoq7hHwg==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
|
||||
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
|
||||
DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB
|
||||
AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC
|
||||
ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL
|
||||
wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D
|
||||
LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK
|
||||
4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5
|
||||
bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y
|
||||
sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ
|
||||
Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4
|
||||
FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc
|
||||
SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql
|
||||
PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND
|
||||
TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
|
||||
SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1
|
||||
c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx
|
||||
+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB
|
||||
ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu
|
||||
b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E
|
||||
U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu
|
||||
MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC
|
||||
5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW
|
||||
9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG
|
||||
WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
|
||||
he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
|
||||
Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
|
||||
-----END CERTIFICATE-----
|
51
certs/privkey.pem
Normal file
51
certs/privkey.pem
Normal file
@ -0,0 +1,51 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
44
src/main.rs
44
src/main.rs
@ -1,16 +1,14 @@
|
||||
pub mod auth;
|
||||
mod config;
|
||||
mod proxies;
|
||||
mod sideload;
|
||||
pub mod warden;
|
||||
|
||||
use actix_web::{App, HttpServer, web};
|
||||
use awc::Client;
|
||||
use lazy_static::lazy_static;
|
||||
use poem::{listener::TcpListener, EndpointExt, Route, Server};
|
||||
use poem_openapi::OpenApiService;
|
||||
use proxies::RoadInstance;
|
||||
use tokio::sync::Mutex;
|
||||
use tracing::{error, info, Level};
|
||||
|
||||
use crate::proxies::route;
|
||||
|
||||
lazy_static! {
|
||||
@ -20,9 +18,6 @@ lazy_static! {
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), std::io::Error> {
|
||||
// Setting up logging
|
||||
if std::env::var_os("RUST_LOG").is_none() {
|
||||
std::env::set_var("RUST_LOG", "poem=debug");
|
||||
}
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(Level::DEBUG)
|
||||
.init();
|
||||
@ -44,36 +39,17 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
};
|
||||
|
||||
// Proxies
|
||||
let proxies_server = Server::new(TcpListener::bind(
|
||||
let proxies_server = HttpServer::new(|| {
|
||||
App::new()
|
||||
.app_data(web::Data::new(Client::default()))
|
||||
.route("/", web::to(route::handle))
|
||||
}).bind(
|
||||
config::C
|
||||
.read()
|
||||
.await
|
||||
.get_string("listen.proxies")
|
||||
.unwrap_or("0.0.0.0:80".to_string()),
|
||||
))
|
||||
.run(route::handle);
|
||||
|
||||
// Sideload
|
||||
let sideload = OpenApiService::new(sideload::SideloadApi, "Sideload API", "1.0")
|
||||
.server("http://localhost:3000/cgi");
|
||||
|
||||
let sideload_server = Server::new(TcpListener::bind(
|
||||
config::C
|
||||
.read()
|
||||
.await
|
||||
.get_string("listen.sideload")
|
||||
.unwrap_or("0.0.0.0:81".to_string()),
|
||||
))
|
||||
.run(
|
||||
Route::new().nest("/cgi", sideload).with(auth::BasicAuth {
|
||||
username: "RoadSign".to_string(),
|
||||
password: config::C
|
||||
.read()
|
||||
.await
|
||||
.get_string("secret")
|
||||
.unwrap_or("password".to_string()),
|
||||
}),
|
||||
);
|
||||
.unwrap_or("0.0.0.0:80".to_string())
|
||||
)?.run();
|
||||
|
||||
// Process manager
|
||||
{
|
||||
@ -85,7 +61,7 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
app.warden.start().await;
|
||||
}
|
||||
|
||||
tokio::try_join!(proxies_server, sideload_server)?;
|
||||
tokio::try_join!(proxies_server)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,52 +0,0 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
pub struct DirectoryTemplate<'a> {
|
||||
pub path: &'a str,
|
||||
pub files: Vec<FileRef>,
|
||||
}
|
||||
|
||||
impl<'a> DirectoryTemplate<'a> {
|
||||
pub fn render(&self) -> String {
|
||||
let mut s = format!(
|
||||
r#"
|
||||
<html>
|
||||
<head>
|
||||
<title>Index of {}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Index of /{}</h1>
|
||||
<ul>"#,
|
||||
self.path, self.path
|
||||
);
|
||||
|
||||
for file in &self.files {
|
||||
if file.is_dir {
|
||||
let _ = write!(
|
||||
s,
|
||||
r#"<li><a href="{}">{}/</a></li>"#,
|
||||
file.url, file.filename
|
||||
);
|
||||
} else {
|
||||
let _ = write!(
|
||||
s,
|
||||
r#"<li><a href="{}">{}</a></li>"#,
|
||||
file.url, file.filename
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
s.push_str(
|
||||
r#"</ul>
|
||||
</body>
|
||||
</html>"#,
|
||||
);
|
||||
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FileRef {
|
||||
pub url: String,
|
||||
pub filename: String,
|
||||
pub is_dir: bool,
|
||||
}
|
@ -75,15 +75,6 @@ impl Destination {
|
||||
.collect::<Vec<_>>()[0]
|
||||
}
|
||||
|
||||
pub fn get_websocket_uri(&self) -> Result<String, ()> {
|
||||
let parts = self.uri.as_str().splitn(2, "://").collect::<Vec<_>>();
|
||||
let url = parts.get(1).unwrap_or(&"");
|
||||
match self.get_protocol() {
|
||||
"http" | "https" => Ok(url.replace("http", "ws")),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_hypertext_uri(&self) -> Result<String, ()> {
|
||||
match self.get_protocol() {
|
||||
"http" => Ok("http://".to_string() + self.get_host()),
|
||||
|
@ -1,5 +1,5 @@
|
||||
use http::Method;
|
||||
use poem::http::{HeaderMap, Uri};
|
||||
use actix_web::http::header::HeaderMap;
|
||||
use actix_web::http::{Method, Uri};
|
||||
use regex::Regex;
|
||||
use wildmatch::WildMatch;
|
||||
|
||||
@ -10,7 +10,6 @@ use self::{
|
||||
metrics::RoadMetrics,
|
||||
};
|
||||
|
||||
pub mod browser;
|
||||
pub mod config;
|
||||
pub mod loader;
|
||||
pub mod metrics;
|
||||
@ -38,7 +37,7 @@ impl RoadInstance {
|
||||
pub fn filter(
|
||||
&self,
|
||||
uri: &Uri,
|
||||
method: Method,
|
||||
method: &Method,
|
||||
headers: &HeaderMap,
|
||||
) -> Option<(&Region, &Location)> {
|
||||
self.regions.iter().find_map(|region| {
|
||||
|
@ -1,117 +1,50 @@
|
||||
use futures_util::{SinkExt, StreamExt};
|
||||
use http::{header, request::Builder, HeaderMap, Method, StatusCode, Uri};
|
||||
use lazy_static::lazy_static;
|
||||
use poem::{
|
||||
web::{websocket::WebSocket, StaticFileRequest},
|
||||
Body, Error, FromRequest, IntoResponse, Request, Response,
|
||||
};
|
||||
use futures_util::{SinkExt};
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
use tokio::sync::RwLock;
|
||||
use tokio_tungstenite::connect_async;
|
||||
|
||||
use super::browser::{DirectoryTemplate, FileRef};
|
||||
|
||||
lazy_static! {
|
||||
pub static ref CLIENT: reqwest::Client = reqwest::Client::new();
|
||||
}
|
||||
|
||||
pub async fn repond_websocket(req: Builder, ws: WebSocket) -> Response {
|
||||
ws.on_upgrade(move |socket| async move {
|
||||
let (mut clientsink, mut clientstream) = socket.split();
|
||||
|
||||
// Start connection to server
|
||||
let (serversocket, _) = connect_async(req.body(()).unwrap()).await.unwrap();
|
||||
let (mut serversink, mut serverstream) = serversocket.split();
|
||||
|
||||
let client_live = Arc::new(RwLock::new(true));
|
||||
let server_live = client_live.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
while let Some(Ok(msg)) = clientstream.next().await {
|
||||
if (serversink.send(msg.into()).await).is_err() {
|
||||
break;
|
||||
};
|
||||
if !*client_live.read().await {
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
*client_live.write().await = false;
|
||||
});
|
||||
|
||||
// Relay server messages to the client
|
||||
tokio::spawn(async move {
|
||||
while let Some(Ok(msg)) = serverstream.next().await {
|
||||
if (clientsink.send(msg.into()).await).is_err() {
|
||||
break;
|
||||
};
|
||||
if !*server_live.read().await {
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
*server_live.write().await = false;
|
||||
});
|
||||
})
|
||||
.into_response()
|
||||
}
|
||||
use actix_files::{NamedFile};
|
||||
use actix_proxy::IntoHttpResponse;
|
||||
use actix_web::{HttpRequest, HttpResponse, web};
|
||||
use actix_web::http::Method;
|
||||
use awc::Client;
|
||||
|
||||
pub async fn respond_hypertext(
|
||||
uri: String,
|
||||
ori: &Uri,
|
||||
req: &Request,
|
||||
method: Method,
|
||||
body: Body,
|
||||
headers: &HeaderMap,
|
||||
) -> Result<Response, Error> {
|
||||
let ip = req.remote_addr().to_string();
|
||||
req: HttpRequest,
|
||||
client: web::Data<Client>,
|
||||
) -> Result<HttpResponse, HttpResponse> {
|
||||
let ip = req.peer_addr().unwrap().ip().to_string();
|
||||
let proto = req.uri().scheme_str().unwrap();
|
||||
let host = req.uri().host().unwrap();
|
||||
|
||||
let mut headers = headers.clone();
|
||||
headers.insert("Server", "RoadSign".parse().unwrap());
|
||||
headers.insert("X-Forward-For", ip.parse().unwrap());
|
||||
headers.insert("X-Forwarded-Proto", proto.parse().unwrap());
|
||||
headers.insert("X-Forwarded-Host", host.parse().unwrap());
|
||||
headers.insert("X-Real-IP", ip.parse().unwrap());
|
||||
let mut headers = req.headers().clone();
|
||||
headers.insert("Server".parse().unwrap(), "RoadSign".parse().unwrap());
|
||||
headers.insert("X-Forward-For".parse().unwrap(), ip.parse().unwrap());
|
||||
headers.insert("X-Forwarded-Proto".parse().unwrap(), proto.parse().unwrap());
|
||||
headers.insert("X-Forwarded-Host".parse().unwrap(), host.parse().unwrap());
|
||||
headers.insert("X-Real-IP".parse().unwrap(), ip.parse().unwrap());
|
||||
headers.insert(
|
||||
"Forwarded",
|
||||
"Forwarded".parse().unwrap(),
|
||||
format!("by={};for={};host={};proto={}", ip, ip, host, proto)
|
||||
.parse()
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let res = CLIENT
|
||||
.request(method, uri + ori.path() + ori.query().unwrap_or(""))
|
||||
.headers(headers.clone())
|
||||
.body(body.into_bytes().await.unwrap())
|
||||
.send()
|
||||
.await;
|
||||
let res = client.get(uri).send().await;
|
||||
|
||||
match res {
|
||||
return match res {
|
||||
Ok(result) => {
|
||||
let mut res = Response::default();
|
||||
res.extensions().clone_from(&result.extensions());
|
||||
result.headers().iter().for_each(|(key, val)| {
|
||||
res.headers_mut().insert(key, val.to_owned());
|
||||
});
|
||||
res.headers_mut()
|
||||
.insert("Server", "RoadSign".parse().unwrap());
|
||||
res.set_status(result.status());
|
||||
res.set_version(result.version());
|
||||
res.set_body(result.bytes().await.unwrap());
|
||||
let mut res = result.into_http_response();
|
||||
res.headers_mut().insert("Server".parse().unwrap(), "RoadSign".parse().unwrap());
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
Err(error) => Err(Error::from_string(
|
||||
error.to_string(),
|
||||
error.status().unwrap_or(StatusCode::BAD_GATEWAY),
|
||||
)),
|
||||
Err(error) => {
|
||||
Err(HttpResponse::BadGateway()
|
||||
.body(format!("Something went wrong... {:}", error)))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub struct StaticResponderConfig {
|
||||
@ -126,14 +59,11 @@ pub struct StaticResponderConfig {
|
||||
|
||||
pub async fn respond_static(
|
||||
cfg: StaticResponderConfig,
|
||||
method: Method,
|
||||
req: &Request,
|
||||
) -> Result<Response, Error> {
|
||||
if method != Method::GET {
|
||||
return Err(Error::from_string(
|
||||
"This destination only support GET request.",
|
||||
StatusCode::METHOD_NOT_ALLOWED,
|
||||
));
|
||||
req: HttpRequest,
|
||||
) -> Result<HttpResponse, HttpResponse> {
|
||||
if req.method() != Method::GET {
|
||||
return Err(HttpResponse::MethodNotAllowed()
|
||||
.body("This destination only support GET request."));
|
||||
}
|
||||
|
||||
let path = req
|
||||
@ -142,9 +72,12 @@ pub async fn respond_static(
|
||||
.trim_start_matches('/')
|
||||
.trim_end_matches('/');
|
||||
|
||||
let path = percent_encoding::percent_decode_str(path)
|
||||
.decode_utf8()
|
||||
.map_err(|_| Error::from_status(StatusCode::NOT_FOUND))?;
|
||||
let path = match percent_encoding::percent_decode_str(path).decode_utf8() {
|
||||
Ok(val) => val,
|
||||
Err(_) => {
|
||||
return Err(HttpResponse::NotFound().body("Not found."));
|
||||
}
|
||||
};
|
||||
|
||||
let base_path = cfg.uri.parse::<PathBuf>().unwrap();
|
||||
let mut file_path = base_path.clone();
|
||||
@ -159,7 +92,8 @@ pub async fn respond_static(
|
||||
}
|
||||
|
||||
if !file_path.starts_with(cfg.uri) {
|
||||
return Err(Error::from_status(StatusCode::FORBIDDEN));
|
||||
return Err(HttpResponse::Forbidden()
|
||||
.body("Unexpected path."));
|
||||
}
|
||||
|
||||
if !file_path.exists() {
|
||||
@ -172,87 +106,30 @@ pub async fn respond_static(
|
||||
file_path.pop();
|
||||
file_path.push((file_name + &suffix).as_str());
|
||||
if file_path.is_file() {
|
||||
return Ok(StaticFileRequest::from_request_without_body(req)
|
||||
.await?
|
||||
.create_response(&file_path, cfg.utf8)?
|
||||
.into_response());
|
||||
return Ok(NamedFile::open(file_path).unwrap().into_response(&req));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(file) = cfg.fallback {
|
||||
let fallback_path = base_path.join(file);
|
||||
if fallback_path.is_file() {
|
||||
return Ok(StaticFileRequest::from_request_without_body(req)
|
||||
.await?
|
||||
.create_response(&fallback_path, cfg.utf8)?
|
||||
.into_response());
|
||||
return Ok(NamedFile::open(fallback_path).unwrap().into_response(&req));
|
||||
}
|
||||
}
|
||||
return Err(Error::from_status(StatusCode::NOT_FOUND));
|
||||
}
|
||||
|
||||
if file_path.is_file() {
|
||||
Ok(StaticFileRequest::from_request_without_body(req)
|
||||
.await?
|
||||
.create_response(&file_path, cfg.utf8)?
|
||||
.into_response())
|
||||
return Err(HttpResponse::NotFound().body("Not found."));
|
||||
}
|
||||
|
||||
return if file_path.is_file() {
|
||||
Ok(NamedFile::open(file_path).unwrap().into_response(&req))
|
||||
} else {
|
||||
if cfg.with_slash
|
||||
&& !req.original_uri().path().ends_with('/')
|
||||
&& (cfg.index.is_some() || cfg.browse)
|
||||
{
|
||||
let redirect_to = format!("{}/", req.original_uri().path());
|
||||
return Ok(Response::builder()
|
||||
.status(StatusCode::FOUND)
|
||||
.header(header::LOCATION, redirect_to)
|
||||
.finish());
|
||||
}
|
||||
|
||||
if let Some(index_file) = &cfg.index {
|
||||
let index_path = file_path.join(index_file);
|
||||
if index_path.is_file() {
|
||||
return Ok(StaticFileRequest::from_request_without_body(req)
|
||||
.await?
|
||||
.create_response(&index_path, cfg.utf8)?
|
||||
.into_response());
|
||||
return Ok(NamedFile::open(index_path).unwrap().into_response(&req));
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.browse {
|
||||
let read_dir = file_path
|
||||
.read_dir()
|
||||
.map_err(|_| Error::from_status(StatusCode::FORBIDDEN))?;
|
||||
let mut template = DirectoryTemplate {
|
||||
path: &path,
|
||||
files: Vec::new(),
|
||||
Err(HttpResponse::NotFound().body("Not found."))
|
||||
};
|
||||
|
||||
for res in read_dir {
|
||||
let entry = res.map_err(|_| Error::from_status(StatusCode::FORBIDDEN))?;
|
||||
|
||||
if let Some(filename) = entry.file_name().to_str() {
|
||||
let mut base_url = req.original_uri().path().to_string();
|
||||
if !base_url.ends_with('/') {
|
||||
base_url.push('/');
|
||||
}
|
||||
let filename_url = percent_encoding::percent_encode(
|
||||
filename.as_bytes(),
|
||||
percent_encoding::NON_ALPHANUMERIC,
|
||||
);
|
||||
template.files.push(FileRef {
|
||||
url: format!("{base_url}{filename_url}"),
|
||||
filename: filename.to_string(),
|
||||
is_dir: entry.path().is_dir(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let html = template.render();
|
||||
Ok(Response::builder()
|
||||
.header(header::CONTENT_TYPE, mime::TEXT_HTML_UTF_8.as_ref())
|
||||
.body(Body::from_string(html)))
|
||||
} else {
|
||||
Err(Error::from_status(StatusCode::NOT_FOUND))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,5 @@
|
||||
use http::Method;
|
||||
use poem::{
|
||||
handler,
|
||||
http::{HeaderMap, StatusCode, Uri},
|
||||
web::websocket::WebSocket,
|
||||
Body, Error, FromRequest, IntoResponse, Request, Response, Result,
|
||||
};
|
||||
use actix_web::{HttpRequest, HttpResponse, web};
|
||||
use awc::Client;
|
||||
use rand::seq::SliceRandom;
|
||||
|
||||
use crate::{
|
||||
@ -15,22 +10,13 @@ use crate::{
|
||||
ROAD,
|
||||
};
|
||||
|
||||
#[handler]
|
||||
pub async fn handle(
|
||||
req: &Request,
|
||||
uri: &Uri,
|
||||
headers: &HeaderMap,
|
||||
method: Method,
|
||||
body: Body,
|
||||
) -> Result<impl IntoResponse, Error> {
|
||||
pub async fn handle(req: HttpRequest, client: web::Data<Client>) -> HttpResponse {
|
||||
let readable_app = ROAD.lock().await;
|
||||
let (region, location) = match readable_app.filter(uri, method.clone(), headers) {
|
||||
let (region, location) = match readable_app.filter(req.uri(), req.method(), req.headers()) {
|
||||
Some(val) => val,
|
||||
None => {
|
||||
return Err(Error::from_string(
|
||||
"There are no region be able to respone this request.",
|
||||
StatusCode::NOT_FOUND,
|
||||
))
|
||||
return HttpResponse::NotFound()
|
||||
.body("There are no region be able to respone this request.");
|
||||
}
|
||||
};
|
||||
|
||||
@ -41,58 +27,31 @@ pub async fn handle(
|
||||
|
||||
async fn forward(
|
||||
end: &Destination,
|
||||
req: &Request,
|
||||
ori: &Uri,
|
||||
headers: &HeaderMap,
|
||||
method: Method,
|
||||
body: Body,
|
||||
) -> Result<Response, Error> {
|
||||
// Handle websocket
|
||||
if let Ok(ws) = WebSocket::from_request_without_body(req).await {
|
||||
// Get uri
|
||||
let Ok(uri) = end.get_websocket_uri() else {
|
||||
return Err(Error::from_string(
|
||||
"This destination was not support websockets.",
|
||||
StatusCode::NOT_IMPLEMENTED,
|
||||
));
|
||||
};
|
||||
|
||||
// Build request
|
||||
let mut ws_req = http::Request::builder().uri(&uri);
|
||||
for (key, value) in headers.iter() {
|
||||
ws_req = ws_req.header(key, value);
|
||||
}
|
||||
|
||||
// Start the websocket connection
|
||||
return Ok(responder::repond_websocket(ws_req, ws).await);
|
||||
}
|
||||
|
||||
req: HttpRequest,
|
||||
client: web::Data<Client>,
|
||||
) -> Result<HttpResponse, HttpResponse> {
|
||||
// Handle normal web request
|
||||
match end.get_type() {
|
||||
DestinationType::Hypertext => {
|
||||
let Ok(uri) = end.get_hypertext_uri() else {
|
||||
return Err(Error::from_string(
|
||||
"This destination was not support web requests.",
|
||||
StatusCode::NOT_IMPLEMENTED,
|
||||
));
|
||||
return Err(HttpResponse::NotImplemented()
|
||||
.body("This destination was not support web requests."));
|
||||
};
|
||||
|
||||
responder::respond_hypertext(uri, ori, req, method, body, headers).await
|
||||
responder::respond_hypertext(uri, req, client).await
|
||||
}
|
||||
DestinationType::StaticFiles => {
|
||||
let Ok(cfg) = end.get_static_config() else {
|
||||
return Err(Error::from_string(
|
||||
"This destination was not support static files.",
|
||||
StatusCode::NOT_IMPLEMENTED,
|
||||
));
|
||||
return Err(HttpResponse::NotImplemented()
|
||||
.body("This destination was not support static files."));
|
||||
};
|
||||
|
||||
responder::respond_static(cfg, method, req).await
|
||||
responder::respond_static(cfg, req).await
|
||||
}
|
||||
_ => {
|
||||
return Err(HttpResponse::NotImplemented()
|
||||
.body("Unsupported destination protocol."));
|
||||
}
|
||||
_ => Err(Error::from_string(
|
||||
"Unsupported destination protocol.",
|
||||
StatusCode::NOT_IMPLEMENTED,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,23 +59,22 @@ pub async fn handle(
|
||||
let loc = location.clone();
|
||||
let end = destination.clone();
|
||||
|
||||
match forward(&end, req, uri, headers, method, body).await {
|
||||
return match forward(&end, req, client).await {
|
||||
Ok(resp) => {
|
||||
tokio::spawn(async move {
|
||||
let writable_app = &mut ROAD.lock().await;
|
||||
writable_app.metrics.add_success_request(reg, loc, end);
|
||||
});
|
||||
Ok(resp)
|
||||
resp
|
||||
}
|
||||
Err(err) => {
|
||||
let message = format!("{:}", err);
|
||||
Err(resp) => {
|
||||
tokio::spawn(async move {
|
||||
let writable_app = &mut ROAD.lock().await;
|
||||
writable_app
|
||||
.metrics
|
||||
.add_faliure_request(reg, loc, end, message);
|
||||
.add_faliure_request(reg, loc, end, "TODO".to_owned());
|
||||
});
|
||||
Err(err)
|
||||
resp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
use poem_openapi::OpenApi;
|
||||
|
||||
pub mod overview;
|
||||
pub mod regions;
|
||||
|
||||
pub struct SideloadApi;
|
||||
|
||||
#[OpenApi]
|
||||
impl SideloadApi {
|
||||
#[oai(path = "/", method = "get")]
|
||||
async fn index(&self) -> overview::OverviewResponse {
|
||||
overview::index().await
|
||||
}
|
||||
|
||||
#[oai(path = "/regions", method = "get")]
|
||||
async fn regions_index(&self) -> regions::RegionResponse {
|
||||
regions::index().await
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
use poem_openapi::{payload::Json, ApiResponse, Object};
|
||||
|
||||
use crate::{
|
||||
proxies::{
|
||||
config::{Destination, Location},
|
||||
metrics::RoadTrace,
|
||||
},
|
||||
ROAD,
|
||||
};
|
||||
|
||||
#[derive(ApiResponse)]
|
||||
pub enum OverviewResponse {
|
||||
/// Return the overview data.
|
||||
#[oai(status = 200)]
|
||||
Ok(Json<OverviewData>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Object, Clone, PartialEq)]
|
||||
pub struct OverviewData {
|
||||
/// Loaded regions count
|
||||
#[oai(read_only)]
|
||||
regions: usize,
|
||||
/// Loaded locations count
|
||||
#[oai(read_only)]
|
||||
locations: usize,
|
||||
/// Loaded destnations count
|
||||
#[oai(read_only)]
|
||||
destinations: usize,
|
||||
/// Recent requests count
|
||||
requests_count: u64,
|
||||
/// Recent requests success count
|
||||
faliures_count: u64,
|
||||
/// Recent requests falied count
|
||||
successes_count: u64,
|
||||
/// Recent requests success rate
|
||||
success_rate: f64,
|
||||
/// Recent successes
|
||||
recent_successes: Vec<RoadTrace>,
|
||||
/// Recent errors
|
||||
recent_errors: Vec<RoadTrace>,
|
||||
}
|
||||
|
||||
pub async fn index() -> OverviewResponse {
|
||||
let locked_app = ROAD.lock().await;
|
||||
let regions = locked_app.regions.clone();
|
||||
let locations = regions
|
||||
.iter()
|
||||
.flat_map(|item| item.locations.clone())
|
||||
.collect::<Vec<Location>>();
|
||||
let destinations = locations
|
||||
.iter()
|
||||
.flat_map(|item| item.destinations.clone())
|
||||
.collect::<Vec<Destination>>();
|
||||
OverviewResponse::Ok(Json(OverviewData {
|
||||
regions: regions.len(),
|
||||
locations: locations.len(),
|
||||
destinations: destinations.len(),
|
||||
requests_count: locked_app.metrics.requests_count,
|
||||
successes_count: locked_app.metrics.requests_count - locked_app.metrics.failures_count,
|
||||
faliures_count: locked_app.metrics.failures_count,
|
||||
success_rate: locked_app.metrics.get_success_rate(),
|
||||
recent_successes: locked_app
|
||||
.metrics
|
||||
.recent_successes
|
||||
.clone()
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>(),
|
||||
recent_errors: locked_app
|
||||
.metrics
|
||||
.recent_errors
|
||||
.clone()
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>(),
|
||||
}))
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
use poem_openapi::{payload::Json, ApiResponse};
|
||||
|
||||
use crate::{proxies::config::Region, ROAD};
|
||||
|
||||
#[derive(ApiResponse)]
|
||||
pub enum RegionResponse {
|
||||
/// Return the region data.
|
||||
#[oai(status = 200)]
|
||||
Ok(Json<Region>),
|
||||
/// Return the list of region data.
|
||||
#[oai(status = 200)]
|
||||
OkMany(Json<Vec<Region>>),
|
||||
/// Return the region data after created.
|
||||
#[oai(status = 201)]
|
||||
Created(Json<Region>),
|
||||
/// Return was not found.
|
||||
#[oai(status = 404)]
|
||||
NotFound,
|
||||
}
|
||||
|
||||
pub async fn index() -> RegionResponse {
|
||||
let locked_app = ROAD.lock().await;
|
||||
|
||||
RegionResponse::OkMany(Json(locked_app.regions.clone()))
|
||||
}
|
179
test/data/warden/dist/client/_astro/Media.7FWSwaPB.js
vendored
Normal file
179
test/data/warden/dist/client/_astro/Media.7FWSwaPB.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
test/data/warden/dist/client/_astro/Media.Co8_pG1j.css
vendored
Normal file
1
test/data/warden/dist/client/_astro/Media.Co8_pG1j.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
test/data/warden/dist/client/_astro/_slug_.bcjV8AoT.css
vendored
Normal file
1
test/data/warden/dist/client/_astro/_slug_.bcjV8AoT.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
:root{--bs-body-font-family: "IBM Plex Serif", "Noto Serif SC", sans-serif !important}html,body{font-family:var(--bs-body-font-family)}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:normal;font-weight:100;src:url(/_astro/ibm-plex-serif-v19-latin-100.6qNbweSL.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:italic;font-weight:100;src:url(/_astro/ibm-plex-serif-v19-latin-100italic.E22nrI7z.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:normal;font-weight:200;src:url(/_astro/ibm-plex-serif-v19-latin-200.GFXE_YJc.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:italic;font-weight:200;src:url(/_astro/ibm-plex-serif-v19-latin-200italic.pJK4yaaG.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:normal;font-weight:300;src:url(/_astro/ibm-plex-serif-v19-latin-300.RVbRgkxX.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:italic;font-weight:300;src:url(/_astro/ibm-plex-serif-v19-latin-300italic.ZdSVgmcR.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:normal;font-weight:400;src:url(/_astro/ibm-plex-serif-v19-latin-regular.HRmMD3sQ.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:italic;font-weight:400;src:url(/_astro/ibm-plex-serif-v19-latin-italic.MiJiQVsi.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:normal;font-weight:500;src:url(/_astro/ibm-plex-serif-v19-latin-500.xAA_w-Ac.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:italic;font-weight:500;src:url(/_astro/ibm-plex-serif-v19-latin-500italic.Unq84pJ7.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:normal;font-weight:600;src:url(/_astro/ibm-plex-serif-v19-latin-600.cuuqzllG.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:italic;font-weight:600;src:url(/_astro/ibm-plex-serif-v19-latin-600italic.vDhUog1q.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:normal;font-weight:700;src:url(/_astro/ibm-plex-serif-v19-latin-700.yX9JjmCp.woff2) format("woff2")}@font-face{font-display:swap;font-family:"IBM Plex Serif";font-style:italic;font-weight:700;src:url(/_astro/ibm-plex-serif-v19-latin-700italic.QM1RA0vx.woff2) format("woff2")}@font-face{font-display:swap;font-family:"Noto Serif SC";font-style:normal;font-weight:200;src:url(/_astro/noto-serif-sc-v22-chinese-simplified-200.g4OBZhIi.woff2) format("woff2")}@font-face{font-display:swap;font-family:"Noto Serif SC";font-style:normal;font-weight:300;src:url(/_astro/noto-serif-sc-v22-chinese-simplified-300.yFtdUYoh.woff2) format("woff2")}@font-face{font-display:swap;font-family:"Noto Serif SC";font-style:normal;font-weight:400;src:url(/_astro/noto-serif-sc-v22-chinese-simplified-regular.9muiKgFz.woff2) format("woff2")}@font-face{font-display:swap;font-family:"Noto Serif SC";font-style:normal;font-weight:500;src:url(/_astro/noto-serif-sc-v22-chinese-simplified-500.exkAspFQ.woff2) format("woff2")}@font-face{font-display:swap;font-family:"Noto Serif SC";font-style:normal;font-weight:600;src:url(/_astro/noto-serif-sc-v22-chinese-simplified-600.4n6uFOXj.woff2) format("woff2")}@font-face{font-display:swap;font-family:"Noto Serif SC";font-style:normal;font-weight:700;src:url(/_astro/noto-serif-sc-v22-chinese-simplified-700.HyiB9Pzv.woff2) format("woff2")}@font-face{font-display:swap;font-family:"Noto Serif SC";font-style:normal;font-weight:900;src:url(/_astro/noto-serif-sc-v22-chinese-simplified-900.ERSRy_0V.woff2) format("woff2")}.astro-route-announcer{position:absolute;left:0;top:0;clip:rect(0 0 0 0);-webkit-clip-path:inset(50%);clip-path:inset(50%);overflow:hidden;white-space:nowrap;width:1px;height:1px}.h-fullpage{height:calc(100vh - 64px)}.max-h-fullpage{max-height:calc(100vh - 64px)}.mt-header{margin-top:64px}.top-header{top:64px}html{overflow-x:hidden!important;overflow-y:auto!important}@keyframes astroFadeInOut{0%{opacity:1}to{opacity:0}}@keyframes astroFadeIn{0%{opacity:0}}@keyframes astroFadeOut{to{opacity:0}}@keyframes astroSlideFromRight{0%{transform:translate(100%)}}@keyframes astroSlideFromLeft{0%{transform:translate(-100%)}}@keyframes astroSlideToRight{to{transform:translate(100%)}}@keyframes astroSlideToLeft{to{transform:translate(-100%)}}@media (prefers-reduced-motion){::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}[data-astro-transition-scope]{animation:none!important}}
|
1
test/data/warden/dist/client/_astro/_slug_.yOjdTrIk.css
vendored
Normal file
1
test/data/warden/dist/client/_astro/_slug_.yOjdTrIk.css
vendored
Normal file
File diff suppressed because one or more lines are too long
24
test/data/warden/dist/client/_astro/client.olTvLX7Y.js
vendored
Normal file
24
test/data/warden/dist/client/_astro/client.olTvLX7Y.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
test/data/warden/dist/client/_astro/hoisted.l-JsOPk0.js
vendored
Normal file
1
test/data/warden/dist/client/_astro/hoisted.l-JsOPk0.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-100.6qNbweSL.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-100.6qNbweSL.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-100italic.E22nrI7z.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-100italic.E22nrI7z.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-200.GFXE_YJc.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-200.GFXE_YJc.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-200italic.pJK4yaaG.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-200italic.pJK4yaaG.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-300.RVbRgkxX.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-300.RVbRgkxX.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-300italic.ZdSVgmcR.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-300italic.ZdSVgmcR.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-500.xAA_w-Ac.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-500.xAA_w-Ac.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-500italic.Unq84pJ7.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-500italic.Unq84pJ7.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-600.cuuqzllG.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-600.cuuqzllG.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-600italic.vDhUog1q.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-600italic.vDhUog1q.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-700.yX9JjmCp.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-700.yX9JjmCp.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-700italic.QM1RA0vx.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-700italic.QM1RA0vx.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-italic.MiJiQVsi.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-italic.MiJiQVsi.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-regular.HRmMD3sQ.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/ibm-plex-serif-v19-latin-regular.HRmMD3sQ.woff2
vendored
Normal file
Binary file not shown.
9
test/data/warden/dist/client/_astro/index.LFf77hJu.js
vendored
Normal file
9
test/data/warden/dist/client/_astro/index.LFf77hJu.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-200.g4OBZhIi.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-200.g4OBZhIi.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-300.yFtdUYoh.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-300.yFtdUYoh.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-500.exkAspFQ.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-500.exkAspFQ.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-600.4n6uFOXj.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-600.4n6uFOXj.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-700.HyiB9Pzv.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-700.HyiB9Pzv.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-900.ERSRy_0V.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-900.ERSRy_0V.woff2
vendored
Normal file
Binary file not shown.
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-regular.9muiKgFz.woff2
vendored
Normal file
BIN
test/data/warden/dist/client/_astro/noto-serif-sc-v22-chinese-simplified-regular.9muiKgFz.woff2
vendored
Normal file
Binary file not shown.
2
test/data/warden/dist/client/admin/.gitignore
vendored
Normal file
2
test/data/warden/dist/client/admin/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
index.html
|
||||
assets/
|
21
test/data/warden/dist/client/favicon.svg
vendored
Normal file
21
test/data/warden/dist/client/favicon.svg
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1024" height="1024">
|
||||
<title>SmartSheep Logo</title>
|
||||
<defs>
|
||||
<image width="124" height="198" id="img1" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHwAAADGCAMAAAAnkRSfAAAAAXNSR0IB2cksfwAAAq9QTFRFAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////J9QBRAAAAOV0Uk5TAA0WEiFfjMLMr40/BRdmtuz//vbQYAQmpfLdQAGovyURj/iOD0r07loDGJfbPDTf/bhd94QLdPrrVQLWcPmtHU31egknzehRg9Ev1xnzbgYHhfzmTMorSOSbFJloKsniReXDKG/7kQ6m8WMw3ue7I4cKNdTZOFTqsR5/Hzra0zZY7al4Ir5SPWHvnpbG4MRrlKJs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"/>
|
||||
<image width="122" height="142" id="img2" href="data:image/png;base64,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"/>
|
||||
</defs>
|
||||
<style>
|
||||
.s0 { fill: #ffffff;stroke: #000000;stroke-miterlimit:100;stroke-width: 56 }
|
||||
.s1 { fill: #4750a3;stroke: #000000;stroke-miterlimit:100;stroke-width: 56 }
|
||||
</style>
|
||||
<path id="Wool" fill-rule="evenodd" class="s0" d="m128 608.4c0 95.9 77.4 173.6 172.8 173.6h441.6c84.8 0 153.6-69.1 153.6-154.3 0-74.6-52.8-136.9-122.9-151.1 4.9-12.9 7.7-27 7.7-41.7 0-63.9-51.6-115.8-115.2-115.8-23.6 0-45.7 7.3-64 19.6-33.2-57.9-95.2-96.7-166.4-96.7-106.1 0-192 86.3-192 192.9 0 3.2 0.1 6.5 0.2 9.7-67.2 23.8-115.4 88.1-115.4 163.8z"/>
|
||||
<g id="Crystal">
|
||||
<path id="Crystal" class="s1" d="m699 224l138.6 80v160l-138.6 80-138.6-80v-160z"/>
|
||||
<use id="Highlight" href="#img1" x="688" y="255"/>
|
||||
</g>
|
||||
<g id="Horn">
|
||||
</g>
|
||||
<g id="Face">
|
||||
<use id="Slime" href="#img2" x="233" y="538"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.1 KiB |
BIN
test/data/warden/dist/client/media/nicolas-saintot-xkFhOdId7mA-unsplash.jpg
vendored
Normal file
BIN
test/data/warden/dist/client/media/nicolas-saintot-xkFhOdId7mA-unsplash.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 MiB |
1
test/data/warden/dist/client/sitemap-0.xml
vendored
Normal file
1
test/data/warden/dist/client/sitemap-0.xml
vendored
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://smartsheep.studio/</loc></url><url><loc>https://smartsheep.studio/events/</loc></url><url><loc>https://smartsheep.studio/posts/</loc></url></urlset>
|
1
test/data/warden/dist/client/sitemap-index.xml
vendored
Normal file
1
test/data/warden/dist/client/sitemap-index.xml
vendored
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><sitemap><loc>https://smartsheep.studio/sitemap-0.xml</loc></sitemap></sitemapindex>
|
3
test/data/warden/dist/server/_empty-middleware.mjs
vendored
Normal file
3
test/data/warden/dist/server/_empty-middleware.mjs
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
const onRequest = undefined;
|
||||
|
||||
export { onRequest };
|
6
test/data/warden/dist/server/chunks/_slug__3BAY271A.mjs
vendored
Normal file
6
test/data/warden/dist/server/chunks/_slug__3BAY271A.mjs
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
export { renderers } from '../renderers.mjs';
|
||||
export { onRequest } from '../_empty-middleware.mjs';
|
||||
|
||||
const page = () => import('./pages/_slug__TUDhKBhQ.mjs').then(n => n.c);
|
||||
|
||||
export { page };
|
6
test/data/warden/dist/server/chunks/_slug__EgGcJ0nJ.mjs
vendored
Normal file
6
test/data/warden/dist/server/chunks/_slug__EgGcJ0nJ.mjs
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
export { renderers } from '../renderers.mjs';
|
||||
export { onRequest } from '../_empty-middleware.mjs';
|
||||
|
||||
const page = () => import('./pages/_slug__TUDhKBhQ.mjs').then(n => n._);
|
||||
|
||||
export { page };
|
6
test/data/warden/dist/server/chunks/_slug__wxGnmrgA.mjs
vendored
Normal file
6
test/data/warden/dist/server/chunks/_slug__wxGnmrgA.mjs
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
export { renderers } from '../renderers.mjs';
|
||||
export { onRequest } from '../_empty-middleware.mjs';
|
||||
|
||||
const page = () => import('./pages/_slug__TUDhKBhQ.mjs').then(n => n.d);
|
||||
|
||||
export { page };
|
342
test/data/warden/dist/server/chunks/astro/assets-service_4dMyVCFm.mjs
vendored
Normal file
342
test/data/warden/dist/server/chunks/astro/assets-service_4dMyVCFm.mjs
vendored
Normal file
@ -0,0 +1,342 @@
|
||||
import { isRemotePath, joinPaths } from '@astrojs/internal-helpers/path';
|
||||
import { A as AstroError, E as ExpectedImage, L as LocalImageUsedWrongly, M as MissingImageDimension, U as UnsupportedImageFormat, I as IncompatibleDescriptorOptions, a as UnsupportedImageConversion, b as MissingSharp } from '../astro_5WdVqH1c.mjs';
|
||||
|
||||
const VALID_SUPPORTED_FORMATS = [
|
||||
"jpeg",
|
||||
"jpg",
|
||||
"png",
|
||||
"tiff",
|
||||
"webp",
|
||||
"gif",
|
||||
"svg",
|
||||
"avif"
|
||||
];
|
||||
const DEFAULT_OUTPUT_FORMAT = "webp";
|
||||
const DEFAULT_HASH_PROPS = ["src", "width", "height", "format", "quality"];
|
||||
|
||||
function isESMImportedImage(src) {
|
||||
return typeof src === "object";
|
||||
}
|
||||
function isRemoteImage(src) {
|
||||
return typeof src === "string";
|
||||
}
|
||||
|
||||
function matchPattern(url, remotePattern) {
|
||||
return matchProtocol(url, remotePattern.protocol) && matchHostname(url, remotePattern.hostname, true) && matchPort(url, remotePattern.port) && matchPathname(url, remotePattern.pathname, true);
|
||||
}
|
||||
function matchPort(url, port) {
|
||||
return !port || port === url.port;
|
||||
}
|
||||
function matchProtocol(url, protocol) {
|
||||
return !protocol || protocol === url.protocol.slice(0, -1);
|
||||
}
|
||||
function matchHostname(url, hostname, allowWildcard) {
|
||||
if (!hostname) {
|
||||
return true;
|
||||
} else if (!allowWildcard || !hostname.startsWith("*")) {
|
||||
return hostname === url.hostname;
|
||||
} else if (hostname.startsWith("**.")) {
|
||||
const slicedHostname = hostname.slice(2);
|
||||
return slicedHostname !== url.hostname && url.hostname.endsWith(slicedHostname);
|
||||
} else if (hostname.startsWith("*.")) {
|
||||
const slicedHostname = hostname.slice(1);
|
||||
const additionalSubdomains = url.hostname.replace(slicedHostname, "").split(".").filter(Boolean);
|
||||
return additionalSubdomains.length === 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function matchPathname(url, pathname, allowWildcard) {
|
||||
if (!pathname) {
|
||||
return true;
|
||||
} else if (!allowWildcard || !pathname.endsWith("*")) {
|
||||
return pathname === url.pathname;
|
||||
} else if (pathname.endsWith("/**")) {
|
||||
const slicedPathname = pathname.slice(0, -2);
|
||||
return slicedPathname !== url.pathname && url.pathname.startsWith(slicedPathname);
|
||||
} else if (pathname.endsWith("/*")) {
|
||||
const slicedPathname = pathname.slice(0, -1);
|
||||
const additionalPathChunks = url.pathname.replace(slicedPathname, "").split("/").filter(Boolean);
|
||||
return additionalPathChunks.length === 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isRemoteAllowed(src, {
|
||||
domains = [],
|
||||
remotePatterns = []
|
||||
}) {
|
||||
if (!isRemotePath(src))
|
||||
return false;
|
||||
const url = new URL(src);
|
||||
return domains.some((domain) => matchHostname(url, domain)) || remotePatterns.some((remotePattern) => matchPattern(url, remotePattern));
|
||||
}
|
||||
|
||||
function isLocalService(service) {
|
||||
if (!service) {
|
||||
return false;
|
||||
}
|
||||
return "transform" in service;
|
||||
}
|
||||
function parseQuality(quality) {
|
||||
let result = parseInt(quality);
|
||||
if (Number.isNaN(result)) {
|
||||
return quality;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
const baseService = {
|
||||
propertiesToHash: DEFAULT_HASH_PROPS,
|
||||
validateOptions(options) {
|
||||
if (!options.src || typeof options.src !== "string" && typeof options.src !== "object") {
|
||||
throw new AstroError({
|
||||
...ExpectedImage,
|
||||
message: ExpectedImage.message(
|
||||
JSON.stringify(options.src),
|
||||
typeof options.src,
|
||||
JSON.stringify(options, (_, v) => v === void 0 ? null : v)
|
||||
)
|
||||
});
|
||||
}
|
||||
if (!isESMImportedImage(options.src)) {
|
||||
if (options.src.startsWith("/@fs/") || !isRemotePath(options.src) && !options.src.startsWith("/")) {
|
||||
throw new AstroError({
|
||||
...LocalImageUsedWrongly,
|
||||
message: LocalImageUsedWrongly.message(options.src)
|
||||
});
|
||||
}
|
||||
let missingDimension;
|
||||
if (!options.width && !options.height) {
|
||||
missingDimension = "both";
|
||||
} else if (!options.width && options.height) {
|
||||
missingDimension = "width";
|
||||
} else if (options.width && !options.height) {
|
||||
missingDimension = "height";
|
||||
}
|
||||
if (missingDimension) {
|
||||
throw new AstroError({
|
||||
...MissingImageDimension,
|
||||
message: MissingImageDimension.message(missingDimension, options.src)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (!VALID_SUPPORTED_FORMATS.includes(options.src.format)) {
|
||||
throw new AstroError({
|
||||
...UnsupportedImageFormat,
|
||||
message: UnsupportedImageFormat.message(
|
||||
options.src.format,
|
||||
options.src.src,
|
||||
VALID_SUPPORTED_FORMATS
|
||||
)
|
||||
});
|
||||
}
|
||||
if (options.widths && options.densities) {
|
||||
throw new AstroError(IncompatibleDescriptorOptions);
|
||||
}
|
||||
if (options.src.format === "svg") {
|
||||
options.format = "svg";
|
||||
}
|
||||
if (options.src.format === "svg" && options.format !== "svg" || options.src.format !== "svg" && options.format === "svg") {
|
||||
throw new AstroError(UnsupportedImageConversion);
|
||||
}
|
||||
}
|
||||
if (!options.format) {
|
||||
options.format = DEFAULT_OUTPUT_FORMAT;
|
||||
}
|
||||
if (options.width)
|
||||
options.width = Math.round(options.width);
|
||||
if (options.height)
|
||||
options.height = Math.round(options.height);
|
||||
return options;
|
||||
},
|
||||
getHTMLAttributes(options) {
|
||||
const { targetWidth, targetHeight } = getTargetDimensions(options);
|
||||
const { src, width, height, format, quality, densities, widths, formats, ...attributes } = options;
|
||||
return {
|
||||
...attributes,
|
||||
width: targetWidth,
|
||||
height: targetHeight,
|
||||
loading: attributes.loading ?? "lazy",
|
||||
decoding: attributes.decoding ?? "async"
|
||||
};
|
||||
},
|
||||
getSrcSet(options) {
|
||||
const srcSet = [];
|
||||
const { targetWidth } = getTargetDimensions(options);
|
||||
const { widths, densities } = options;
|
||||
const targetFormat = options.format ?? DEFAULT_OUTPUT_FORMAT;
|
||||
let imageWidth = options.width;
|
||||
let maxWidth = Infinity;
|
||||
if (isESMImportedImage(options.src)) {
|
||||
imageWidth = options.src.width;
|
||||
maxWidth = imageWidth;
|
||||
}
|
||||
const {
|
||||
width: transformWidth,
|
||||
height: transformHeight,
|
||||
...transformWithoutDimensions
|
||||
} = options;
|
||||
const allWidths = [];
|
||||
if (densities) {
|
||||
const densityValues = densities.map((density) => {
|
||||
if (typeof density === "number") {
|
||||
return density;
|
||||
} else {
|
||||
return parseFloat(density);
|
||||
}
|
||||
});
|
||||
const densityWidths = densityValues.sort().map((density) => Math.round(targetWidth * density));
|
||||
allWidths.push(
|
||||
...densityWidths.map((width, index) => ({
|
||||
maxTargetWidth: Math.min(width, maxWidth),
|
||||
descriptor: `${densityValues[index]}x`
|
||||
}))
|
||||
);
|
||||
} else if (widths) {
|
||||
allWidths.push(
|
||||
...widths.map((width) => ({
|
||||
maxTargetWidth: Math.min(width, maxWidth),
|
||||
descriptor: `${width}w`
|
||||
}))
|
||||
);
|
||||
}
|
||||
for (const { maxTargetWidth, descriptor } of allWidths) {
|
||||
const srcSetTransform = { ...transformWithoutDimensions };
|
||||
if (maxTargetWidth !== imageWidth) {
|
||||
srcSetTransform.width = maxTargetWidth;
|
||||
} else {
|
||||
if (options.width && options.height) {
|
||||
srcSetTransform.width = options.width;
|
||||
srcSetTransform.height = options.height;
|
||||
}
|
||||
}
|
||||
srcSet.push({
|
||||
transform: srcSetTransform,
|
||||
descriptor,
|
||||
attributes: {
|
||||
type: `image/${targetFormat}`
|
||||
}
|
||||
});
|
||||
}
|
||||
return srcSet;
|
||||
},
|
||||
getURL(options, imageConfig) {
|
||||
const searchParams = new URLSearchParams();
|
||||
if (isESMImportedImage(options.src)) {
|
||||
searchParams.append("href", options.src.src);
|
||||
} else if (isRemoteAllowed(options.src, imageConfig)) {
|
||||
searchParams.append("href", options.src);
|
||||
} else {
|
||||
return options.src;
|
||||
}
|
||||
const params = {
|
||||
w: "width",
|
||||
h: "height",
|
||||
q: "quality",
|
||||
f: "format"
|
||||
};
|
||||
Object.entries(params).forEach(([param, key]) => {
|
||||
options[key] && searchParams.append(param, options[key].toString());
|
||||
});
|
||||
const imageEndpoint = joinPaths("/", "/_image");
|
||||
return `${imageEndpoint}?${searchParams}`;
|
||||
},
|
||||
parseURL(url) {
|
||||
const params = url.searchParams;
|
||||
if (!params.has("href")) {
|
||||
return void 0;
|
||||
}
|
||||
const transform = {
|
||||
src: params.get("href"),
|
||||
width: params.has("w") ? parseInt(params.get("w")) : void 0,
|
||||
height: params.has("h") ? parseInt(params.get("h")) : void 0,
|
||||
format: params.get("f"),
|
||||
quality: params.get("q")
|
||||
};
|
||||
return transform;
|
||||
}
|
||||
};
|
||||
function getTargetDimensions(options) {
|
||||
let targetWidth = options.width;
|
||||
let targetHeight = options.height;
|
||||
if (isESMImportedImage(options.src)) {
|
||||
const aspectRatio = options.src.width / options.src.height;
|
||||
if (targetHeight && !targetWidth) {
|
||||
targetWidth = Math.round(targetHeight * aspectRatio);
|
||||
} else if (targetWidth && !targetHeight) {
|
||||
targetHeight = Math.round(targetWidth / aspectRatio);
|
||||
} else if (!targetWidth && !targetHeight) {
|
||||
targetWidth = options.src.width;
|
||||
targetHeight = options.src.height;
|
||||
}
|
||||
}
|
||||
return {
|
||||
targetWidth,
|
||||
targetHeight
|
||||
};
|
||||
}
|
||||
|
||||
let sharp;
|
||||
const qualityTable = {
|
||||
low: 25,
|
||||
mid: 50,
|
||||
high: 80,
|
||||
max: 100
|
||||
};
|
||||
async function loadSharp() {
|
||||
let sharpImport;
|
||||
try {
|
||||
sharpImport = (await import('sharp')).default;
|
||||
} catch (e) {
|
||||
throw new AstroError(MissingSharp);
|
||||
}
|
||||
return sharpImport;
|
||||
}
|
||||
const sharpService = {
|
||||
validateOptions: baseService.validateOptions,
|
||||
getURL: baseService.getURL,
|
||||
parseURL: baseService.parseURL,
|
||||
getHTMLAttributes: baseService.getHTMLAttributes,
|
||||
getSrcSet: baseService.getSrcSet,
|
||||
async transform(inputBuffer, transformOptions, config) {
|
||||
if (!sharp)
|
||||
sharp = await loadSharp();
|
||||
const transform = transformOptions;
|
||||
if (transform.format === "svg")
|
||||
return { data: inputBuffer, format: "svg" };
|
||||
const result = sharp(inputBuffer, {
|
||||
failOnError: false,
|
||||
pages: -1,
|
||||
limitInputPixels: config.service.config.limitInputPixels
|
||||
});
|
||||
result.rotate();
|
||||
if (transform.height && !transform.width) {
|
||||
result.resize({ height: Math.round(transform.height) });
|
||||
} else if (transform.width) {
|
||||
result.resize({ width: Math.round(transform.width) });
|
||||
}
|
||||
if (transform.format) {
|
||||
let quality = void 0;
|
||||
if (transform.quality) {
|
||||
const parsedQuality = parseQuality(transform.quality);
|
||||
if (typeof parsedQuality === "number") {
|
||||
quality = parsedQuality;
|
||||
} else {
|
||||
quality = transform.quality in qualityTable ? qualityTable[transform.quality] : void 0;
|
||||
}
|
||||
}
|
||||
result.toFormat(transform.format, { quality });
|
||||
}
|
||||
const { data, info } = await result.toBuffer({ resolveWithObject: true });
|
||||
return {
|
||||
data,
|
||||
format: info.format
|
||||
};
|
||||
}
|
||||
};
|
||||
var sharp_default = sharpService;
|
||||
|
||||
const sharp$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: sharp_default
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
export { DEFAULT_HASH_PROPS as D, isLocalService as a, isRemoteImage as b, isRemoteAllowed as c, isESMImportedImage as i, sharp$1 as s };
|
2196
test/data/warden/dist/server/chunks/astro_5WdVqH1c.mjs
vendored
Normal file
2196
test/data/warden/dist/server/chunks/astro_5WdVqH1c.mjs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
test/data/warden/dist/server/chunks/index_5_WFUSxR.mjs
vendored
Normal file
6
test/data/warden/dist/server/chunks/index_5_WFUSxR.mjs
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
export { renderers } from '../renderers.mjs';
|
||||
export { onRequest } from '../_empty-middleware.mjs';
|
||||
|
||||
const page = () => import('./pages/index_l5vwnKzb.mjs').then(n => n.b);
|
||||
|
||||
export { page };
|
6
test/data/warden/dist/server/chunks/index_6C3b8yBv.mjs
vendored
Normal file
6
test/data/warden/dist/server/chunks/index_6C3b8yBv.mjs
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
export { renderers } from '../renderers.mjs';
|
||||
export { onRequest } from '../_empty-middleware.mjs';
|
||||
|
||||
const page = () => import('./pages/index_l5vwnKzb.mjs').then(n => n.i);
|
||||
|
||||
export { page };
|
6
test/data/warden/dist/server/chunks/index_Ij1Dwoh1.mjs
vendored
Normal file
6
test/data/warden/dist/server/chunks/index_Ij1Dwoh1.mjs
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
export { renderers } from '../renderers.mjs';
|
||||
export { onRequest } from '../_empty-middleware.mjs';
|
||||
|
||||
const page = () => import('./pages/index_l5vwnKzb.mjs').then(n => n.a);
|
||||
|
||||
export { page };
|
6
test/data/warden/dist/server/chunks/node_0Fr8CwHA.mjs
vendored
Normal file
6
test/data/warden/dist/server/chunks/node_0Fr8CwHA.mjs
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
export { renderers } from '../renderers.mjs';
|
||||
export { onRequest } from '../_empty-middleware.mjs';
|
||||
|
||||
const page = () => import('./pages/node_hIg2I-Kh.mjs');
|
||||
|
||||
export { page };
|
245
test/data/warden/dist/server/chunks/pages/_slug__TUDhKBhQ.mjs
vendored
Normal file
245
test/data/warden/dist/server/chunks/pages/_slug__TUDhKBhQ.mjs
vendored
Normal file
@ -0,0 +1,245 @@
|
||||
/* empty css */
|
||||
import 'html-escaper';
|
||||
import { c as createAstro, d as createComponent, r as renderTemplate, m as maybeRenderHead, e as addAttribute, f as renderSlot, g as renderTransition, h as renderComponent, i as renderHead } from '../astro_5WdVqH1c.mjs';
|
||||
import 'kleur/colors';
|
||||
import 'clsx';
|
||||
import { DocumentRenderer } from '@keystone-6/document-renderer';
|
||||
/* empty css */
|
||||
/* empty css */
|
||||
|
||||
const $$Astro$7 = createAstro("https://smartsheep.studio");
|
||||
const $$Navbar = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro$7, $$props, $$slots);
|
||||
Astro2.self = $$Navbar;
|
||||
const items = [
|
||||
{
|
||||
label: "\u60C5\u62A5",
|
||||
children: [
|
||||
{ href: "/posts", label: "\u8BB0\u5F55" },
|
||||
{ href: "/events", label: "\u6D3B\u52A8" }
|
||||
]
|
||||
}
|
||||
];
|
||||
return renderTemplate`${maybeRenderHead()}<div class="fixed top-0 navbar shadow-md bg-base-100 lg:px-5 z-10"> <div class="navbar-start"> <div class="dropdown"> <div tabindex="0" role="button" class="btn btn-ghost lg:hidden"> <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h8m-8 6h16"></path> </svg> </div> <ul tabindex="0" class="menu menu-sm dropdown-content mt-3 z-[1] p-2 shadow bg-base-100 rounded-box w-52"> ${items.map((item) => renderTemplate`<li> <a${addAttribute(item.href, "href")}>${item.label}</a> ${item.children && renderTemplate`<ul class="p-2"> ${item.children?.map((child) => renderTemplate`<li> <a${addAttribute(child.href, "href")}>${child.label}</a> </li>`)} </ul>`} </li>`)} </ul> </div> <a class="btn btn-ghost text-xl" href="/">山羊寒舍</a> </div> <div class="navbar-center hidden lg:flex"> <ul class="menu menu-horizontal px-1"> ${items.map((item) => renderTemplate`<li> ${item.children ? renderTemplate`<details> <summary>${item.label}</summary> <ul class="p-2"> ${item.children?.map((child) => renderTemplate`<li> <a${addAttribute(child.href, "href")}>${child.label}</a> </li>`)} </ul> </details>` : renderTemplate`<a${addAttribute(item.href, "href")}>${item.label}</a>`} </li>`)} </ul> </div> <div class="navbar-end"> <label class="swap swap-rotate px-[16px]"> <input type="checkbox" class="theme-controller" value="light" checked> <svg class="swap-on fill-current w-8 h-8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z"></path> </svg> <svg class="swap-off fill-current w-8 h-8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z"></path> </svg> </label> </div> </div>`;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/src/components/Navbar.astro", void 0);
|
||||
|
||||
const $$Astro$6 = createAstro("https://smartsheep.studio");
|
||||
const $$ViewTransitions = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro$6, $$props, $$slots);
|
||||
Astro2.self = $$ViewTransitions;
|
||||
const { fallback = "animate" } = Astro2.props;
|
||||
return renderTemplate`<meta name="astro-view-transitions-enabled" content="true"><meta name="astro-view-transitions-fallback"${addAttribute(fallback, "content")}>`;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/node_modules/astro/components/ViewTransitions.astro", void 0);
|
||||
|
||||
var __freeze = Object.freeze;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", { value: __freeze(raw || cooked.slice()) }));
|
||||
var _a;
|
||||
const $$Astro$5 = createAstro("https://smartsheep.studio");
|
||||
const $$RootLayout = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro$5, $$props, $$slots);
|
||||
Astro2.self = $$RootLayout;
|
||||
const { title } = Astro2.props;
|
||||
return renderTemplate(_a || (_a = __template(['<html lang="en" data-astro-cid-mdysn4oi> <head><meta charset="utf-8"><link rel="icon" type="image/svg+xml" href="/favicon.svg"><meta name="viewport" content="width=device-width"><meta name="generator"', ">", "", "", "", "</head> <body data-astro-cid-mdysn4oi> <!-- Header --> ", " <!-- Content --> <main data-astro-cid-mdysn4oi", "> ", ' </main> <!-- Styles --> <script async src="https://analytics.smartsheep.studio/script.js" data-website-id="9d676a27-b473-44a3-b444-5a7d851e31e8"><\/script> </body> </html>'])), addAttribute(Astro2.generator, "content"), title && renderTemplate`<title>山羊寒舍 | ${title}</title>`, !title && renderTemplate`<title>山羊寒舍</title>`, renderComponent($$result, "ViewTransitions", $$ViewTransitions, { "data-astro-cid-mdysn4oi": true }), renderHead(), renderComponent($$result, "Navbar", $$Navbar, { "data-astro-cid-mdysn4oi": true }), addAttribute(renderTransition($$result, "53mar5bf", "slide", ""), "data-astro-transition-scope"), renderSlot($$result, $$slots["default"]));
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/src/layouts/RootLayout.astro", "self");
|
||||
|
||||
const $$Astro$4 = createAstro("https://smartsheep.studio");
|
||||
const $$PageLayout = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro$4, $$props, $$slots);
|
||||
Astro2.self = $$PageLayout;
|
||||
const { title } = Astro2.props;
|
||||
return renderTemplate`${renderComponent($$result, "RootLayout", $$RootLayout, { "title": title }, { "default": ($$result2) => renderTemplate` ${maybeRenderHead()}<main class="container mx-auto h-fullpage mt-header"> ${renderSlot($$result2, $$slots["default"])} </main> ` })}`;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/src/layouts/PageLayout.astro", void 0);
|
||||
|
||||
const defaultCms = "https://smartsheep.studio";
|
||||
async function graphQuery(query, variables) {
|
||||
const response = await fetch(`${process.env.PUBLIC_CMS ?? defaultCms}/api/graphql`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
query,
|
||||
variables
|
||||
})
|
||||
});
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
const POST_TYPES = {
|
||||
article: "文章",
|
||||
podcast: "播客",
|
||||
announcements: "通告"
|
||||
};
|
||||
|
||||
const $$Astro$3 = createAstro("https://smartsheep.studio");
|
||||
const $$PostList = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro$3, $$props, $$slots);
|
||||
Astro2.self = $$PostList;
|
||||
const { posts } = Astro2.props;
|
||||
return renderTemplate`${maybeRenderHead()}<div class="grid justify-items-strench shadow-lg"> ${posts?.map((item) => renderTemplate`<a${addAttribute(`/p/${item.slug}`, "href")}> <div class="card sm:card-side hover:bg-base-200 transition-colors sm:max-w-none"> ${item.cover.image.url && renderTemplate`<figure class="mx-auto w-full object-cover p-6 max-sm:pb-0 sm:max-w-[12rem] sm:pe-0"> <img loading="lazy"${addAttribute(item.cover.image.url, "src")} class="border-base-content bg-base-300 rounded-btn border border-opacity-5"${addAttribute(item.title, "alt")}> </figure>`} <div class="card-body"> <h2 class="text-xl">${item.title}</h2> <div class="mx-[-2px] mt-[-4px]"> <span class="badge badge-accent">${POST_TYPES[item.type]}</span> ${item.categories?.map((category) => renderTemplate`<span class="badge badge-primary">${category.name}</span>`)} ${item.tags?.map((tag) => renderTemplate`<span class="badge badge-secondary">${tag.name}</span>`)} </div> <div class="text-xs opacity-60 line-clamp-3"> ${item.description} </div> </div> </div> </a>`)} </div>`;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/src/components/PostList.astro", void 0);
|
||||
|
||||
const $$Astro$2 = createAstro("https://smartsheep.studio");
|
||||
const prerender$2 = false;
|
||||
const $$slug$2 = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro$2, $$props, $$slots);
|
||||
Astro2.self = $$slug$2;
|
||||
const { slug } = Astro2.params;
|
||||
const { posts } = (await graphQuery(
|
||||
`query Query($where: PostWhereInput!, $orderBy: [PostOrderByInput!]!) {
|
||||
posts(where: $where, orderBy: $orderBy) {
|
||||
slug
|
||||
type
|
||||
title
|
||||
description
|
||||
cover {
|
||||
image {
|
||||
url
|
||||
}
|
||||
}
|
||||
content {
|
||||
document
|
||||
}
|
||||
categories {
|
||||
name
|
||||
}
|
||||
tags {
|
||||
name
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
}`,
|
||||
{
|
||||
orderBy: [
|
||||
{
|
||||
createdAt: "desc"
|
||||
}
|
||||
],
|
||||
where: { categories: { some: { slug: { equals: slug } } } }
|
||||
}
|
||||
)).data;
|
||||
return renderTemplate`${renderComponent($$result, "PageLayout", $$PageLayout, { "title": "\u5206\u7C7B\u68C0\u7D22" }, { "default": ($$result2) => renderTemplate` ${maybeRenderHead()}<div class="max-w-[720px] mx-auto"> <div class="pt-16 pb-6 px-6"> <h1 class="text-4xl font-bold">分类检索</h1> <p class="pt-3">以下是包含该分类的记录……</p> </div> ${renderComponent($$result2, "PostList", $$PostList, { "posts": posts })} </div> ` })}`;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/src/pages/categories/[slug].astro", void 0);
|
||||
|
||||
const $$file$2 = "/Users/littlesheep/Documents/Projects/Capital/src/pages/categories/[slug].astro";
|
||||
const $$url$2 = "/categories/[slug]";
|
||||
|
||||
const _slug_$2 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$slug$2,
|
||||
file: $$file$2,
|
||||
prerender: prerender$2,
|
||||
url: $$url$2
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const $$Astro$1 = createAstro("https://smartsheep.studio");
|
||||
const prerender$1 = false;
|
||||
const $$slug$1 = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro$1, $$props, $$slots);
|
||||
Astro2.self = $$slug$1;
|
||||
const { slug } = Astro2.params;
|
||||
const { post } = (await graphQuery(
|
||||
`query Query($where: PostWhereUniqueInput!) {
|
||||
post(where: $where) {
|
||||
slug
|
||||
type
|
||||
title
|
||||
description
|
||||
author {
|
||||
name
|
||||
}
|
||||
assets {
|
||||
caption
|
||||
url
|
||||
type
|
||||
}
|
||||
cover {
|
||||
image {
|
||||
url
|
||||
}
|
||||
}
|
||||
content {
|
||||
document
|
||||
}
|
||||
categories {
|
||||
slug
|
||||
name
|
||||
}
|
||||
tags {
|
||||
slug
|
||||
name
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
}`,
|
||||
{
|
||||
where: { slug }
|
||||
}
|
||||
)).data;
|
||||
return renderTemplate`${renderComponent($$result, "PageLayout", $$PageLayout, { "title": post.title, "data-astro-cid-gysqo7gh": true }, { "default": ($$result2) => renderTemplate` ${maybeRenderHead()}<div class="wrapper" data-astro-cid-gysqo7gh> <div class="card w-full shadow-xl" data-astro-cid-gysqo7gh> ${post.cover && renderTemplate`<figure data-astro-cid-gysqo7gh> <img${addAttribute(post.cover.image.url, "src")}${addAttribute(post.title, "alt")} data-astro-cid-gysqo7gh> </figure>`} <div class="card-body" data-astro-cid-gysqo7gh> <h2 class="card-title" data-astro-cid-gysqo7gh>${post.title}</h2> <p class="description" data-astro-cid-gysqo7gh>${post.description ?? "No description"}</p> <div class="divider" data-astro-cid-gysqo7gh></div> ${post.assets?.length > 0 && renderTemplate`<div class="mb-5 w-full" data-astro-cid-gysqo7gh> ${renderComponent($$result2, "Media", null, { "client:only": true, "sources": post.assets, "author": post.author, "client:component-hydration": "only", "data-astro-cid-gysqo7gh": true, "client:component-path": "/Users/littlesheep/Documents/Projects/Capital/src/components/posts/Media", "client:component-export": "default" })} </div>`} <div class="prose max-w-none" data-astro-cid-gysqo7gh> ${renderComponent($$result2, "DocumentRenderer", DocumentRenderer, { "document": post.content.document, "data-astro-cid-gysqo7gh": true })} </div> </div> </div> <div class="h-fit sticky top-header" data-astro-cid-gysqo7gh> <div class="card shadow-xl" data-astro-cid-gysqo7gh> <div class="card-body" data-astro-cid-gysqo7gh> <div class="gap-2 text-sm metadata description" data-astro-cid-gysqo7gh> <div data-astro-cid-gysqo7gh> <div data-astro-cid-gysqo7gh>作者</div> <div data-astro-cid-gysqo7gh>${post.author?.name ?? "\u4F5A\u540D"}</div> </div> <div data-astro-cid-gysqo7gh> <div data-astro-cid-gysqo7gh>类型</div> <div class="text-accent" data-astro-cid-gysqo7gh> ${POST_TYPES[post.type]} </div> </div> <div data-astro-cid-gysqo7gh> <div data-astro-cid-gysqo7gh>分类</div> <div class="flex gap-1" data-astro-cid-gysqo7gh> ${post.categories?.map((category) => renderTemplate`<a${addAttribute(`/categories/${category.slug}`, "href")} class="link link-primary" data-astro-cid-gysqo7gh> ${category.name} </a>`)} </div> </div> <div data-astro-cid-gysqo7gh> <div data-astro-cid-gysqo7gh>标签</div> <div class="flex gap-1" data-astro-cid-gysqo7gh> ${post.tags?.map((tag) => renderTemplate`<a${addAttribute(`/tags/${tag.slug}`, "href")} class="link link-secondary" data-astro-cid-gysqo7gh> ${tag.name} </a>`)} </div> </div> <div data-astro-cid-gysqo7gh> <div data-astro-cid-gysqo7gh>发布于</div> <div data-astro-cid-gysqo7gh>${new Date(post.createdAt).toLocaleString()}</div> </div> </div> </div> </div> </div> </div> ` })} `;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/src/pages/posts/[slug].astro", void 0);
|
||||
|
||||
const $$file$1 = "/Users/littlesheep/Documents/Projects/Capital/src/pages/posts/[slug].astro";
|
||||
const $$url$1 = "/posts/[slug]";
|
||||
|
||||
const _slug_$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$slug$1,
|
||||
file: $$file$1,
|
||||
prerender: prerender$1,
|
||||
url: $$url$1
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const $$Astro = createAstro("https://smartsheep.studio");
|
||||
const prerender = false;
|
||||
const $$slug = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||||
Astro2.self = $$slug;
|
||||
const { slug } = Astro2.params;
|
||||
const { posts } = (await graphQuery(
|
||||
`query Query($where: PostWhereInput!, $orderBy: [PostOrderByInput!]!) {
|
||||
posts(where: $where, orderBy: $orderBy) {
|
||||
slug
|
||||
type
|
||||
title
|
||||
description
|
||||
cover {
|
||||
image {
|
||||
url
|
||||
}
|
||||
}
|
||||
content {
|
||||
document
|
||||
}
|
||||
categories {
|
||||
name
|
||||
}
|
||||
tags {
|
||||
name
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
}`,
|
||||
{
|
||||
orderBy: [
|
||||
{
|
||||
createdAt: "desc"
|
||||
}
|
||||
],
|
||||
where: { tags: { some: { slug: { equals: slug } } } }
|
||||
}
|
||||
)).data;
|
||||
return renderTemplate`${renderComponent($$result, "PageLayout", $$PageLayout, { "title": "\u6807\u7B7E\u68C0\u7D22" }, { "default": ($$result2) => renderTemplate` ${maybeRenderHead()}<div class="max-w-[720px] mx-auto"> <div class="pt-16 pb-6 px-6"> <h1 class="text-4xl font-bold">标签检索</h1> <p class="pt-3">以下是包含该标签的记录……</p> </div> ${renderComponent($$result2, "PostList", $$PostList, { "posts": posts })} </div> ` })}`;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/src/pages/tags/[slug].astro", void 0);
|
||||
|
||||
const $$file = "/Users/littlesheep/Documents/Projects/Capital/src/pages/tags/[slug].astro";
|
||||
const $$url = "/tags/[slug]";
|
||||
|
||||
const _slug_ = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$slug,
|
||||
file: $$file,
|
||||
prerender,
|
||||
url: $$url
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
export { $$PageLayout as $, _slug_$2 as _, $$PostList as a, $$RootLayout as b, _slug_$1 as c, _slug_ as d, graphQuery as g };
|
153
test/data/warden/dist/server/chunks/pages/index_l5vwnKzb.mjs
vendored
Normal file
153
test/data/warden/dist/server/chunks/pages/index_l5vwnKzb.mjs
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
/* empty css */
|
||||
import { c as createAstro, d as createComponent, r as renderTemplate, h as renderComponent, m as maybeRenderHead, e as addAttribute } from '../astro_5WdVqH1c.mjs';
|
||||
import 'kleur/colors';
|
||||
import 'html-escaper';
|
||||
import { g as graphQuery, $ as $$PageLayout, a as $$PostList, b as $$RootLayout } from './_slug__TUDhKBhQ.mjs';
|
||||
import { DocumentRenderer } from '@keystone-6/document-renderer';
|
||||
import 'clsx';
|
||||
/* empty css */
|
||||
|
||||
const $$Astro$2 = createAstro("https://smartsheep.studio");
|
||||
const prerender$2 = false;
|
||||
const $$Index$2 = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro$2, $$props, $$slots);
|
||||
Astro2.self = $$Index$2;
|
||||
const { events } = (await graphQuery(
|
||||
`query Query($where: EventWhereInput!) {
|
||||
events(where: $where) {
|
||||
slug
|
||||
title
|
||||
description
|
||||
content {
|
||||
document
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
}`,
|
||||
{
|
||||
where: {
|
||||
isHistory: {
|
||||
equals: true
|
||||
}
|
||||
}
|
||||
}
|
||||
)).data;
|
||||
return renderTemplate`${renderComponent($$result, "PageLayout", $$PageLayout, { "title": "\u6D3B\u52A8" }, { "default": ($$result2) => renderTemplate` ${maybeRenderHead()}<div class="max-w-[720px] mx-auto"> <div class="card w-full shadow-xl"> <div class="card-body"> <h2 class="card-title">活动</h2> <p>读岁月史书,涨人生阅历</p> <div class="divider"></div> <ul class="timeline timeline-snap-icon max-md:timeline-compact timeline-vertical"> ${events?.map((item, idx) => {
|
||||
let align = idx % 2 === 0 ? "timeline-start" : "timeline-end";
|
||||
let textAlign = idx % 2 === 0 ? "md:text-right" : "md:text-left";
|
||||
return renderTemplate`<li> ${idx > 0 && renderTemplate`<hr>`} <div class="timeline-middle"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="h-5 w-5"> <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd"></path> </svg> </div> <div${addAttribute(`${align} ${textAlign} mb-10`, "class")}> <time class="font-mono italic"> ${new Date(item.createdAt).toLocaleDateString()} </time> <div class="text-lg font-black">${item.title}</div> ${renderComponent($$result2, "DocumentRenderer", DocumentRenderer, { "document": item.content.document })} </div> <hr> </li>`;
|
||||
})} </ul> <div class="text-center max-md:text-left italic">
|
||||
我们的故事还在继续……
|
||||
</div> </div> </div> </div> ` })}`;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/src/pages/events/index.astro", void 0);
|
||||
|
||||
const $$file$2 = "/Users/littlesheep/Documents/Projects/Capital/src/pages/events/index.astro";
|
||||
const $$url$2 = "/events";
|
||||
|
||||
const index$2 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$Index$2,
|
||||
file: $$file$2,
|
||||
prerender: prerender$2,
|
||||
url: $$url$2
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const $$Astro$1 = createAstro("https://smartsheep.studio");
|
||||
const prerender$1 = false;
|
||||
const $$Index$1 = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro$1, $$props, $$slots);
|
||||
Astro2.self = $$Index$1;
|
||||
const { posts } = (await graphQuery(
|
||||
`query Query($where: PostWhereInput!, $orderBy: [PostOrderByInput!]!) {
|
||||
posts(where: $where, orderBy: $orderBy) {
|
||||
slug
|
||||
type
|
||||
title
|
||||
description
|
||||
cover {
|
||||
image {
|
||||
url
|
||||
}
|
||||
}
|
||||
content {
|
||||
document
|
||||
}
|
||||
categories {
|
||||
name
|
||||
}
|
||||
tags {
|
||||
name
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
}`,
|
||||
{
|
||||
orderBy: [
|
||||
{
|
||||
createdAt: "desc"
|
||||
}
|
||||
],
|
||||
where: {}
|
||||
}
|
||||
)).data;
|
||||
return renderTemplate`${renderComponent($$result, "PageLayout", $$PageLayout, { "title": "\u8BB0\u5F55" }, { "default": ($$result2) => renderTemplate` ${maybeRenderHead()}<div class="max-w-[720px] mx-auto"> <div class="pt-16 pb-6 px-6"> <h1 class="text-4xl font-bold">记录</h1> <p class="pt-2">记录生活,记录理想,记录记录……</p> </div> ${renderComponent($$result2, "PostList", $$PostList, { "posts": posts })} </div> ` })}`;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/src/pages/posts/index.astro", void 0);
|
||||
|
||||
const $$file$1 = "/Users/littlesheep/Documents/Projects/Capital/src/pages/posts/index.astro";
|
||||
const $$url$1 = "/posts";
|
||||
|
||||
const index$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$Index$1,
|
||||
file: $$file$1,
|
||||
prerender: prerender$1,
|
||||
url: $$url$1
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const $$Astro = createAstro("https://smartsheep.studio");
|
||||
const prerender = false;
|
||||
const $$Index = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||||
Astro2.self = $$Index;
|
||||
const { events } = (await graphQuery(
|
||||
`query Query($where: EventWhereInput!) {
|
||||
events(where: $where) {
|
||||
slug
|
||||
title
|
||||
description
|
||||
createdAt
|
||||
}
|
||||
}`,
|
||||
{
|
||||
where: {
|
||||
isHistory: {
|
||||
equals: true
|
||||
}
|
||||
}
|
||||
}
|
||||
)).data;
|
||||
return renderTemplate`${renderComponent($$result, "RootLayout", $$RootLayout, { "data-astro-cid-j7pv25f6": true }, { "default": ($$result2) => renderTemplate` ${maybeRenderHead()}<div class="max-h-fullpage mt-header wrapper px-5 snap-y snap-mandatory" data-astro-cid-j7pv25f6> <div id="hello" class="hero h-fullpage snap-start" data-astro-cid-j7pv25f6> <div class="hero-content w-full grid grid-cols-1 md:grid-cols-2 max-md:gap-[60px]" data-astro-cid-j7pv25f6> <div class="max-md:text-center" data-astro-cid-j7pv25f6> <h1 class="text-5xl font-bold" data-astro-cid-j7pv25f6>你好呀 👋</h1> <p class="py-6" data-astro-cid-j7pv25f6>
|
||||
欢迎来到 SmartSheep Studio
|
||||
的官方网站!在这里了解,订阅,跟踪我们的最新消息。
|
||||
接触我们最大的官方社区,并且尝试最新产品,参与各种活动,提供反馈,让我们更好的服务您。
|
||||
</p> <a href="#about" class="btn btn-primary btn-md" data-astro-cid-j7pv25f6>了解更多</a> </div> <div class="flex justify-center md:justify-end max-md:order-first" data-astro-cid-j7pv25f6> <div class="spinning p-3 md:p-5 shadow-2xl aspect-square rounded-[30%] w-[192px] md:w-[256px] lg:w-[384px]" data-astro-cid-j7pv25f6> <img src="/favicon.svg" alt="logo" loading="lazy" data-astro-cid-j7pv25f6> </div> </div> </div> </div> <div id="about" class="hero h-fullpage snap-start" data-astro-cid-j7pv25f6> <div class="hero-content w-full grid grid-cols-1 md:grid-cols-2 max-md:gap-[60px]" data-astro-cid-j7pv25f6> <div class="flex justify-center md:justify-start" data-astro-cid-j7pv25f6> <div class="stats shadow overflow-x-auto" data-astro-cid-j7pv25f6> <div class="stat" data-astro-cid-j7pv25f6> <div class="stat-figure text-secondary" data-astro-cid-j7pv25f6> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-8 h-8 stroke-current" data-astro-cid-j7pv25f6><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" data-astro-cid-j7pv25f6></path></svg> </div> <div class="stat-title" data-astro-cid-j7pv25f6>People</div> <div class="stat-value" data-astro-cid-j7pv25f6>1</div> <div class="stat-desc" data-astro-cid-j7pv25f6>2019 - ${(/* @__PURE__ */ new Date()).getFullYear()}</div> </div> <div class="stat" data-astro-cid-j7pv25f6> <div class="stat-figure text-secondary" data-astro-cid-j7pv25f6> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-8 h-8 stroke-current" data-astro-cid-j7pv25f6><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" data-astro-cid-j7pv25f6></path></svg> </div> <div class="stat-title" data-astro-cid-j7pv25f6>Clients</div> <div class="stat-value" data-astro-cid-j7pv25f6>180</div> <div class="stat-desc" data-astro-cid-j7pv25f6>↗︎ 80 (44%)</div> </div> <div class="stat" data-astro-cid-j7pv25f6> <div class="stat-figure text-secondary" data-astro-cid-j7pv25f6> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-8 h-8 stroke-current" data-astro-cid-j7pv25f6><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4" data-astro-cid-j7pv25f6></path></svg> </div> <div class="stat-title" data-astro-cid-j7pv25f6>Products</div> <div class="stat-value" data-astro-cid-j7pv25f6>4</div> <div class="stat-desc" data-astro-cid-j7pv25f6>↘︎ 8 (67%)</div> </div> </div> </div> <div class="max-md:text-center" data-astro-cid-j7pv25f6> <h1 class="text-5xl font-bold" data-astro-cid-j7pv25f6>关于我们 🔖</h1> <p class="py-6" data-astro-cid-j7pv25f6>
|
||||
我们是一群充满活力、对开源充满热情的开发者。成立于 2019
|
||||
年。自那年起我们一直在开发让人喜欢的开源软件。在我们这里,“取之于开源,用之于开源”
|
||||
不仅是原则,更是我们信仰的座右铭。
|
||||
</p> <a href="#history" class="btn btn-primary btn-md pl-[24px]" data-astro-cid-j7pv25f6>
|
||||
查看「岁月史书」
|
||||
</a> </div> </div> </div> <div id="history" class="flex flex-col justify-center items-center h-fullpage snap-start" data-astro-cid-j7pv25f6> <div class="text-center" data-astro-cid-j7pv25f6> <div data-astro-cid-j7pv25f6> <h1 class="text-4xl font-bold" data-astro-cid-j7pv25f6>岁月史书</h1> <p class="pt-2 pb-4 tracking-[8px]" data-astro-cid-j7pv25f6>但当涉猎,见往事耳</p> <ul class="pb-6 mx-[-20px] max-w-[100vw] px-5 flex justify-center history timeline timeline-horizontal" data-astro-cid-j7pv25f6> ${events?.map((item, idx) => renderTemplate`<li data-astro-cid-j7pv25f6> ${idx > 0 && renderTemplate`<hr data-astro-cid-j7pv25f6>`} <div class="timeline-start" data-astro-cid-j7pv25f6> ${new Date(item.createdAt).toLocaleDateString()} </div> <div class="timeline-middle" data-astro-cid-j7pv25f6> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5" data-astro-cid-j7pv25f6> <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" data-astro-cid-j7pv25f6></path> </svg> </div> <div class="timeline-end timeline-box" data-astro-cid-j7pv25f6> <h2 class="font-bold text-lg" data-astro-cid-j7pv25f6>${item.title}</h2> <div class="line-clamp-2" data-astro-cid-j7pv25f6>${item.description}</div> </div> ${idx < events?.length - 1 && renderTemplate`<hr data-astro-cid-j7pv25f6>`} </li>`)} </ul> <a class="btn btn-primary" href="/events" data-astro-cid-j7pv25f6>查看更多</a> </div> </div> </div> </div> ` })} `;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/src/pages/index.astro", void 0);
|
||||
|
||||
const $$file = "/Users/littlesheep/Documents/Projects/Capital/src/pages/index.astro";
|
||||
const $$url = "";
|
||||
|
||||
const index = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$Index,
|
||||
file: $$file,
|
||||
prerender,
|
||||
url: $$url
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
export { index$1 as a, index as b, index$2 as i };
|
240
test/data/warden/dist/server/chunks/pages/node_hIg2I-Kh.mjs
vendored
Normal file
240
test/data/warden/dist/server/chunks/pages/node_hIg2I-Kh.mjs
vendored
Normal file
@ -0,0 +1,240 @@
|
||||
import { isRemotePath } from '@astrojs/internal-helpers/path';
|
||||
import { readFile } from 'fs/promises';
|
||||
import mime from 'mime/lite.js';
|
||||
import 'os';
|
||||
import { A as AstroError, j as InvalidImageService, k as ExpectedImageOptions, E as ExpectedImage, c as createAstro, d as createComponent, l as ImageMissingAlt, r as renderTemplate, m as maybeRenderHead, e as addAttribute, s as spreadAttributes } from '../astro_5WdVqH1c.mjs';
|
||||
import { i as isESMImportedImage, a as isLocalService, b as isRemoteImage, D as DEFAULT_HASH_PROPS, c as isRemoteAllowed } from '../astro/assets-service_4dMyVCFm.mjs';
|
||||
import 'html-escaper';
|
||||
import 'clsx';
|
||||
|
||||
async function getConfiguredImageService() {
|
||||
if (!globalThis?.astroAsset?.imageService) {
|
||||
const { default: service } = await import(
|
||||
// @ts-expect-error
|
||||
'../astro/assets-service_4dMyVCFm.mjs'
|
||||
).then(n => n.s).catch((e) => {
|
||||
const error = new AstroError(InvalidImageService);
|
||||
error.cause = e;
|
||||
throw error;
|
||||
});
|
||||
if (!globalThis.astroAsset)
|
||||
globalThis.astroAsset = {};
|
||||
globalThis.astroAsset.imageService = service;
|
||||
return service;
|
||||
}
|
||||
return globalThis.astroAsset.imageService;
|
||||
}
|
||||
async function getImage$1(options, imageConfig) {
|
||||
if (!options || typeof options !== "object") {
|
||||
throw new AstroError({
|
||||
...ExpectedImageOptions,
|
||||
message: ExpectedImageOptions.message(JSON.stringify(options))
|
||||
});
|
||||
}
|
||||
if (typeof options.src === "undefined") {
|
||||
throw new AstroError({
|
||||
...ExpectedImage,
|
||||
message: ExpectedImage.message(
|
||||
options.src,
|
||||
"undefined",
|
||||
JSON.stringify(options)
|
||||
)
|
||||
});
|
||||
}
|
||||
const service = await getConfiguredImageService();
|
||||
const resolvedOptions = {
|
||||
...options,
|
||||
src: typeof options.src === "object" && "then" in options.src ? (await options.src).default ?? await options.src : options.src
|
||||
};
|
||||
const originalPath = isESMImportedImage(resolvedOptions.src) ? resolvedOptions.src.fsPath : resolvedOptions.src;
|
||||
const clonedSrc = isESMImportedImage(resolvedOptions.src) ? (
|
||||
// @ts-expect-error - clone is a private, hidden prop
|
||||
resolvedOptions.src.clone ?? resolvedOptions.src
|
||||
) : resolvedOptions.src;
|
||||
resolvedOptions.src = clonedSrc;
|
||||
const validatedOptions = service.validateOptions ? await service.validateOptions(resolvedOptions, imageConfig) : resolvedOptions;
|
||||
const srcSetTransforms = service.getSrcSet ? await service.getSrcSet(validatedOptions, imageConfig) : [];
|
||||
let imageURL = await service.getURL(validatedOptions, imageConfig);
|
||||
let srcSets = await Promise.all(
|
||||
srcSetTransforms.map(async (srcSet) => ({
|
||||
transform: srcSet.transform,
|
||||
url: await service.getURL(srcSet.transform, imageConfig),
|
||||
descriptor: srcSet.descriptor,
|
||||
attributes: srcSet.attributes
|
||||
}))
|
||||
);
|
||||
if (isLocalService(service) && globalThis.astroAsset.addStaticImage && !(isRemoteImage(validatedOptions.src) && imageURL === validatedOptions.src)) {
|
||||
const propsToHash = service.propertiesToHash ?? DEFAULT_HASH_PROPS;
|
||||
imageURL = globalThis.astroAsset.addStaticImage(validatedOptions, propsToHash, originalPath);
|
||||
srcSets = srcSetTransforms.map((srcSet) => ({
|
||||
transform: srcSet.transform,
|
||||
url: globalThis.astroAsset.addStaticImage(srcSet.transform, propsToHash, originalPath),
|
||||
descriptor: srcSet.descriptor,
|
||||
attributes: srcSet.attributes
|
||||
}));
|
||||
}
|
||||
return {
|
||||
rawOptions: resolvedOptions,
|
||||
options: validatedOptions,
|
||||
src: imageURL,
|
||||
srcSet: {
|
||||
values: srcSets,
|
||||
attribute: srcSets.map((srcSet) => `${srcSet.url} ${srcSet.descriptor}`).join(", ")
|
||||
},
|
||||
attributes: service.getHTMLAttributes !== void 0 ? await service.getHTMLAttributes(validatedOptions, imageConfig) : {}
|
||||
};
|
||||
}
|
||||
|
||||
const fnv1a52 = (str) => {
|
||||
const len = str.length;
|
||||
let i = 0, t0 = 0, v0 = 8997, t1 = 0, v1 = 33826, t2 = 0, v2 = 40164, t3 = 0, v3 = 52210;
|
||||
while (i < len) {
|
||||
v0 ^= str.charCodeAt(i++);
|
||||
t0 = v0 * 435;
|
||||
t1 = v1 * 435;
|
||||
t2 = v2 * 435;
|
||||
t3 = v3 * 435;
|
||||
t2 += v0 << 8;
|
||||
t3 += v1 << 8;
|
||||
t1 += t0 >>> 16;
|
||||
v0 = t0 & 65535;
|
||||
t2 += t1 >>> 16;
|
||||
v1 = t1 & 65535;
|
||||
v3 = t3 + (t2 >>> 16) & 65535;
|
||||
v2 = t2 & 65535;
|
||||
}
|
||||
return (v3 & 15) * 281474976710656 + v2 * 4294967296 + v1 * 65536 + (v0 ^ v3 >> 4);
|
||||
};
|
||||
const etag = (payload, weak = false) => {
|
||||
const prefix = weak ? 'W/"' : '"';
|
||||
return prefix + fnv1a52(payload).toString(36) + payload.length.toString(36) + '"';
|
||||
};
|
||||
|
||||
const $$Astro$1 = createAstro("https://smartsheep.studio");
|
||||
const $$Image = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro$1, $$props, $$slots);
|
||||
Astro2.self = $$Image;
|
||||
const props = Astro2.props;
|
||||
if (props.alt === void 0 || props.alt === null) {
|
||||
throw new AstroError(ImageMissingAlt);
|
||||
}
|
||||
if (typeof props.width === "string") {
|
||||
props.width = parseInt(props.width);
|
||||
}
|
||||
if (typeof props.height === "string") {
|
||||
props.height = parseInt(props.height);
|
||||
}
|
||||
const image = await getImage(props);
|
||||
const additionalAttributes = {};
|
||||
if (image.srcSet.values.length > 0) {
|
||||
additionalAttributes.srcset = image.srcSet.attribute;
|
||||
}
|
||||
return renderTemplate`${maybeRenderHead()}<img${addAttribute(image.src, "src")}${spreadAttributes(additionalAttributes)}${spreadAttributes(image.attributes)}>`;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/node_modules/astro/components/Image.astro", void 0);
|
||||
|
||||
const $$Astro = createAstro("https://smartsheep.studio");
|
||||
const $$Picture = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||||
Astro2.self = $$Picture;
|
||||
const defaultFormats = ["webp"];
|
||||
const defaultFallbackFormat = "png";
|
||||
const specialFormatsFallback = ["gif", "svg", "jpg", "jpeg"];
|
||||
const { formats = defaultFormats, pictureAttributes = {}, fallbackFormat, ...props } = Astro2.props;
|
||||
if (props.alt === void 0 || props.alt === null) {
|
||||
throw new AstroError(ImageMissingAlt);
|
||||
}
|
||||
const optimizedImages = await Promise.all(
|
||||
formats.map(
|
||||
async (format) => await getImage({ ...props, format, widths: props.widths, densities: props.densities })
|
||||
)
|
||||
);
|
||||
let resultFallbackFormat = fallbackFormat ?? defaultFallbackFormat;
|
||||
if (!fallbackFormat && isESMImportedImage(props.src) && specialFormatsFallback.includes(props.src.format)) {
|
||||
resultFallbackFormat = props.src.format;
|
||||
}
|
||||
const fallbackImage = await getImage({
|
||||
...props,
|
||||
format: resultFallbackFormat,
|
||||
widths: props.widths,
|
||||
densities: props.densities
|
||||
});
|
||||
const imgAdditionalAttributes = {};
|
||||
const sourceAdditionaAttributes = {};
|
||||
if (props.sizes) {
|
||||
sourceAdditionaAttributes.sizes = props.sizes;
|
||||
}
|
||||
if (fallbackImage.srcSet.values.length > 0) {
|
||||
imgAdditionalAttributes.srcset = fallbackImage.srcSet.attribute;
|
||||
}
|
||||
return renderTemplate`${maybeRenderHead()}<picture${spreadAttributes(pictureAttributes)}> ${Object.entries(optimizedImages).map(([_, image]) => {
|
||||
const srcsetAttribute = props.densities || !props.densities && !props.widths ? `${image.src}${image.srcSet.values.length > 0 ? ", " + image.srcSet.attribute : ""}` : image.srcSet.attribute;
|
||||
return renderTemplate`<source${addAttribute(srcsetAttribute, "srcset")}${addAttribute("image/" + image.options.format, "type")}${spreadAttributes(sourceAdditionaAttributes)}>`;
|
||||
})} <img${addAttribute(fallbackImage.src, "src")}${spreadAttributes(imgAdditionalAttributes)}${spreadAttributes(fallbackImage.attributes)}> </picture>`;
|
||||
}, "/Users/littlesheep/Documents/Projects/Capital/node_modules/astro/components/Picture.astro", void 0);
|
||||
|
||||
const imageConfig = {"service":{"entrypoint":"astro/assets/services/sharp","config":{}},"domains":[],"remotePatterns":[],"endpoint":"astro/assets/endpoint/node"};
|
||||
const assetsDir = new URL("file:///Users/littlesheep/Documents/Projects/Capital/dist/client/");
|
||||
const getImage = async (options) => await getImage$1(options, imageConfig);
|
||||
|
||||
async function loadLocalImage(src, url) {
|
||||
const filePath = new URL("." + src, assetsDir);
|
||||
let buffer = void 0;
|
||||
try {
|
||||
buffer = await readFile(filePath);
|
||||
} catch (e) {
|
||||
const sourceUrl = new URL(src, url.origin);
|
||||
buffer = await loadRemoteImage(sourceUrl);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
async function loadRemoteImage(src) {
|
||||
try {
|
||||
const res = await fetch(src);
|
||||
if (!res.ok) {
|
||||
return void 0;
|
||||
}
|
||||
return Buffer.from(await res.arrayBuffer());
|
||||
} catch (err) {
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
const GET = async ({ request }) => {
|
||||
try {
|
||||
const imageService = await getConfiguredImageService();
|
||||
if (!("transform" in imageService)) {
|
||||
throw new Error("Configured image service is not a local service");
|
||||
}
|
||||
const url = new URL(request.url);
|
||||
const transform = await imageService.parseURL(url, imageConfig);
|
||||
if (!transform?.src) {
|
||||
throw new Error("Incorrect transform returned by `parseURL`");
|
||||
}
|
||||
let inputBuffer = void 0;
|
||||
if (isRemotePath(transform.src)) {
|
||||
if (isRemoteAllowed(transform.src, imageConfig) === false) {
|
||||
return new Response("Forbidden", { status: 403 });
|
||||
}
|
||||
inputBuffer = await loadRemoteImage(new URL(transform.src));
|
||||
} else {
|
||||
inputBuffer = await loadLocalImage(transform.src, url);
|
||||
}
|
||||
if (!inputBuffer) {
|
||||
return new Response("Not Found", { status: 404 });
|
||||
}
|
||||
const { data, format } = await imageService.transform(inputBuffer, transform, imageConfig);
|
||||
return new Response(data, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": mime.getType(format) ?? `image/${format}`,
|
||||
"Cache-Control": "public, max-age=31536000",
|
||||
ETag: etag(data.toString()),
|
||||
Date: (/* @__PURE__ */ new Date()).toUTCString()
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Could not process image request:", err);
|
||||
return new Response(`Server Error: ${err}`, { status: 500 });
|
||||
}
|
||||
};
|
||||
|
||||
export { GET };
|
31
test/data/warden/dist/server/chunks/vnode-children_3wEZly-Z.mjs
vendored
Normal file
31
test/data/warden/dist/server/chunks/vnode-children_3wEZly-Z.mjs
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
import { parse, DOCUMENT_NODE, ELEMENT_NODE, TEXT_NODE } from 'ultrahtml';
|
||||
import { createElement, Fragment } from 'react';
|
||||
|
||||
let ids = 0;
|
||||
function convert(children) {
|
||||
let doc = parse(children.toString().trim());
|
||||
let id = ids++;
|
||||
let key = 0;
|
||||
|
||||
function createReactElementFromNode(node) {
|
||||
const childVnodes =
|
||||
Array.isArray(node.children) && node.children.length
|
||||
? node.children.map((child) => createReactElementFromNode(child)).filter(Boolean)
|
||||
: undefined;
|
||||
|
||||
if (node.type === DOCUMENT_NODE) {
|
||||
return createElement(Fragment, {}, childVnodes);
|
||||
} else if (node.type === ELEMENT_NODE) {
|
||||
const { class: className, ...props } = node.attributes;
|
||||
return createElement(node.name, { ...props, className, key: `${id}-${key++}` }, childVnodes);
|
||||
} else if (node.type === TEXT_NODE) {
|
||||
// 0-length text gets omitted in JSX
|
||||
return node.value.trim() ? node.value : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const root = createReactElementFromNode(doc);
|
||||
return root.props.children;
|
||||
}
|
||||
|
||||
export { convert as default };
|
2355
test/data/warden/dist/server/entry.mjs
vendored
Normal file
2355
test/data/warden/dist/server/entry.mjs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
197
test/data/warden/dist/server/manifest_irk0fM_a.mjs
vendored
Normal file
197
test/data/warden/dist/server/manifest_irk0fM_a.mjs
vendored
Normal file
File diff suppressed because one or more lines are too long
263
test/data/warden/dist/server/renderers.mjs
vendored
Normal file
263
test/data/warden/dist/server/renderers.mjs
vendored
Normal file
@ -0,0 +1,263 @@
|
||||
import React, { createElement } from 'react';
|
||||
import ReactDOM from 'react-dom/server';
|
||||
|
||||
/**
|
||||
* Astro passes `children` as a string of HTML, so we need
|
||||
* a wrapper `div` to render that content as VNodes.
|
||||
*
|
||||
* As a bonus, we can signal to React that this subtree is
|
||||
* entirely static and will never change via `shouldComponentUpdate`.
|
||||
*/
|
||||
const StaticHtml = ({ value, name, hydrate = true }) => {
|
||||
if (!value) return null;
|
||||
const tagName = hydrate ? 'astro-slot' : 'astro-static-slot';
|
||||
return createElement(tagName, {
|
||||
name,
|
||||
suppressHydrationWarning: true,
|
||||
dangerouslySetInnerHTML: { __html: value },
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* This tells React to opt-out of re-rendering this subtree,
|
||||
* In addition to being a performance optimization,
|
||||
* this also allows other frameworks to attach to `children`.
|
||||
*
|
||||
* See https://preactjs.com/guide/v8/external-dom-mutations
|
||||
*/
|
||||
StaticHtml.shouldComponentUpdate = () => false;
|
||||
|
||||
const contexts = new WeakMap();
|
||||
|
||||
const ID_PREFIX = 'r';
|
||||
|
||||
function getContext(rendererContextResult) {
|
||||
if (contexts.has(rendererContextResult)) {
|
||||
return contexts.get(rendererContextResult);
|
||||
}
|
||||
const ctx = {
|
||||
currentIndex: 0,
|
||||
get id() {
|
||||
return ID_PREFIX + this.currentIndex.toString();
|
||||
},
|
||||
};
|
||||
contexts.set(rendererContextResult, ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
function incrementId(rendererContextResult) {
|
||||
const ctx = getContext(rendererContextResult);
|
||||
const id = ctx.id;
|
||||
ctx.currentIndex++;
|
||||
return id;
|
||||
}
|
||||
|
||||
const opts = {
|
||||
experimentalReactChildren: false
|
||||
};
|
||||
|
||||
const slotName = (str) => str.trim().replace(/[-_]([a-z])/g, (_, w) => w.toUpperCase());
|
||||
const reactTypeof = Symbol.for('react.element');
|
||||
|
||||
function errorIsComingFromPreactComponent(err) {
|
||||
return (
|
||||
err.message &&
|
||||
(err.message.startsWith("Cannot read property '__H'") ||
|
||||
err.message.includes("(reading '__H')"))
|
||||
);
|
||||
}
|
||||
|
||||
async function check(Component, props, children) {
|
||||
// Note: there are packages that do some unholy things to create "components".
|
||||
// Checking the $$typeof property catches most of these patterns.
|
||||
if (typeof Component === 'object') {
|
||||
return Component['$$typeof'].toString().slice('Symbol('.length).startsWith('react');
|
||||
}
|
||||
if (typeof Component !== 'function') return false;
|
||||
if (Component.name === 'QwikComponent') return false;
|
||||
|
||||
// Preact forwarded-ref components can be functions, which React does not support
|
||||
if (typeof Component === 'function' && Component['$$typeof'] === Symbol.for('react.forward_ref'))
|
||||
return false;
|
||||
|
||||
if (Component.prototype != null && typeof Component.prototype.render === 'function') {
|
||||
return React.Component.isPrototypeOf(Component) || React.PureComponent.isPrototypeOf(Component);
|
||||
}
|
||||
|
||||
let error = null;
|
||||
let isReactComponent = false;
|
||||
function Tester(...args) {
|
||||
try {
|
||||
const vnode = Component(...args);
|
||||
if (vnode && vnode['$$typeof'] === reactTypeof) {
|
||||
isReactComponent = true;
|
||||
}
|
||||
} catch (err) {
|
||||
if (!errorIsComingFromPreactComponent(err)) {
|
||||
error = err;
|
||||
}
|
||||
}
|
||||
|
||||
return React.createElement('div');
|
||||
}
|
||||
|
||||
await renderToStaticMarkup(Tester, props, children, {});
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
return isReactComponent;
|
||||
}
|
||||
|
||||
async function getNodeWritable() {
|
||||
let nodeStreamBuiltinModuleName = 'node:stream';
|
||||
let { Writable } = await import(/* @vite-ignore */ nodeStreamBuiltinModuleName);
|
||||
return Writable;
|
||||
}
|
||||
|
||||
function needsHydration(metadata) {
|
||||
// Adjust how this is hydrated only when the version of Astro supports `astroStaticSlot`
|
||||
return metadata.astroStaticSlot ? !!metadata.hydrate : true;
|
||||
}
|
||||
|
||||
async function renderToStaticMarkup(Component, props, { default: children, ...slotted }, metadata) {
|
||||
let prefix;
|
||||
if (this && this.result) {
|
||||
prefix = incrementId(this.result);
|
||||
}
|
||||
const attrs = { prefix };
|
||||
|
||||
delete props['class'];
|
||||
const slots = {};
|
||||
for (const [key, value] of Object.entries(slotted)) {
|
||||
const name = slotName(key);
|
||||
slots[name] = React.createElement(StaticHtml, {
|
||||
hydrate: needsHydration(metadata),
|
||||
value,
|
||||
name,
|
||||
});
|
||||
}
|
||||
// Note: create newProps to avoid mutating `props` before they are serialized
|
||||
const newProps = {
|
||||
...props,
|
||||
...slots,
|
||||
};
|
||||
const newChildren = children ?? props.children;
|
||||
if (children && opts.experimentalReactChildren) {
|
||||
attrs['data-react-children'] = true;
|
||||
const convert = await import('./chunks/vnode-children_3wEZly-Z.mjs').then((mod) => mod.default);
|
||||
newProps.children = convert(children);
|
||||
} else if (newChildren != null) {
|
||||
newProps.children = React.createElement(StaticHtml, {
|
||||
hydrate: needsHydration(metadata),
|
||||
value: newChildren,
|
||||
});
|
||||
}
|
||||
const vnode = React.createElement(Component, newProps);
|
||||
const renderOptions = {
|
||||
identifierPrefix: prefix,
|
||||
};
|
||||
let html;
|
||||
if (metadata?.hydrate) {
|
||||
if ('renderToReadableStream' in ReactDOM) {
|
||||
html = await renderToReadableStreamAsync(vnode, renderOptions);
|
||||
} else {
|
||||
html = await renderToPipeableStreamAsync(vnode, renderOptions);
|
||||
}
|
||||
} else {
|
||||
if ('renderToReadableStream' in ReactDOM) {
|
||||
html = await renderToReadableStreamAsync(vnode, renderOptions);
|
||||
} else {
|
||||
html = await renderToStaticNodeStreamAsync(vnode, renderOptions);
|
||||
}
|
||||
}
|
||||
return { html, attrs };
|
||||
}
|
||||
|
||||
async function renderToPipeableStreamAsync(vnode, options) {
|
||||
const Writable = await getNodeWritable();
|
||||
let html = '';
|
||||
return new Promise((resolve, reject) => {
|
||||
let error = undefined;
|
||||
let stream = ReactDOM.renderToPipeableStream(vnode, {
|
||||
...options,
|
||||
onError(err) {
|
||||
error = err;
|
||||
reject(error);
|
||||
},
|
||||
onAllReady() {
|
||||
stream.pipe(
|
||||
new Writable({
|
||||
write(chunk, _encoding, callback) {
|
||||
html += chunk.toString('utf-8');
|
||||
callback();
|
||||
},
|
||||
destroy() {
|
||||
resolve(html);
|
||||
},
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function renderToStaticNodeStreamAsync(vnode, options) {
|
||||
const Writable = await getNodeWritable();
|
||||
let html = '';
|
||||
return new Promise((resolve, reject) => {
|
||||
let stream = ReactDOM.renderToStaticNodeStream(vnode, options);
|
||||
stream.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
stream.pipe(
|
||||
new Writable({
|
||||
write(chunk, _encoding, callback) {
|
||||
html += chunk.toString('utf-8');
|
||||
callback();
|
||||
},
|
||||
destroy() {
|
||||
resolve(html);
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a while loop instead of "for await" due to cloudflare and Vercel Edge issues
|
||||
* See https://github.com/facebook/react/issues/24169
|
||||
*/
|
||||
async function readResult(stream) {
|
||||
const reader = stream.getReader();
|
||||
let result = '';
|
||||
const decoder = new TextDecoder('utf-8');
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) {
|
||||
if (value) {
|
||||
result += decoder.decode(value);
|
||||
} else {
|
||||
// This closes the decoder
|
||||
decoder.decode(new Uint8Array());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
result += decoder.decode(value, { stream: true });
|
||||
}
|
||||
}
|
||||
|
||||
async function renderToReadableStreamAsync(vnode, options) {
|
||||
return await readResult(await ReactDOM.renderToReadableStream(vnode, options));
|
||||
}
|
||||
|
||||
const _renderer0 = {
|
||||
check,
|
||||
renderToStaticMarkup,
|
||||
supportsAstroStaticSlot: true,
|
||||
};
|
||||
|
||||
const renderers = [Object.assign({"name":"@astrojs/react","clientEntrypoint":"@astrojs/react/client.js","serverEntrypoint":"@astrojs/react/server.js"}, { ssr: _renderer0 }),];
|
||||
|
||||
export { renderers };
|
Loading…
Reference in New Issue
Block a user