@yaebal/rich 0.0.1 → 0.0.2

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.
Files changed (95) hide show
  1. package/README.md +104 -30
  2. package/lib/blocks.d.ts +93 -32
  3. package/lib/blocks.d.ts.map +1 -1
  4. package/lib/blocks.js +227 -71
  5. package/lib/blocks.js.map +1 -1
  6. package/lib/blocks.test.d.ts +2 -0
  7. package/lib/blocks.test.d.ts.map +1 -0
  8. package/lib/blocks.test.js +142 -0
  9. package/lib/blocks.test.js.map +1 -0
  10. package/lib/document.d.ts +28 -0
  11. package/lib/document.d.ts.map +1 -0
  12. package/lib/document.js +46 -0
  13. package/lib/document.js.map +1 -0
  14. package/lib/draft.d.ts +46 -9
  15. package/lib/draft.d.ts.map +1 -1
  16. package/lib/draft.js +115 -19
  17. package/lib/draft.js.map +1 -1
  18. package/lib/draft.test.d.ts +2 -0
  19. package/lib/draft.test.d.ts.map +1 -0
  20. package/lib/draft.test.js +122 -0
  21. package/lib/draft.test.js.map +1 -0
  22. package/lib/escape.d.ts +8 -0
  23. package/lib/escape.d.ts.map +1 -1
  24. package/lib/escape.js +17 -0
  25. package/lib/escape.js.map +1 -1
  26. package/lib/escape.test.d.ts +2 -0
  27. package/lib/escape.test.d.ts.map +1 -0
  28. package/lib/escape.test.js +28 -0
  29. package/lib/escape.test.js.map +1 -0
  30. package/lib/guards.test.d.ts +2 -0
  31. package/lib/guards.test.d.ts.map +1 -0
  32. package/lib/guards.test.js +85 -0
  33. package/lib/guards.test.js.map +1 -0
  34. package/lib/index.d.ts +18 -9
  35. package/lib/index.d.ts.map +1 -1
  36. package/lib/index.js +17 -8
  37. package/lib/index.js.map +1 -1
  38. package/lib/index.test.js +73 -103
  39. package/lib/index.test.js.map +1 -1
  40. package/lib/inline.d.ts +48 -59
  41. package/lib/inline.d.ts.map +1 -1
  42. package/lib/inline.js +87 -82
  43. package/lib/inline.js.map +1 -1
  44. package/lib/inline.test.d.ts +2 -0
  45. package/lib/inline.test.d.ts.map +1 -0
  46. package/lib/inline.test.js +84 -0
  47. package/lib/inline.test.js.map +1 -0
  48. package/lib/node.d.ts +25 -0
  49. package/lib/node.d.ts.map +1 -0
  50. package/lib/node.js +21 -0
  51. package/lib/node.js.map +1 -0
  52. package/lib/plaintext.test.d.ts +2 -0
  53. package/lib/plaintext.test.d.ts.map +1 -0
  54. package/lib/plaintext.test.js +100 -0
  55. package/lib/plaintext.test.js.map +1 -0
  56. package/lib/render.d.ts +17 -0
  57. package/lib/render.d.ts.map +1 -0
  58. package/lib/render.js +30 -0
  59. package/lib/render.js.map +1 -0
  60. package/lib/send.d.ts +6 -3
  61. package/lib/send.d.ts.map +1 -1
  62. package/lib/send.js +12 -3
  63. package/lib/send.js.map +1 -1
  64. package/lib/template.d.ts +46 -0
  65. package/lib/template.d.ts.map +1 -0
  66. package/lib/template.js +82 -0
  67. package/lib/template.js.map +1 -0
  68. package/lib/template.test.d.ts +2 -0
  69. package/lib/template.test.d.ts.map +1 -0
  70. package/lib/template.test.js +78 -0
  71. package/lib/template.test.js.map +1 -0
  72. package/package.json +6 -5
  73. package/src/blocks.test.ts +233 -0
  74. package/src/blocks.ts +304 -86
  75. package/src/document.ts +51 -0
  76. package/src/draft.test.ts +167 -0
  77. package/src/draft.ts +148 -21
  78. package/src/escape.test.ts +38 -0
  79. package/src/escape.ts +20 -0
  80. package/src/guards.test.ts +138 -0
  81. package/src/index.test.ts +79 -140
  82. package/src/index.ts +26 -11
  83. package/src/inline.test.ts +125 -0
  84. package/src/inline.ts +131 -97
  85. package/src/node.ts +43 -0
  86. package/src/plaintext.test.ts +141 -0
  87. package/src/render.ts +54 -0
  88. package/src/send.ts +17 -10
  89. package/src/template.test.ts +100 -0
  90. package/src/template.ts +115 -0
  91. package/lib/message.d.ts +0 -26
  92. package/lib/message.d.ts.map +0 -1
  93. package/lib/message.js +0 -31
  94. package/lib/message.js.map +0 -1
  95. package/src/message.ts +0 -45
@@ -0,0 +1,85 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { isAnchorBlock, isAnchorLink, isAnchorText, isAnimation, isAudio, isBankCardNumber, isBlockquote, isBold, isBotCommand, isCashtag, isCodeText, isCollage, isCustomEmoji, isDateTime, isDetails, isDivider, isEmailAddress, isFooter, isHashtag, isHeading, isItalic, isList, isMap, isMarked, isMathBlock, isMathText, isMentionText, isParagraph, isPhoneNumber, isPhoto, isPreformatted, isPullquote, isReference, isReferenceLink, isSlideshow, isSpoilerText, isStrikethrough, isSubscript, isSuperscript, isTable, isTextMention, isThinking, isUnderline, isUrlText, isVideo, isVoiceNote, } from "./guards.js";
4
+ const BLOCK_GUARDS = [
5
+ ["paragraph", isParagraph],
6
+ ["heading", isHeading],
7
+ ["pre", isPreformatted],
8
+ ["footer", isFooter],
9
+ ["divider", isDivider],
10
+ ["mathematical_expression", isMathBlock],
11
+ ["anchor", isAnchorBlock],
12
+ ["list", isList],
13
+ ["blockquote", isBlockquote],
14
+ ["pullquote", isPullquote],
15
+ ["collage", isCollage],
16
+ ["slideshow", isSlideshow],
17
+ ["table", isTable],
18
+ ["details", isDetails],
19
+ ["map", isMap],
20
+ ["animation", isAnimation],
21
+ ["audio", isAudio],
22
+ ["photo", isPhoto],
23
+ ["video", isVideo],
24
+ ["voice_note", isVoiceNote],
25
+ ["thinking", isThinking],
26
+ ];
27
+ const TEXT_GUARDS = [
28
+ ["bold", isBold],
29
+ ["italic", isItalic],
30
+ ["underline", isUnderline],
31
+ ["strikethrough", isStrikethrough],
32
+ ["spoiler", isSpoilerText],
33
+ ["date_time", isDateTime],
34
+ ["text_mention", isTextMention],
35
+ ["subscript", isSubscript],
36
+ ["superscript", isSuperscript],
37
+ ["marked", isMarked],
38
+ ["code", isCodeText],
39
+ ["custom_emoji", isCustomEmoji],
40
+ ["mathematical_expression", isMathText],
41
+ ["url", isUrlText],
42
+ ["email_address", isEmailAddress],
43
+ ["phone_number", isPhoneNumber],
44
+ ["bank_card_number", isBankCardNumber],
45
+ ["mention", isMentionText],
46
+ ["hashtag", isHashtag],
47
+ ["cashtag", isCashtag],
48
+ ["bot_command", isBotCommand],
49
+ ["anchor", isAnchorText],
50
+ ["anchor_link", isAnchorLink],
51
+ ["reference", isReference],
52
+ ["reference_link", isReferenceLink],
53
+ ];
54
+ test("every RichBlock guard matches its own .type and rejects every other guard's", () => {
55
+ for (const [type, guard] of BLOCK_GUARDS) {
56
+ const block = { type };
57
+ assert.equal(guard(block), true, `${type} guard should match its own type`);
58
+ for (const [otherType, otherGuard] of BLOCK_GUARDS) {
59
+ if (otherType === type)
60
+ continue;
61
+ assert.equal(otherGuard(block), false, `${otherType} guard should reject a "${type}" block`);
62
+ }
63
+ }
64
+ });
65
+ test("every RichText guard matches its own .type and rejects every other guard's", () => {
66
+ for (const [type, guard] of TEXT_GUARDS) {
67
+ const text = { type };
68
+ assert.equal(guard(text), true, `${type} guard should match its own type`);
69
+ for (const [otherType, otherGuard] of TEXT_GUARDS) {
70
+ if (otherType === type)
71
+ continue;
72
+ assert.equal(otherGuard(text), false, `${otherType} guard should reject a "${type}" text`);
73
+ }
74
+ }
75
+ });
76
+ test("guards narrow RichBlock by .type despite the generated field being `string`", () => {
77
+ const blocks = [
78
+ { type: "table", cells: [[{ text: "x", align: "left", valign: "top" }]] },
79
+ { type: "photo", photo: [] },
80
+ ];
81
+ assert.equal(isTable(blocks[0]), true);
82
+ assert.equal(isPhoto(blocks[1]), true);
83
+ assert.equal(isTable(blocks[1]), false);
84
+ });
85
+ //# sourceMappingURL=guards.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.test.js","sourceRoot":"","sources":["../src/guards.test.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts CHANGED
@@ -6,12 +6,17 @@
6
6
  * parses it server-side, and you get the same tree back on `message.rich_message`.
7
7
  * this package covers all three parts of that surface:
8
8
  *
9
- * - **write**: `document()` + block builders (blocks.ts) and inline mark builders
10
- * (inline.ts) assemble an `InputRichMessage` without hand-written angle brackets.
9
+ * - **write**: one dual-dialect builder set. every builder (`bold`, `paragraph`,
10
+ * `table`, …) returns a dialect-agnostic `RichNode`; the `html`/`md` template
11
+ * tags (or `document()`) pick the wire dialect once, at the edge, and emit a
12
+ * `RichDocument` — the `rich_message` envelope with fluent `.rtl()` /
13
+ * `.noEntityDetection()` flags. interpolated text is always dialect-escaped,
14
+ * so user input can never inject markup in either dialect.
11
15
  * - **stream**: `RichMessageDraft` (draft.ts) owns the fiddly part of
12
16
  * `sendRichMessageDraft` — the draft is ephemeral (telegram drops it 30s after
13
- * the last push) and must be closed with a real `sendRichMessage` or explicitly
14
- * cancelled.
17
+ * the last push) and must be closed with a real `sendRichMessage` (`send()`) or
18
+ * explicitly `cancel()`led. `rewrite()` replaces the whole draft, `write()`
19
+ * appends to it.
15
20
  * - **read**: type guards (guards.ts) and plain-text flattening (plaintext.ts)
16
21
  * cover every `RichBlock`/`RichText` variant telegram can hand back.
17
22
  *
@@ -23,11 +28,15 @@
23
28
  * /bot_command) auto-detected from plain text by telegram itself.
24
29
  */
25
30
  export type { InputRichMessage, InputRichMessageContent, RichBlock, RichBlockAnchor, RichBlockAnimation, RichBlockAudio, RichBlockBlockQuotation, RichBlockCaption, RichBlockCollage, RichBlockDetails, RichBlockDivider, RichBlockFooter, RichBlockList, RichBlockListItem, RichBlockMap, RichBlockMathematicalExpression, RichBlockParagraph, RichBlockPhoto, RichBlockPreformatted, RichBlockPullQuotation, RichBlockSectionHeading, RichBlockSlideshow, RichBlockTable, RichBlockTableCell, RichBlockThinking, RichBlockVideo, RichBlockVoiceNote, RichMessage, RichText, RichTextAnchor, RichTextAnchorLink, RichTextBankCardNumber, RichTextBold, RichTextBotCommand, RichTextCashtag, RichTextCode, RichTextCustomEmoji, RichTextDateTime, RichTextEmailAddress, RichTextHashtag, RichTextItalic, RichTextMarked, RichTextMathematicalExpression, RichTextMention, RichTextPhoneNumber, RichTextReference, RichTextReferenceLink, RichTextSpoiler, RichTextStrikethrough, RichTextSubscript, RichTextSuperscript, RichTextTextMention, RichTextUnderline, RichTextUrl, SendRichMessageDraftParams, SendRichMessageParams, } from "@yaebal/types";
26
- export { anchorBlock, audio, blockquote, type Caption, cell, collage, type DetailsOptions, details, divider, footer, heading, image, item, type ListItemOptions, type ListOptions, list, type MapOptions, type MediaOptions, map, mathBlock, paragraph, preformatted, pullquote, slideshow, type TableCellOptions, type TableOptions, table, thinking, video, } from "./blocks.js";
31
+ export { anchorBlock, audio, blockquote, type Caption, cell, collage, type DetailsOptions, details, divider, footer, h1, h2, h3, h4, h5, h6, heading, image, item, join, type ListItem, type ListItemOptions, type ListOptions, list, type MapOptions, type MediaOptions, map, mathBlock, paragraph, preformatted, pullquote, slideshow, type TableCell, type TableCellOptions, type TableOptions, table, thinking, video, } from "./blocks.js";
32
+ export { RichDocument } from "./document.js";
27
33
  export { RichMessageDraft, type RichMessageDraftOptions } from "./draft.js";
28
- export { isAnchorBlock, isAnchorLink, isAnchorText, isAnimation, isAudio, isBankCardNumber, isBlockquote, isBold, isBotCommand, isCashtag, isCodeText, isCollage, isCustomEmoji, isDateTime, isDetails, isDivider, isEmailAddress, isFooter, isHashtag, isHeading, isList, isMap, isMarked, isMathBlock, isMathText, isMentionText, isParagraph, isPhoneNumber, isPhoto, isPreformatted, isPullquote, isReference, isReferenceLink, isSlideshow, isSpoilerText, isStrikethrough, isSubscript, isSuperscript, isTable, isTextMention, isThinking, isUnderline, isUrlText, isVideo, isVoiceNote, } from "./guards.js";
29
- export { anchor, anchorLink, bold, code, customEmoji, dateTime, html, type Insertable, isRichNode, italic, link, marked, math, type RichNode, reference, referenceLink, spoiler, strikethrough, subscript, superscript, textMention, toHtml, underline, } from "./inline.js";
30
- export { type DocumentOptions, document, markdown } from "./message.js";
34
+ export { escapeMarkdown, escapeMarkdownUrl } from "./escape.js";
35
+ export { isAnchorBlock, isAnchorLink, isAnchorText, isAnimation, isAudio, isBankCardNumber, isBlockquote, isBold, isBotCommand, isCashtag, isCodeText, isCollage, isCustomEmoji, isDateTime, isDetails, isDivider, isEmailAddress, isFooter, isHashtag, isHeading, isItalic, isList, isMap, isMarked, isMathBlock, isMathText, isMentionText, isParagraph, isPhoneNumber, isPhoto, isPreformatted, isPullquote, isReference, isReferenceLink, isSlideshow, isSpoilerText, isStrikethrough, isSubscript, isSuperscript, isTable, isTextMention, isThinking, isUnderline, isUrlText, isVideo, isVoiceNote, } from "./guards.js";
36
+ export { anchor, anchorLink, bold, br, code, customEmoji, dateTime, italic, link, marked, math, reference, referenceLink, spoiler, strikethrough, subscript, superscript, textMention, underline, } from "./inline.js";
37
+ export { type Dialect, isRichNode, type Level, RichError, type RichNode } from "./node.js";
31
38
  export { richBlockToPlainText, richMessageToPlainText, richTextToPlainText } from "./plaintext.js";
32
- export { type RichContext, rich, sendRichMessage, sendRichMessageDraft, } from "./send.js";
39
+ export { escapeFor, type Insertable, render } from "./render.js";
40
+ export { type RichContext, type RichSource, rich, sendRichMessage, sendRichMessageDraft, } from "./send.js";
41
+ export { type DocumentOptions, document, html, md, type RichTemplate } from "./template.js";
33
42
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,YAAY,EACX,gBAAgB,EAChB,uBAAuB,EACvB,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,+BAA+B,EAC/B,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,QAAQ,EACR,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,cAAc,EACd,8BAA8B,EAC9B,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,EACX,0BAA0B,EAC1B,qBAAqB,GACrB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACN,WAAW,EACX,KAAK,EACL,UAAU,EACV,KAAK,OAAO,EACZ,IAAI,EACJ,OAAO,EACP,KAAK,cAAc,EACnB,OAAO,EACP,OAAO,EACP,MAAM,EACN,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,OAAO,EACP,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,IAAI,EACJ,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,GAAG,EACH,SAAS,EACT,SAAS,EACT,YAAY,EACZ,SAAS,EACT,SAAS,EACT,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,EACL,QAAQ,EACR,KAAK,GACL,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EACN,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,SAAS,EACT,UAAU,EACV,SAAS,EACT,aAAa,EACb,UAAU,EACV,SAAS,EACT,SAAS,EACT,cAAc,EACd,QAAQ,EACR,SAAS,EACT,SAAS,EACT,QAAQ,EACR,MAAM,EACN,KAAK,EACL,QAAQ,EACR,WAAW,EACX,UAAU,EACV,aAAa,EACb,WAAW,EACX,aAAa,EACb,OAAO,EACP,cAAc,EACd,WAAW,EACX,WAAW,EACX,eAAe,EACf,WAAW,EACX,aAAa,EACb,eAAe,EACf,WAAW,EACX,aAAa,EACb,OAAO,EACP,aAAa,EACb,UAAU,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,WAAW,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,MAAM,EACN,UAAU,EACV,IAAI,EACJ,EAAE,EACF,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,SAAS,EACT,aAAa,EACb,OAAO,EACP,aAAa,EACb,SAAS,EACT,WAAW,EACX,WAAW,EACX,SAAS,GACT,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,OAAO,EAAE,UAAU,EAAE,KAAK,KAAK,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3F,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACnG,OAAO,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,IAAI,EACJ,eAAe,EACf,oBAAoB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC"}
package/lib/index.js CHANGED
@@ -6,12 +6,17 @@
6
6
  * parses it server-side, and you get the same tree back on `message.rich_message`.
7
7
  * this package covers all three parts of that surface:
8
8
  *
9
- * - **write**: `document()` + block builders (blocks.ts) and inline mark builders
10
- * (inline.ts) assemble an `InputRichMessage` without hand-written angle brackets.
9
+ * - **write**: one dual-dialect builder set. every builder (`bold`, `paragraph`,
10
+ * `table`, …) returns a dialect-agnostic `RichNode`; the `html`/`md` template
11
+ * tags (or `document()`) pick the wire dialect once, at the edge, and emit a
12
+ * `RichDocument` — the `rich_message` envelope with fluent `.rtl()` /
13
+ * `.noEntityDetection()` flags. interpolated text is always dialect-escaped,
14
+ * so user input can never inject markup in either dialect.
11
15
  * - **stream**: `RichMessageDraft` (draft.ts) owns the fiddly part of
12
16
  * `sendRichMessageDraft` — the draft is ephemeral (telegram drops it 30s after
13
- * the last push) and must be closed with a real `sendRichMessage` or explicitly
14
- * cancelled.
17
+ * the last push) and must be closed with a real `sendRichMessage` (`send()`) or
18
+ * explicitly `cancel()`led. `rewrite()` replaces the whole draft, `write()`
19
+ * appends to it.
15
20
  * - **read**: type guards (guards.ts) and plain-text flattening (plaintext.ts)
16
21
  * cover every `RichBlock`/`RichText` variant telegram can hand back.
17
22
  *
@@ -22,11 +27,15 @@
22
27
  * documented tag or (for url/email/phone/bank-card/@mention/#hashtag/$cashtag/
23
28
  * /bot_command) auto-detected from plain text by telegram itself.
24
29
  */
25
- export { anchorBlock, audio, blockquote, cell, collage, details, divider, footer, heading, image, item, list, map, mathBlock, paragraph, preformatted, pullquote, slideshow, table, thinking, video, } from "./blocks.js";
30
+ export { anchorBlock, audio, blockquote, cell, collage, details, divider, footer, h1, h2, h3, h4, h5, h6, heading, image, item, join, list, map, mathBlock, paragraph, preformatted, pullquote, slideshow, table, thinking, video, } from "./blocks.js";
31
+ export { RichDocument } from "./document.js";
26
32
  export { RichMessageDraft } from "./draft.js";
27
- export { isAnchorBlock, isAnchorLink, isAnchorText, isAnimation, isAudio, isBankCardNumber, isBlockquote, isBold, isBotCommand, isCashtag, isCodeText, isCollage, isCustomEmoji, isDateTime, isDetails, isDivider, isEmailAddress, isFooter, isHashtag, isHeading, isList, isMap, isMarked, isMathBlock, isMathText, isMentionText, isParagraph, isPhoneNumber, isPhoto, isPreformatted, isPullquote, isReference, isReferenceLink, isSlideshow, isSpoilerText, isStrikethrough, isSubscript, isSuperscript, isTable, isTextMention, isThinking, isUnderline, isUrlText, isVideo, isVoiceNote, } from "./guards.js";
28
- export { anchor, anchorLink, bold, code, customEmoji, dateTime, html, isRichNode, italic, link, marked, math, reference, referenceLink, spoiler, strikethrough, subscript, superscript, textMention, toHtml, underline, } from "./inline.js";
29
- export { document, markdown } from "./message.js";
33
+ export { escapeMarkdown, escapeMarkdownUrl } from "./escape.js";
34
+ export { isAnchorBlock, isAnchorLink, isAnchorText, isAnimation, isAudio, isBankCardNumber, isBlockquote, isBold, isBotCommand, isCashtag, isCodeText, isCollage, isCustomEmoji, isDateTime, isDetails, isDivider, isEmailAddress, isFooter, isHashtag, isHeading, isItalic, isList, isMap, isMarked, isMathBlock, isMathText, isMentionText, isParagraph, isPhoneNumber, isPhoto, isPreformatted, isPullquote, isReference, isReferenceLink, isSlideshow, isSpoilerText, isStrikethrough, isSubscript, isSuperscript, isTable, isTextMention, isThinking, isUnderline, isUrlText, isVideo, isVoiceNote, } from "./guards.js";
35
+ export { anchor, anchorLink, bold, br, code, customEmoji, dateTime, italic, link, marked, math, reference, referenceLink, spoiler, strikethrough, subscript, superscript, textMention, underline, } from "./inline.js";
36
+ export { isRichNode, RichError } from "./node.js";
30
37
  export { richBlockToPlainText, richMessageToPlainText, richTextToPlainText } from "./plaintext.js";
38
+ export { escapeFor, render } from "./render.js";
31
39
  export { rich, sendRichMessage, sendRichMessageDraft, } from "./send.js";
40
+ export { document, html, md } from "./template.js";
32
41
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA+DH,OAAO,EACN,WAAW,EACX,KAAK,EACL,UAAU,EAEV,IAAI,EACJ,OAAO,EAEP,OAAO,EACP,OAAO,EACP,MAAM,EACN,OAAO,EACP,KAAK,EACL,IAAI,EAGJ,IAAI,EAGJ,GAAG,EACH,SAAS,EACT,SAAS,EACT,YAAY,EACZ,SAAS,EACT,SAAS,EAGT,KAAK,EACL,QAAQ,EACR,KAAK,GACL,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAgC,MAAM,YAAY,CAAC;AAC5E,OAAO,EACN,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,SAAS,EACT,UAAU,EACV,SAAS,EACT,aAAa,EACb,UAAU,EACV,SAAS,EACT,SAAS,EACT,cAAc,EACd,QAAQ,EACR,SAAS,EACT,SAAS,EACT,MAAM,EACN,KAAK,EACL,QAAQ,EACR,WAAW,EACX,UAAU,EACV,aAAa,EACb,WAAW,EACX,aAAa,EACb,OAAO,EACP,cAAc,EACd,WAAW,EACX,WAAW,EACX,eAAe,EACf,WAAW,EACX,aAAa,EACb,eAAe,EACf,WAAW,EACX,aAAa,EACb,OAAO,EACP,aAAa,EACb,UAAU,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,WAAW,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,MAAM,EACN,UAAU,EACV,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,IAAI,EAEJ,UAAU,EACV,MAAM,EACN,IAAI,EACJ,MAAM,EACN,IAAI,EAEJ,SAAS,EACT,aAAa,EACb,OAAO,EACP,aAAa,EACb,SAAS,EACT,WAAW,EACX,WAAW,EACX,MAAM,EACN,SAAS,GACT,MAAM,aAAa,CAAC;AACrB,OAAO,EAAwB,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExE,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACnG,OAAO,EAEN,IAAI,EACJ,eAAe,EACf,oBAAoB,GACpB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AA+DH,OAAO,EACN,WAAW,EACX,KAAK,EACL,UAAU,EAEV,IAAI,EACJ,OAAO,EAEP,OAAO,EACP,OAAO,EACP,MAAM,EACN,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,OAAO,EACP,KAAK,EACL,IAAI,EACJ,IAAI,EAIJ,IAAI,EAGJ,GAAG,EACH,SAAS,EACT,SAAS,EACT,YAAY,EACZ,SAAS,EACT,SAAS,EAIT,KAAK,EACL,QAAQ,EACR,KAAK,GACL,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAgC,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EACN,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,SAAS,EACT,UAAU,EACV,SAAS,EACT,aAAa,EACb,UAAU,EACV,SAAS,EACT,SAAS,EACT,cAAc,EACd,QAAQ,EACR,SAAS,EACT,SAAS,EACT,QAAQ,EACR,MAAM,EACN,KAAK,EACL,QAAQ,EACR,WAAW,EACX,UAAU,EACV,aAAa,EACb,WAAW,EACX,aAAa,EACb,OAAO,EACP,cAAc,EACd,WAAW,EACX,WAAW,EACX,eAAe,EACf,WAAW,EACX,aAAa,EACb,eAAe,EACf,WAAW,EACX,aAAa,EACb,OAAO,EACP,aAAa,EACb,UAAU,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,WAAW,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,MAAM,EACN,UAAU,EACV,IAAI,EACJ,EAAE,EACF,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,SAAS,EACT,aAAa,EACb,OAAO,EACP,aAAa,EACb,SAAS,EACT,WAAW,EACX,WAAW,EACX,SAAS,GACT,MAAM,aAAa,CAAC;AACrB,OAAO,EAAgB,UAAU,EAAc,SAAS,EAAiB,MAAM,WAAW,CAAC;AAC3F,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACnG,OAAO,EAAE,SAAS,EAAmB,MAAM,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAGN,IAAI,EACJ,eAAe,EACf,oBAAoB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAwB,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAqB,MAAM,eAAe,CAAC"}
package/lib/index.test.js CHANGED
@@ -1,72 +1,44 @@
1
1
  import assert from "node:assert/strict";
2
2
  import test from "node:test";
3
3
  import { Composer, Context } from "@yaebal/core";
4
- import { bold, cell, details, document, heading, html, image, isPhoto, isTable, item, link, list, paragraph, RichMessageDraft, rich, richMessageToPlainText, sendRichMessage, sendRichMessageDraft, table, thinking, } from "./index.js";
5
- function mockApi() {
6
- const calls = [];
7
- return {
8
- calls,
9
- call: async (method, params) => {
10
- calls.push([method, params]);
11
- return {};
12
- },
13
- };
14
- }
15
- test("html template escapes interpolations and splices RichNode subs", () => {
16
- const node = html `<p>hi ${"<b>hax</b>"} — ${bold("safe")}</p>`;
17
- assert.equal(node.html, "<p>hi &lt;b&gt;hax&lt;/b&gt; — <b>safe</b></p>");
18
- });
19
- test("inline builders emit the documented tags", () => {
20
- assert.equal(bold("x").html, "<b>x</b>");
21
- assert.equal(link("https://yaeb.al", "docs").html, '<a href="https://yaeb.al">docs</a>');
22
- });
23
- test("block builders compose into a document", () => {
24
- const input = document([
25
- heading(1, "title"),
26
- paragraph("hello ", bold("world")),
27
- list([item(["a"]), item(["b"], { checkbox: true, checked: true })]),
28
- details("more", [paragraph("hidden")], { open: false }),
29
- ]);
30
- assert.equal(input.html, "<h1>title</h1>" +
31
- "<p>hello <b>world</b></p>" +
32
- '<ul><li>a</li><li><input type="checkbox" checked/> b</li></ul>' +
33
- "<details><summary>more</summary><p>hidden</p></details>");
34
- });
35
- test("table() and cell() render alignment attributes telegram's schema documents", () => {
36
- const node = table([
37
- [cell("a", { header: true, align: "center" }), cell("b", { valign: "middle" })],
38
- ]);
39
- assert.equal(node.html, '<table><tr><th align="center">a</th><td valign="middle">b</td></tr></table>');
40
- });
41
- test("image() wraps caption/credit in figure/figcaption/cite", () => {
42
- const node = image("https://example.com/x.jpg", { caption: "a cat", credit: "photographer" });
43
- assert.equal(node.html, '<figure><img src="https://example.com/x.jpg"></img><figcaption>a cat<cite>photographer</cite></figcaption></figure>');
44
- });
45
- test("thinking() is exposed for draft-only use", () => {
46
- assert.equal(thinking("…").html, "<tg-thinking>…</tg-thinking>");
47
- });
4
+ import { mockApi } from "@yaebal/test";
5
+ import { bold, document, md, paragraph, RichMessageDraft, rich, sendRichMessage, sendRichMessageDraft, } from "./index.js";
6
+ // integration-level coverage for the parts that tie the package together: the raw
7
+ // send/draft functions, and the `rich()` plugin's ctx decoration. per-builder output
8
+ // (blocks.test.ts/inline.test.ts/markdown.test.ts), guards (guards.test.ts),
9
+ // plaintext flattening (plaintext.test.ts), and RichMessageDraft's rewrite/write/send
10
+ // state machine (draft.test.ts) all have their own dedicated test files.
48
11
  test("sendRichMessage posts chat_id + rich_message to the raw api", async () => {
49
- const api = mockApi();
12
+ const { api, calls } = mockApi();
50
13
  await sendRichMessage(api, 42, document([paragraph("hi")]), { reply_markup: { x: 1 } });
51
- assert.deepEqual(api.calls, [
52
- [
53
- "sendRichMessage",
54
- { chat_id: 42, rich_message: { html: "<p>hi</p>" }, reply_markup: { x: 1 } },
55
- ],
56
- ]);
14
+ assert.equal(calls[0]?.method, "sendRichMessage");
15
+ assert.deepEqual(calls[0]?.params, {
16
+ chat_id: 42,
17
+ rich_message: { html: "<p>hi</p>" },
18
+ reply_markup: { x: 1 },
19
+ });
20
+ });
21
+ test("sendRichMessage unwraps a markdown RichDocument with its fluent flags", async () => {
22
+ const { api, calls } = mockApi();
23
+ await sendRichMessage(api, 42, md `# hi ${bold("there")}`.rtl());
24
+ assert.equal(calls[0]?.method, "sendRichMessage");
25
+ assert.deepEqual(calls[0]?.params, {
26
+ chat_id: 42,
27
+ rich_message: { markdown: "# hi **there**", is_rtl: true },
28
+ });
57
29
  });
58
30
  test("sendRichMessageDraft posts draft_id alongside chat_id + rich_message", async () => {
59
- const api = mockApi();
31
+ const { api, calls } = mockApi();
60
32
  await sendRichMessageDraft(api, 42, 7, "<tg-thinking>…</tg-thinking>");
61
- assert.deepEqual(api.calls, [
62
- [
63
- "sendRichMessageDraft",
64
- { chat_id: 42, draft_id: 7, rich_message: { html: "<tg-thinking>…</tg-thinking>" } },
65
- ],
66
- ]);
33
+ assert.equal(calls[0]?.method, "sendRichMessageDraft");
34
+ assert.deepEqual(calls[0]?.params, {
35
+ chat_id: 42,
36
+ draft_id: 7,
37
+ rich_message: { html: "<tg-thinking>…</tg-thinking>" },
38
+ });
67
39
  });
68
- test("rich() plugin decorates ctx.sendRichMessage bound to the current chat", async () => {
69
- const api = mockApi();
40
+ test("rich() plugin decorates ctx.sendRichMessage/ctx.richMessageDraft bound to the current chat", async () => {
41
+ const { api, calls } = mockApi();
70
42
  const composer = new Composer().install(rich());
71
43
  const ctx = new Context({
72
44
  api,
@@ -79,52 +51,50 @@ test("rich() plugin decorates ctx.sendRichMessage bound to the current chat", as
79
51
  await composer.toMiddleware()(ctx, async () => { });
80
52
  const decorated = ctx;
81
53
  await decorated.sendRichMessage(document([paragraph("hi")]));
82
- assert.deepEqual(api.calls[0], [
83
- "sendRichMessage",
84
- { chat_id: 5, rich_message: { html: "<p>hi</p>" } },
85
- ]);
54
+ assert.equal(calls[0]?.method, "sendRichMessage");
55
+ assert.deepEqual(calls[0]?.params, { chat_id: 5, rich_message: { html: "<p>hi</p>" } });
86
56
  const draft = decorated.richMessageDraft(1);
87
57
  assert.ok(draft instanceof RichMessageDraft);
88
58
  });
89
- test("RichMessageDraft.push() re-arms a keep-alive timer and commit() stops it", async () => {
90
- const api = mockApi();
91
- const draft = new RichMessageDraft(api, 1, 1, { keepAliveMs: 60_000 });
92
- await draft.push(thinking("…"));
93
- assert.equal(api.calls[0]?.[0], "sendRichMessageDraft");
94
- await draft.commit(document([paragraph("done")]));
95
- assert.equal(api.calls[1]?.[0], "sendRichMessage");
96
- assert.equal(draft.closed, true);
97
- await assert.rejects(() => draft.push("late"), /after commit\(\)\/cancel\(\)/);
98
- });
99
- test("RichMessageDraft.cancel() closes without persisting", async () => {
100
- const api = mockApi();
101
- const draft = new RichMessageDraft(api, 1, 2);
102
- await draft.push("draft text");
103
- draft.cancel();
104
- assert.equal(draft.closed, true);
105
- assert.equal(api.calls.some(([method]) => method === "sendRichMessage"), false);
106
- });
107
- test("guards narrow RichBlock by .type despite the generated field being `string`", () => {
108
- const blocks = [
109
- { type: "table", cells: [[{ text: "x", align: "left", valign: "top" }]] },
110
- { type: "photo", photo: [] },
111
- ];
112
- assert.equal(isTable(blocks[0]), true);
113
- assert.equal(isPhoto(blocks[1]), true);
114
- assert.equal(isTable(blocks[1]), false);
115
- });
116
- test("richMessageToPlainText flattens a full block tree", () => {
117
- const message = {
118
- blocks: [
119
- { type: "heading", text: "title", size: 1 },
120
- { type: "paragraph", text: [{ type: "bold", text: "hi" }, " there"] },
121
- { type: "divider" },
122
- {
123
- type: "list",
124
- items: [{ label: "1", blocks: [{ type: "paragraph", text: "one" }] }],
59
+ test("rich() plugin routes ctx.sendRichMessage through the business connection/topic", async () => {
60
+ const { api, calls } = mockApi();
61
+ const composer = new Composer().install(rich());
62
+ const ctx = new Context({
63
+ api,
64
+ update: {
65
+ update_id: 1,
66
+ business_message: {
67
+ message_id: 1,
68
+ date: 0,
69
+ chat: { id: 5, type: "private" },
70
+ business_connection_id: "bc1",
71
+ message_thread_id: 9,
125
72
  },
126
- ],
127
- };
128
- assert.equal(richMessageToPlainText(message), "title\nhi there\n---\n- one");
73
+ },
74
+ updateType: "business_message",
75
+ });
76
+ await composer.toMiddleware()(ctx, async () => { });
77
+ const decorated = ctx;
78
+ await decorated.sendRichMessage(document([paragraph("hi")]));
79
+ assert.equal(calls[0]?.method, "sendRichMessage");
80
+ assert.deepEqual(calls[0]?.params, {
81
+ chat_id: 5,
82
+ rich_message: { html: "<p>hi</p>" },
83
+ business_connection_id: "bc1",
84
+ message_thread_id: 9,
85
+ });
86
+ });
87
+ test("sendRichMessage()/richMessageDraft() reject when the update has no chat", async () => {
88
+ const { api } = mockApi();
89
+ const composer = new Composer().install(rich());
90
+ const ctx = new Context({
91
+ api,
92
+ update: { update_id: 1 },
93
+ updateType: "message",
94
+ });
95
+ await composer.toMiddleware()(ctx, async () => { });
96
+ const decorated = ctx;
97
+ await assert.rejects(() => decorated.sendRichMessage("x"), /no chat in this update/);
98
+ assert.throws(() => decorated.richMessageDraft(1), /no chat in this update/);
129
99
  });
130
100
  //# sourceMappingURL=index.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
package/lib/inline.d.ts CHANGED
@@ -1,79 +1,68 @@
1
1
  import type { User } from "@yaebal/core";
2
+ import { type RichNode } from "./node.js";
3
+ import { type Insertable } from "./render.js";
4
+ /** `RichTextBold` — `<b>` / `**x**`. */
5
+ export declare const bold: (...items: Insertable[]) => RichNode;
6
+ /** `RichTextItalic` — `<i>` / `*x*`. */
7
+ export declare const italic: (...items: Insertable[]) => RichNode;
8
+ /** `RichTextUnderline` — `<u>`; no markdown token, the raw tag is embedded there too. */
9
+ export declare const underline: (...items: Insertable[]) => RichNode;
10
+ /** `RichTextStrikethrough` — `<s>` / `~~x~~`. */
11
+ export declare const strikethrough: (...items: Insertable[]) => RichNode;
12
+ /** `RichTextSpoiler` — `<tg-spoiler>` / `||x||`. */
13
+ export declare const spoiler: (...items: Insertable[]) => RichNode;
14
+ /** `RichTextCode` — `<code>` / `` `x` ``. */
15
+ export declare const code: (...items: Insertable[]) => RichNode;
16
+ /** line break — hard newline in markdown, `<br/>` in html. */
17
+ export declare function br(): RichNode;
2
18
  /**
3
- * a fragment of the extended html telegram parses into a `RichMessage` (see
4
- * `InputRichMessage.html`). unlike `@yaebal/fmt`'s `FormatResult` (a flat
5
- * `{ text, entities }` pair), rich messages are a block tree parsed server-side —
6
- * there is nothing to build client-side except this html string.
7
- */
8
- export interface RichNode {
9
- readonly html: string;
10
- }
11
- export type Insertable = RichNode | string | number | bigint | boolean | null | undefined;
12
- export declare function isRichNode(value: unknown): value is RichNode;
13
- /** render one interpolation: a `RichNode` is spliced raw, anything else is escaped text. */
14
- export declare function toHtml(value: Insertable): string;
15
- /**
16
- * an extended-html template: interpolations are auto-escaped (never re-parsed as
17
- * markup), and a nested `RichNode` (from these builders, or another `html`
18
- * template) is spliced in raw. mirrors `@yaebal/fmt`'s `html` tag, but for the
19
- * rich-message dialect instead of the classic entity one.
20
- */
21
- export declare function html(strings: TemplateStringsArray, ...subs: Insertable[]): RichNode;
22
- /** `RichTextBold`, `<b>`. */
23
- export declare const bold: (...children: Insertable[]) => RichNode;
24
- /** `RichTextItalic`, `<i>`. */
25
- export declare const italic: (...children: Insertable[]) => RichNode;
26
- /** `RichTextUnderline`, `<u>`. */
27
- export declare const underline: (...children: Insertable[]) => RichNode;
28
- /** `RichTextStrikethrough`, `<s>`. */
29
- export declare const strikethrough: (...children: Insertable[]) => RichNode;
30
- /** `RichTextSpoiler`, `<tg-spoiler>`. */
31
- export declare const spoiler: (...children: Insertable[]) => RichNode;
32
- /** `RichTextCode`, `<code>`. */
33
- export declare const code: (...children: Insertable[]) => RichNode;
34
- /**
35
- * `RichTextCustomEmoji`, `<tg-emoji emoji-id="…">`. same custom tag classic
36
- * `parse_mode: "HTML"` uses for custom emoji — telegram documents it as reused
37
- * verbatim here. `fallback` is the plain emoji shown where custom emoji can't render.
19
+ * `RichTextCustomEmoji` `<tg-emoji emoji-id="…">`, the same custom tag classic
20
+ * `parse_mode: "HTML"` uses (telegram documents it as reused verbatim here);
21
+ * best-effort `![fallback](tg://emoji?id=…)` in markdown. `fallback` is the
22
+ * plain emoji shown where custom emoji can't render.
38
23
  */
39
24
  export declare function customEmoji(emojiId: string, fallback: string): RichNode;
25
+ /** `RichTextUrl`, an explicit link. for a bare auto-linked url, just write it as plain text. */
26
+ export declare function link(url: string, ...items: Insertable[]): RichNode;
40
27
  /**
41
- * `RichTextTextMention`, a mention of a user who may have no `@username` — same
42
- * `tg://user?id=…` link telegram's classic html dialect uses for `text_mention`.
28
+ * `RichTextTextMention`, a mention of a user who may have no `@username` — the
29
+ * same `tg://user?id=…` link telegram's classic dialects use for `text_mention`.
43
30
  * for `@username` mentions (`RichTextMention`), just write `@username` as plain
44
- * text — the schema lists it as auto-detected (see `skipEntityDetection`).
31
+ * text — the schema lists it as auto-detected (see `noEntityDetection`).
45
32
  */
46
- export declare function textMention(user: Pick<User, "id">, ...children: Insertable[]): RichNode;
47
- /** `RichTextUrl`, an explicit link. for a bare auto-linked url, just write it as plain text. */
48
- export declare function link(url: string, ...children: Insertable[]): RichNode;
49
- /** `RichTextAnchor` (inline form) — a named jump target, `<a name="…">`. */
33
+ export declare function textMention(user: Pick<User, "id">, ...items: Insertable[]): RichNode;
34
+ /** `RichTextAnchor` (inline form) a named jump target, `<a name="…">` in both dialects. */
50
35
  export declare function anchor(name: string): RichNode;
51
36
  /**
52
37
  * `RichTextAnchorLink`, a link to an `anchor()` elsewhere in the message —
53
- * `<a href="#name">`. an empty `name` jumps back to the top (per the schema).
38
+ * `<a href="#name">` / `[text](#name)`. an empty `name` jumps back to the top
39
+ * (per the schema).
54
40
  */
55
- export declare function anchorLink(name: string, ...children: Insertable[]): RichNode;
56
- /** `RichTextMarked`, best-effort `<mark>` (standard html5 highlight). */
57
- export declare const marked: (...children: Insertable[]) => RichNode;
58
- /** `RichTextSubscript`, best-effort `<sub>`. */
59
- export declare const subscript: (...children: Insertable[]) => RichNode;
60
- /** `RichTextSuperscript`, best-effort `<sup>`. */
61
- export declare const superscript: (...children: Insertable[]) => RichNode;
41
+ export declare function anchorLink(name: string, ...items: Insertable[]): RichNode;
42
+ /** `RichTextMarked`, highlighted text — best-effort `<mark>` / `==x==`. */
43
+ export declare const marked: (...items: Insertable[]) => RichNode;
44
+ /** `RichTextSubscript` best-effort `<sub>`; no markdown token, raw tag embedded there too. */
45
+ export declare const subscript: (...items: Insertable[]) => RichNode;
46
+ /** `RichTextSuperscript` best-effort `<sup>`; no markdown token, raw tag embedded there too. */
47
+ export declare const superscript: (...items: Insertable[]) => RichNode;
62
48
  /**
63
- * `RichTextMathematicalExpression` (inline), best-effort `<tg-math>` (the block
64
- * form is confirmed as `<tg-math-block>` — see `mathBlock` in blocks.ts).
49
+ * `RichTextMathematicalExpression` (inline) best-effort `<tg-math>` / `$x$`
50
+ * (the block form is confirmed as `<tg-math-block>` — see `mathBlock` in
51
+ * blocks.ts). `expression` is raw LaTeX — not markdown-escaped.
65
52
  */
66
53
  export declare function math(expression: string): RichNode;
67
54
  /**
68
- * `RichTextDateTime`, best-effort `<time>`. `format` is telegram's date-time
69
- * entity format string; attribute name is a guess (`data-format`).
55
+ * `RichTextDateTime`, auto-formatted date-time — best-effort `<time>` (attribute
56
+ * name `data-format` is a guess) / `![label](tg://time?unix=…&format=…)`.
57
+ * `format` is telegram's date-time entity format string.
70
58
  */
71
- export declare function dateTime(unixTime: number, format: string, ...children: Insertable[]): RichNode;
59
+ export declare function dateTime(unixTime: number, format: string, ...items: Insertable[]): RichNode;
72
60
  /**
73
61
  * `RichTextReference`, a footnote definition. no tag is documented anywhere in
74
- * the scraped schema — this is a from-scratch `tg-*`-style guess.
62
+ * the scraped schema — `<tg-reference>` is a from-scratch `tg-*`-style guess,
63
+ * `[^name]: …` the standard markdown footnote line (place it at line start).
75
64
  */
76
- export declare function reference(name: string, ...children: Insertable[]): RichNode;
77
- /** `RichTextReferenceLink`, a link to a `reference()`. same caveat as `reference`. */
78
- export declare function referenceLink(name: string, ...children: Insertable[]): RichNode;
65
+ export declare function reference(name: string, ...items: Insertable[]): RichNode;
66
+ /** `RichTextReferenceLink`, a link to a `reference()` same caveat as `reference`. */
67
+ export declare function referenceLink(name: string, ...items: Insertable[]): RichNode;
79
68
  //# sourceMappingURL=inline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"inline.d.ts","sourceRoot":"","sources":["../src/inline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAGzC;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;AAE1F,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAI5D;AAED,4FAA4F;AAC5F,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAGhD;AAUD;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,GAAG,QAAQ,CASnF;AAID,6BAA6B;AAC7B,eAAO,MAAM,IAAI,gBAvBK,UAAU,EAAE,KAAG,QAuBR,CAAC;AAC9B,+BAA+B;AAC/B,eAAO,MAAM,MAAM,gBAzBG,UAAU,EAAE,KAAG,QAyBN,CAAC;AAChC,kCAAkC;AAClC,eAAO,MAAM,SAAS,gBA3BA,UAAU,EAAE,KAAG,QA2BH,CAAC;AACnC,sCAAsC;AACtC,eAAO,MAAM,aAAa,gBA7BJ,UAAU,EAAE,KAAG,QA6BC,CAAC;AACvC,yCAAyC;AACzC,eAAO,MAAM,OAAO,gBA/BE,UAAU,EAAE,KAAG,QA+BI,CAAC;AAC1C,gCAAgC;AAChC,eAAO,MAAM,IAAI,gBAjCK,UAAU,EAAE,KAAG,QAiCL,CAAC;AAEjC;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,QAAQ,CAEvF;AAED,gGAAgG;AAChG,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,QAAQ,CAErE;AAED,4EAA4E;AAC5E,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAE7C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,QAAQ,CAE5E;AAWD,yEAAyE;AACzE,eAAO,MAAM,MAAM,gBAlFG,UAAU,EAAE,KAAG,QAkFH,CAAC;AACnC,gDAAgD;AAChD,eAAO,MAAM,SAAS,gBApFA,UAAU,EAAE,KAAG,QAoFD,CAAC;AACrC,kDAAkD;AAClD,eAAO,MAAM,WAAW,gBAtFF,UAAU,EAAE,KAAG,QAsFC,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,CAEjD;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,QAAQ,CAI9F;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,QAAQ,CAE3E;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,QAAQ,CAI/E"}
1
+ {"version":3,"file":"inline.d.ts","sourceRoot":"","sources":["../src/inline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAA0B,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EAAa,KAAK,UAAU,EAAU,MAAM,aAAa,CAAC;AAkBjE,wCAAwC;AACxC,eAAO,MAAM,IAAI,aAPE,UAAU,EAAE,KAAG,QAUjC,CAAC;AACF,wCAAwC;AACxC,eAAO,MAAM,MAAM,aAZA,UAAU,EAAE,KAAG,QAejC,CAAC;AACF,yFAAyF;AACzF,eAAO,MAAM,SAAS,aAjBH,UAAU,EAAE,KAAG,QAoBjC,CAAC;AACF,iDAAiD;AACjD,eAAO,MAAM,aAAa,aAtBP,UAAU,EAAE,KAAG,QAyBjC,CAAC;AACF,oDAAoD;AACpD,eAAO,MAAM,OAAO,aA3BD,UAAU,EAAE,KAAG,QA8BjC,CAAC;AACF,6CAA6C;AAC7C,eAAO,MAAM,IAAI,aAhCE,UAAU,EAAE,KAAG,QAmCjC,CAAC;AAEF,8DAA8D;AAC9D,wBAAgB,EAAE,IAAI,QAAQ,CAE7B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAMvE;AAQD,gGAAgG;AAChG,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAMlE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAEpF;AAED,6FAA6F;AAC7F,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAMzE;AAWD,2EAA2E;AAC3E,eAAO,MAAM,MAAM,aA7GA,UAAU,EAAE,KAAG,QAgHjC,CAAC;AACF,gGAAgG;AAChG,eAAO,MAAM,SAAS,aAlHH,UAAU,EAAE,KAAG,QAqHjC,CAAC;AACF,kGAAkG;AAClG,eAAO,MAAM,WAAW,aAvHL,UAAU,EAAE,KAAG,QA0HjC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,CAIjD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAQ3F;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAMxE;AAED,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAM5E"}