stitchkit 0.100.2 → 0.100.3
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/CHANGELOG.md +86 -0
- package/README.md +2 -1
- package/dist/entrypoints/agent-runtime/browser.js +119 -119
- package/dist/entrypoints/agent-runtime/coding-tools.js +15 -20
- package/dist/entrypoints/agent-runtime/harness.js +55 -63
- package/dist/entrypoints/agent-runtime/openrouter.js +6 -6
- package/dist/entrypoints/agent-runtime/sandbox.js +20 -25
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +11 -13
- package/dist/entrypoints/agent-runtime/sqlite/node.js +11 -13
- package/dist/entrypoints/agent-runtime/testing.js +32 -34
- package/dist/entrypoints/agent-runtime.js +395 -402
- package/dist/entrypoints/application/diagnostic-journal.js +26 -27
- package/dist/entrypoints/application/directory-inbox.js +16 -17
- package/dist/entrypoints/application/grammy.js +13 -13
- package/dist/entrypoints/application/opentelemetry.js +13 -13
- package/dist/entrypoints/application/schemas.js +24 -24
- package/dist/entrypoints/application.js +208 -210
- package/dist/entrypoints/bin/upgrade-cli.js +2 -2
- package/dist/entrypoints/cli.js +81 -84
- package/dist/entrypoints/contract.js +54 -57
- package/dist/entrypoints/declaration.js +22 -22
- package/dist/entrypoints/files.js +18 -21
- package/dist/entrypoints/geo.js +7 -8
- package/dist/entrypoints/google.js +2 -2
- package/dist/entrypoints/index.js +150 -154
- package/dist/entrypoints/live.js +45 -47
- package/dist/entrypoints/node.js +68 -74
- package/dist/entrypoints/oauth.js +6 -6
- package/dist/entrypoints/observability.d.ts +1 -0
- package/dist/entrypoints/observability.d.ts.map +1 -1
- package/dist/entrypoints/observability.js +115 -87
- package/dist/entrypoints/primitives.js +35 -35
- package/dist/entrypoints/react/keyboard.d.ts +4 -0
- package/dist/entrypoints/react/keyboard.d.ts.map +1 -0
- package/dist/entrypoints/react/keyboard.js +397 -0
- package/dist/entrypoints/react.js +10 -10
- package/dist/entrypoints/release.js +7 -7
- package/dist/entrypoints/remote.js +15 -17
- package/dist/entrypoints/server.js +198 -200
- package/dist/entrypoints/telegram/html.d.ts +5 -0
- package/dist/entrypoints/telegram/html.d.ts.map +1 -0
- package/dist/entrypoints/telegram/html.js +26 -0
- package/dist/entrypoints/telegram/screens.d.ts +14 -0
- package/dist/entrypoints/telegram/screens.d.ts.map +1 -0
- package/dist/entrypoints/telegram/screens.js +2028 -0
- package/dist/entrypoints/telegram.d.ts +5 -1
- package/dist/entrypoints/telegram.d.ts.map +1 -1
- package/dist/entrypoints/telegram.js +548 -156
- package/dist/entrypoints/testing.js +75 -79
- package/dist/entrypoints/tools/connections.js +30 -32
- package/dist/entrypoints/tools/contract.js +18 -20
- package/dist/entrypoints/tools/invoker.js +12 -17
- package/dist/entrypoints/tools.js +223 -229
- package/dist/entrypoints/tracking/server.js +6 -6
- package/dist/entrypoints/tracking.js +40 -42
- package/dist/entrypoints/voice.js +3 -3
- package/dist/{index-eaysmdtq.js → index-0ndk4555.js} +56 -56
- package/dist/{index-2bxbyab0.js → index-1bx1xv1k.js} +1 -1
- package/dist/{index-p5r7qpdd.js → index-1eeqpadm.js} +4 -4
- package/dist/{index-hadmp193.js → index-3ct7hhq6.js} +210 -210
- package/dist/{index-e01r054k.js → index-45tdvqa3.js} +26 -26
- package/dist/{index-dce5wxcq.js → index-4s0fep5q.js} +8 -8
- package/dist/index-50ejfz75.js +9 -0
- package/dist/{index-m9zn6cpq.js → index-5107q189.js} +12 -12
- package/dist/{index-sbdmyz75.js → index-5cc6r990.js} +3 -3
- package/dist/index-6k1svmjh.js +141 -0
- package/dist/{index-c6bxbsnc.js → index-7kxw1awn.js} +2 -2
- package/dist/{index-0r0fbk7z.js → index-7z9ym7t8.js} +28 -28
- package/dist/{index-p7hgdyhb.js → index-814xpr6d.js} +2 -2
- package/dist/{index-gtj3zc53.js → index-8kzct1d6.js} +99 -99
- package/dist/{index-1zbbzgfh.js → index-9pw0a51a.js} +4 -4
- package/dist/{index-79z7m7dt.js → index-a9pd417t.js} +35 -35
- package/dist/{index-ham5sz8m.js → index-aaj97r4y.js} +45 -45
- package/dist/{index-s812ycat.js → index-aan6hqb9.js} +3 -3
- package/dist/{index-10x2hbx0.js → index-adhgd4pe.js} +44 -44
- package/dist/{index-2gxzjvyr.js → index-afjvjyck.js} +23 -23
- package/dist/{index-qmy6zq75.js → index-ahvsksw5.js} +16 -16
- package/dist/{index-hr4tzbwq.js → index-ap3gqe56.js} +3 -3
- package/dist/{index-znfs20ss.js → index-b2bz0kdm.js} +16 -16
- package/dist/{index-r066jx76.js → index-c6aagrbd.js} +148 -120
- package/dist/{index-k30h66yd.js → index-ck71tbcf.js} +9 -9
- package/dist/{index-eqqvgdb3.js → index-ct75c3at.js} +2 -2
- package/dist/{index-gw8bmyaj.js → index-djjhhgjk.js} +41 -41
- package/dist/{index-8qt2m66q.js → index-dvwj1f43.js} +43 -43
- package/dist/{index-fhwqwxe0.js → index-ej331hah.js} +1 -1
- package/dist/{index-9t3dffv2.js → index-ewbaywk5.js} +5 -5
- package/dist/{index-7p1f0vp2.js → index-fyphpknh.js} +25 -25
- package/dist/{index-83bdg97s.js → index-g149e9pk.js} +1 -1
- package/dist/{index-ngfhvfpd.js → index-g6a3na27.js} +4 -4
- package/dist/{index-qwhynv6x.js → index-h124epcf.js} +20 -20
- package/dist/{index-h6eeys1v.js → index-h97tqqp1.js} +9 -9
- package/dist/{index-zcgf3gqf.js → index-hby4qhax.js} +10 -10
- package/dist/{index-5jrd0yng.js → index-j8aw2c0e.js} +4 -4
- package/dist/{index-d8m8zpd8.js → index-jzczzcsb.js} +14 -14
- package/dist/index-kqnd6a85.js +26 -0
- package/dist/{index-35mh5bhj.js → index-kw1ws0cs.js} +12 -12
- package/dist/{index-yw4fzmdz.js → index-kzz6rq0w.js} +28 -17
- package/dist/{index-4gcnakhx.js → index-m38ej7e5.js} +2 -2
- package/dist/{index-ndddxtyx.js → index-m79yr938.js} +19 -19
- package/dist/{index-5p2m7we1.js → index-m9fndta6.js} +11 -11
- package/dist/index-mnkk1ffz.js +150 -0
- package/dist/index-n15jny5b.js +4 -0
- package/dist/{index-2vtcmrj9.js → index-n53mswt3.js} +20 -20
- package/dist/{index-bt14acb5.js → index-n5yqxd3d.js} +21 -21
- package/dist/{index-bm5rx7n6.js → index-n9tyz8z3.js} +12 -12
- package/dist/index-nmaqxdx7.js +463 -0
- package/dist/{index-mqv3b5rh.js → index-nx6eazt0.js} +30 -30
- package/dist/{index-3z73fh2c.js → index-q0th8q0z.js} +9 -9
- package/dist/{index-v260df89.js → index-qjeggp8w.js} +20 -20
- package/dist/{index-zfrhfn82.js → index-r1z0rd9c.js} +20 -20
- package/dist/{index-wqgjfstn.js → index-r5c4fedv.js} +3 -3
- package/dist/{index-cyktc4bp.js → index-r5hsgkz5.js} +118 -118
- package/dist/{index-0b1ess5e.js → index-r7a7r7ha.js} +1 -1
- package/dist/{index-1j8pm5t0.js → index-rfkh44ss.js} +15 -15
- package/dist/index-rz3z13e9.js +47 -0
- package/dist/{index-k6gpggb9.js → index-s80awwsw.js} +35 -35
- package/dist/{index-vqr7f7v8.js → index-ssmd41kh.js} +124 -124
- package/dist/{index-ensd0r74.js → index-v14qqmys.js} +41 -41
- package/dist/{index-paz6sgdp.js → index-v4a2fjtk.js} +36 -36
- package/dist/{index-d9pk3td4.js → index-w0eqdhyd.js} +14 -14
- package/dist/{index-5qn1kx34.js → index-w575evhq.js} +29 -29
- package/dist/{index-3gye9wzb.js → index-w5s3xftz.js} +26 -26
- package/dist/{index-tm88avnj.js → index-wykebpn9.js} +3 -3
- package/dist/{index-sh3s86na.js → index-xkhk5d6g.js} +17 -17
- package/dist/{index-6k1937bx.js → index-xqhede6x.js} +4 -4
- package/dist/{index-f4fx2tza.js → index-zs4ms3th.js} +181 -181
- package/dist/{index-k5hsfc3j.js → index-zsvzhjtk.js} +1 -1
- package/dist/observability/bounded-logger.d.ts +2 -0
- package/dist/observability/bounded-logger.d.ts.map +1 -1
- package/dist/observability/sanitize.d.ts +6 -0
- package/dist/observability/sanitize.d.ts.map +1 -1
- package/dist/observability/secret-values.d.ts +25 -0
- package/dist/observability/secret-values.d.ts.map +1 -0
- package/dist/react/keyboard/hooks.d.ts +71 -0
- package/dist/react/keyboard/hooks.d.ts.map +1 -0
- package/dist/react/keyboard/layers.d.ts +98 -0
- package/dist/react/keyboard/layers.d.ts.map +1 -0
- package/dist/react/keyboard/zone.d.ts +139 -0
- package/dist/react/keyboard/zone.d.ts.map +1 -0
- package/dist/telegram/crypto.d.ts +16 -0
- package/dist/telegram/crypto.d.ts.map +1 -0
- package/dist/telegram/html/check.d.ts +26 -0
- package/dist/telegram/html/check.d.ts.map +1 -0
- package/dist/telegram/html/nodes.d.ts +70 -0
- package/dist/telegram/html/nodes.d.ts.map +1 -0
- package/dist/telegram/html/parse.d.ts +35 -0
- package/dist/telegram/html/parse.d.ts.map +1 -0
- package/dist/telegram/html/render.d.ts +39 -0
- package/dist/telegram/html/render.d.ts.map +1 -0
- package/dist/telegram/init-data.d.ts.map +1 -1
- package/dist/telegram/operator-channel.d.ts +36 -3
- package/dist/telegram/operator-channel.d.ts.map +1 -1
- package/dist/telegram/screens/callback-codec.d.ts +34 -0
- package/dist/telegram/screens/callback-codec.d.ts.map +1 -0
- package/dist/telegram/screens/dispatch.d.ts +22 -0
- package/dist/telegram/screens/dispatch.d.ts.map +1 -0
- package/dist/telegram/screens/display.d.ts +70 -0
- package/dist/telegram/screens/display.d.ts.map +1 -0
- package/dist/telegram/screens/execute.d.ts +57 -0
- package/dist/telegram/screens/execute.d.ts.map +1 -0
- package/dist/telegram/screens/html.d.ts +36 -0
- package/dist/telegram/screens/html.d.ts.map +1 -0
- package/dist/telegram/screens/outcome.d.ts +74 -0
- package/dist/telegram/screens/outcome.d.ts.map +1 -0
- package/dist/telegram/screens/path.d.ts +29 -0
- package/dist/telegram/screens/path.d.ts.map +1 -0
- package/dist/telegram/screens/reconcile.d.ts +67 -0
- package/dist/telegram/screens/reconcile.d.ts.map +1 -0
- package/dist/telegram/screens/registry.d.ts +23 -0
- package/dist/telegram/screens/registry.d.ts.map +1 -0
- package/dist/telegram/screens/render.d.ts +70 -0
- package/dist/telegram/screens/render.d.ts.map +1 -0
- package/dist/telegram/screens/runtime.d.ts +133 -0
- package/dist/telegram/screens/runtime.d.ts.map +1 -0
- package/dist/telegram/screens/screen-types.d.ts +130 -0
- package/dist/telegram/screens/screen-types.d.ts.map +1 -0
- package/dist/telegram/screens/screen.d.ts +138 -0
- package/dist/telegram/screens/screen.d.ts.map +1 -0
- package/dist/telegram/screens/state.d.ts +115 -0
- package/dist/telegram/screens/state.d.ts.map +1 -0
- package/dist/telegram/screens/telegram-screens.d.ts +18 -0
- package/dist/telegram/screens/telegram-screens.d.ts.map +1 -0
- package/dist/telegram/screens/test-chat-telegram.d.ts +47 -0
- package/dist/telegram/screens/test-chat-telegram.d.ts.map +1 -0
- package/dist/telegram/screens/test-chat.d.ts +66 -0
- package/dist/telegram/screens/test-chat.d.ts.map +1 -0
- package/dist/telegram/screens/view.d.ts +89 -0
- package/dist/telegram/screens/view.d.ts.map +1 -0
- package/dist/telegram/send-failure.d.ts +19 -0
- package/dist/telegram/send-failure.d.ts.map +1 -1
- package/dist/telegram/update-intake.d.ts +78 -0
- package/dist/telegram/update-intake.d.ts.map +1 -0
- package/dist/telegram/update-store-sqlite.d.ts +26 -0
- package/dist/telegram/update-store-sqlite.d.ts.map +1 -0
- package/dist/telegram/update-store.d.ts +67 -0
- package/dist/telegram/update-store.d.ts.map +1 -0
- package/dist/telegram/webhook.d.ts +105 -0
- package/dist/telegram/webhook.d.ts.map +1 -0
- package/dist/tools/cli/args-fields.d.ts +8 -0
- package/dist/tools/cli/args-fields.d.ts.map +1 -1
- package/dist/tools/cli/args-route.d.ts.map +1 -1
- package/dist/tools/cli/args.d.ts.map +1 -1
- package/dist/tools/cli/help.d.ts.map +1 -1
- package/llms/cli.txt +8 -2
- package/llms/observability.txt +2 -1
- package/llms/react-keyboard.txt +193 -0
- package/llms/stitchkit.txt +7 -1
- package/llms/telegram-html.txt +35 -0
- package/llms/telegram-screens.txt +365 -0
- package/llms/telegram.txt +160 -4
- package/llms-full.txt +736 -8
- package/llms.txt +10 -5
- package/package.json +17 -2
- package/dist/index-2k4yrqkc.js +0 -9
- package/dist/index-crykmqkr.js +0 -26
- package/dist/index-y64k3s0h.js +0 -150
- package/dist/index-y91ry9h2.js +0 -4
- /package/dist/{index-hffjpmq9.js → index-9jfdm5tg.js} +0 -0
- /package/dist/{index-zjjyynm3.js → index-d4pa2bgs.js} +0 -0
- /package/dist/{index-rxfy4cq7.js → index-dwfv9a85.js} +0 -0
- /package/dist/{index-5jm36zv1.js → index-gfk7nrht.js} +0 -0
- /package/dist/{index-b9aefrqd.js → index-n1dqr7gf.js} +0 -0
- /package/dist/{index-q3pyb9n0.js → index-sykb5ag7.js} +0 -0
- /package/dist/{index-48ffdxgk.js → index-xhzq2qvj.js} +0 -0
- /package/dist/{index-kzfs85xp.js → index-zsarb5xp.js} +0 -0
|
@@ -16,6 +16,8 @@ export interface BoundedLoggerOptions {
|
|
|
16
16
|
};
|
|
17
17
|
readonly bounds?: BoundedLoggerBounds;
|
|
18
18
|
readonly sensitiveUrlPatterns?: readonly RegExp[];
|
|
19
|
+
/** Exact secret values masked in every string — see `SanitizeOptions.sensitiveValues`. */
|
|
20
|
+
readonly sensitiveValues?: readonly string[];
|
|
19
21
|
}
|
|
20
22
|
/** Decorate any canonical logger with context, redaction, and hard bounds. */
|
|
21
23
|
export declare function createBoundedLogger(options: BoundedLoggerOptions): StitchLogger;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bounded-logger.d.ts","sourceRoot":"","sources":["../../src/observability/bounded-logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,eAAO,MAAM,oBAAoB,mBAW/B,CAAC;AAEH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,0GAA0G;IAC1G,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"bounded-logger.d.ts","sourceRoot":"","sources":["../../src/observability/bounded-logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,eAAO,MAAM,oBAAoB,mBAW/B,CAAC;AAEH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,0GAA0G;IAC1G,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClD,0FAA0F;IAC1F,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AAwDD,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,YAAY,CAkD/E"}
|
|
@@ -17,6 +17,12 @@ export interface SanitizeOptions {
|
|
|
17
17
|
sensitivePaths?: readonly string[];
|
|
18
18
|
/** Patterns whose matching portions are masked in every string, including messages. */
|
|
19
19
|
sensitiveUrlPatterns?: readonly RegExp[];
|
|
20
|
+
/**
|
|
21
|
+
* Exact secret values masked wherever they occur in any string — a
|
|
22
|
+
* provider's key has no shape a pattern could guess. `secretValuesFromEnv`
|
|
23
|
+
* collects them from the environment.
|
|
24
|
+
*/
|
|
25
|
+
sensitiveValues?: readonly string[];
|
|
20
26
|
/** Cap on the serialised payload — anything larger collapses to a preview. Default 16 KB. */
|
|
21
27
|
maxBytes?: number;
|
|
22
28
|
/** Recursion limit — deeper nesting collapses to a marker. Default 20. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/observability/sanitize.ts"],"names":[],"mappings":"AAOA,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,EAAE,GACX;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEjC,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,uFAAuF;IACvF,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;;;OAaG;IACH,oBAAoB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,mEAAmE;IACnE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,8BAA8B;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,cAAc,CAAC,EAAE,IAAI,CAAC;CACvB;
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/observability/sanitize.ts"],"names":[],"mappings":"AAOA,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,EAAE,GACX;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEjC,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,uFAAuF;IACvF,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC;;;;OAIG;IACH,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;;;OAaG;IACH,oBAAoB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,mEAAmE;IACnE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,8BAA8B;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,cAAc,CAAC,EAAE,IAAI,CAAC;CACvB;AAmGD;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,eAAoB,GAAG,SAAS,CA6L/E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,SAAoB,GAAG,SAAS,CAgBzF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,eAAoB,GAC5B,SAAS,GAAG,IAAI,CAOlB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAqBvD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The secret values an environment holds, to be masked by value.
|
|
3
|
+
*
|
|
4
|
+
* A pattern masks what it can recognise — a bot token, a bearer header — and a
|
|
5
|
+
* provider's API key, a webhook secret or a database password looks like any
|
|
6
|
+
* other string. The environment already says which values are secret: by the
|
|
7
|
+
* variable's name. So the schema names the secrets, not the code that logs:
|
|
8
|
+
* a key added to the environment is masked from its first line.
|
|
9
|
+
*/
|
|
10
|
+
export interface SecretValuesOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Shorter values are not collected. Default 8: a short value occurs in
|
|
13
|
+
* ordinary text by itself, and masking it there would spoil lines without
|
|
14
|
+
* protecting anything.
|
|
15
|
+
*/
|
|
16
|
+
readonly minLength?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Every secret value in `env`: variables named as a token, secret, key,
|
|
20
|
+
* password or credential, the password and secret query values inside any URL
|
|
21
|
+
* variable (`DATABASE_URL`), and each of them URL-encoded too. For a logger's
|
|
22
|
+
* and an operator channel's `sensitiveValues`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function secretValuesFromEnv(env: Readonly<Record<string, unknown>>, options?: SecretValuesOptions): string[];
|
|
25
|
+
//# sourceMappingURL=secret-values.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-values.d.ts","sourceRoot":"","sources":["../../src/observability/secret-values.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAaD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACtC,OAAO,GAAE,mBAAwB,GAChC,MAAM,EAAE,CAYV"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The React binding of the key layers and zones: hooks only, no component and
|
|
3
|
+
* no provider. The stack is one per window, created by the first layer that
|
|
4
|
+
* mounts, so a layer inside a portal is on the same stack as the page.
|
|
5
|
+
*/
|
|
6
|
+
import { type RefObject } from 'react';
|
|
7
|
+
import { type KeyLayerKind } from './layers.js';
|
|
8
|
+
import { type NavZoneOptions, type ZoneItemId, type ZoneOrientation } from './zone.js';
|
|
9
|
+
export interface KeyLayerOptions {
|
|
10
|
+
readonly kind: KeyLayerKind;
|
|
11
|
+
/** Return `true` when the key was taken: its default is prevented and no layer below hears it. */
|
|
12
|
+
onKey(event: KeyboardEvent): boolean;
|
|
13
|
+
/** Default `true`. Becoming active puts the layer on top of its kind. */
|
|
14
|
+
readonly active?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* The element the layer belongs to. Given, the layer is heard only while the
|
|
17
|
+
* element is mounted, visible and not `inert`, and it outranks layers of its
|
|
18
|
+
* kind whose elements contain it.
|
|
19
|
+
*/
|
|
20
|
+
readonly scope?: RefObject<Element | null>;
|
|
21
|
+
/** Default `'skip'`: keys pressed in fields and `data-local-keys` areas, except Escape, pass it by. */
|
|
22
|
+
readonly fields?: 'skip' | 'include';
|
|
23
|
+
}
|
|
24
|
+
/** Put a layer on the window's key stack for as long as the component is mounted. */
|
|
25
|
+
export declare function useKeyLayer(options: KeyLayerOptions): void;
|
|
26
|
+
export interface EscapeLayerOptions {
|
|
27
|
+
readonly kind: 'overlay' | 'local' | 'route';
|
|
28
|
+
/** Close one level. Return `false` when there was nothing to close, and the layer below is asked. */
|
|
29
|
+
onEscape(): unknown;
|
|
30
|
+
readonly active?: boolean;
|
|
31
|
+
readonly scope?: RefObject<Element | null>;
|
|
32
|
+
}
|
|
33
|
+
/** One Escape closes one level: the first layer that takes it is the only one that hears it. */
|
|
34
|
+
export declare function useEscapeLayer(options: EscapeLayerOptions): void;
|
|
35
|
+
/** Spread on the zone's element. */
|
|
36
|
+
export interface NavZoneProps {
|
|
37
|
+
readonly ref: (element: HTMLElement | null) => void;
|
|
38
|
+
readonly role: 'listbox' | 'tablist' | undefined;
|
|
39
|
+
readonly 'aria-orientation': ZoneOrientation;
|
|
40
|
+
readonly 'aria-label': string | undefined;
|
|
41
|
+
readonly 'data-keyboard-zone': '';
|
|
42
|
+
readonly onKeyDown: (event: {
|
|
43
|
+
readonly nativeEvent: KeyboardEvent;
|
|
44
|
+
}) => void;
|
|
45
|
+
}
|
|
46
|
+
/** Spread on each item's element. */
|
|
47
|
+
export interface NavZoneItemProps {
|
|
48
|
+
readonly ref: (element: HTMLElement | null) => void;
|
|
49
|
+
readonly tabIndex: 0 | -1;
|
|
50
|
+
readonly role: 'option' | 'tab' | undefined;
|
|
51
|
+
readonly 'aria-selected': boolean | undefined;
|
|
52
|
+
readonly 'aria-current': 'true' | undefined;
|
|
53
|
+
readonly onFocus: () => void;
|
|
54
|
+
}
|
|
55
|
+
export interface NavZone<Id extends ZoneItemId> {
|
|
56
|
+
/** Spread on the zone's element; it carries the element's `ref`. */
|
|
57
|
+
readonly zoneProps: NavZoneProps;
|
|
58
|
+
/** The zone's element, for what else needs it — an Escape layer scoped to the zone. */
|
|
59
|
+
readonly element: RefObject<HTMLElement | null>;
|
|
60
|
+
itemProps(id: Id): NavZoneItemProps;
|
|
61
|
+
/** The tab stop: the item focus is on or was last on, else the chosen one, else the first. */
|
|
62
|
+
readonly current: Id | null;
|
|
63
|
+
/** Put focus on `id`, or on the current item — to move into this zone from another. */
|
|
64
|
+
focus(id?: Id): boolean;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A list the arrows move through with real focus. See `zone.ts` for the
|
|
68
|
+
* modes, the cross axis and what happens past an end.
|
|
69
|
+
*/
|
|
70
|
+
export declare function useNavZone<Id extends ZoneItemId>(options: NavZoneOptions<Id>): NavZone<Id>;
|
|
71
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/react/keyboard/hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who gets a key: one listener, a fixed order of layers, and the innermost
|
|
3
|
+
* layer of a kind first.
|
|
4
|
+
*
|
|
5
|
+
* A page with a menu, a dialog, a list and section shortcuts usually ends up
|
|
6
|
+
* with a `keydown` listener per concern, and their order is the order they
|
|
7
|
+
* happened to mount in: Escape closes the dialog and the page behind it, an
|
|
8
|
+
* arrow in a dialog switches the section underneath. Here every concern is a
|
|
9
|
+
* layer on one stack, asked in a fixed order until one of them takes the key:
|
|
10
|
+
*
|
|
11
|
+
* overlay → local → route → zone → global
|
|
12
|
+
*
|
|
13
|
+
* - **overlay** — something modal. While one is live, nothing below it hears a
|
|
14
|
+
* key at all, handled or not.
|
|
15
|
+
* - **local** — a component that has the user's attention without being modal:
|
|
16
|
+
* an open command menu, an editor's own mode.
|
|
17
|
+
* - **route** — the page's "go up one level": Escape closes the open entity.
|
|
18
|
+
* - **zone** — a list the keys move through when focus is not in any list
|
|
19
|
+
* (see `zone.ts`).
|
|
20
|
+
* - **global** — shortcuts of the whole screen, such as switching sections.
|
|
21
|
+
*
|
|
22
|
+
* Within a kind the innermost layer wins: of two layers whose elements nest,
|
|
23
|
+
* the inner one; otherwise the one activated last. React runs a child's effects
|
|
24
|
+
* before its parent's, so activation order alone would let a page's layer
|
|
25
|
+
* shadow the panel inside it when both mount together — the element tree is
|
|
26
|
+
* what says which is inside which.
|
|
27
|
+
*
|
|
28
|
+
* The listener sits on the window, in the bubbling phase: everything closer to
|
|
29
|
+
* the key — a widget's own `onKeyDown`, a text field, a popover that closes on
|
|
30
|
+
* Escape — hears it first and keeps it by `preventDefault` or
|
|
31
|
+
* `stopPropagation`. A layer only gets what nobody nearer wanted.
|
|
32
|
+
*/
|
|
33
|
+
export type KeyLayerKind = 'overlay' | 'local' | 'route' | 'zone' | 'global';
|
|
34
|
+
/** The part of a `keydown` event the stack reads; a DOM `KeyboardEvent` is one. */
|
|
35
|
+
export interface LayerKeyEvent {
|
|
36
|
+
readonly key: string;
|
|
37
|
+
readonly repeat: boolean;
|
|
38
|
+
readonly isComposing: boolean;
|
|
39
|
+
readonly defaultPrevented: boolean;
|
|
40
|
+
readonly target: EventTarget | null;
|
|
41
|
+
preventDefault(): void;
|
|
42
|
+
}
|
|
43
|
+
/** The part of an element the stack reads to decide whether a layer is live and where it sits. */
|
|
44
|
+
export interface LayerScope<S> {
|
|
45
|
+
readonly isConnected: boolean;
|
|
46
|
+
contains(other: S | null): boolean;
|
|
47
|
+
closest(selectors: string): unknown;
|
|
48
|
+
checkVisibility?(): boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Where keys belong to the element rather than to the page: fields, controls
|
|
52
|
+
* that move on arrows themselves, and any area marked `data-local-keys`.
|
|
53
|
+
*/
|
|
54
|
+
export declare const KEY_FIELD_SELECTOR: string;
|
|
55
|
+
/** The nearest element matching `selectors` from an event target, or `null`. */
|
|
56
|
+
export declare function closestFromTarget(target: EventTarget | null, selectors: string): unknown;
|
|
57
|
+
/** The key was pressed in a field or an area that keeps its keys. */
|
|
58
|
+
export declare function isKeyFieldTarget(target: EventTarget | null): boolean;
|
|
59
|
+
export interface KeyLayerState<E extends LayerKeyEvent, S extends LayerScope<S>> {
|
|
60
|
+
readonly kind: KeyLayerKind;
|
|
61
|
+
/** Default `true`. A layer that is not active is skipped; becoming active puts it on top of its kind. */
|
|
62
|
+
readonly active?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* The element the layer belongs to. Given, the layer is live only while the
|
|
65
|
+
* element is connected, visible and outside any `inert` subtree, and it is
|
|
66
|
+
* ordered by nesting against layers of its kind. `null` means "declared, not
|
|
67
|
+
* mounted": the layer is skipped.
|
|
68
|
+
*/
|
|
69
|
+
readonly scope?: () => S | null;
|
|
70
|
+
/**
|
|
71
|
+
* `'skip'` (default): keys pressed in a field or a `data-local-keys` area do
|
|
72
|
+
* not reach the layer — except Escape, which a field that wants it keeps by
|
|
73
|
+
* `preventDefault`. `'include'`: the layer hears them too.
|
|
74
|
+
*/
|
|
75
|
+
readonly fields?: 'skip' | 'include';
|
|
76
|
+
/** Return `true` when the key was taken: its default is prevented and no layer below hears it. */
|
|
77
|
+
onKey(event: E): boolean;
|
|
78
|
+
}
|
|
79
|
+
export interface KeyLayerHandle<E extends LayerKeyEvent, S extends LayerScope<S>> {
|
|
80
|
+
update(state: KeyLayerState<E, S>): void;
|
|
81
|
+
remove(): void;
|
|
82
|
+
}
|
|
83
|
+
/** Where the stack listens. A `Window` is one. */
|
|
84
|
+
export interface KeyListenerTarget<E> {
|
|
85
|
+
addEventListener(type: 'keydown', listener: (event: E) => void): void;
|
|
86
|
+
removeEventListener(type: 'keydown', listener: (event: E) => void): void;
|
|
87
|
+
}
|
|
88
|
+
export interface KeyLayerStack<E extends LayerKeyEvent, S extends LayerScope<S>> {
|
|
89
|
+
add(state: KeyLayerState<E, S>): KeyLayerHandle<E, S>;
|
|
90
|
+
/** Offer one key to the layers; `true` when one took it. The installed listener calls this. */
|
|
91
|
+
dispatch(event: E): boolean;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* A stack listening on `target`. The listener is attached with the first
|
|
95
|
+
* layer and detached with the last, so a page without layers carries none.
|
|
96
|
+
*/
|
|
97
|
+
export declare function createKeyLayerStack<E extends LayerKeyEvent, S extends LayerScope<S>>(target: KeyListenerTarget<E>): KeyLayerStack<E, S>;
|
|
98
|
+
//# sourceMappingURL=layers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../../../src/react/keyboard/layers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAU7E,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC,cAAc,IAAI,IAAI,CAAC;CACxB;AAED,kGAAkG;AAClG,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC;IACnC,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC,eAAe,CAAC,IAAI,OAAO,CAAC;CAC7B;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAUpB,CAAC;AAeZ,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAExF;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAGpE;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,aAAa,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC;IAC7E,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,yGAAyG;IACzG,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,kGAAkG;IAClG,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,aAAa,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC;IAC9E,MAAM,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;IACzC,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,kDAAkD;AAClD,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACtE,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;CAC1E;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,aAAa,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC;IAC7E,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACtD,+FAA+F;IAC/F,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC;CAC7B;AAwDD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,aAAa,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAClF,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC3B,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CA6CrB"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A list the arrow keys move through — with real focus.
|
|
3
|
+
*
|
|
4
|
+
* A zone is an ordered set of items, one of which is the tab stop (roving
|
|
5
|
+
* tabindex): Tab enters the zone at that item, the arrows move DOM focus
|
|
6
|
+
* between items, Tab leaves. Focus is the browser's own, so a screen reader
|
|
7
|
+
* follows it, `:focus-visible` draws it and the browser scrolls to it; there is
|
|
8
|
+
* no second "highlighted" state beside focus for a page to keep in sync.
|
|
9
|
+
*
|
|
10
|
+
* Two modes, by what moving means:
|
|
11
|
+
*
|
|
12
|
+
* - **select** — moving is choosing: the arrow calls `onChange(id, 'arrow')`
|
|
13
|
+
* (a sidebar whose item opens as you move).
|
|
14
|
+
* - **highlight** — moving only points; Enter chooses with
|
|
15
|
+
* `onChange(id, 'confirm')` (a list where opening is expensive).
|
|
16
|
+
*
|
|
17
|
+
* Each zone keeps its own pointed item, so two zones on a page never share one.
|
|
18
|
+
* The cross axis leaves the zone on purpose: `onEnter` (→ in a vertical zone)
|
|
19
|
+
* goes into what the item opens, `onExit` (←) back out; past either end the
|
|
20
|
+
* zone either loops or hands the key to `onBoundary`. A key the zone does not
|
|
21
|
+
* take bubbles on — to the layers, where a section switch may want it.
|
|
22
|
+
*
|
|
23
|
+
* This file has no framework in it: `useNavZone` is a thin React binding.
|
|
24
|
+
*/
|
|
25
|
+
import { type LayerKeyEvent } from './layers.js';
|
|
26
|
+
export type ZoneOrientation = 'vertical' | 'horizontal';
|
|
27
|
+
export type ZoneMove = 'next' | 'previous' | 'first' | 'last';
|
|
28
|
+
export type ZoneIntent = {
|
|
29
|
+
readonly type: 'move';
|
|
30
|
+
readonly move: ZoneMove;
|
|
31
|
+
} | {
|
|
32
|
+
readonly type: 'enter';
|
|
33
|
+
} | {
|
|
34
|
+
readonly type: 'exit';
|
|
35
|
+
} | {
|
|
36
|
+
readonly type: 'confirm';
|
|
37
|
+
};
|
|
38
|
+
/** Marks a zone's element; a key pressed inside it belongs to that zone. */
|
|
39
|
+
export declare const ZONE_ATTRIBUTE = "data-keyboard-zone";
|
|
40
|
+
export interface NextZoneIndexInput {
|
|
41
|
+
readonly length: number;
|
|
42
|
+
/** The current index; `-1` when nothing is current. */
|
|
43
|
+
readonly index: number;
|
|
44
|
+
readonly move: ZoneMove;
|
|
45
|
+
readonly loop: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Where a move lands: an index, or the end it ran past. From nothing current,
|
|
49
|
+
* `next` lands on the first item and `previous` on the last. An empty zone has
|
|
50
|
+
* no index: every move runs past an end.
|
|
51
|
+
*/
|
|
52
|
+
export declare function nextZoneIndex({ length, index, move, loop, }: NextZoneIndexInput): number | 'before-start' | 'after-end';
|
|
53
|
+
export interface ZoneKey {
|
|
54
|
+
readonly key: string;
|
|
55
|
+
readonly altKey: boolean;
|
|
56
|
+
readonly ctrlKey: boolean;
|
|
57
|
+
readonly metaKey: boolean;
|
|
58
|
+
readonly shiftKey: boolean;
|
|
59
|
+
}
|
|
60
|
+
/** What a key means to a zone of this orientation; `null` for keys a zone leaves alone. */
|
|
61
|
+
export declare function zoneIntent(event: ZoneKey, orientation: ZoneOrientation): ZoneIntent | null;
|
|
62
|
+
export type ZoneItemId = string | number;
|
|
63
|
+
export type ZoneChangeCause = 'arrow' | 'confirm';
|
|
64
|
+
export interface NavZoneOptions<Id extends ZoneItemId> {
|
|
65
|
+
/** The items in order. An id not listed here has no place in the zone. */
|
|
66
|
+
readonly items: readonly Id[];
|
|
67
|
+
/** The chosen item, or `null`. The zone never holds it: it reports changes. */
|
|
68
|
+
readonly value: Id | null;
|
|
69
|
+
onChange(id: Id, cause: ZoneChangeCause): void;
|
|
70
|
+
/** Default `'select'`. */
|
|
71
|
+
readonly mode?: 'select' | 'highlight';
|
|
72
|
+
/** Default `'vertical'`. */
|
|
73
|
+
readonly orientation?: ZoneOrientation;
|
|
74
|
+
/**
|
|
75
|
+
* Default `'listbox'`: the zone is a listbox and its items options, marked
|
|
76
|
+
* `aria-selected`. `'tablist'`: tabs. `'none'`: the items keep their own
|
|
77
|
+
* semantics (links, buttons) and the chosen one is marked `aria-current`.
|
|
78
|
+
*/
|
|
79
|
+
readonly role?: 'listbox' | 'tablist' | 'none';
|
|
80
|
+
/** Default `false`: moving past an end goes to `onBoundary`. `true`: it wraps. */
|
|
81
|
+
readonly loop?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* The cross-axis forward key (→ in a vertical zone), and Enter in select
|
|
84
|
+
* mode. Returning `false` leaves the key to the page; anything else takes it —
|
|
85
|
+
* so do `onExit` and `onBoundary`.
|
|
86
|
+
*/
|
|
87
|
+
onEnter?(id: Id): unknown;
|
|
88
|
+
/** The cross-axis backward key (← in a vertical zone). */
|
|
89
|
+
onExit?(): unknown;
|
|
90
|
+
/** A move past an end of a zone that does not loop. */
|
|
91
|
+
onBoundary?(side: 'start' | 'end'): unknown;
|
|
92
|
+
/**
|
|
93
|
+
* Default `true`. An active zone takes its arrows when focus is in no zone
|
|
94
|
+
* at all — the first arrow on a page puts focus on the zone's current item.
|
|
95
|
+
* Of several active zones the innermost, then the last activated, does.
|
|
96
|
+
*/
|
|
97
|
+
readonly active?: boolean;
|
|
98
|
+
/** The zone's accessible name. */
|
|
99
|
+
readonly label?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Focus went to an item that has no element yet — a row of a virtualized
|
|
102
|
+
* list outside the rendered range. Scroll it in; focus lands on it as soon as
|
|
103
|
+
* its element mounts.
|
|
104
|
+
*/
|
|
105
|
+
onReveal?(id: Id): void;
|
|
106
|
+
}
|
|
107
|
+
/** The part of an item element the zone drives. An `HTMLElement` is one. */
|
|
108
|
+
export interface ZoneItemElement {
|
|
109
|
+
focus(options?: {
|
|
110
|
+
preventScroll?: boolean;
|
|
111
|
+
}): void;
|
|
112
|
+
scrollIntoView?(options?: {
|
|
113
|
+
block?: 'nearest';
|
|
114
|
+
inline?: 'nearest';
|
|
115
|
+
}): void;
|
|
116
|
+
}
|
|
117
|
+
export interface ZoneKeyEvent extends LayerKeyEvent, ZoneKey {
|
|
118
|
+
}
|
|
119
|
+
export interface NavZoneController<Id extends ZoneItemId> {
|
|
120
|
+
update(options: NavZoneOptions<Id>): void;
|
|
121
|
+
readonly options: NavZoneOptions<Id>;
|
|
122
|
+
/** The tab stop: the pointed item, else the chosen one, else the first. */
|
|
123
|
+
current(): Id | null;
|
|
124
|
+
/** A key pressed inside the zone's element (`zone` is that element). `true` when taken. */
|
|
125
|
+
keyDown(event: ZoneKeyEvent, zone: unknown): boolean;
|
|
126
|
+
/** A key pressed outside every zone, offered by the zone's layer. `true` when taken. */
|
|
127
|
+
keyFromOutside(event: ZoneKeyEvent): boolean;
|
|
128
|
+
/** An item received focus by any means — a click, Tab, a move. */
|
|
129
|
+
focused(id: Id): void;
|
|
130
|
+
/**
|
|
131
|
+
* Put focus on `id`, or on the current item — now, or when its element mounts.
|
|
132
|
+
* `false` when there is no item to focus.
|
|
133
|
+
*/
|
|
134
|
+
focus(id?: Id): boolean;
|
|
135
|
+
setItemElement(id: Id, element: ZoneItemElement | null): void;
|
|
136
|
+
subscribe(listener: () => void): () => void;
|
|
137
|
+
}
|
|
138
|
+
export declare function createNavZone<Id extends ZoneItemId>(initial: NavZoneOptions<Id>): NavZoneController<Id>;
|
|
139
|
+
//# sourceMappingURL=zone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zone.d.ts","sourceRoot":"","sources":["../../../src/react/keyboard/zone.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two cryptographic steps Telegram's protocols share: an HMAC-SHA-256 over
|
|
3
|
+
* WebCrypto, so it runs on Bun, Node and anything with `crypto.subtle`, and a
|
|
4
|
+
* comparison that does not say where two values first differ.
|
|
5
|
+
*/
|
|
6
|
+
export declare function hmacSha256(key: ArrayBuffer | Uint8Array, message: string): Promise<ArrayBuffer>;
|
|
7
|
+
export declare function toHex(buffer: ArrayBuffer): string;
|
|
8
|
+
/**
|
|
9
|
+
* Compare two strings without leaking where they first differ.
|
|
10
|
+
*
|
|
11
|
+
* A plain `===` on a digest returns as soon as one byte disagrees, and the time
|
|
12
|
+
* it took is a measurement of how much of the digest was right. The whole point
|
|
13
|
+
* of the comparison is that an attacker cannot get a partial answer.
|
|
14
|
+
*/
|
|
15
|
+
export declare function digestsEqual(a: string, b: string): boolean;
|
|
16
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/telegram/crypto.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,WAAW,GAAG,UAAU,EAC7B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CAStB;AAED,wBAAgB,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAIjD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAO1D"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Would Telegram refuse this markup as it stands? The strict counterpart of
|
|
3
|
+
* the lenient parse: no repair, the first thing Telegram would stop at.
|
|
4
|
+
*
|
|
5
|
+
* For markup a person typed and should hear about before it is sent — an
|
|
6
|
+
* editor warning that Telegram will refuse the text — rather than markup to be
|
|
7
|
+
* repaired, which is `sanitizeTelegramHtml`'s. The screens test chat refuses
|
|
8
|
+
* with it, so a bot's test fails where production would.
|
|
9
|
+
*/
|
|
10
|
+
export type TelegramHtmlProblem = {
|
|
11
|
+
readonly kind: 'bare-character';
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: 'unsupported-tag';
|
|
14
|
+
readonly tag: string;
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: 'unmatched-end-tag';
|
|
17
|
+
} | {
|
|
18
|
+
readonly kind: 'unclosed-tag';
|
|
19
|
+
};
|
|
20
|
+
export interface TelegramHtmlCheck {
|
|
21
|
+
readonly problem?: TelegramHtmlProblem;
|
|
22
|
+
/** The visible text up to the problem, or all of it. */
|
|
23
|
+
readonly text: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function checkTelegramHtml(markup: string): TelegramHtmlCheck;
|
|
26
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/telegram/html/check.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyBH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,GACnC;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAA;CAAE,GACtC;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC;AAEtC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IACvC,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAgBnE"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram's HTML parse mode as a tree, and the rules that tree obeys.
|
|
3
|
+
*
|
|
4
|
+
* Telegram accepts a small, fixed subset of HTML and refuses the whole message
|
|
5
|
+
* over one tag outside it, one bare `<` or one entity nested where it may not
|
|
6
|
+
* be. Every bot that sends text written by someone else — a model, an editor,
|
|
7
|
+
* an owner's greeting — has to turn arbitrary markup into that subset, and every
|
|
8
|
+
* bot that sends a long text has to cut it without cutting a tag in half. Both
|
|
9
|
+
* are answered once here, on a tree: markup is parsed into nodes that can only
|
|
10
|
+
* express what Telegram accepts, and everything else — cleaning, cutting,
|
|
11
|
+
* measuring, previewing — is a walk over those nodes.
|
|
12
|
+
*
|
|
13
|
+
* The nesting rules are Telegram's (Bot API, "Formatting options"): bold,
|
|
14
|
+
* italic, underline, strikethrough and spoiler may contain and be contained by
|
|
15
|
+
* anything except `pre` and `code`; a block quotation is never inside another;
|
|
16
|
+
* all other entities never contain each other.
|
|
17
|
+
*/
|
|
18
|
+
/** Text formatting that nests freely, except inside `pre` and `code`. */
|
|
19
|
+
export type TelegramHtmlStyle = 'b' | 'i' | 'u' | 's' | 'tg-spoiler';
|
|
20
|
+
export interface TelegramHtmlTextNode {
|
|
21
|
+
readonly kind: 'text';
|
|
22
|
+
/** The text as a reader sees it — entities decoded, nothing escaped. */
|
|
23
|
+
readonly text: string;
|
|
24
|
+
}
|
|
25
|
+
interface ElementBase {
|
|
26
|
+
readonly kind: 'element';
|
|
27
|
+
readonly children: readonly TelegramHtmlNode[];
|
|
28
|
+
}
|
|
29
|
+
export type TelegramHtmlElement = (ElementBase & {
|
|
30
|
+
readonly tag: TelegramHtmlStyle | 'code';
|
|
31
|
+
}) | (ElementBase & {
|
|
32
|
+
readonly tag: 'a';
|
|
33
|
+
readonly href: string;
|
|
34
|
+
}) | (ElementBase & {
|
|
35
|
+
readonly tag: 'pre';
|
|
36
|
+
readonly language?: string;
|
|
37
|
+
}) | (ElementBase & {
|
|
38
|
+
readonly tag: 'blockquote';
|
|
39
|
+
readonly expandable: boolean;
|
|
40
|
+
}) | (ElementBase & {
|
|
41
|
+
readonly tag: 'tg-emoji';
|
|
42
|
+
readonly emojiId: string;
|
|
43
|
+
}) | (ElementBase & {
|
|
44
|
+
readonly tag: 'tg-time';
|
|
45
|
+
readonly unix: number;
|
|
46
|
+
readonly format?: string;
|
|
47
|
+
});
|
|
48
|
+
export type TelegramHtmlNode = TelegramHtmlTextNode | TelegramHtmlElement;
|
|
49
|
+
export type TelegramHtmlTag = TelegramHtmlElement['tag'];
|
|
50
|
+
/** Telegram's limit for a message's text, after its markup is parsed. */
|
|
51
|
+
export declare const TELEGRAM_TEXT_LIMIT = 4096;
|
|
52
|
+
/** Telegram's limit for a media caption, after its markup is parsed. */
|
|
53
|
+
export declare const TELEGRAM_CAPTION_LIMIT = 1024;
|
|
54
|
+
export declare function isStyle(tag: string): tag is TelegramHtmlStyle;
|
|
55
|
+
/** Holds only text: no element of any kind inside. */
|
|
56
|
+
export declare function holdsOnlyText(tag: TelegramHtmlTag): boolean;
|
|
57
|
+
/** Rendered whole or not at all: its text is one thing, never cut. */
|
|
58
|
+
export declare function isAtomic(tag: TelegramHtmlTag): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Whether an element of `tag` may open inside `ancestors` (outermost first).
|
|
61
|
+
* A style is refused only under an element that holds text alone; any other
|
|
62
|
+
* element is refused under any element that is not a style.
|
|
63
|
+
*/
|
|
64
|
+
export declare function mayOpenInside(tag: TelegramHtmlTag, ancestors: readonly TelegramHtmlTag[]): boolean;
|
|
65
|
+
/** The visible text of nodes: what Telegram counts against its limits. */
|
|
66
|
+
export declare function textOf(nodes: readonly TelegramHtmlNode[]): string;
|
|
67
|
+
/** The same element holding other children. */
|
|
68
|
+
export declare function withChildren(element: TelegramHtmlElement, children: readonly TelegramHtmlNode[]): TelegramHtmlElement;
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=nodes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../../../src/telegram/html/nodes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,yEAAyE;AACzE,MAAM,MAAM,iBAAiB,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,YAAY,CAAC;AAErE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAChD;AAED,MAAM,MAAM,mBAAmB,GAC3B,CAAC,WAAW,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAAA;CAAE,CAAC,GAC5D,CAAC,WAAW,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAC5D,CAAC,WAAW,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACnE,CAAC,WAAW,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAAC,GAC5E,CAAC,WAAW,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GACtE,CAAC,WAAW,GAAG;IACb,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC,CAAC;AAEP,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG,mBAAmB,CAAC;AAE1E,MAAM,MAAM,eAAe,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;AAEzD,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,OAAQ,CAAC;AACzC,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,OAAQ,CAAC;AAU5C,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAE7D;AAED,sDAAsD;AACtD,wBAAgB,aAAa,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAE3D;AAED,sEAAsE;AACtE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,eAAe,EACpB,SAAS,EAAE,SAAS,eAAe,EAAE,GACpC,OAAO,CAGT;AAED,0EAA0E;AAC1E,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,CAIjE;AAED,+CAA+C;AAC/C,wBAAgB,YAAY,CAC1B,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,SAAS,gBAAgB,EAAE,GACpC,mBAAmB,CAErB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markup in, a tree Telegram accepts out — whatever the markup was.
|
|
3
|
+
*
|
|
4
|
+
* The parser is lenient on purpose: its input is text someone else wrote, and
|
|
5
|
+
* the only useful answer to a tag Telegram does not know is to keep the words
|
|
6
|
+
* and lose the tag. Synonyms become Telegram's tags (`strong` → `b`), block
|
|
7
|
+
* tags (`p`, `div`, `li`, `br`, headings) become line breaks, a link keeps only
|
|
8
|
+
* an `href` with a scheme Telegram opens, an element opened where Telegram
|
|
9
|
+
* forbids it stays text, and a closing tag closes the element it names along
|
|
10
|
+
* with whatever was left open inside it. No DOM and nothing executed, so the
|
|
11
|
+
* same parse serves a server and a browser preview.
|
|
12
|
+
*/
|
|
13
|
+
import { type TelegramHtmlNode } from './nodes.js';
|
|
14
|
+
export type Token = {
|
|
15
|
+
readonly type: 'text';
|
|
16
|
+
readonly text: string;
|
|
17
|
+
} | {
|
|
18
|
+
readonly type: 'entity';
|
|
19
|
+
readonly text: string;
|
|
20
|
+
readonly named: boolean;
|
|
21
|
+
readonly telegram: boolean;
|
|
22
|
+
} | {
|
|
23
|
+
readonly type: 'bare';
|
|
24
|
+
readonly char: string;
|
|
25
|
+
} | {
|
|
26
|
+
readonly type: 'tag';
|
|
27
|
+
readonly closing: boolean;
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly attributes: ReadonlyMap<string, string>;
|
|
30
|
+
};
|
|
31
|
+
/** Markup as tokens: tags, entities, runs of text, and the bare `<`, `>`, `&` Telegram refuses. */
|
|
32
|
+
export declare function tokenize(markup: string): Generator<Token>;
|
|
33
|
+
/** Parse markup into the tree Telegram accepts. Never throws. */
|
|
34
|
+
export declare function parseTelegramHtml(markup: string): TelegramHtmlNode[];
|
|
35
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../src/telegram/html/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAIL,KAAK,gBAAgB,EAEtB,MAAM,SAAS,CAAC;AAiDjB,MAAM,MAAM,KAAK,GACb;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChD;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChD;IACE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD,CAAC;AAkBN,mGAAmG;AACnG,wBAAiB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAsD1D;AAwMD,iEAAiE;AACjE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAapE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tree back to markup, and the operations that go through the tree:
|
|
3
|
+
* cleaning, cutting to Telegram's limits, measuring.
|
|
4
|
+
*
|
|
5
|
+
* Telegram's limits count the text after the markup is parsed — 4096 for a
|
|
6
|
+
* message, 1024 for a caption — so a long text is cut by what the reader
|
|
7
|
+
* sees, never by the length of its tags. A cut prefers a paragraph break, then
|
|
8
|
+
* a line break, then a space, then any place that does not split a character
|
|
9
|
+
* or a custom emoji; every element open across the cut is closed in one part
|
|
10
|
+
* and opened again, with its attributes, in the next. Length is counted in
|
|
11
|
+
* UTF-16 code units, the unit of Telegram's entity offsets: a text within the
|
|
12
|
+
* limit by this count is within it however Telegram counts.
|
|
13
|
+
*/
|
|
14
|
+
import { type TelegramHtmlNode } from './nodes.js';
|
|
15
|
+
/** `&`, `<` and `>` as Telegram's HTML requires them, and `"` for attributes. */
|
|
16
|
+
export declare function escapeTelegramHtml(text: string): string;
|
|
17
|
+
/** The markup Telegram parses back into exactly these nodes. */
|
|
18
|
+
export declare function renderTelegramHtml(nodes: readonly TelegramHtmlNode[]): string;
|
|
19
|
+
/** Any markup as markup Telegram accepts: its tags, its nesting, its escaping. */
|
|
20
|
+
export declare function sanitizeTelegramHtml(markup: string): string;
|
|
21
|
+
/** What the reader sees: the text of the markup, entities decoded. */
|
|
22
|
+
export declare function telegramHtmlText(markup: string): string;
|
|
23
|
+
export interface TelegramHtmlLimitOptions {
|
|
24
|
+
/** Visible characters per part. Default 4096 — a message; 1024 for a caption. */
|
|
25
|
+
readonly limit?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Cut markup into parts Telegram accepts one by one, each within `limit`
|
|
29
|
+
* visible characters and each valid on its own. Markup that fits is one part;
|
|
30
|
+
* text with nothing visible is no parts.
|
|
31
|
+
*/
|
|
32
|
+
export declare function splitTelegramHtml(markup: string, options?: TelegramHtmlLimitOptions): string[];
|
|
33
|
+
export interface TelegramHtmlTruncateOptions extends TelegramHtmlLimitOptions {
|
|
34
|
+
/** Appended when text was cut. Default `…`. */
|
|
35
|
+
readonly ellipsis?: string;
|
|
36
|
+
}
|
|
37
|
+
/** Markup cut to `limit` visible characters, the ellipsis included, still valid. */
|
|
38
|
+
export declare function truncateTelegramHtml(markup: string, options?: TelegramHtmlTruncateOptions): string;
|
|
39
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/telegram/html/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAIL,KAAK,gBAAgB,EAGtB,MAAM,SAAS,CAAC;AAGjB,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvD;AA4BD,gEAAgE;AAChE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,CAS7E;AAED,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AA+FD,MAAM,WAAW,wBAAwB;IACvC,iFAAiF;IACjF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,wBAA6B,GACrC,MAAM,EAAE,CAkBV;AAED,MAAM,WAAW,2BAA4B,SAAQ,wBAAwB;IAC3E,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,2BAAgC,GACxC,MAAM,CAWR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-data.d.ts","sourceRoot":"","sources":["../../src/telegram/init-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"init-data.d.ts","sourceRoot":"","sources":["../../src/telegram/init-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;;;;GAOG;AACH,QAAA,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsB3B,CAAC;AAEN,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,wCAAwC;IACxC,QAAQ,EAAE,IAAI,CAAC;IACf,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,uBAAuB,GAC/B,cAAc,GACd,oBAAoB,GACpB,WAAW,GACX,SAAS,CAAC;AAEd,MAAM,MAAM,4BAA4B,GACpC;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,GACzD;IACE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEN,MAAM,WAAW,6BAA6B;IAC5C,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAWD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,4BAA4B,CAAC,CAuEvC"}
|