acrylblends 0.6.2 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/docs/framework/README.md +3 -2
- package/docs/framework/UPSTREAM.md +1 -1
- package/docs/framework/cordis/acryl-in-a-cordis-app.md +6 -0
- package/docs/framework/getting-started/basic.md +1 -0
- package/docs/framework/getting-started/desktop.md +41 -0
- package/docs/framework/guides/jsx-dom.md +0 -3
- package/docs/framework/guides/jsx.md +24 -3
- package/docs/framework/helpers/css.md +0 -3
- package/docs/framework/helpers/ssg.md +3 -6
- package/docs/framework/middleware/builtin/jsx-renderer.md +0 -3
- package/docs/framework/upstream.json +3 -3
- package/lib/accepts.d.ts +1 -1
- package/lib/acryl-base.d.ts +1 -1
- package/lib/adapter.d.ts +1 -1
- package/lib/{app-BdrVHBlJ.d.ts → app-D8riatvv.d.ts} +1 -1
- package/lib/base-BpQy2Rk7.d.ts +783 -0
- package/lib/base-ddiVmiE7.js +721 -0
- package/lib/basic-auth.d.ts +1 -1
- package/lib/bearer-auth.d.ts +1 -1
- package/lib/body-limit.d.ts +1 -1
- package/lib/cache.d.ts +1 -1
- package/lib/cache.js +4 -4
- package/lib/{client-BHTr318g.js → client-DDLXwhBo.js} +2 -125
- package/lib/client.d.ts +2 -2
- package/lib/client.js +2 -1
- package/lib/combine.d.ts +1 -1
- package/lib/common-D8Z4JRCw.d.ts +46 -0
- package/lib/components-0o0CBYNv.js +268 -0
- package/lib/components-DdI7-ns7.js +24 -0
- package/lib/compress.d.ts +1 -1
- package/lib/conninfo.d.ts +2 -2
- package/lib/constants-BR9jM9BC.js +9 -0
- package/lib/{context-B5Y1lLha.d.ts → context-DS3fYyG-.d.ts} +2 -2
- package/lib/context-DxFdY_un.d.ts +250 -0
- package/lib/context-storage.d.ts +1 -1
- package/lib/{cookie-D9_nQbsM.d.ts → cookie-CCelEqky.d.ts} +1 -1
- package/lib/cookie.d.ts +3 -3
- package/lib/cors.d.ts +1 -1
- package/lib/csrf.d.ts +1 -1
- package/lib/css-D2jb7X8b.js +320 -0
- package/lib/css.d.ts +82 -0
- package/lib/css.js +134 -0
- package/lib/dev.d.ts +2 -2
- package/lib/etag.d.ts +1 -1
- package/lib/factory.d.ts +2 -2
- package/lib/hooks-BMw6BAyP.js +762 -0
- package/lib/html-SllAe0YT.d.ts +46 -0
- package/lib/html.d.ts +1 -1
- package/lib/{index-m12zcmph.d.ts → index-Bb7YJKCq.d.ts} +3 -3
- package/lib/{index-Kqou8Fjh.d.ts → index-BvFh1Gfx.d.ts} +2 -2
- package/lib/index-C850MeBA.d.ts +94 -0
- package/lib/{index-DtEoak1i.d.ts → index-CTy4N7ng.d.ts} +2 -2
- package/lib/index.d.ts +4 -4
- package/lib/ip-restriction.d.ts +2 -2
- package/lib/jsx/dom/client.d.ts +30 -0
- package/lib/jsx/dom/client.js +49 -0
- package/lib/jsx/dom/css.d.ts +84 -0
- package/lib/jsx/dom/css.js +2 -0
- package/lib/jsx/dom/jsx-dev-runtime.d.ts +3 -0
- package/lib/jsx/dom/jsx-dev-runtime.js +2 -0
- package/lib/jsx/dom/jsx-runtime.d.ts +3 -0
- package/lib/jsx/dom/jsx-runtime.js +2 -0
- package/lib/jsx/dom/server.d.ts +105 -0
- package/lib/jsx/dom/server.js +37 -0
- package/lib/jsx/dom.d.ts +5 -0
- package/lib/jsx/dom.js +74 -0
- package/lib/jsx/jsx-dev-runtime.d.ts +6 -0
- package/lib/jsx/jsx-dev-runtime.js +14 -0
- package/lib/jsx/jsx-runtime.d.ts +10 -0
- package/lib/jsx/jsx-runtime.js +30 -0
- package/lib/jsx/streaming.d.ts +2 -0
- package/lib/jsx/streaming.js +2 -0
- package/lib/jsx-dev-runtime-B22O-Npk.d.ts +7 -0
- package/lib/jsx-dev-runtime-D18Y35TI.js +354 -0
- package/lib/jsx-renderer.d.ts +75 -0
- package/lib/jsx-renderer.js +99 -0
- package/lib/jsx-runtime-BVVgDSdq.d.ts +1 -0
- package/lib/jsx.d.ts +3 -0
- package/lib/jsx.js +47 -0
- package/lib/jwk.d.ts +4 -4
- package/lib/{jwt-BA65QhnJ.d.ts → jwt-BARhotDz.d.ts} +1 -1
- package/lib/jwt.d.ts +4 -4
- package/lib/language.d.ts +1 -1
- package/lib/logger.d.ts +1 -1
- package/lib/loopback-only.d.ts +1 -1
- package/lib/method-not-allowed.d.ts +2 -2
- package/lib/method-override.d.ts +2 -2
- package/lib/mount.d.ts +1 -1
- package/lib/node-server/conninfo.d.ts +1 -1
- package/lib/node-server/serve-static.d.ts +1 -1
- package/lib/node-server/serve-static.js +1 -1
- package/lib/node-server.d.ts +1 -1
- package/lib/node-server.js +1 -1
- package/lib/powered-by.d.ts +1 -1
- package/lib/pretty-json.d.ts +1 -1
- package/lib/proxy.d.ts +1 -1
- package/lib/quick.d.ts +1 -1
- package/lib/request-id.d.ts +1 -1
- package/lib/request.d.ts +1 -1
- package/lib/route.d.ts +1 -1
- package/lib/schema-validator.d.ts +1 -1
- package/lib/secure-headers.d.ts +1 -1
- package/lib/{serve-static-Dw_m6KxR.js → serve-static-B14MF1Va.js} +2 -0
- package/lib/serve-static.d.ts +1 -1
- package/lib/ssg-BwjcA-Ge.js +389 -0
- package/lib/ssg.d.ts +156 -0
- package/lib/ssg.js +2 -0
- package/lib/streaming.d.ts +1 -1
- package/lib/testing.d.ts +4 -4
- package/lib/testing.js +1 -1
- package/lib/timeout.d.ts +1 -1
- package/lib/timing.d.ts +1 -1
- package/lib/tiny.d.ts +1 -1
- package/lib/trailing-slash.d.ts +1 -1
- package/lib/{types-ZM9gIiKh.d.ts → types-Dv_nV2cv.d.ts} +1 -1
- package/lib/{types-D9DEXMjE.d.ts → types-Lqx5BxQF.d.ts} +8 -1
- package/lib/{types-Bd29gh2o.d.ts → types-zNxyEpG2.d.ts} +3 -3
- package/lib/types.d.ts +1 -1
- package/lib/utils/body.d.ts +1 -1
- package/lib/utils/cookie.d.ts +1 -1
- package/lib/utils/crypto.d.ts +1 -1
- package/lib/utils/html.d.ts +1 -45
- package/lib/utils/ipaddr.d.ts +1 -1
- package/lib/utils/jwt.d.ts +1 -1
- package/lib/utils/types.d.ts +2 -2
- package/lib/utils-Cx61GFMC.js +125 -0
- package/lib/validator.d.ts +2 -2
- package/lib/ws.d.ts +1 -1
- package/package.json +53 -1
- package/plugins/acryl-inspect/upstream.json +1 -1
- package/plugins/acryl-node-server/upstream.json +1 -1
- package/plugins/acryl-router/src/core/helper/css/common.ts +337 -0
- package/plugins/acryl-router/src/core/helper/css/index.ts +262 -0
- package/plugins/acryl-router/src/core/helper/ssg/index.ts +14 -0
- package/plugins/acryl-router/src/core/helper/ssg/middleware.ts +83 -0
- package/plugins/acryl-router/src/core/helper/ssg/plugins.ts +72 -0
- package/plugins/acryl-router/src/core/helper/ssg/ssg.ts +471 -0
- package/plugins/acryl-router/src/core/helper/ssg/utils.ts +118 -0
- package/plugins/acryl-router/src/core/jsx/base.ts +490 -0
- package/plugins/acryl-router/src/core/jsx/children.ts +20 -0
- package/plugins/acryl-router/src/core/jsx/components.ts +257 -0
- package/plugins/acryl-router/src/core/jsx/constants.ts +6 -0
- package/plugins/acryl-router/src/core/jsx/context.ts +266 -0
- package/plugins/acryl-router/src/core/jsx/dom/client.ts +89 -0
- package/plugins/acryl-router/src/core/jsx/dom/components.ts +39 -0
- package/plugins/acryl-router/src/core/jsx/dom/context.ts +52 -0
- package/plugins/acryl-router/src/core/jsx/dom/css.ts +263 -0
- package/plugins/acryl-router/src/core/jsx/dom/hooks/index.ts +91 -0
- package/plugins/acryl-router/src/core/jsx/dom/index.ts +170 -0
- package/plugins/acryl-router/src/core/jsx/dom/intrinsic-element/components.ts +438 -0
- package/plugins/acryl-router/src/core/jsx/dom/jsx-dev-runtime.ts +23 -0
- package/plugins/acryl-router/src/core/jsx/dom/jsx-runtime.ts +8 -0
- package/plugins/acryl-router/src/core/jsx/dom/render.ts +879 -0
- package/plugins/acryl-router/src/core/jsx/dom/server.ts +76 -0
- package/plugins/acryl-router/src/core/jsx/dom/utils.ts +7 -0
- package/plugins/acryl-router/src/core/jsx/hooks/index.ts +437 -0
- package/plugins/acryl-router/src/core/jsx/index.ts +115 -0
- package/plugins/acryl-router/src/core/jsx/intrinsic-element/common.ts +23 -0
- package/plugins/acryl-router/src/core/jsx/intrinsic-element/components.ts +210 -0
- package/plugins/acryl-router/src/core/jsx/intrinsic-elements.ts +938 -0
- package/plugins/acryl-router/src/core/jsx/jsx-dev-runtime.ts +26 -0
- package/plugins/acryl-router/src/core/jsx/jsx-runtime.ts +51 -0
- package/plugins/acryl-router/src/core/jsx/streaming.ts +231 -0
- package/plugins/acryl-router/src/core/jsx/types.ts +41 -0
- package/plugins/acryl-router/src/core/jsx/utils.ts +202 -0
- package/plugins/acryl-router/src/core/middleware/cache/index.ts +4 -4
- package/plugins/acryl-router/src/core/middleware/jsx-renderer/index.ts +162 -0
- package/plugins/acryl-router/src/core/utils/types.ts +6 -0
- package/plugins/acryl-router/src/helpers/index.ts +2 -0
- package/plugins/acryl-router/src/middleware/index.ts +1 -0
- package/plugins/acryl-router/upstream.json +3 -3
- package/plugins/acryl-router-http/upstream.json +1 -1
- package/plugins/acryl-state/upstream.json +1 -1
- package/plugins/desktop/upstream.json +1 -1
- package/plugins/desktop-web/upstream.json +1 -1
- package/plugins/extensions/resolve.ts +4 -0
- package/plugins/save/plugin.json +1 -1
- package/shared/AGENTS.core.md +4 -0
- package/templates/agent/tsconfig.json +7 -1
- package/templates/todo/upstream.json +1 -1
- package/plugins/acryl-inspect/tests/report.spec.ts +0 -69
- package/plugins/acryl-inspect/tests/service.spec.ts +0 -121
- package/plugins/acryl-node-server/tests/adapter/app.ts +0 -76
- package/plugins/acryl-node-server/tests/adapter/assets/.static/plain.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/favicon.ico +0 -0
- package/plugins/acryl-node-server/tests/adapter/assets/secret.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static/acryl.html +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static/admin/secret.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static/data.json +0 -5
- package/plugins/acryl-node-server/tests/adapter/assets/static/extensionless +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static/foo..bar.txt +0 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static/index.html +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static/plain.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-context-path/plain.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin.br +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.br +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.zst +0 -1
- package/plugins/acryl-node-server/tests/adapter/conninfo.test.ts +0 -34
- package/plugins/acryl-node-server/tests/adapter/content-length.test.ts +0 -248
- package/plugins/acryl-node-server/tests/adapter/early-hints.test.ts +0 -457
- package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-cert.pem +0 -23
- package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-key.pem +0 -27
- package/plugins/acryl-node-server/tests/adapter/headers.test.ts +0 -252
- package/plugins/acryl-node-server/tests/adapter/helpers/request.ts +0 -190
- package/plugins/acryl-node-server/tests/adapter/listener.test.ts +0 -727
- package/plugins/acryl-node-server/tests/adapter/request-client-disconnect.test.ts +0 -189
- package/plugins/acryl-node-server/tests/adapter/request.test.ts +0 -1230
- package/plugins/acryl-node-server/tests/adapter/response.test.ts +0 -285
- package/plugins/acryl-node-server/tests/adapter/serve-static.test.ts +0 -849
- package/plugins/acryl-node-server/tests/adapter/server-socket.test.ts +0 -790
- package/plugins/acryl-node-server/tests/adapter/server.test.ts +0 -1312
- package/plugins/acryl-node-server/tests/adapter/setup.ts +0 -16
- package/plugins/acryl-node-server/tests/adapter/url.test.ts +0 -76
- package/plugins/acryl-node-server/tests/adapter/utils/response.test.ts +0 -23
- package/plugins/acryl-node-server/tests/adapter/utils/stream.test.ts +0 -75
- package/plugins/acryl-node-server/tests/adapter/utils.test.ts +0 -235
- package/plugins/acryl-node-server/tests/adapter/websocket.test.ts +0 -260
- package/plugins/acryl-node-server/tests/server.spec.ts +0 -141
- package/plugins/acryl-router/src/core/app.test.ts +0 -3833
- package/plugins/acryl-router/src/core/client/client.test.ts +0 -2313
- package/plugins/acryl-router/src/core/client/types.test.ts +0 -149
- package/plugins/acryl-router/src/core/client/utils.test.ts +0 -405
- package/plugins/acryl-router/src/core/compose.test.ts +0 -751
- package/plugins/acryl-router/src/core/context.test.ts +0 -629
- package/plugins/acryl-router/src/core/helper/accepts/accepts.test.ts +0 -344
- package/plugins/acryl-router/src/core/helper/adapter/index.test.ts +0 -55
- package/plugins/acryl-router/src/core/helper/cookie/index.test.ts +0 -510
- package/plugins/acryl-router/src/core/helper/dev/index.test.ts +0 -181
- package/plugins/acryl-router/src/core/helper/factory/index.test.ts +0 -434
- package/plugins/acryl-router/src/core/helper/html/index.test.ts +0 -78
- package/plugins/acryl-router/src/core/helper/proxy/index.test.ts +0 -356
- package/plugins/acryl-router/src/core/helper/route/index.test.ts +0 -259
- package/plugins/acryl-router/src/core/helper/streaming/stream.test.ts +0 -128
- package/plugins/acryl-router/src/core/helper/streaming/text.test.ts +0 -34
- package/plugins/acryl-router/src/core/helper/testing/index.test.ts +0 -42
- package/plugins/acryl-router/src/core/helper/websocket/index.test.ts +0 -124
- package/plugins/acryl-router/src/core/http-exception.test.ts +0 -45
- package/plugins/acryl-router/src/core/middleware/basic-auth/index.test.ts +0 -434
- package/plugins/acryl-router/src/core/middleware/bearer-auth/index.test.ts +0 -1018
- package/plugins/acryl-router/src/core/middleware/body-limit/index.test.ts +0 -273
- package/plugins/acryl-router/src/core/middleware/cache/index.test.ts +0 -1211
- package/plugins/acryl-router/src/core/middleware/combine/index.test.ts +0 -355
- package/plugins/acryl-router/src/core/middleware/compress/index.test.ts +0 -535
- package/plugins/acryl-router/src/core/middleware/context-storage/index.test.ts +0 -43
- package/plugins/acryl-router/src/core/middleware/cors/index.test.ts +0 -532
- package/plugins/acryl-router/src/core/middleware/csrf/index.test.ts +0 -534
- package/plugins/acryl-router/src/core/middleware/etag/digest.test.ts +0 -21
- package/plugins/acryl-router/src/core/middleware/etag/index.test.ts +0 -503
- package/plugins/acryl-router/src/core/middleware/ip-restriction/index.test.ts +0 -217
- package/plugins/acryl-router/src/core/middleware/jwk/index.test.ts +0 -1135
- package/plugins/acryl-router/src/core/middleware/jwk/keys.test.json +0 -48
- package/plugins/acryl-router/src/core/middleware/jwt/index.test.ts +0 -802
- package/plugins/acryl-router/src/core/middleware/language/index.test.ts +0 -552
- package/plugins/acryl-router/src/core/middleware/logger/index.test.ts +0 -204
- package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.test.ts +0 -292
- package/plugins/acryl-router/src/core/middleware/method-override/index.test.ts +0 -221
- package/plugins/acryl-router/src/core/middleware/mount/index.test.ts +0 -334
- package/plugins/acryl-router/src/core/middleware/powered-by/index.test.ts +0 -37
- package/plugins/acryl-router/src/core/middleware/pretty-json/index.test.ts +0 -218
- package/plugins/acryl-router/src/core/middleware/request-id/index.test.ts +0 -168
- package/plugins/acryl-router/src/core/middleware/secure-headers/index.test.ts +0 -671
- package/plugins/acryl-router/src/core/middleware/serve-static/index.test.ts +0 -450
- package/plugins/acryl-router/src/core/middleware/serve-static/path.test.ts +0 -50
- package/plugins/acryl-router/src/core/middleware/timeout/index.test.ts +0 -70
- package/plugins/acryl-router/src/core/middleware/timing/index.test.ts +0 -310
- package/plugins/acryl-router/src/core/middleware/trailing-slash/index.test.ts +0 -381
- package/plugins/acryl-router/src/core/preset/quick.test.ts +0 -42
- package/plugins/acryl-router/src/core/preset/tiny.test.ts +0 -42
- package/plugins/acryl-router/src/core/request.test.ts +0 -751
- package/plugins/acryl-router/src/core/router/common.case.test.ts +0 -1132
- package/plugins/acryl-router/src/core/router/linear-router/router.test.ts +0 -80
- package/plugins/acryl-router/src/core/router/pattern-router/router.test.ts +0 -46
- package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.test.ts +0 -154
- package/plugins/acryl-router/src/core/router/reg-exp-router/router.test.ts +0 -265
- package/plugins/acryl-router/src/core/router/smart-router/router.test.ts +0 -13
- package/plugins/acryl-router/src/core/router/trie-router/node.test.ts +0 -896
- package/plugins/acryl-router/src/core/router/trie-router/router.test.ts +0 -8
- package/plugins/acryl-router/src/core/types.test.ts +0 -4134
- package/plugins/acryl-router/src/core/utils/accept.test.ts +0 -299
- package/plugins/acryl-router/src/core/utils/basic-auth.test.ts +0 -56
- package/plugins/acryl-router/src/core/utils/body.test.ts +0 -496
- package/plugins/acryl-router/src/core/utils/buffer.test.ts +0 -147
- package/plugins/acryl-router/src/core/utils/color.test.ts +0 -23
- package/plugins/acryl-router/src/core/utils/concurrent.test.ts +0 -69
- package/plugins/acryl-router/src/core/utils/cookie.test.ts +0 -460
- package/plugins/acryl-router/src/core/utils/crypto.test.ts +0 -43
- package/plugins/acryl-router/src/core/utils/encode.test.ts +0 -61
- package/plugins/acryl-router/src/core/utils/filepath.test.ts +0 -78
- package/plugins/acryl-router/src/core/utils/html.test.ts +0 -16
- package/plugins/acryl-router/src/core/utils/ipaddr.test.ts +0 -149
- package/plugins/acryl-router/src/core/utils/jwt/jwa.test.ts +0 -86
- package/plugins/acryl-router/src/core/utils/jwt/jwt.test.ts +0 -1788
- package/plugins/acryl-router/src/core/utils/mime.test.ts +0 -64
- package/plugins/acryl-router/src/core/utils/stream.test.ts +0 -212
- package/plugins/acryl-router/src/core/utils/types.test.ts +0 -295
- package/plugins/acryl-router/src/core/utils/url.test.ts +0 -384
- package/plugins/acryl-router/src/core/validator/utils.test.ts +0 -82
- package/plugins/acryl-router/src/core/validator/validator.test.ts +0 -1488
- package/plugins/acryl-router/tests/docs-examples.spec.ts +0 -152
- package/plugins/acryl-router/tests/live-install.spec.ts +0 -64
- package/plugins/acryl-router/tests/loader.spec.ts +0 -72
- package/plugins/acryl-router/tests/loopback-only.spec.ts +0 -80
- package/plugins/acryl-router/tests/no-dom/consumer.ts +0 -11
- package/plugins/acryl-router/tests/no-dom/tsconfig.json +0 -13
- package/plugins/acryl-router/tests/service.spec.ts +0 -426
- package/plugins/acryl-router/tests/shadow-state.spec.ts +0 -79
- package/plugins/acryl-router-http/tests/adapter.spec.ts +0 -174
- package/plugins/acryl-router-http/tests/stream.spec.ts +0 -133
- package/plugins/acryl-router-http/tests/surfaces.spec.ts +0 -101
- package/plugins/acryl-state/src/react.ts +0 -11
- package/plugins/acryl-state/tests/cell.spec.ts +0 -71
- package/plugins/acryl-state/tests/react.spec.ts +0 -39
- package/plugins/acryl-state/tests/service.spec.ts +0 -132
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
// provide utility functions for css helper both on server and client
|
|
2
|
+
export const PSEUDO_GLOBAL_SELECTOR = ':-acryl-global'
|
|
3
|
+
export const isPseudoGlobalSelectorRe = new RegExp(`^${PSEUDO_GLOBAL_SELECTOR}{(.*)}$`)
|
|
4
|
+
export const DEFAULT_STYLE_ID = 'acryl-css'
|
|
5
|
+
|
|
6
|
+
export const SELECTOR: unique symbol = Symbol()
|
|
7
|
+
export const CLASS_NAME: unique symbol = Symbol()
|
|
8
|
+
export const STYLE_STRING: unique symbol = Symbol()
|
|
9
|
+
export const SELECTORS: unique symbol = Symbol()
|
|
10
|
+
export const EXTERNAL_CLASS_NAMES: unique symbol = Symbol()
|
|
11
|
+
const CSS_ESCAPED: unique symbol = Symbol()
|
|
12
|
+
|
|
13
|
+
export interface CssClassName {
|
|
14
|
+
[SELECTOR]: string
|
|
15
|
+
[CLASS_NAME]: string
|
|
16
|
+
[STYLE_STRING]: string
|
|
17
|
+
[SELECTORS]: CssClassName[]
|
|
18
|
+
[EXTERNAL_CLASS_NAMES]: string[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const IS_CSS_ESCAPED = Symbol()
|
|
22
|
+
|
|
23
|
+
interface CssEscapedString {
|
|
24
|
+
[CSS_ESCAPED]: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @experimental
|
|
29
|
+
* `rawCssString` is an experimental feature.
|
|
30
|
+
* The API might be changed.
|
|
31
|
+
*/
|
|
32
|
+
export const rawCssString = (value: string): CssEscapedString => {
|
|
33
|
+
return {
|
|
34
|
+
[CSS_ESCAPED]: value,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Used the goober'code as a reference:
|
|
40
|
+
* https://github.com/cristianbote/goober/blob/master/src/core/to-hash.js
|
|
41
|
+
* MIT License, Copyright (c) 2019 Cristian Bote
|
|
42
|
+
*/
|
|
43
|
+
const toHash = (str: string): string => {
|
|
44
|
+
let i = 0,
|
|
45
|
+
out = 11
|
|
46
|
+
while (i < str.length) {
|
|
47
|
+
out = (101 * out + str.charCodeAt(i++)) >>> 0
|
|
48
|
+
}
|
|
49
|
+
return 'css-' + out
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const normalizeLabel = (label: string): string => {
|
|
53
|
+
return label.trim().replace(/\s+/g, '-')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const isValidClassName = (name: string): boolean => /^-?[_a-zA-Z][_a-zA-Z0-9-]*$/.test(name)
|
|
57
|
+
|
|
58
|
+
// `<`, `{`, `}` never appear in valid class names but can break out of a <style> element
|
|
59
|
+
// or inject a CSS rule when an external cx() class name is used as a selector.
|
|
60
|
+
const hasUnsafeSelectorChar = (name: string): boolean => /[<{}]/.test(name)
|
|
61
|
+
|
|
62
|
+
// CSS-wide keywords that are invalid as @keyframes names per the spec
|
|
63
|
+
const RESERVED_KEYFRAME_NAMES = new Set([
|
|
64
|
+
'default',
|
|
65
|
+
'inherit',
|
|
66
|
+
'initial',
|
|
67
|
+
'none',
|
|
68
|
+
'revert',
|
|
69
|
+
'revert-layer',
|
|
70
|
+
'unset',
|
|
71
|
+
])
|
|
72
|
+
const isValidKeyframeName = (name: string): boolean =>
|
|
73
|
+
isValidClassName(name) && !RESERVED_KEYFRAME_NAMES.has(name.toLowerCase())
|
|
74
|
+
|
|
75
|
+
const defaultOnInvalidSlug = (slug: string) => {
|
|
76
|
+
console.warn(`Invalid slug: ${slug}`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const cssStringReStr: string = [
|
|
80
|
+
'"(?:(?:\\\\[\\s\\S]|[^"\\\\])*)"', // double quoted string
|
|
81
|
+
|
|
82
|
+
"'(?:(?:\\\\[\\s\\S]|[^'\\\\])*)'", // single quoted string
|
|
83
|
+
|
|
84
|
+
'url\\(\\s*[^)"\'\\s]*\\s*\\)', // unquoted url, which may contain "//"
|
|
85
|
+
].join('|')
|
|
86
|
+
const minifyCssRe: RegExp = new RegExp(
|
|
87
|
+
[
|
|
88
|
+
'(' + cssStringReStr + ')', // $1: quoted string or unquoted url
|
|
89
|
+
|
|
90
|
+
'(?:' +
|
|
91
|
+
[
|
|
92
|
+
'^\\s+', // head whitespace
|
|
93
|
+
'\\/\\*.*?\\*\\/\\s*', // multi-line comment
|
|
94
|
+
'\\/\\/.*\\n\\s*', // single-line comment
|
|
95
|
+
'\\s+$', // tail whitespace
|
|
96
|
+
].join('|') +
|
|
97
|
+
')',
|
|
98
|
+
|
|
99
|
+
'\\s*;\\s*(}|$)\\s*', // $2: trailing semicolon
|
|
100
|
+
'\\s*([{};,])\\s*', // $3: whitespace around { } , ;
|
|
101
|
+
// $4: whitespace after : (the whitespace before it is a descendant combinator in a selector)
|
|
102
|
+
'(:)\\s*',
|
|
103
|
+
'(\\s)\\s+', // $5: 2+ spaces
|
|
104
|
+
].join('|'),
|
|
105
|
+
'g'
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
export const minify = (css: string): string => {
|
|
109
|
+
return css.replace(minifyCssRe, (_, $1, $2, $3, $4, $5) => $1 || $2 || $3 || $4 || $5 || '')
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
type CssVariableBasicType =
|
|
113
|
+
| CssClassName
|
|
114
|
+
| CssEscapedString
|
|
115
|
+
| string
|
|
116
|
+
| number
|
|
117
|
+
| boolean
|
|
118
|
+
| null
|
|
119
|
+
| undefined
|
|
120
|
+
type CssVariableAsyncType = Promise<CssVariableBasicType>
|
|
121
|
+
type CssVariableArrayType = (CssVariableBasicType | CssVariableAsyncType)[]
|
|
122
|
+
export type CssVariableType = CssVariableBasicType | CssVariableAsyncType | CssVariableArrayType
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* A function that customizes generated CSS class names.
|
|
126
|
+
*
|
|
127
|
+
* @param hash - The default hash-based class name (e.g. `css-1234567890`)
|
|
128
|
+
* @param label - The comment label extracted from the CSS template, may be empty.
|
|
129
|
+
* Whitespace is trimmed and inner spaces are replaced with hyphens.
|
|
130
|
+
* @param styleString - The minified CSS style string
|
|
131
|
+
* @returns The custom class name to use. Must be a safe CSS identifier;
|
|
132
|
+
* otherwise, the default hash is used as a fallback.
|
|
133
|
+
*/
|
|
134
|
+
export type ClassNameSlug = (hash: string, label: string, styleString: string) => string
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* A callback function called when an invalid slug is returned from ClassNameSlug.
|
|
138
|
+
*
|
|
139
|
+
* @param slug - The invalid slug
|
|
140
|
+
*/
|
|
141
|
+
export type OnInvalidSlug = (slug: string) => void
|
|
142
|
+
|
|
143
|
+
export const buildStyleString = (
|
|
144
|
+
strings: TemplateStringsArray,
|
|
145
|
+
values: CssVariableType[]
|
|
146
|
+
): [string, string, CssClassName[], string[]] => {
|
|
147
|
+
const selectors: CssClassName[] = []
|
|
148
|
+
const externalClassNames: string[] = []
|
|
149
|
+
|
|
150
|
+
const label = strings[0].match(/^\s*\/\*(.*?)\*\//)?.[1] || ''
|
|
151
|
+
let styleString = ''
|
|
152
|
+
for (let i = 0, len = strings.length; i < len; i++) {
|
|
153
|
+
styleString += strings[i]
|
|
154
|
+
let vArray = values[i]
|
|
155
|
+
if (typeof vArray === 'boolean' || vArray === null || vArray === undefined) {
|
|
156
|
+
continue
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!Array.isArray(vArray)) {
|
|
160
|
+
vArray = [vArray]
|
|
161
|
+
}
|
|
162
|
+
for (let j = 0, len = vArray.length; j < len; j++) {
|
|
163
|
+
let value = vArray[j]
|
|
164
|
+
if (typeof value === 'boolean' || value === null || value === undefined) {
|
|
165
|
+
continue
|
|
166
|
+
}
|
|
167
|
+
if (typeof value === 'string') {
|
|
168
|
+
if (/([\\"'\/])/.test(value)) {
|
|
169
|
+
styleString += value.replace(/([\\"']|(?<=<)\/)/g, '\\$1')
|
|
170
|
+
} else {
|
|
171
|
+
styleString += value
|
|
172
|
+
}
|
|
173
|
+
} else if (typeof value === 'number') {
|
|
174
|
+
styleString += value
|
|
175
|
+
} else if ((value as CssEscapedString)[CSS_ESCAPED]) {
|
|
176
|
+
styleString += (value as CssEscapedString)[CSS_ESCAPED]
|
|
177
|
+
} else if ((value as CssClassName)[CLASS_NAME].startsWith('@keyframes ')) {
|
|
178
|
+
selectors.push(value as CssClassName)
|
|
179
|
+
styleString += ` ${(value as CssClassName)[CLASS_NAME].substring(11)} `
|
|
180
|
+
} else {
|
|
181
|
+
if (strings[i + 1]?.match(/^\s*{/)) {
|
|
182
|
+
// assume this value is a class name
|
|
183
|
+
selectors.push(value as CssClassName)
|
|
184
|
+
value = `.${(value as CssClassName)[CLASS_NAME]}`
|
|
185
|
+
} else {
|
|
186
|
+
selectors.push(...(value as CssClassName)[SELECTORS])
|
|
187
|
+
externalClassNames.push(...(value as CssClassName)[EXTERNAL_CLASS_NAMES])
|
|
188
|
+
value = (value as CssClassName)[STYLE_STRING]
|
|
189
|
+
const valueLen = value.length
|
|
190
|
+
if (valueLen > 0) {
|
|
191
|
+
const lastChar = value[valueLen - 1]
|
|
192
|
+
if (lastChar !== ';' && lastChar !== '}') {
|
|
193
|
+
value += ';'
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
styleString += `${value || ''}`
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return [label, minify(styleString), selectors, externalClassNames]
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export const cssCommon = (
|
|
206
|
+
strings: TemplateStringsArray,
|
|
207
|
+
values: CssVariableType[],
|
|
208
|
+
classNameSlug?: ClassNameSlug,
|
|
209
|
+
onInvalidSlug?: OnInvalidSlug
|
|
210
|
+
): CssClassName => {
|
|
211
|
+
let [label, thisStyleString, selectors, externalClassNames] = buildStyleString(strings, values)
|
|
212
|
+
const isPseudoGlobal = isPseudoGlobalSelectorRe.exec(thisStyleString)
|
|
213
|
+
if (isPseudoGlobal) {
|
|
214
|
+
thisStyleString = isPseudoGlobal[1]
|
|
215
|
+
}
|
|
216
|
+
const hash = toHash(label + thisStyleString)
|
|
217
|
+
|
|
218
|
+
let customSlug: string | undefined
|
|
219
|
+
if (classNameSlug) {
|
|
220
|
+
const slug = classNameSlug(hash, normalizeLabel(label), thisStyleString)
|
|
221
|
+
if (slug) {
|
|
222
|
+
if (isValidClassName(slug)) {
|
|
223
|
+
customSlug = slug
|
|
224
|
+
} else {
|
|
225
|
+
;(onInvalidSlug || defaultOnInvalidSlug)(slug)
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const selector = (isPseudoGlobal ? PSEUDO_GLOBAL_SELECTOR : '') + (customSlug || hash)
|
|
231
|
+
const className = (
|
|
232
|
+
isPseudoGlobal ? selectors.map((s) => s[CLASS_NAME]) : [selector, ...externalClassNames]
|
|
233
|
+
).join(' ')
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
[SELECTOR]: selector,
|
|
237
|
+
[CLASS_NAME]: className,
|
|
238
|
+
[STYLE_STRING]: thisStyleString,
|
|
239
|
+
[SELECTORS]: selectors,
|
|
240
|
+
[EXTERNAL_CLASS_NAMES]: externalClassNames,
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export const cxCommon = (
|
|
245
|
+
args: (string | boolean | null | undefined | CssClassName)[]
|
|
246
|
+
): (string | boolean | null | undefined | CssClassName)[] => {
|
|
247
|
+
for (let i = 0, len = args.length; i < len; i++) {
|
|
248
|
+
const arg = args[i]
|
|
249
|
+
if (typeof arg === 'string') {
|
|
250
|
+
args[i] = {
|
|
251
|
+
[SELECTOR]: '',
|
|
252
|
+
[CLASS_NAME]: '',
|
|
253
|
+
[STYLE_STRING]: '',
|
|
254
|
+
[SELECTORS]: [],
|
|
255
|
+
// drop names that are unsafe to emit as a selector
|
|
256
|
+
[EXTERNAL_CLASS_NAMES]: hasUnsafeSelectorChar(arg) ? [] : [arg],
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return args
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export const keyframesCommon = (
|
|
265
|
+
strings: TemplateStringsArray,
|
|
266
|
+
values: CssVariableType[],
|
|
267
|
+
classNameSlug?: ClassNameSlug,
|
|
268
|
+
onInvalidSlug?: OnInvalidSlug
|
|
269
|
+
): CssClassName => {
|
|
270
|
+
const [label, styleString] = buildStyleString(strings, values)
|
|
271
|
+
const hash = toHash(label + styleString)
|
|
272
|
+
|
|
273
|
+
let customSlug: string | undefined
|
|
274
|
+
if (classNameSlug) {
|
|
275
|
+
const slug = classNameSlug(hash, normalizeLabel(label), styleString)
|
|
276
|
+
if (slug) {
|
|
277
|
+
if (isValidKeyframeName(slug)) {
|
|
278
|
+
customSlug = slug
|
|
279
|
+
} else {
|
|
280
|
+
;(onInvalidSlug || defaultOnInvalidSlug)(slug)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return {
|
|
286
|
+
[SELECTOR]: '',
|
|
287
|
+
[CLASS_NAME]: `@keyframes ${customSlug || hash}`,
|
|
288
|
+
[STYLE_STRING]: styleString,
|
|
289
|
+
[SELECTORS]: [],
|
|
290
|
+
[EXTERNAL_CLASS_NAMES]: [],
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
type ViewTransitionType = {
|
|
295
|
+
(
|
|
296
|
+
strings: TemplateStringsArray,
|
|
297
|
+
values: CssVariableType[],
|
|
298
|
+
classNameSlug?: ClassNameSlug,
|
|
299
|
+
onInvalidSlug?: OnInvalidSlug
|
|
300
|
+
): CssClassName
|
|
301
|
+
(content: CssClassName): CssClassName
|
|
302
|
+
(): CssClassName
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
let viewTransitionNameIndex = 0
|
|
306
|
+
export const viewTransitionCommon: ViewTransitionType = ((
|
|
307
|
+
strings: TemplateStringsArray | CssClassName | undefined,
|
|
308
|
+
values: CssVariableType[],
|
|
309
|
+
classNameSlug?: ClassNameSlug,
|
|
310
|
+
onInvalidSlug?: OnInvalidSlug
|
|
311
|
+
): CssClassName => {
|
|
312
|
+
if (!strings) {
|
|
313
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
314
|
+
strings = [`/* h-v-t ${viewTransitionNameIndex++} */`] as any
|
|
315
|
+
}
|
|
316
|
+
const content = Array.isArray(strings)
|
|
317
|
+
? cssCommon(strings as TemplateStringsArray, values, classNameSlug, onInvalidSlug)
|
|
318
|
+
: (strings as CssClassName)
|
|
319
|
+
|
|
320
|
+
const transitionName = content[CLASS_NAME]
|
|
321
|
+
const res = cssCommon(
|
|
322
|
+
['view-transition-name:', ''] as any, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
323
|
+
[transitionName],
|
|
324
|
+
classNameSlug,
|
|
325
|
+
onInvalidSlug
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
content[CLASS_NAME] = PSEUDO_GLOBAL_SELECTOR + content[CLASS_NAME]
|
|
329
|
+
content[STYLE_STRING] = content[STYLE_STRING].replace(
|
|
330
|
+
/(?<=::view-transition(?:[a-z-]*)\()(?=\))/g,
|
|
331
|
+
transitionName
|
|
332
|
+
)
|
|
333
|
+
res[CLASS_NAME] = res[SELECTOR] = transitionName
|
|
334
|
+
res[SELECTORS] = [...content[SELECTORS], content]
|
|
335
|
+
|
|
336
|
+
return res
|
|
337
|
+
}) as ViewTransitionType
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* css Helper for Acryl.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { raw } from '../html/index.ts'
|
|
7
|
+
import { DOM_RENDERER } from '../../jsx/constants.ts'
|
|
8
|
+
import { createCssJsxDomObjects } from '../../jsx/dom/css.ts'
|
|
9
|
+
import { escapeToBuffer } from '../../utils/html.ts'
|
|
10
|
+
import type { HtmlEscapedCallback, HtmlEscapedString } from '../../utils/html.ts'
|
|
11
|
+
import type {
|
|
12
|
+
ClassNameSlug,
|
|
13
|
+
CssClassName as CssClassNameCommon,
|
|
14
|
+
CssVariableType,
|
|
15
|
+
OnInvalidSlug,
|
|
16
|
+
} from './common.ts'
|
|
17
|
+
import {
|
|
18
|
+
CLASS_NAME,
|
|
19
|
+
DEFAULT_STYLE_ID,
|
|
20
|
+
PSEUDO_GLOBAL_SELECTOR,
|
|
21
|
+
SELECTOR,
|
|
22
|
+
SELECTORS,
|
|
23
|
+
STYLE_STRING,
|
|
24
|
+
cssCommon,
|
|
25
|
+
cxCommon,
|
|
26
|
+
keyframesCommon,
|
|
27
|
+
viewTransitionCommon,
|
|
28
|
+
} from './common.ts'
|
|
29
|
+
export { rawCssString } from './common.ts'
|
|
30
|
+
export type { ClassNameSlug, OnInvalidSlug } from './common.ts'
|
|
31
|
+
|
|
32
|
+
type CssClassName = HtmlEscapedString & CssClassNameCommon
|
|
33
|
+
|
|
34
|
+
type usedClassNameData = [
|
|
35
|
+
Record<string, string>, // class name to add
|
|
36
|
+
Record<string, true>, // class name already added
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
interface CssType {
|
|
40
|
+
(strings: TemplateStringsArray, ...values: CssVariableType[]): Promise<string>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface CxType {
|
|
44
|
+
(
|
|
45
|
+
...args: (CssClassName | Promise<string> | string | boolean | null | undefined)[]
|
|
46
|
+
): Promise<string>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface KeyframesType {
|
|
50
|
+
(strings: TemplateStringsArray, ...values: CssVariableType[]): CssClassNameCommon
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface ViewTransitionType {
|
|
54
|
+
(strings: TemplateStringsArray, ...values: CssVariableType[]): Promise<string>
|
|
55
|
+
(content: Promise<string>): Promise<string>
|
|
56
|
+
(): Promise<string>
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface StyleType {
|
|
60
|
+
(args?: { children?: Promise<string>; nonce?: string }): HtmlEscapedString
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @experimental
|
|
65
|
+
* `createCssContext` is an experimental feature.
|
|
66
|
+
* The API might be changed.
|
|
67
|
+
*
|
|
68
|
+
* @param options.id - The ID for the style element
|
|
69
|
+
* @param options.classNameSlug - Optional function to customize generated CSS class names
|
|
70
|
+
* @param options.onInvalidSlug - Optional callback function called when an invalid slug is returned from ClassNameSlug
|
|
71
|
+
*/
|
|
72
|
+
export const createCssContext = ({
|
|
73
|
+
id,
|
|
74
|
+
classNameSlug,
|
|
75
|
+
onInvalidSlug,
|
|
76
|
+
}: {
|
|
77
|
+
id: Readonly<string>
|
|
78
|
+
classNameSlug?: ClassNameSlug
|
|
79
|
+
onInvalidSlug?: OnInvalidSlug
|
|
80
|
+
}): DefaultContextType => {
|
|
81
|
+
const [cssJsxDomObject, StyleRenderToDom] = createCssJsxDomObjects({ id })
|
|
82
|
+
|
|
83
|
+
const contextMap: WeakMap<object, usedClassNameData> = new WeakMap()
|
|
84
|
+
const nonceMap: WeakMap<object, string | undefined> = new WeakMap()
|
|
85
|
+
|
|
86
|
+
const replaceStyleRe = new RegExp(`(<style id="${id}"(?: nonce="[^"]*")?>.*?)(</style>)`, 's')
|
|
87
|
+
|
|
88
|
+
const newCssClassNameObject = (cssClassName: CssClassNameCommon): Promise<string> => {
|
|
89
|
+
const appendStyle: HtmlEscapedCallback = ({ buffer, context }): Promise<string> | undefined => {
|
|
90
|
+
const [toAdd, added] = contextMap.get(context) as usedClassNameData
|
|
91
|
+
const names = Object.keys(toAdd)
|
|
92
|
+
|
|
93
|
+
if (!names.length) {
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let stylesStr = ''
|
|
98
|
+
names.forEach((className) => {
|
|
99
|
+
added[className] = true
|
|
100
|
+
stylesStr += className.startsWith(PSEUDO_GLOBAL_SELECTOR)
|
|
101
|
+
? toAdd[className]
|
|
102
|
+
: `${className[0] === '@' ? '' : '.'}${className}{${toAdd[className]}}`
|
|
103
|
+
})
|
|
104
|
+
contextMap.set(context, [{}, added])
|
|
105
|
+
|
|
106
|
+
if (buffer && replaceStyleRe.test(buffer[0])) {
|
|
107
|
+
buffer[0] = buffer[0].replace(replaceStyleRe, (_, pre, post) => `${pre}${stylesStr}${post}`)
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const nonce = nonceMap.get(context)
|
|
112
|
+
const appendStyleScript = `<script${
|
|
113
|
+
nonce ? ` nonce="${nonce}"` : ''
|
|
114
|
+
}>document.querySelector('#${id}').textContent+=${JSON.stringify(stylesStr)}</script>`
|
|
115
|
+
|
|
116
|
+
if (buffer) {
|
|
117
|
+
buffer[0] = `${appendStyleScript}${buffer[0]}`
|
|
118
|
+
return
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return Promise.resolve(appendStyleScript)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const addClassNameToContext: HtmlEscapedCallback = ({ context }) => {
|
|
125
|
+
if (!contextMap.has(context)) {
|
|
126
|
+
contextMap.set(context, [{}, {}])
|
|
127
|
+
}
|
|
128
|
+
const [toAdd, added] = contextMap.get(context) as usedClassNameData
|
|
129
|
+
let allAdded = true
|
|
130
|
+
if (!added[cssClassName[SELECTOR]]) {
|
|
131
|
+
allAdded = false
|
|
132
|
+
toAdd[cssClassName[SELECTOR]] = cssClassName[STYLE_STRING]
|
|
133
|
+
}
|
|
134
|
+
cssClassName[SELECTORS].forEach(
|
|
135
|
+
({ [CLASS_NAME]: className, [STYLE_STRING]: styleString }) => {
|
|
136
|
+
if (!added[className]) {
|
|
137
|
+
allAdded = false
|
|
138
|
+
toAdd[className] = styleString
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
if (allAdded) {
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return Promise.resolve(raw('', [appendStyle]))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// external class names from cx() are untrusted but the result is marked isEscaped,
|
|
150
|
+
// so escape it here. skip the buffer when there is nothing to escape.
|
|
151
|
+
const rawClassName = cssClassName[CLASS_NAME]
|
|
152
|
+
let escapedClassName = rawClassName
|
|
153
|
+
if (/[&<>'"]/.test(rawClassName)) {
|
|
154
|
+
const escapedBuffer: [string] = ['']
|
|
155
|
+
escapeToBuffer(rawClassName, escapedBuffer)
|
|
156
|
+
escapedClassName = escapedBuffer[0]
|
|
157
|
+
}
|
|
158
|
+
const className = new String(escapedClassName) as CssClassName
|
|
159
|
+
Object.assign(className, cssClassName)
|
|
160
|
+
;(className as HtmlEscapedString).isEscaped = true
|
|
161
|
+
;(className as HtmlEscapedString).callbacks = [addClassNameToContext]
|
|
162
|
+
const promise = Promise.resolve(className)
|
|
163
|
+
Object.assign(promise, cssClassName)
|
|
164
|
+
|
|
165
|
+
promise.toString = cssJsxDomObject.toString
|
|
166
|
+
return promise
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const css: CssType = (strings, ...values) => {
|
|
170
|
+
return newCssClassNameObject(cssCommon(strings, values, classNameSlug, onInvalidSlug))
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const cx: CxType = (...args) => {
|
|
174
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
175
|
+
args = cxCommon(args as any) as any
|
|
176
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
177
|
+
return css(Array(args.length).fill('') as any, ...args)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const keyframes: KeyframesType = (strings, ...values) =>
|
|
181
|
+
keyframesCommon(strings, values, classNameSlug, onInvalidSlug)
|
|
182
|
+
|
|
183
|
+
const viewTransition: ViewTransitionType = ((
|
|
184
|
+
strings: TemplateStringsArray | Promise<string> | undefined,
|
|
185
|
+
...values: CssVariableType[]
|
|
186
|
+
) => {
|
|
187
|
+
return newCssClassNameObject(
|
|
188
|
+
viewTransitionCommon(strings as any, values, classNameSlug, onInvalidSlug) // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
189
|
+
)
|
|
190
|
+
}) as ViewTransitionType
|
|
191
|
+
|
|
192
|
+
const Style: StyleType = ({ children, nonce } = {}) =>
|
|
193
|
+
raw(
|
|
194
|
+
`<style id="${id}"${nonce ? ` nonce="${nonce}"` : ''}>${
|
|
195
|
+
children ? (children as unknown as CssClassName)[STYLE_STRING] : ''
|
|
196
|
+
}</style>`,
|
|
197
|
+
[
|
|
198
|
+
({ context }) => {
|
|
199
|
+
nonceMap.set(context, nonce)
|
|
200
|
+
return undefined
|
|
201
|
+
},
|
|
202
|
+
]
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
206
|
+
;(Style as any)[DOM_RENDERER] = StyleRenderToDom
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
css,
|
|
210
|
+
cx,
|
|
211
|
+
keyframes,
|
|
212
|
+
viewTransition: viewTransition as ViewTransitionType,
|
|
213
|
+
Style,
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
interface DefaultContextType {
|
|
218
|
+
css: CssType
|
|
219
|
+
cx: CxType
|
|
220
|
+
keyframes: KeyframesType
|
|
221
|
+
viewTransition: ViewTransitionType
|
|
222
|
+
Style: StyleType
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const defaultContext: DefaultContextType = createCssContext({
|
|
226
|
+
id: DEFAULT_STYLE_ID,
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* @experimental
|
|
231
|
+
* `css` is an experimental feature.
|
|
232
|
+
* The API might be changed.
|
|
233
|
+
*/
|
|
234
|
+
export const css = defaultContext.css
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @experimental
|
|
238
|
+
* `cx` is an experimental feature.
|
|
239
|
+
* The API might be changed.
|
|
240
|
+
*/
|
|
241
|
+
export const cx = defaultContext.cx
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* @experimental
|
|
245
|
+
* `keyframes` is an experimental feature.
|
|
246
|
+
* The API might be changed.
|
|
247
|
+
*/
|
|
248
|
+
export const keyframes = defaultContext.keyframes
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @experimental
|
|
252
|
+
* `viewTransition` is an experimental feature.
|
|
253
|
+
* The API might be changed.
|
|
254
|
+
*/
|
|
255
|
+
export const viewTransition = defaultContext.viewTransition
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* @experimental
|
|
259
|
+
* `Style` is an experimental feature.
|
|
260
|
+
* The API might be changed.
|
|
261
|
+
*/
|
|
262
|
+
export const Style = defaultContext.Style
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* SSG Helper for Acryl.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export * from './ssg.ts'
|
|
7
|
+
export {
|
|
8
|
+
X_ACRYL_DISABLE_SSG_HEADER_KEY,
|
|
9
|
+
ssgParams,
|
|
10
|
+
isSSGContext,
|
|
11
|
+
disableSSG,
|
|
12
|
+
onlySSG,
|
|
13
|
+
} from './middleware.ts'
|
|
14
|
+
export { defaultPlugin, redirectPlugin } from './plugins.ts'
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Context } from '../../context.ts'
|
|
2
|
+
import type { Env, MiddlewareHandler } from '../../types.ts'
|
|
3
|
+
import { isDynamicRoute } from './utils.ts'
|
|
4
|
+
|
|
5
|
+
export const SSG_CONTEXT = 'ACRYL_SSG_CONTEXT'
|
|
6
|
+
export const X_ACRYL_DISABLE_SSG_HEADER_KEY = 'x-acryl-disable-ssg'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated
|
|
10
|
+
* Use `X_ACRYL_DISABLE_SSG_HEADER_KEY` instead.
|
|
11
|
+
* This constant will be removed in the next minor version.
|
|
12
|
+
*/
|
|
13
|
+
export const SSG_DISABLED_RESPONSE = (() => {
|
|
14
|
+
try {
|
|
15
|
+
return new Response('SSG is disabled', {
|
|
16
|
+
status: 404,
|
|
17
|
+
headers: { [X_ACRYL_DISABLE_SSG_HEADER_KEY]: 'true' },
|
|
18
|
+
})
|
|
19
|
+
} catch {
|
|
20
|
+
return null
|
|
21
|
+
}
|
|
22
|
+
})() as Response
|
|
23
|
+
|
|
24
|
+
interface SSGParam {
|
|
25
|
+
[key: string]: string
|
|
26
|
+
}
|
|
27
|
+
export type SSGParams = SSGParam[]
|
|
28
|
+
|
|
29
|
+
interface SSGParamsMiddleware {
|
|
30
|
+
<E extends Env = Env>(
|
|
31
|
+
generateParams: (c: Context<E>) => SSGParams | Promise<SSGParams>
|
|
32
|
+
): MiddlewareHandler<E>
|
|
33
|
+
<E extends Env = Env>(params: SSGParams): MiddlewareHandler<E>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type AddedSSGDataRequest = Request & {
|
|
37
|
+
ssgParams?: SSGParams
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Define SSG Route
|
|
42
|
+
*/
|
|
43
|
+
export const ssgParams: SSGParamsMiddleware = (params) => async (c, next) => {
|
|
44
|
+
if (isDynamicRoute(c.req.path)) {
|
|
45
|
+
;(c.req.raw as AddedSSGDataRequest).ssgParams = Array.isArray(params) ? params : await params(c)
|
|
46
|
+
return c.notFound() // Prevent subsequent handler execution after ssgParams
|
|
47
|
+
}
|
|
48
|
+
await next()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @experimental
|
|
53
|
+
* `isSSGContext` is an experimental feature.
|
|
54
|
+
* The API might be changed.
|
|
55
|
+
*/
|
|
56
|
+
export const isSSGContext = (c: Context): boolean => !!c.env?.[SSG_CONTEXT]
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @experimental
|
|
60
|
+
* `disableSSG` is an experimental feature.
|
|
61
|
+
* The API might be changed.
|
|
62
|
+
*/
|
|
63
|
+
export const disableSSG = (): MiddlewareHandler =>
|
|
64
|
+
async function disableSSG(c, next) {
|
|
65
|
+
if (isSSGContext(c)) {
|
|
66
|
+
c.header(X_ACRYL_DISABLE_SSG_HEADER_KEY, 'true')
|
|
67
|
+
return c.notFound()
|
|
68
|
+
}
|
|
69
|
+
await next()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @experimental
|
|
74
|
+
* `onlySSG` is an experimental feature.
|
|
75
|
+
* The API might be changed.
|
|
76
|
+
*/
|
|
77
|
+
export const onlySSG = (): MiddlewareHandler =>
|
|
78
|
+
async function onlySSG(c, next) {
|
|
79
|
+
if (!isSSGContext(c)) {
|
|
80
|
+
return c.notFound()
|
|
81
|
+
}
|
|
82
|
+
await next()
|
|
83
|
+
}
|