mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-14 00:27:12 +00:00
examples: include axum_js_ssr
for discussion of integrating JS libraries (#2878)
This commit is contained in:
parent
92ea39ddac
commit
4dea1195e2
21 changed files with 4423 additions and 0 deletions
111
examples/axum_js_ssr/Cargo.toml
Normal file
111
examples/axum_js_ssr/Cargo.toml
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
[package]
|
||||||
|
name = "axum_js_ssr"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
axum = { version = "0.7.5", optional = true }
|
||||||
|
console_error_panic_hook = "0.1.7"
|
||||||
|
console_log = "1.0"
|
||||||
|
gloo-utils = "0.2.0"
|
||||||
|
html-escape = "0.2.13"
|
||||||
|
http-body-util = { version = "0.1.0", optional = true }
|
||||||
|
js-sys = { version = "0.3.69", optional = true }
|
||||||
|
leptos = { path = "../../leptos", features = ["tracing"] }
|
||||||
|
leptos_meta = { path = "../../meta" }
|
||||||
|
leptos_axum = { path = "../../integrations/axum", optional = true }
|
||||||
|
leptos_router = { path = "../../router" }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
thiserror = "1.0"
|
||||||
|
tokio = { version = "1.39", features = [ "rt-multi-thread", "macros", "time" ], optional = true }
|
||||||
|
tower = { version = "0.4.13", optional = true }
|
||||||
|
tower-http = { version = "0.5.2", features = ["fs"], optional = true }
|
||||||
|
wasm-bindgen = "0.2.92"
|
||||||
|
web-sys = { version = "0.3.69", features = [ "AddEventListenerOptions", "Document", "Element", "Event", "EventListener", "EventTarget", "Performance", "Window" ], optional = true }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
hydrate = [
|
||||||
|
"leptos/hydrate",
|
||||||
|
"dep:js-sys",
|
||||||
|
"dep:web-sys",
|
||||||
|
]
|
||||||
|
ssr = [
|
||||||
|
"dep:axum",
|
||||||
|
"dep:http-body-util",
|
||||||
|
"dep:tower",
|
||||||
|
"dep:tower-http",
|
||||||
|
"dep:tokio",
|
||||||
|
"leptos/ssr",
|
||||||
|
"leptos_meta/ssr",
|
||||||
|
"dep:leptos_axum",
|
||||||
|
"leptos_router/ssr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[profile.wasm-release]
|
||||||
|
inherits = "release"
|
||||||
|
opt-level = 'z'
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[package.metadata.cargo-all-features]
|
||||||
|
denylist = ["axum", "tower", "tower-http", "tokio", "sqlx", "leptos_axum"]
|
||||||
|
skip_feature_sets = [["ssr", "hydrate"]]
|
||||||
|
|
||||||
|
[package.metadata.leptos]
|
||||||
|
# The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name
|
||||||
|
output-name = "axum_js_ssr"
|
||||||
|
# The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup.
|
||||||
|
site-root = "target/site"
|
||||||
|
# The site-root relative folder where all compiled output (JS, WASM and CSS) is written
|
||||||
|
# Defaults to pkg
|
||||||
|
site-pkg-dir = "pkg"
|
||||||
|
# [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to <site-root>/<site-pkg>/app.css
|
||||||
|
style-file = "style/main.scss"
|
||||||
|
# Assets source dir. All files found here will be copied and synchronized to site-root.
|
||||||
|
# The assets-dir cannot have a sub directory with the same name/path as site-pkg-dir.
|
||||||
|
#
|
||||||
|
# Optional. Env: LEPTOS_ASSETS_DIR.
|
||||||
|
assets-dir = "assets"
|
||||||
|
# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup.
|
||||||
|
site-addr = "127.0.0.1:3000"
|
||||||
|
# The port to use for automatic reload monitoring
|
||||||
|
reload-port = 3001
|
||||||
|
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
|
||||||
|
# [Windows] for non-WSL use "npx.cmd playwright test"
|
||||||
|
# This binary name can be checked in Powershell with Get-Command npx
|
||||||
|
end2end-cmd = "npx playwright test"
|
||||||
|
end2end-dir = "end2end"
|
||||||
|
# The browserlist query used for optimizing the CSS.
|
||||||
|
browserquery = "defaults"
|
||||||
|
# Set by cargo-leptos watch when building with that tool. Controls whether autoreload JS will be included in the head
|
||||||
|
watch = false
|
||||||
|
# The environment Leptos will run in, usually either "DEV" or "PROD"
|
||||||
|
env = "DEV"
|
||||||
|
# The features to use when compiling the bin target
|
||||||
|
#
|
||||||
|
# Optional. Can be over-ridden with the command line parameter --bin-features
|
||||||
|
bin-features = ["ssr"]
|
||||||
|
|
||||||
|
# If the --no-default-features flag should be used when compiling the bin target
|
||||||
|
#
|
||||||
|
# Optional. Defaults to false.
|
||||||
|
bin-default-features = false
|
||||||
|
|
||||||
|
# The features to use when compiling the lib target
|
||||||
|
#
|
||||||
|
# Optional. Can be over-ridden with the command line parameter --lib-features
|
||||||
|
lib-features = ["hydrate"]
|
||||||
|
|
||||||
|
# If the --no-default-features flag should be used when compiling the lib target
|
||||||
|
#
|
||||||
|
# Optional. Defaults to false.
|
||||||
|
lib-default-features = false
|
||||||
|
|
||||||
|
lib-profile-release = "wasm-release"
|
21
examples/axum_js_ssr/LICENSE
Normal file
21
examples/axum_js_ssr/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Tommy Yu
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
8
examples/axum_js_ssr/Makefile.toml
Normal file
8
examples/axum_js_ssr/Makefile.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
extend = [
|
||||||
|
{ path = "../cargo-make/main.toml" },
|
||||||
|
{ path = "../cargo-make/cargo-leptos.toml" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[env]
|
||||||
|
|
||||||
|
CLIENT_PROCESS_NAME = "axum_js_ssr"
|
10
examples/axum_js_ssr/README.md
Normal file
10
examples/axum_js_ssr/README.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Leptos Axum JS SSR Example
|
||||||
|
|
||||||
|
This example shows the various ways that JavaScript may be included into
|
||||||
|
a Leptos application. The intent is to demonstrate how this may be done
|
||||||
|
and how it may cause the application to fail in an unexpected manner if
|
||||||
|
done incorrectly.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
Run `cargo leptos watch` to run this example.
|
BIN
examples/axum_js_ssr/assets/favicon.ico
Normal file
BIN
examples/axum_js_ssr/assets/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
29
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/LICENSE
generated
vendored
Normal file
29
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2006, Ivan Sagalaev.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
47
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/README.md
generated
vendored
Normal file
47
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/README.md
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# Highlight.js CDN Assets
|
||||||
|
|
||||||
|
**Note: this contains only a subset of files from the full package from NPM.**
|
||||||
|
|
||||||
|
[![install size](https://packagephobia.now.sh/badge?p=highlight.js)](https://packagephobia.now.sh/result?p=highlight.js)
|
||||||
|
|
||||||
|
**This package contains only the CDN build assets of highlight.js.**
|
||||||
|
|
||||||
|
This may be what you want if you'd like to install the pre-built distributable highlight.js client-side assets via NPM. If you're wanting to use highlight.js mainly on the server-side you likely want the [highlight.js][1] package instead.
|
||||||
|
|
||||||
|
To access these files via CDN:<br>
|
||||||
|
https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@latest/build/
|
||||||
|
|
||||||
|
**If you just want a single .js file with the common languages built-in:
|
||||||
|
<https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@latest/build/highlight.min.js>**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Highlight.js
|
||||||
|
|
||||||
|
Highlight.js is a syntax highlighter written in JavaScript. It works in
|
||||||
|
the browser as well as on the server. It works with pretty much any
|
||||||
|
markup, doesn’t depend on any framework, and has automatic language
|
||||||
|
detection.
|
||||||
|
|
||||||
|
If you'd like to read the full README:<br>
|
||||||
|
<https://github.com/highlightjs/highlight.js/blob/main/README.md>
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Highlight.js is released under the BSD License. See [LICENSE][7] file
|
||||||
|
for details.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
The official site for the library is at <https://highlightjs.org/>.
|
||||||
|
|
||||||
|
The Github project may be found at: <https://github.com/highlightjs/highlight.js>
|
||||||
|
|
||||||
|
Further in-depth documentation for the API and other topics is at
|
||||||
|
<http://highlightjs.readthedocs.io/>.
|
||||||
|
|
||||||
|
A list of the Core Team and contributors can be found in the [CONTRIBUTORS.md][8] file.
|
||||||
|
|
||||||
|
[1]: https://www.npmjs.com/package/highlight.js
|
||||||
|
[7]: https://github.com/highlightjs/highlight.js/blob/main/LICENSE
|
||||||
|
[8]: https://github.com/highlightjs/highlight.js/blob/main/CONTRIBUTORS.md
|
1230
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/es/highlight.min.js
generated
vendored
Normal file
1230
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/es/highlight.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1232
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/highlight.min.js
generated
vendored
Normal file
1232
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/highlight.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
93
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/package.json
generated
vendored
Normal file
93
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/package.json
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
{
|
||||||
|
"name": "@highlightjs/cdn-assets",
|
||||||
|
"description": "Syntax highlighting with language autodetection. (pre-compiled CDN assets)",
|
||||||
|
"keywords": [
|
||||||
|
"highlight",
|
||||||
|
"syntax"
|
||||||
|
],
|
||||||
|
"homepage": "https://highlightjs.org/",
|
||||||
|
"version": "11.10.0",
|
||||||
|
"author": "Josh Goebel <hello@joshgoebel.com>",
|
||||||
|
"contributors": [
|
||||||
|
"Josh Goebel <hello@joshgoebel.com>",
|
||||||
|
"Egor Rogov <e.rogov@postgrespro.ru>",
|
||||||
|
"Vladimir Jimenez <me@allejo.io>",
|
||||||
|
"Ivan Sagalaev <maniac@softwaremaniacs.org>",
|
||||||
|
"Jeremy Hull <sourdrums@gmail.com>",
|
||||||
|
"Oleg Efimov <efimovov@gmail.com>",
|
||||||
|
"Gidi Meir Morris <gidi@gidi.io>",
|
||||||
|
"Jan T. Sott <git@idleberg.com>",
|
||||||
|
"Li Xuanji <xuanji@gmail.com>",
|
||||||
|
"Marcos Cáceres <marcos@marcosc.com>",
|
||||||
|
"Sang Dang <sang.dang@polku.io>"
|
||||||
|
],
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/highlightjs/highlight.js/issues"
|
||||||
|
},
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/highlightjs/highlight.js.git"
|
||||||
|
},
|
||||||
|
"sideEffects": [
|
||||||
|
"./es/common.js",
|
||||||
|
"./lib/common.js",
|
||||||
|
"*.css",
|
||||||
|
"*.scss"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"mocha": "mocha",
|
||||||
|
"lint": "eslint src/*.js src/lib/*.js demo/*.js tools/**/*.js --ignore-pattern vendor",
|
||||||
|
"lint-languages": "eslint --no-eslintrc -c .eslintrc.lang.js src/languages/**/*.js",
|
||||||
|
"build_and_test": "npm run build && npm run test",
|
||||||
|
"build_and_test_browser": "npm run build-browser && npm run test-browser",
|
||||||
|
"build": "node ./tools/build.js -t node",
|
||||||
|
"build-cdn": "node ./tools/build.js -t cdn",
|
||||||
|
"build-browser": "node ./tools/build.js -t browser :common",
|
||||||
|
"devtool": "npx http-server",
|
||||||
|
"test": "mocha test",
|
||||||
|
"test-markup": "mocha test/markup",
|
||||||
|
"test-detect": "mocha test/detect",
|
||||||
|
"test-browser": "mocha test/browser",
|
||||||
|
"test-parser": "mocha test/parser"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@colors/colors": "^1.6.0",
|
||||||
|
"@rollup/plugin-commonjs": "^26.0.1",
|
||||||
|
"@rollup/plugin-json": "^6.0.1",
|
||||||
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||||
|
"@types/mocha": "^10.0.2",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^7.15.0",
|
||||||
|
"@typescript-eslint/parser": "^7.15.0",
|
||||||
|
"clean-css": "^5.3.2",
|
||||||
|
"cli-table": "^0.3.1",
|
||||||
|
"commander": "^12.1.0",
|
||||||
|
"css": "^3.0.0",
|
||||||
|
"css-color-names": "^1.0.1",
|
||||||
|
"deep-freeze-es6": "^3.0.2",
|
||||||
|
"del": "^7.1.0",
|
||||||
|
"dependency-resolver": "^2.0.1",
|
||||||
|
"eslint": "^8.57.0",
|
||||||
|
"eslint-config-standard": "^17.1.0",
|
||||||
|
"eslint-plugin-import": "^2.28.1",
|
||||||
|
"eslint-plugin-node": "^11.1.0",
|
||||||
|
"eslint-plugin-promise": "^6.1.1",
|
||||||
|
"glob": "^8.1.0",
|
||||||
|
"glob-promise": "^6.0.5",
|
||||||
|
"handlebars": "^4.7.8",
|
||||||
|
"http-server": "^14.1.1",
|
||||||
|
"jsdom": "^24.1.0",
|
||||||
|
"lodash": "^4.17.20",
|
||||||
|
"mocha": "^10.2.0",
|
||||||
|
"refa": "^0.4.1",
|
||||||
|
"rollup": "^4.0.2",
|
||||||
|
"should": "^13.2.3",
|
||||||
|
"terser": "^5.21.0",
|
||||||
|
"tiny-worker": "^2.3.0",
|
||||||
|
"typescript": "^5.2.2",
|
||||||
|
"wcag-contrast": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
10
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/styles/github-dark.min.css
generated
vendored
Normal file
10
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/styles/github-dark.min.css
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
|
||||||
|
Theme: GitHub Dark
|
||||||
|
Description: Dark theme as seen on github.com
|
||||||
|
Author: github.com
|
||||||
|
Maintainer: @Hirse
|
||||||
|
Updated: 2021-05-15
|
||||||
|
|
||||||
|
Outdated base version: https://github.com/primer/github-syntax-dark
|
||||||
|
Current colors taken from GitHub's CSS
|
||||||
|
*/.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#79c0ff}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-code,.hljs-comment,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}
|
10
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/styles/github.min.css
generated
vendored
Normal file
10
examples/axum_js_ssr/node_modules/@highlightjs/cdn-assets/styles/github.min.css
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
|
||||||
|
Theme: GitHub
|
||||||
|
Description: Light theme as seen on github.com
|
||||||
|
Author: github.com
|
||||||
|
Maintainer: @Hirse
|
||||||
|
Updated: 2021-05-15
|
||||||
|
|
||||||
|
Outdated base version: https://github.com/primer/github-syntax-light
|
||||||
|
Current colors taken from GitHub's CSS
|
||||||
|
*/.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}
|
6
examples/axum_js_ssr/package.json
Normal file
6
examples/axum_js_ssr/package.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "axum_js_ssr",
|
||||||
|
"dependencies": {
|
||||||
|
"@highlightjs/cdn-assets": "^11.10.0"
|
||||||
|
}
|
||||||
|
}
|
2
examples/axum_js_ssr/rust-toolchain.toml
Normal file
2
examples/axum_js_ssr/rust-toolchain.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[toolchain]
|
||||||
|
channel = "stable" # test change
|
8
examples/axum_js_ssr/src/api.rs
Normal file
8
examples/axum_js_ssr/src/api.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
use leptos::{prelude::ServerFnError, server};
|
||||||
|
|
||||||
|
#[server]
|
||||||
|
pub async fn fetch_code() -> Result<String, ServerFnError> {
|
||||||
|
// emulate loading of code from a database/version control/etc
|
||||||
|
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
|
||||||
|
Ok(crate::consts::CH05_02A.to_string())
|
||||||
|
}
|
1134
examples/axum_js_ssr/src/app.rs
Normal file
1134
examples/axum_js_ssr/src/app.rs
Normal file
File diff suppressed because it is too large
Load diff
39
examples/axum_js_ssr/src/consts.rs
Normal file
39
examples/axum_js_ssr/src/consts.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Example programs from the Rust Programming Language Book
|
||||||
|
|
||||||
|
pub const CH03_05A: &str = r#"fn main() {
|
||||||
|
let number = 3;
|
||||||
|
|
||||||
|
if number < 5 {
|
||||||
|
println!("condition was true");
|
||||||
|
} else {
|
||||||
|
println!("condition was false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"#;
|
||||||
|
|
||||||
|
// For some reason, swapping the code examples "fixes" example 6. It
|
||||||
|
// might have something to do with the lower complexity of highlighting
|
||||||
|
// a shorter example. Anyway, including extra newlines for the shorter
|
||||||
|
// example to match with the longer in order to avoid reflowing the
|
||||||
|
// table during the async resource loading for CSR.
|
||||||
|
|
||||||
|
pub const CH05_02A: &str = r#"fn main() {
|
||||||
|
let width1 = 30;
|
||||||
|
let height1 = 50;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"The area of the rectangle is {} square pixels.",
|
||||||
|
area(width1, height1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn area(width: u32, height: u32) -> u32 {
|
||||||
|
width * height
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
pub const LEPTOS_HYDRATED: &str = "_leptos_hydrated";
|
59
examples/axum_js_ssr/src/hljs.rs
Normal file
59
examples/axum_js_ssr/src/hljs.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#[cfg(not(feature = "ssr"))]
|
||||||
|
mod csr {
|
||||||
|
use gloo_utils::format::JsValueSerdeExt;
|
||||||
|
use js_sys::{
|
||||||
|
Object,
|
||||||
|
Reflect::{get, set},
|
||||||
|
};
|
||||||
|
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||||
|
|
||||||
|
#[wasm_bindgen(
|
||||||
|
module = "/node_modules/@highlightjs/cdn-assets/es/highlight.min.js"
|
||||||
|
)]
|
||||||
|
extern "C" {
|
||||||
|
type HighlightOptions;
|
||||||
|
|
||||||
|
#[wasm_bindgen(catch, js_namespace = default, js_name = highlight)]
|
||||||
|
fn highlight_lang(
|
||||||
|
code: String,
|
||||||
|
options: Object,
|
||||||
|
) -> Result<Object, JsValue>;
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_namespace = default, js_name = highlightAll)]
|
||||||
|
pub fn highlight_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keeping the `ignoreIllegals` argument out of the default case, and since there is no optional arguments
|
||||||
|
// in Rust, this will have to be provided in a separate function (e.g. `highlight_ignore_illegals`), much
|
||||||
|
// like how `web_sys` does it for the browser APIs. For simplicity, only the highlighted HTML code is
|
||||||
|
// returned on success, and None on error.
|
||||||
|
pub fn highlight(code: String, lang: String) -> Option<String> {
|
||||||
|
let options = js_sys::Object::new();
|
||||||
|
set(&options, &"language".into(), &lang.into())
|
||||||
|
.expect("failed to assign lang to options");
|
||||||
|
highlight_lang(code, options)
|
||||||
|
.map(|result| {
|
||||||
|
let value = get(&result, &"value".into())
|
||||||
|
.expect("HighlightResult failed to contain the value key");
|
||||||
|
value.into_serde().expect("Value should have been a string")
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
mod ssr {
|
||||||
|
// noop under ssr
|
||||||
|
pub fn highlight_all() {}
|
||||||
|
|
||||||
|
// TODO see if there is a Rust-based solution that will enable isomorphic rendering for this feature.
|
||||||
|
// the current (disabled) implementation simply calls html_escape.
|
||||||
|
// pub fn highlight(code: String, _lang: String) -> Option<String> {
|
||||||
|
// Some(html_escape::encode_text(&code).into_owned())
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ssr"))]
|
||||||
|
pub use csr::*;
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
pub use ssr::*;
|
51
examples/axum_js_ssr/src/lib.rs
Normal file
51
examples/axum_js_ssr/src/lib.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
pub mod api;
|
||||||
|
pub mod app;
|
||||||
|
pub mod consts;
|
||||||
|
pub mod hljs;
|
||||||
|
|
||||||
|
#[cfg(feature = "hydrate")]
|
||||||
|
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||||
|
pub fn hydrate() {
|
||||||
|
use app::*;
|
||||||
|
use consts::LEPTOS_HYDRATED;
|
||||||
|
use std::panic;
|
||||||
|
panic::set_hook(Box::new(|info| {
|
||||||
|
// this custom hook will call out to show the usual error log at
|
||||||
|
// the console while also attempt to update the UI to indicate
|
||||||
|
// a restart of the application is required to continue.
|
||||||
|
console_error_panic_hook::hook(info);
|
||||||
|
let window = leptos::prelude::window();
|
||||||
|
if !matches!(
|
||||||
|
js_sys::Reflect::get(&window, &wasm_bindgen::JsValue::from_str(LEPTOS_HYDRATED)),
|
||||||
|
Ok(t) if t == true
|
||||||
|
) {
|
||||||
|
let document = leptos::prelude::document();
|
||||||
|
let _ = document.query_selector("#reset").map(|el| {
|
||||||
|
el.map(|el| {
|
||||||
|
el.set_class_name("panicked");
|
||||||
|
})
|
||||||
|
});
|
||||||
|
let _ = document.query_selector("#notice").map(|el| {
|
||||||
|
el.map(|el| {
|
||||||
|
el.set_class_name("panicked");
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
leptos::mount::hydrate_body(App);
|
||||||
|
|
||||||
|
let window = leptos::prelude::window();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&window,
|
||||||
|
&wasm_bindgen::JsValue::from_str(LEPTOS_HYDRATED),
|
||||||
|
&wasm_bindgen::JsValue::TRUE,
|
||||||
|
)
|
||||||
|
.expect("error setting hydrated status");
|
||||||
|
let event = web_sys::Event::new(LEPTOS_HYDRATED)
|
||||||
|
.expect("error creating hydrated event");
|
||||||
|
let document = leptos::prelude::document();
|
||||||
|
document
|
||||||
|
.dispatch_event(&event)
|
||||||
|
.expect("error dispatching hydrated event");
|
||||||
|
leptos::logging::log!("dispatched hydrated event");
|
||||||
|
}
|
152
examples/axum_js_ssr/src/main.rs
Normal file
152
examples/axum_js_ssr/src/main.rs
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
mod latency {
|
||||||
|
use std::sync::{Mutex, OnceLock};
|
||||||
|
pub static LATENCY: OnceLock<
|
||||||
|
Mutex<std::iter::Cycle<std::slice::Iter<'_, u64>>>,
|
||||||
|
> = OnceLock::new();
|
||||||
|
pub static ES_LATENCY: OnceLock<
|
||||||
|
Mutex<std::iter::Cycle<std::slice::Iter<'_, u64>>>,
|
||||||
|
> = OnceLock::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
use axum::{
|
||||||
|
body::Body,
|
||||||
|
extract::Request,
|
||||||
|
http::{
|
||||||
|
header::{self, HeaderValue},
|
||||||
|
StatusCode,
|
||||||
|
},
|
||||||
|
middleware::{self, Next},
|
||||||
|
response::{IntoResponse, Response},
|
||||||
|
routing::get,
|
||||||
|
Router,
|
||||||
|
};
|
||||||
|
use axum_js_ssr::app::*;
|
||||||
|
use http_body_util::BodyExt;
|
||||||
|
use leptos::prelude::*;
|
||||||
|
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||||
|
|
||||||
|
latency::LATENCY.get_or_init(|| [0, 4, 40, 400].iter().cycle().into());
|
||||||
|
latency::ES_LATENCY.get_or_init(|| [0].iter().cycle().into());
|
||||||
|
// Having the ES_LATENCY (a cycle of latency for the loading of the es
|
||||||
|
// module) in an identical cycle as LATENCY (for the standard version)
|
||||||
|
// adversely influences the intended demo, as this ultimately delays
|
||||||
|
// hydration when set too high which can cause panic under every case.
|
||||||
|
// If you want to test the effects of the delay just modify the list of
|
||||||
|
// values for the desired cycle of delays.
|
||||||
|
|
||||||
|
let conf = get_configuration(None).unwrap();
|
||||||
|
let addr = conf.leptos_options.site_addr;
|
||||||
|
let leptos_options = conf.leptos_options;
|
||||||
|
// Generate the list of routes in your Leptos App
|
||||||
|
let routes = generate_route_list(App);
|
||||||
|
|
||||||
|
async fn highlight_js() -> impl IntoResponse {
|
||||||
|
(
|
||||||
|
[(header::CONTENT_TYPE, "text/javascript")],
|
||||||
|
include_str!(
|
||||||
|
"../node_modules/@highlightjs/cdn-assets/highlight.min.js"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn latency_for_highlight_js(
|
||||||
|
req: Request,
|
||||||
|
next: Next,
|
||||||
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
|
let uri_parts = &mut req.uri().path().rsplit('/');
|
||||||
|
|
||||||
|
let is_highlightjs = uri_parts.next() == Some("highlight.min.js");
|
||||||
|
let es = uri_parts.next() == Some("es");
|
||||||
|
let module_type = if es { "es module " } else { "standard " };
|
||||||
|
let res = next.run(req).await;
|
||||||
|
if is_highlightjs {
|
||||||
|
// additional processing if the filename is the test subject
|
||||||
|
let (mut parts, body) = res.into_parts();
|
||||||
|
let bytes = body
|
||||||
|
.collect()
|
||||||
|
.await
|
||||||
|
.map_err(|err| {
|
||||||
|
(
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
format!("error reading body: {err}"),
|
||||||
|
)
|
||||||
|
})?
|
||||||
|
.to_bytes();
|
||||||
|
let latency = if es {
|
||||||
|
&latency::ES_LATENCY
|
||||||
|
} else {
|
||||||
|
&latency::LATENCY
|
||||||
|
};
|
||||||
|
|
||||||
|
let delay = match latency
|
||||||
|
.get()
|
||||||
|
.expect("latency cycle wasn't set up")
|
||||||
|
.try_lock()
|
||||||
|
{
|
||||||
|
Ok(ref mut mutex) => {
|
||||||
|
*mutex.next().expect("cycle always has next")
|
||||||
|
}
|
||||||
|
Err(_) => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// inject the logging of the delay used into the target script
|
||||||
|
log!(
|
||||||
|
"loading {module_type}highlight.min.js with latency of \
|
||||||
|
{delay} ms"
|
||||||
|
);
|
||||||
|
let js_log = format!(
|
||||||
|
"\nconsole.log('loaded {module_type}highlight.js with a \
|
||||||
|
minimum latency of {delay} ms');"
|
||||||
|
);
|
||||||
|
tokio::time::sleep(std::time::Duration::from_millis(delay)).await;
|
||||||
|
|
||||||
|
let bytes = [bytes, js_log.into()].concat();
|
||||||
|
let length = bytes.len();
|
||||||
|
let body = Body::from(bytes);
|
||||||
|
|
||||||
|
// Provide the bare minimum set of headers to avoid browser cache.
|
||||||
|
parts.headers = header::HeaderMap::from_iter(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
header::CONTENT_TYPE,
|
||||||
|
HeaderValue::from_static("text/javascript"),
|
||||||
|
),
|
||||||
|
(header::CONTENT_LENGTH, HeaderValue::from(length)),
|
||||||
|
]
|
||||||
|
.into_iter(),
|
||||||
|
);
|
||||||
|
Ok(Response::from_parts(parts, body))
|
||||||
|
} else {
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let app = Router::new()
|
||||||
|
.route("/highlight.min.js", get(highlight_js))
|
||||||
|
.leptos_routes(&leptos_options, routes, {
|
||||||
|
let leptos_options = leptos_options.clone();
|
||||||
|
move || shell(leptos_options.clone())
|
||||||
|
})
|
||||||
|
.fallback(leptos_axum::file_and_error_handler(shell))
|
||||||
|
.layer(middleware::from_fn(latency_for_highlight_js))
|
||||||
|
.with_state(leptos_options);
|
||||||
|
|
||||||
|
// run our app with hyper
|
||||||
|
// `axum::Server` is a re-export of `hyper::Server`
|
||||||
|
log!("listening on http://{}", &addr);
|
||||||
|
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
||||||
|
axum::serve(listener, app.into_make_service())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ssr"))]
|
||||||
|
pub fn main() {
|
||||||
|
// no client-side main function
|
||||||
|
// unless we want this to work with e.g., Trunk for pure client-side testing
|
||||||
|
// see lib.rs for hydration function instead
|
||||||
|
}
|
171
examples/axum_js_ssr/style/main.scss
Normal file
171
examples/axum_js_ssr/style/main.scss
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: sans-serif;
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
min-width: 17em;
|
||||||
|
height: 100vh;
|
||||||
|
counter-reset: example-counter 0;
|
||||||
|
list-style-type: none;
|
||||||
|
list-style-position: outside;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a {
|
||||||
|
display: block;
|
||||||
|
padding: 0.5em 2em;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a small {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a.example::before {
|
||||||
|
counter-reset: subexample-counter 0;
|
||||||
|
counter-increment: example-counter 1;
|
||||||
|
content: counter(example-counter) ". ";
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a.subexample::before {
|
||||||
|
counter-increment: subexample-counter 1;
|
||||||
|
content: counter(example-counter) "." counter(subexample-counter) " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
div#notice {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div#notice.panicked {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
padding: 0.5em 2em;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
width: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
main article {
|
||||||
|
max-width: 60em;
|
||||||
|
margin: 0 1em;
|
||||||
|
padding: 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
main p, main li {
|
||||||
|
line-height: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
main li pre code, main div pre code {
|
||||||
|
display: block;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
main ol, main ul {
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2>code, p>code, li>code {
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li pre code, div pre code {
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#code-demo {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#code-demo table {
|
||||||
|
width: 50em;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#code-demo table td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#code-demo table code {
|
||||||
|
display: block;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
nav {
|
||||||
|
background: #f7f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a[aria-current="page"] {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a:hover, h2>code, p>code, li>code {
|
||||||
|
background-color: #e7e7e7;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a.panicked, main div#notice.panicked {
|
||||||
|
background: #fdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div#notice.panicked a {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a.section {
|
||||||
|
border-bottom: 1px solid #777;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
nav {
|
||||||
|
background: #080808;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a[aria-current="page"] {
|
||||||
|
background-color: #3f3f3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a:hover, h2>code, p>code, li>code {
|
||||||
|
background-color: #383838;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a.panicked, main div#notice.panicked {
|
||||||
|
background: #733;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div#notice.panicked a {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a.section {
|
||||||
|
border-bottom: 1px solid #888;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just include the raw style as-is because I can't find a quick and easy way to import them just for the
|
||||||
|
// appropriate media type...
|
||||||
|
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}
|
||||||
|
@media (prefers-color-scheme: light){.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}}
|
||||||
|
@media (prefers-color-scheme: dark){.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#79c0ff}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-code,.hljs-comment,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}}
|
Loading…
Reference in a new issue