feat(DIS-105): codeblock-aware message splitting for Discord 2000-char limit #47
2 changed files with 26 additions and 1 deletions
|
|
@ -28,6 +28,12 @@ export function splitForDiscord(text: string, limit = 1900): string[] {
|
||||||
let fenceLang = "";
|
let fenceLang = "";
|
||||||
|
|
||||||
const flush = () => {
|
const flush = () => {
|
||||||
|
// Hard-split if current exceeds the Discord hard limit (e.g. because
|
||||||
|
// a fence closure "\n```" was appended after the soft-limit check).
|
||||||
|
while (current.length > DISCORD_HARD_LIMIT) {
|
||||||
|
chunks.push(current.slice(0, DISCORD_HARD_LIMIT));
|
||||||
|
current = current.slice(DISCORD_HARD_LIMIT);
|
||||||
|
}
|
||||||
if (current.length > 0) {
|
if (current.length > 0) {
|
||||||
chunks.push(current);
|
chunks.push(current);
|
||||||
current = "";
|
current = "";
|
||||||
|
|
@ -43,7 +49,10 @@ export function splitForDiscord(text: string, limit = 1900): string[] {
|
||||||
const separator = current.length > 0 ? "\n" : "";
|
const separator = current.length > 0 ? "\n" : "";
|
||||||
const addition = separator + line;
|
const addition = separator + line;
|
||||||
|
|
||||||
if (current.length + addition.length > effectiveLimit) {
|
// Reserve space for a closing fence (``` + newline) when inside a code block
|
||||||
|
const fenceOverhead = inFence ? 4 : 0; // "\n```".length
|
||||||
|
|
||||||
|
if (current.length + addition.length + fenceOverhead > effectiveLimit) {
|
||||||
// Need to flush before adding this line
|
// Need to flush before adding this line
|
||||||
if (inFence) {
|
if (inFence) {
|
||||||
// Close the open fence before flushing
|
// Close the open fence before flushing
|
||||||
|
|
|
||||||
|
|
@ -101,4 +101,20 @@ describe("splitForDiscord", () => {
|
||||||
const idx = result.indexOf(closingChunk!);
|
const idx = result.indexOf(closingChunk!);
|
||||||
expect(result[idx + 1]).toMatch(/^```python/);
|
expect(result[idx + 1]).toMatch(/^```python/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Regression: fence closure "\n```" must not push a chunk beyond the 2000 hard limit
|
||||||
|
it("does not exceed 2000 chars even when fence closure is appended at limit boundary", () => {
|
||||||
|
const fenceOpen = "```typescript\n";
|
||||||
|
// Line long enough that current is near 2000 when fence closure is added
|
||||||
|
const longLine = "x".repeat(1984);
|
||||||
|
const nextLine = "y".repeat(10);
|
||||||
|
const fenceClose = "\n```";
|
||||||
|
|
||||||
|
const text = fenceOpen + longLine + "\n" + nextLine + fenceClose;
|
||||||
|
const result = splitForDiscord(text, 2000);
|
||||||
|
|
||||||
|
for (const chunk of result) {
|
||||||
|
expect(chunk.length).toBeLessThanOrEqual(DISCORD_HARD_LIMIT);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue