@yaebal/rich 0.0.1

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 (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +109 -0
  3. package/lib/blocks.d.ts +115 -0
  4. package/lib/blocks.d.ts.map +1 -0
  5. package/lib/blocks.js +149 -0
  6. package/lib/blocks.js.map +1 -0
  7. package/lib/draft.d.ts +44 -0
  8. package/lib/draft.d.ts.map +1 -0
  9. package/lib/draft.js +85 -0
  10. package/lib/draft.js.map +1 -0
  11. package/lib/escape.d.ts +5 -0
  12. package/lib/escape.d.ts.map +1 -0
  13. package/lib/escape.js +9 -0
  14. package/lib/escape.js.map +1 -0
  15. package/lib/guards.d.ts +106 -0
  16. package/lib/guards.d.ts.map +1 -0
  17. package/lib/guards.js +55 -0
  18. package/lib/guards.js.map +1 -0
  19. package/lib/index.d.ts +33 -0
  20. package/lib/index.d.ts.map +1 -0
  21. package/lib/index.js +32 -0
  22. package/lib/index.js.map +1 -0
  23. package/lib/index.test.d.ts +2 -0
  24. package/lib/index.test.d.ts.map +1 -0
  25. package/lib/index.test.js +130 -0
  26. package/lib/index.test.js.map +1 -0
  27. package/lib/inline.d.ts +79 -0
  28. package/lib/inline.d.ts.map +1 -0
  29. package/lib/inline.js +120 -0
  30. package/lib/inline.js.map +1 -0
  31. package/lib/message.d.ts +26 -0
  32. package/lib/message.d.ts.map +1 -0
  33. package/lib/message.js +31 -0
  34. package/lib/message.js.map +1 -0
  35. package/lib/plaintext.d.ts +16 -0
  36. package/lib/plaintext.d.ts.map +1 -0
  37. package/lib/plaintext.js +104 -0
  38. package/lib/plaintext.js.map +1 -0
  39. package/lib/send.d.ts +27 -0
  40. package/lib/send.d.ts.map +1 -0
  41. package/lib/send.js +52 -0
  42. package/lib/send.js.map +1 -0
  43. package/package.json +51 -0
  44. package/src/blocks.ts +250 -0
  45. package/src/draft.ts +116 -0
  46. package/src/escape.ts +9 -0
  47. package/src/guards.ts +169 -0
  48. package/src/index.test.ts +201 -0
  49. package/src/index.ts +199 -0
  50. package/src/inline.ts +152 -0
  51. package/src/message.ts +45 -0
  52. package/src/plaintext.ts +143 -0
  53. package/src/send.ts +81 -0
@@ -0,0 +1,106 @@
1
+ import type { RichBlock, RichBlockAnchor, RichBlockAnimation, RichBlockAudio, RichBlockBlockQuotation, RichBlockCollage, RichBlockDetails, RichBlockDivider, RichBlockFooter, RichBlockList, RichBlockMap, RichBlockMathematicalExpression, RichBlockParagraph, RichBlockPhoto, RichBlockPreformatted, RichBlockPullQuotation, RichBlockSectionHeading, RichBlockSlideshow, RichBlockTable, RichBlockThinking, RichBlockVideo, RichBlockVoiceNote, 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 } from "@yaebal/types";
2
+ /**
3
+ * the generated `.type` field is typed as plain `string` (the codegen doesn't turn
4
+ * telegram's "always X" doc convention into a literal type), so `RichBlock["type"]`
5
+ * can't discriminate the union on its own — `Extract<RichBlock, { type: "table" }>`
6
+ * would just be `never`. this lookup map is the narrowing telescope instead: one
7
+ * entry per `.type` string, hand-matched to its interface.
8
+ */
9
+ interface RichBlockByType {
10
+ paragraph: RichBlockParagraph;
11
+ heading: RichBlockSectionHeading;
12
+ pre: RichBlockPreformatted;
13
+ footer: RichBlockFooter;
14
+ divider: RichBlockDivider;
15
+ mathematical_expression: RichBlockMathematicalExpression;
16
+ anchor: RichBlockAnchor;
17
+ list: RichBlockList;
18
+ blockquote: RichBlockBlockQuotation;
19
+ pullquote: RichBlockPullQuotation;
20
+ collage: RichBlockCollage;
21
+ slideshow: RichBlockSlideshow;
22
+ table: RichBlockTable;
23
+ details: RichBlockDetails;
24
+ map: RichBlockMap;
25
+ animation: RichBlockAnimation;
26
+ audio: RichBlockAudio;
27
+ photo: RichBlockPhoto;
28
+ video: RichBlockVideo;
29
+ voice_note: RichBlockVoiceNote;
30
+ thinking: RichBlockThinking;
31
+ }
32
+ interface RichTextByType {
33
+ bold: RichTextBold;
34
+ italic: RichTextItalic;
35
+ underline: RichTextUnderline;
36
+ strikethrough: RichTextStrikethrough;
37
+ spoiler: RichTextSpoiler;
38
+ date_time: RichTextDateTime;
39
+ text_mention: RichTextTextMention;
40
+ subscript: RichTextSubscript;
41
+ superscript: RichTextSuperscript;
42
+ marked: RichTextMarked;
43
+ code: RichTextCode;
44
+ custom_emoji: RichTextCustomEmoji;
45
+ mathematical_expression: RichTextMathematicalExpression;
46
+ url: RichTextUrl;
47
+ email_address: RichTextEmailAddress;
48
+ phone_number: RichTextPhoneNumber;
49
+ bank_card_number: RichTextBankCardNumber;
50
+ mention: RichTextMention;
51
+ hashtag: RichTextHashtag;
52
+ cashtag: RichTextCashtag;
53
+ bot_command: RichTextBotCommand;
54
+ anchor: RichTextAnchor;
55
+ anchor_link: RichTextAnchorLink;
56
+ reference: RichTextReference;
57
+ reference_link: RichTextReferenceLink;
58
+ }
59
+ export declare const isParagraph: (block: RichBlock) => block is RichBlockByType["paragraph"];
60
+ export declare const isHeading: (block: RichBlock) => block is RichBlockByType["heading"];
61
+ export declare const isPreformatted: (block: RichBlock) => block is RichBlockByType["pre"];
62
+ export declare const isFooter: (block: RichBlock) => block is RichBlockByType["footer"];
63
+ export declare const isDivider: (block: RichBlock) => block is RichBlockByType["divider"];
64
+ export declare const isMathBlock: (block: RichBlock) => block is RichBlockByType["mathematical_expression"];
65
+ export declare const isAnchorBlock: (block: RichBlock) => block is RichBlockByType["anchor"];
66
+ export declare const isList: (block: RichBlock) => block is RichBlockByType["list"];
67
+ export declare const isBlockquote: (block: RichBlock) => block is RichBlockByType["blockquote"];
68
+ export declare const isPullquote: (block: RichBlock) => block is RichBlockByType["pullquote"];
69
+ export declare const isCollage: (block: RichBlock) => block is RichBlockByType["collage"];
70
+ export declare const isSlideshow: (block: RichBlock) => block is RichBlockByType["slideshow"];
71
+ export declare const isTable: (block: RichBlock) => block is RichBlockByType["table"];
72
+ export declare const isDetails: (block: RichBlock) => block is RichBlockByType["details"];
73
+ export declare const isMap: (block: RichBlock) => block is RichBlockByType["map"];
74
+ export declare const isAnimation: (block: RichBlock) => block is RichBlockByType["animation"];
75
+ export declare const isAudio: (block: RichBlock) => block is RichBlockByType["audio"];
76
+ export declare const isPhoto: (block: RichBlock) => block is RichBlockByType["photo"];
77
+ export declare const isVideo: (block: RichBlock) => block is RichBlockByType["video"];
78
+ export declare const isVoiceNote: (block: RichBlock) => block is RichBlockByType["voice_note"];
79
+ export declare const isThinking: (block: RichBlock) => block is RichBlockByType["thinking"];
80
+ export declare const isBold: (text: RichText) => text is RichTextByType["bold"];
81
+ export declare const isItalic: (text: RichText) => text is RichTextByType["italic"];
82
+ export declare const isUnderline: (text: RichText) => text is RichTextByType["underline"];
83
+ export declare const isStrikethrough: (text: RichText) => text is RichTextByType["strikethrough"];
84
+ export declare const isSpoilerText: (text: RichText) => text is RichTextByType["spoiler"];
85
+ export declare const isDateTime: (text: RichText) => text is RichTextByType["date_time"];
86
+ export declare const isTextMention: (text: RichText) => text is RichTextByType["text_mention"];
87
+ export declare const isSubscript: (text: RichText) => text is RichTextByType["subscript"];
88
+ export declare const isSuperscript: (text: RichText) => text is RichTextByType["superscript"];
89
+ export declare const isMarked: (text: RichText) => text is RichTextByType["marked"];
90
+ export declare const isCodeText: (text: RichText) => text is RichTextByType["code"];
91
+ export declare const isCustomEmoji: (text: RichText) => text is RichTextByType["custom_emoji"];
92
+ export declare const isMathText: (text: RichText) => text is RichTextByType["mathematical_expression"];
93
+ export declare const isUrlText: (text: RichText) => text is RichTextByType["url"];
94
+ export declare const isEmailAddress: (text: RichText) => text is RichTextByType["email_address"];
95
+ export declare const isPhoneNumber: (text: RichText) => text is RichTextByType["phone_number"];
96
+ export declare const isBankCardNumber: (text: RichText) => text is RichTextByType["bank_card_number"];
97
+ export declare const isMentionText: (text: RichText) => text is RichTextByType["mention"];
98
+ export declare const isHashtag: (text: RichText) => text is RichTextByType["hashtag"];
99
+ export declare const isCashtag: (text: RichText) => text is RichTextByType["cashtag"];
100
+ export declare const isBotCommand: (text: RichText) => text is RichTextByType["bot_command"];
101
+ export declare const isAnchorText: (text: RichText) => text is RichTextByType["anchor"];
102
+ export declare const isAnchorLink: (text: RichText) => text is RichTextByType["anchor_link"];
103
+ export declare const isReference: (text: RichText) => text is RichTextByType["reference"];
104
+ export declare const isReferenceLink: (text: RichText) => text is RichTextByType["reference_link"];
105
+ export {};
106
+ //# sourceMappingURL=guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,+BAA+B,EAC/B,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,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,MAAM,eAAe,CAAC;AAEvB;;;;;;GAMG;AACH,UAAU,eAAe;IACxB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,OAAO,EAAE,uBAAuB,CAAC;IACjC,GAAG,EAAE,qBAAqB,CAAC;IAC3B,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,uBAAuB,EAAE,+BAA+B,CAAC;IACzD,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,uBAAuB,CAAC;IACpC,SAAS,EAAE,sBAAsB,CAAC;IAClC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,EAAE,kBAAkB,CAAC;IAC9B,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,GAAG,EAAE,YAAY,CAAC;IAClB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,QAAQ,EAAE,iBAAiB,CAAC;CAC5B;AAED,UAAU,cAAc;IACvB,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,aAAa,EAAE,qBAAqB,CAAC;IACrC,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,YAAY,EAAE,mBAAmB,CAAC;IAClC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,WAAW,EAAE,mBAAmB,CAAC;IACjC,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,YAAY,CAAC;IACnB,YAAY,EAAE,mBAAmB,CAAC;IAClC,uBAAuB,EAAE,8BAA8B,CAAC;IACxD,GAAG,EAAE,WAAW,CAAC;IACjB,aAAa,EAAE,oBAAoB,CAAC;IACpC,YAAY,EAAE,mBAAmB,CAAC;IAClC,gBAAgB,EAAE,sBAAsB,CAAC;IACzC,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,kBAAkB,CAAC;IAChC,MAAM,EAAE,cAAc,CAAC;IACvB,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,cAAc,EAAE,qBAAqB,CAAC;CACtC;AAYD,eAAO,MAAM,WAAW,UATR,SAAS,KAAG,KAAK,IAAI,eAAe,aASF,CAAC;AACnD,eAAO,MAAM,SAAS,UAVN,SAAS,KAAG,KAAK,IAAI,eAAe,WAUN,CAAC;AAC/C,eAAO,MAAM,cAAc,UAXX,SAAS,KAAG,KAAK,IAAI,eAAe,OAWL,CAAC;AAChD,eAAO,MAAM,QAAQ,UAZL,SAAS,KAAG,KAAK,IAAI,eAAe,UAYR,CAAC;AAC7C,eAAO,MAAM,SAAS,UAbN,SAAS,KAAG,KAAK,IAAI,eAAe,WAaN,CAAC;AAC/C,eAAO,MAAM,WAAW,UAdR,SAAS,KAAG,KAAK,IAAI,eAAe,2BAcY,CAAC;AACjE,eAAO,MAAM,aAAa,UAfV,SAAS,KAAG,KAAK,IAAI,eAAe,UAeH,CAAC;AAClD,eAAO,MAAM,MAAM,UAhBH,SAAS,KAAG,KAAK,IAAI,eAAe,QAgBZ,CAAC;AACzC,eAAO,MAAM,YAAY,UAjBT,SAAS,KAAG,KAAK,IAAI,eAAe,cAiBA,CAAC;AACrD,eAAO,MAAM,WAAW,UAlBR,SAAS,KAAG,KAAK,IAAI,eAAe,aAkBF,CAAC;AACnD,eAAO,MAAM,SAAS,UAnBN,SAAS,KAAG,KAAK,IAAI,eAAe,WAmBN,CAAC;AAC/C,eAAO,MAAM,WAAW,UApBR,SAAS,KAAG,KAAK,IAAI,eAAe,aAoBF,CAAC;AACnD,eAAO,MAAM,OAAO,UArBJ,SAAS,KAAG,KAAK,IAAI,eAAe,SAqBV,CAAC;AAC3C,eAAO,MAAM,SAAS,UAtBN,SAAS,KAAG,KAAK,IAAI,eAAe,WAsBN,CAAC;AAC/C,eAAO,MAAM,KAAK,UAvBF,SAAS,KAAG,KAAK,IAAI,eAAe,OAuBd,CAAC;AACvC,eAAO,MAAM,WAAW,UAxBR,SAAS,KAAG,KAAK,IAAI,eAAe,aAwBF,CAAC;AACnD,eAAO,MAAM,OAAO,UAzBJ,SAAS,KAAG,KAAK,IAAI,eAAe,SAyBV,CAAC;AAC3C,eAAO,MAAM,OAAO,UA1BJ,SAAS,KAAG,KAAK,IAAI,eAAe,SA0BV,CAAC;AAC3C,eAAO,MAAM,OAAO,UA3BJ,SAAS,KAAG,KAAK,IAAI,eAAe,SA2BV,CAAC;AAC3C,eAAO,MAAM,WAAW,UA5BR,SAAS,KAAG,KAAK,IAAI,eAAe,cA4BD,CAAC;AACpD,eAAO,MAAM,UAAU,UA7BP,SAAS,KAAG,KAAK,IAAI,eAAe,YA6BJ,CAAC;AAIjD,eAAO,MAAM,MAAM,SA7BJ,QAAQ,KAAG,IAAI,IAAI,cAAc,QA6BT,CAAC;AACxC,eAAO,MAAM,QAAQ,SA9BN,QAAQ,KAAG,IAAI,IAAI,cAAc,UA8BL,CAAC;AAC5C,eAAO,MAAM,WAAW,SA/BT,QAAQ,KAAG,IAAI,IAAI,cAAc,aA+BC,CAAC;AAClD,eAAO,MAAM,eAAe,SAhCb,QAAQ,KAAG,IAAI,IAAI,cAAc,iBAgCS,CAAC;AAC1D,eAAO,MAAM,aAAa,SAjCX,QAAQ,KAAG,IAAI,IAAI,cAAc,WAiCC,CAAC;AAClD,eAAO,MAAM,UAAU,SAlCR,QAAQ,KAAG,IAAI,IAAI,cAAc,aAkCA,CAAC;AACjD,eAAO,MAAM,aAAa,SAnCX,QAAQ,KAAG,IAAI,IAAI,cAAc,gBAmCM,CAAC;AACvD,eAAO,MAAM,WAAW,SApCT,QAAQ,KAAG,IAAI,IAAI,cAAc,aAoCC,CAAC;AAClD,eAAO,MAAM,aAAa,SArCX,QAAQ,KAAG,IAAI,IAAI,cAAc,eAqCK,CAAC;AACtD,eAAO,MAAM,QAAQ,SAtCN,QAAQ,KAAG,IAAI,IAAI,cAAc,UAsCL,CAAC;AAC5C,eAAO,MAAM,UAAU,SAvCR,QAAQ,KAAG,IAAI,IAAI,cAAc,QAuCL,CAAC;AAC5C,eAAO,MAAM,aAAa,SAxCX,QAAQ,KAAG,IAAI,IAAI,cAAc,gBAwCM,CAAC;AACvD,eAAO,MAAM,UAAU,SAzCR,QAAQ,KAAG,IAAI,IAAI,cAAc,2BAyCc,CAAC;AAC/D,eAAO,MAAM,SAAS,SA1CP,QAAQ,KAAG,IAAI,IAAI,cAAc,OA0CP,CAAC;AAC1C,eAAO,MAAM,cAAc,SA3CZ,QAAQ,KAAG,IAAI,IAAI,cAAc,iBA2CQ,CAAC;AACzD,eAAO,MAAM,aAAa,SA5CX,QAAQ,KAAG,IAAI,IAAI,cAAc,gBA4CM,CAAC;AACvD,eAAO,MAAM,gBAAgB,SA7Cd,QAAQ,KAAG,IAAI,IAAI,cAAc,oBA6Ca,CAAC;AAC9D,eAAO,MAAM,aAAa,SA9CX,QAAQ,KAAG,IAAI,IAAI,cAAc,WA8CC,CAAC;AAClD,eAAO,MAAM,SAAS,SA/CP,QAAQ,KAAG,IAAI,IAAI,cAAc,WA+CH,CAAC;AAC9C,eAAO,MAAM,SAAS,SAhDP,QAAQ,KAAG,IAAI,IAAI,cAAc,WAgDH,CAAC;AAC9C,eAAO,MAAM,YAAY,SAjDV,QAAQ,KAAG,IAAI,IAAI,cAAc,eAiDI,CAAC;AACrD,eAAO,MAAM,YAAY,SAlDV,QAAQ,KAAG,IAAI,IAAI,cAAc,UAkDD,CAAC;AAChD,eAAO,MAAM,YAAY,SAnDV,QAAQ,KAAG,IAAI,IAAI,cAAc,eAmDI,CAAC;AACrD,eAAO,MAAM,WAAW,SApDT,QAAQ,KAAG,IAAI,IAAI,cAAc,aAoDC,CAAC;AAClD,eAAO,MAAM,eAAe,SArDb,QAAQ,KAAG,IAAI,IAAI,cAAc,kBAqDU,CAAC"}
package/lib/guards.js ADDED
@@ -0,0 +1,55 @@
1
+ function blockGuard(type) {
2
+ return (block) => block.type === type;
3
+ }
4
+ function textGuard(type) {
5
+ return (text) => text.type === type;
6
+ }
7
+ // --- RichBlock (21 variants) — one guard per `.type` discriminant ---
8
+ export const isParagraph = blockGuard("paragraph");
9
+ export const isHeading = blockGuard("heading");
10
+ export const isPreformatted = blockGuard("pre");
11
+ export const isFooter = blockGuard("footer");
12
+ export const isDivider = blockGuard("divider");
13
+ export const isMathBlock = blockGuard("mathematical_expression");
14
+ export const isAnchorBlock = blockGuard("anchor");
15
+ export const isList = blockGuard("list");
16
+ export const isBlockquote = blockGuard("blockquote");
17
+ export const isPullquote = blockGuard("pullquote");
18
+ export const isCollage = blockGuard("collage");
19
+ export const isSlideshow = blockGuard("slideshow");
20
+ export const isTable = blockGuard("table");
21
+ export const isDetails = blockGuard("details");
22
+ export const isMap = blockGuard("map");
23
+ export const isAnimation = blockGuard("animation");
24
+ export const isAudio = blockGuard("audio");
25
+ export const isPhoto = blockGuard("photo");
26
+ export const isVideo = blockGuard("video");
27
+ export const isVoiceNote = blockGuard("voice_note");
28
+ export const isThinking = blockGuard("thinking");
29
+ // --- RichText (25 variants) ---
30
+ export const isBold = textGuard("bold");
31
+ export const isItalic = textGuard("italic");
32
+ export const isUnderline = textGuard("underline");
33
+ export const isStrikethrough = textGuard("strikethrough");
34
+ export const isSpoilerText = textGuard("spoiler");
35
+ export const isDateTime = textGuard("date_time");
36
+ export const isTextMention = textGuard("text_mention");
37
+ export const isSubscript = textGuard("subscript");
38
+ export const isSuperscript = textGuard("superscript");
39
+ export const isMarked = textGuard("marked");
40
+ export const isCodeText = textGuard("code");
41
+ export const isCustomEmoji = textGuard("custom_emoji");
42
+ export const isMathText = textGuard("mathematical_expression");
43
+ export const isUrlText = textGuard("url");
44
+ export const isEmailAddress = textGuard("email_address");
45
+ export const isPhoneNumber = textGuard("phone_number");
46
+ export const isBankCardNumber = textGuard("bank_card_number");
47
+ export const isMentionText = textGuard("mention");
48
+ export const isHashtag = textGuard("hashtag");
49
+ export const isCashtag = textGuard("cashtag");
50
+ export const isBotCommand = textGuard("bot_command");
51
+ export const isAnchorText = textGuard("anchor");
52
+ export const isAnchorLink = textGuard("anchor_link");
53
+ export const isReference = textGuard("reference");
54
+ export const isReferenceLink = textGuard("reference_link");
55
+ //# sourceMappingURL=guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.js","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @yaebal/rich — telegram's `sendRichMessage` / `sendRichMessageDraft`.
3
+ *
4
+ * unlike classic `parse_mode`/entities (see `@yaebal/fmt`), a rich message is a
5
+ * block-tree document: you write extended html (or markdown) once, telegram
6
+ * parses it server-side, and you get the same tree back on `message.rich_message`.
7
+ * this package covers all three parts of that surface:
8
+ *
9
+ * - **write**: `document()` + block builders (blocks.ts) and inline mark builders
10
+ * (inline.ts) assemble an `InputRichMessage` without hand-written angle brackets.
11
+ * - **stream**: `RichMessageDraft` (draft.ts) owns the fiddly part of
12
+ * `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.
15
+ * - **read**: type guards (guards.ts) and plain-text flattening (plaintext.ts)
16
+ * cover every `RichBlock`/`RichText` variant telegram can hand back.
17
+ *
18
+ * a handful of inline/block tags have no "corresponding to the html tag …" note in
19
+ * the schema (marked, subscript, superscript, date_time, inline math, map,
20
+ * reference/reference_link, table borders) — those are flagged best-effort in
21
+ * their doc comments in inline.ts/blocks.ts. everything else is either a
22
+ * documented tag or (for url/email/phone/bank-card/@mention/#hashtag/$cashtag/
23
+ * /bot_command) auto-detected from plain text by telegram itself.
24
+ */
25
+ 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";
27
+ 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";
31
+ export { richBlockToPlainText, richMessageToPlainText, richTextToPlainText } from "./plaintext.js";
32
+ export { type RichContext, rich, sendRichMessage, sendRichMessageDraft, } from "./send.js";
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/lib/index.js ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @yaebal/rich — telegram's `sendRichMessage` / `sendRichMessageDraft`.
3
+ *
4
+ * unlike classic `parse_mode`/entities (see `@yaebal/fmt`), a rich message is a
5
+ * block-tree document: you write extended html (or markdown) once, telegram
6
+ * parses it server-side, and you get the same tree back on `message.rich_message`.
7
+ * this package covers all three parts of that surface:
8
+ *
9
+ * - **write**: `document()` + block builders (blocks.ts) and inline mark builders
10
+ * (inline.ts) assemble an `InputRichMessage` without hand-written angle brackets.
11
+ * - **stream**: `RichMessageDraft` (draft.ts) owns the fiddly part of
12
+ * `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.
15
+ * - **read**: type guards (guards.ts) and plain-text flattening (plaintext.ts)
16
+ * cover every `RichBlock`/`RichText` variant telegram can hand back.
17
+ *
18
+ * a handful of inline/block tags have no "corresponding to the html tag …" note in
19
+ * the schema (marked, subscript, superscript, date_time, inline math, map,
20
+ * reference/reference_link, table borders) — those are flagged best-effort in
21
+ * their doc comments in inline.ts/blocks.ts. everything else is either a
22
+ * documented tag or (for url/email/phone/bank-card/@mention/#hashtag/$cashtag/
23
+ * /bot_command) auto-detected from plain text by telegram itself.
24
+ */
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";
26
+ 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";
30
+ export { richBlockToPlainText, richMessageToPlainText, richTextToPlainText } from "./plaintext.js";
31
+ export { rich, sendRichMessage, sendRichMessageDraft, } from "./send.js";
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,130 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
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
+ });
48
+ test("sendRichMessage posts chat_id + rich_message to the raw api", async () => {
49
+ const api = mockApi();
50
+ 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
+ ]);
57
+ });
58
+ test("sendRichMessageDraft posts draft_id alongside chat_id + rich_message", async () => {
59
+ const api = mockApi();
60
+ 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
+ ]);
67
+ });
68
+ test("rich() plugin decorates ctx.sendRichMessage bound to the current chat", async () => {
69
+ const api = mockApi();
70
+ const composer = new Composer().install(rich());
71
+ const ctx = new Context({
72
+ api,
73
+ update: {
74
+ update_id: 1,
75
+ message: { message_id: 1, date: 0, chat: { id: 5, type: "private" } },
76
+ },
77
+ updateType: "message",
78
+ });
79
+ await composer.toMiddleware()(ctx, async () => { });
80
+ const decorated = ctx;
81
+ 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
+ ]);
86
+ const draft = decorated.richMessageDraft(1);
87
+ assert.ok(draft instanceof RichMessageDraft);
88
+ });
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" }] }],
125
+ },
126
+ ],
127
+ };
128
+ assert.equal(richMessageToPlainText(message), "title\nhi there\n---\n- one");
129
+ });
130
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ import type { User } from "@yaebal/core";
2
+ /**
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.
38
+ */
39
+ export declare function customEmoji(emojiId: string, fallback: string): RichNode;
40
+ /**
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`.
43
+ * for `@username` mentions (`RichTextMention`), just write `@username` as plain
44
+ * text — the schema lists it as auto-detected (see `skipEntityDetection`).
45
+ */
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="…">`. */
50
+ export declare function anchor(name: string): RichNode;
51
+ /**
52
+ * `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).
54
+ */
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;
62
+ /**
63
+ * `RichTextMathematicalExpression` (inline), best-effort `<tg-math>` (the block
64
+ * form is confirmed as `<tg-math-block>` — see `mathBlock` in blocks.ts).
65
+ */
66
+ export declare function math(expression: string): RichNode;
67
+ /**
68
+ * `RichTextDateTime`, best-effort `<time>`. `format` is telegram's date-time
69
+ * entity format string; attribute name is a guess (`data-format`).
70
+ */
71
+ export declare function dateTime(unixTime: number, format: string, ...children: Insertable[]): RichNode;
72
+ /**
73
+ * `RichTextReference`, a footnote definition. no tag is documented anywhere in
74
+ * the scraped schema — this is a from-scratch `tg-*`-style guess.
75
+ */
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;
79
+ //# sourceMappingURL=inline.d.ts.map
@@ -0,0 +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"}
package/lib/inline.js ADDED
@@ -0,0 +1,120 @@
1
+ import { escapeAttr, escapeText } from "./escape.js";
2
+ export function isRichNode(value) {
3
+ return (typeof value === "object" && value !== null && typeof value.html === "string");
4
+ }
5
+ /** render one interpolation: a `RichNode` is spliced raw, anything else is escaped text. */
6
+ export function toHtml(value) {
7
+ if (isRichNode(value))
8
+ return value.html;
9
+ return value == null ? "" : escapeText(String(value));
10
+ }
11
+ function join(children) {
12
+ return children.map(toHtml).join("");
13
+ }
14
+ function wrap(tag) {
15
+ return (...children) => ({ html: `<${tag}>${join(children)}</${tag}>` });
16
+ }
17
+ /**
18
+ * an extended-html template: interpolations are auto-escaped (never re-parsed as
19
+ * markup), and a nested `RichNode` (from these builders, or another `html`
20
+ * template) is spliced in raw. mirrors `@yaebal/fmt`'s `html` tag, but for the
21
+ * rich-message dialect instead of the classic entity one.
22
+ */
23
+ export function html(strings, ...subs) {
24
+ let out = "";
25
+ for (let i = 0; i < strings.length; i++) {
26
+ out += strings[i] ?? "";
27
+ if (i < subs.length)
28
+ out += toHtml(subs[i]);
29
+ }
30
+ return { html: out };
31
+ }
32
+ // --- inline marks — confirmed tags (same dialect as classic parse_mode html) ---
33
+ /** `RichTextBold`, `<b>`. */
34
+ export const bold = wrap("b");
35
+ /** `RichTextItalic`, `<i>`. */
36
+ export const italic = wrap("i");
37
+ /** `RichTextUnderline`, `<u>`. */
38
+ export const underline = wrap("u");
39
+ /** `RichTextStrikethrough`, `<s>`. */
40
+ export const strikethrough = wrap("s");
41
+ /** `RichTextSpoiler`, `<tg-spoiler>`. */
42
+ export const spoiler = wrap("tg-spoiler");
43
+ /** `RichTextCode`, `<code>`. */
44
+ export const code = wrap("code");
45
+ /**
46
+ * `RichTextCustomEmoji`, `<tg-emoji emoji-id="…">`. same custom tag classic
47
+ * `parse_mode: "HTML"` uses for custom emoji — telegram documents it as reused
48
+ * verbatim here. `fallback` is the plain emoji shown where custom emoji can't render.
49
+ */
50
+ export function customEmoji(emojiId, fallback) {
51
+ return { html: `<tg-emoji emoji-id="${escapeAttr(emojiId)}">${escapeText(fallback)}</tg-emoji>` };
52
+ }
53
+ /**
54
+ * `RichTextTextMention`, a mention of a user who may have no `@username` — same
55
+ * `tg://user?id=…` link telegram's classic html dialect uses for `text_mention`.
56
+ * for `@username` mentions (`RichTextMention`), just write `@username` as plain
57
+ * text — the schema lists it as auto-detected (see `skipEntityDetection`).
58
+ */
59
+ export function textMention(user, ...children) {
60
+ return { html: `<a href="tg://user?id=${user.id}">${join(children)}</a>` };
61
+ }
62
+ /** `RichTextUrl`, an explicit link. for a bare auto-linked url, just write it as plain text. */
63
+ export function link(url, ...children) {
64
+ return { html: `<a href="${escapeAttr(url)}">${join(children)}</a>` };
65
+ }
66
+ /** `RichTextAnchor` (inline form) — a named jump target, `<a name="…">`. */
67
+ export function anchor(name) {
68
+ return { html: `<a name="${escapeAttr(name)}"></a>` };
69
+ }
70
+ /**
71
+ * `RichTextAnchorLink`, a link to an `anchor()` elsewhere in the message —
72
+ * `<a href="#name">`. an empty `name` jumps back to the top (per the schema).
73
+ */
74
+ export function anchorLink(name, ...children) {
75
+ return { html: `<a href="#${escapeAttr(name)}">${join(children)}</a>` };
76
+ }
77
+ // --- inline marks — best-effort tags ---
78
+ //
79
+ // telegram's schema names these types and their fields, but (as scraped) does not
80
+ // state an explicit "corresponding to the html tag …" for them the way it does for
81
+ // bold/italic/code/etc above. the guesses below follow telegram's own pattern of
82
+ // reusing standard html5 semantics (sub/sup/mark/time) or its `tg-*` custom-tag
83
+ // convention — verify against the live "rich message formatting options" docs
84
+ // before depending on the exact tag/attribute spelling in production.
85
+ /** `RichTextMarked`, best-effort `<mark>` (standard html5 highlight). */
86
+ export const marked = wrap("mark");
87
+ /** `RichTextSubscript`, best-effort `<sub>`. */
88
+ export const subscript = wrap("sub");
89
+ /** `RichTextSuperscript`, best-effort `<sup>`. */
90
+ export const superscript = wrap("sup");
91
+ /**
92
+ * `RichTextMathematicalExpression` (inline), best-effort `<tg-math>` (the block
93
+ * form is confirmed as `<tg-math-block>` — see `mathBlock` in blocks.ts).
94
+ */
95
+ export function math(expression) {
96
+ return { html: `<tg-math>${escapeText(expression)}</tg-math>` };
97
+ }
98
+ /**
99
+ * `RichTextDateTime`, best-effort `<time>`. `format` is telegram's date-time
100
+ * entity format string; attribute name is a guess (`data-format`).
101
+ */
102
+ export function dateTime(unixTime, format, ...children) {
103
+ return {
104
+ html: `<time datetime="${unixTime}" data-format="${escapeAttr(format)}">${join(children)}</time>`,
105
+ };
106
+ }
107
+ /**
108
+ * `RichTextReference`, a footnote definition. no tag is documented anywhere in
109
+ * the scraped schema — this is a from-scratch `tg-*`-style guess.
110
+ */
111
+ export function reference(name, ...children) {
112
+ return { html: `<tg-reference name="${escapeAttr(name)}">${join(children)}</tg-reference>` };
113
+ }
114
+ /** `RichTextReferenceLink`, a link to a `reference()`. same caveat as `reference`. */
115
+ export function referenceLink(name, ...children) {
116
+ return {
117
+ html: `<tg-reference-link name="${escapeAttr(name)}">${join(children)}</tg-reference-link>`,
118
+ };
119
+ }
120
+ //# sourceMappingURL=inline.js.map