Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ out/
package-lock.json
bun.lock
*.tgz
package
78 changes: 39 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ It is built directly on grammY's own [`grammy/types`](https://grammy.dev), so bu
## Installation

```sh
npm i grammy-rich-messages
npm i @grammyjs/format
```

`grammy` is a peer dependency; install it alongside this library when sending messages through a bot.
Expand All @@ -24,23 +24,23 @@ npm i grammy-rich-messages
On Deno, import from `denopkg.com`:

```ts
import { richMessage } from "https://denopkg.com/roziscoding/grammy-rich-messages/src/core.ts";
import { richMessage } from "https://denopkg.com/roziscoding/@grammyjs/format/src/core.ts";
```

If you prefer package-style specifiers, add optional aliases for the surfaces you use in `deno.jsonc`:

```jsonc
{
"imports": {
"grammy-rich-messages/core": "https://denopkg.com/roziscoding/grammy-rich-messages/src/core.ts",
"grammy-rich-messages/components": "https://denopkg.com/roziscoding/grammy-rich-messages/src/components.ts",
"grammy-rich-messages/chaining": "https://denopkg.com/roziscoding/grammy-rich-messages/src/chaining.ts"
}
"@grammyjs/format/core": "https://denopkg.com/roziscoding/@grammyjs/format/src/core.ts",
"@grammyjs/format/components": "https://denopkg.com/roziscoding/@grammyjs/format/src/components.ts",
"@grammyjs/format/chaining": "https://denopkg.com/roziscoding/@grammyjs/format/src/chaining.ts",
},
}
```

```ts
import { richMessage } from "grammy-rich-messages/core";
import { richMessage } from "@grammyjs/format/core";
```

The examples below use these package-style specifiers; on Deno, either add the matching aliases or import the `src/` entrypoints directly from `denopkg.com`.
Expand All @@ -51,7 +51,7 @@ This library only builds the message object. grammY already exposes the Bot API'

```tsx
import { Bot } from "grammy";
import { Bold, Paragraph, richMessage } from "grammy-rich-messages/components";
import { Bold, Paragraph, richMessage } from "@grammyjs/format/components";

const bot = new Bot(process.env.TELEGRAM_TOKEN!);

Expand All @@ -62,7 +62,8 @@ bot.command("start", (ctx) =>
Hello, <Bold>{ctx.from?.first_name ?? "there"}!</Bold>
</Paragraph>,
),
));
),
);

bot.start();
```
Expand Down Expand Up @@ -90,7 +91,7 @@ import {
table,
tableCell,
tableRow,
} from "grammy-rich-messages/core";
} from "@grammyjs/format/core";

const message = richMessage(
heading({ size: 1 }, "Build report"),
Expand Down Expand Up @@ -122,8 +123,8 @@ The same checks run at runtime for plain JavaScript and for values coming from `
### Chaining

```ts
import { RichMessage } from "grammy-rich-messages/chaining";
import { bold } from "grammy-rich-messages/core";
import { RichMessage } from "@grammyjs/format/chaining";
import { bold } from "@grammyjs/format/core";

const results = [
{ model: "Aster-1", score: 98.4 },
Expand All @@ -133,19 +134,18 @@ const results = [
const message = new RichMessage({ skipEntityDetection: true })
.heading("Build report", { size: 1 })
.paragraph("Status: ", bold("green"))
.table(
{ bordered: true, caption: "Benchmark" },
(table) =>
table
.row((row) =>
row
.cell("Model", { header: true })
.cell("Score", { header: true, align: "right" })
)
.rows(results, (row, result) =>
row
.cell(result.model)
.cell(bold(result.score), { align: "right" })),
.table({ bordered: true, caption: "Benchmark" }, (table) =>
table
.row((row) =>
row
.cell("Model", { header: true })
.cell("Score", { header: true, align: "right" }),
)
.rows(results, (row, result) =>
row
.cell(result.model)
.cell(bold(result.score), { align: "right" }),
),
);
```

Expand All @@ -159,7 +159,7 @@ Point TypeScript at the library's JSX runtime — no React required.
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "grammy-rich-messages/jsx"
"jsxImportSource": "@grammyjs/format/jsx"
}
}
```
Expand All @@ -169,12 +169,12 @@ For Deno, add the JSX runtime import alias so the compiler can resolve `jsxImpor
```jsonc
{
"imports": {
"grammy-rich-messages/jsx/jsx-runtime": "https://denopkg.com/roziscoding/grammy-rich-messages/src/components/jsx-runtime.ts"
}
"@grammyjs/format/jsx/jsx-runtime": "https://denopkg.com/roziscoding/@grammyjs/format/src/components/jsx-runtime.ts",
},
}
```

`jsxImportSource` only tells the compiler where the JSX runtime lives; the components themselves come from `grammy-rich-messages/components`, or `https://denopkg.com/roziscoding/grammy-rich-messages/src/components.ts` on Deno if you did not add the optional [`components` alias](#deno):
`jsxImportSource` only tells the compiler where the JSX runtime lives; the components themselves come from `@grammyjs/format/components`, or `https://denopkg.com/roziscoding/@grammyjs/format/src/components.ts` on Deno if you did not add the optional [`components` alias](#deno):

```tsx
import {
Expand All @@ -185,7 +185,7 @@ import {
Table,
TableCell,
TableRow,
} from "grammy-rich-messages/components";
} from "@grammyjs/format/components";

const message = richMessage(
{ skipEntityDetection: true },
Expand Down Expand Up @@ -213,8 +213,8 @@ const message = richMessage(
Functional values can go straight into TSX, and vice versa:

```tsx
import { bold, table, tableCell, tableRow } from "grammy-rich-messages/core";
import { Paragraph, richMessage } from "grammy-rich-messages/components";
import { bold, table, tableCell, tableRow } from "@grammyjs/format/core";
import { Paragraph, richMessage } from "@grammyjs/format/components";

richMessage(
<Paragraph>Generated with TSX.</Paragraph>,
Expand All @@ -228,12 +228,12 @@ richMessage(
TypeScript widens JSX expressions to `JSX.Element`, so a JSX value entering a strict functional boundary needs a runtime narrowing guard:

```tsx
import { table } from "grammy-rich-messages/core";
import { table } from "@grammyjs/format/core";
import {
expectTableRow,
TableCell,
TableRow,
} from "grammy-rich-messages/components";
} from "@grammyjs/format/components";

const row = (
<TableRow>
Expand All @@ -248,11 +248,11 @@ The guards — `expectRichText`, `expectBlock`, `expectListItem`, `expectTableRo

## Entrypoints

| Entrypoint | Exports |
| --------------------------------- | ------------------------------------------------------------------- |
| `grammy-rich-messages/core` | Functional builders, the `richMessage` root, and the Telegram types |
| `grammy-rich-messages/components` | TSX components, the `richMessage` root, and narrowing guards |
| `grammy-rich-messages/chaining` | `RichMessage`, `TableBuilder`, and `TableRowBuilder` |
| Entrypoint | Exports |
| ----------------------------- | ------------------------------------------------------------------- |
| `@grammyjs/format/core` | Functional builders, the `richMessage` root, and the Telegram types |
| `@grammyjs/format/components` | TSX components, the `richMessage` root, and narrowing guards |
| `@grammyjs/format/chaining` | `RichMessage`, `TableBuilder`, and `TableRowBuilder` |

On Deno, these same specifiers work if you add the optional aliases shown in [Deno setup](#deno). Otherwise, import the matching source modules directly from `denopkg.com`: `src/core.ts`, `src/components.ts`, and `src/chaining.ts`.

Expand Down
38 changes: 22 additions & 16 deletions deno.jsonc
Original file line number Diff line number Diff line change
@@ -1,34 +1,40 @@
{
"name": "@grammyjs/format",
"version": "0.0.1-beta.1",
"exports": {
"./chaining": "./src/chaining.ts",
"./components": "./src/components.ts",
"./core": "./src/core.ts",
"./jsx/jsx-runtime": "./src/components/jsx-runtime.ts",
"./jsx/jsx-dev-runtime": "./src/components/jsx-runtime.ts"
},
"lock": false,
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "grammy-rich-messages/jsx"
"jsxImportSource": "@grammyjs/format/jsx"
},
"imports": {
"grammy-rich-messages/jsx/jsx-runtime": "./src/components/jsx-runtime.ts",
"grammy-rich-messages/jsx/jsx-dev-runtime": "./src/components/jsx-runtime.ts",
"@grammyjs/format/jsx/jsx-runtime": "./src/components/jsx-runtime.ts",
"@grammyjs/format/jsx/jsx-dev-runtime": "./src/components/jsx-runtime.ts",
"@std/expect": "jsr:@std/expect@^1",
"@std/testing": "jsr:@std/testing@^1"
"@std/testing": "jsr:@std/testing@^1",
"grammy": "npm:grammy@^1.45.1"
},
"tasks": {
"check": "deno check --allow-import src/core.ts src/components.ts src/chaining.ts test/ examples/",
"test": "deno test --allow-import",
"ok": "deno fmt --check && deno lint && deno task test && deno task check"
"ok": "deno fmt --check && deno lint && deno task test && deno task check",
"drypack": "deno pack --allow-dirty --dry-run src",
"pack": "deno pack --allow-dirty src"
},
"fmt": {
"indentWidth": 4,
"proseWrap": "preserve",
"exclude": [
"./node_modules/",
"./out/",
"./package-lock.json"
]
"proseWrap": "preserve"
},
"lint": {
"exclude": [
"./node_modules/",
"./out/",
"./package-lock.json"
]
"exclude": ["./node_modules/", "./out/", "./package-lock.json"],
"rules": {
"exclude": ["explicit-function-return-type"]
}
}
}
3 changes: 1 addition & 2 deletions examples/bot.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// deno-lint-ignore-file no-import-prefix -- grammy pulled directly from denopkg in the example
import { Bot } from "https://denopkg.com/grammyjs/grammY@v1.45.1/src/mod.ts";
import { Bot } from "grammy";
import {
Bold,
Divider,
Expand Down
2 changes: 1 addition & 1 deletion examples/chaining/simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ import { RichMessage } from "../../src/chaining.ts";
// core entrypoint.
export const simple = new RichMessage()
.heading("Welcome", { size: 1 })
.paragraph("Hello from ", bold("grammy-rich-messages"), ".");
.paragraph("Hello from ", bold("@grammyjs/format"), ".");

export const simpleJson = JSON.stringify(simple);
2 changes: 1 addition & 1 deletion examples/components/simple.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Bold, Heading, Paragraph, richMessage } from "../../src/components.ts";
export const simple = richMessage(
<Heading size={1}>Welcome</Heading>,
<Paragraph>
Hello from <Bold>grammy-rich-messages</Bold>.
Hello from <Bold>@grammyjs/format</Bold>.
</Paragraph>,
);

Expand Down
2 changes: 1 addition & 1 deletion examples/core/simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { bold, heading, paragraph, richMessage } from "../../src/core.ts";
// builder accepts as a child.
export const simple = richMessage(
heading({ size: 1 }, "Welcome"),
paragraph("Hello from ", bold("grammy-rich-messages"), "."),
paragraph("Hello from ", bold("@grammyjs/format"), "."),
);

export const simpleJson = JSON.stringify(simple);
32 changes: 32 additions & 0 deletions examples/core/slideshow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Bot } from "grammy";
import { divider, photo, richMessage, slideshow } from "../../src/core.ts";

const bot = new Bot(process.env.BOT_TOKEN!);

type DbImage = { src: string };

function buildCaption(images: DbImage[]) {
if (images.length <= 50) return;
const notSentImages = images.slice(50).map((p) => p.src).join("\n");
return ["Not sent", "\n\n", notSentImages].join("\n");
}

function buildSlideshow(images: DbImage[]) {
if (!images.length) return undefined;

const hasMoreThanFiftyImages = images.length > 50;
const caption = buildCaption(images);
const slicedImages = hasMoreThanFiftyImages ? images.slice(0, 50) : images;
const photos = slicedImages.map((p) =>
photo({ media: { type: "photo", media: p.src } })
);

return [
slideshow({ caption }, ...photos),
divider(),
];
}

bot.on("message", (ctx) => {
return ctx.replyWithRichMessage(richMessage(buildSlideshow([])));
});
57 changes: 0 additions & 57 deletions package.json

This file was deleted.

2 changes: 1 addition & 1 deletion src/chaining/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {
cloneValue,
type RichMessageValue,
} from "../core/values.ts";
import type { InputRichMessage } from "../deps.deno.ts";
import type { InputRichMessage } from "grammy/types";
import { TableBuilder, type TableConfigurator } from "./table.ts";

/**
Expand Down
2 changes: 1 addition & 1 deletion src/chaining/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
type TableCellValue,
type TableRowValue,
} from "../core/values.ts";
import type { InputRichBlockTable } from "../deps.deno.ts";
import type { InputRichBlockTable } from "grammy/types";

/**
* Callback that populates a {@link TableRowBuilder}. Receives the row builder
Expand Down
Loading
Loading