devdaily-ai 0.5.0 → 0.6.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.
- package/CHANGELOG.md +203 -0
- package/CONTRIBUTING.md +264 -0
- package/LICENSE +1 -1
- package/README.md +279 -608
- package/dist/index.js +143 -142
- package/dist/index.js.map +1 -1
- package/package.json +10 -5
- package/README.md.bak +0 -595
package/dist/index.js
CHANGED
|
@@ -3386,6 +3386,147 @@ Requirements:
|
|
|
3386
3386
|
}
|
|
3387
3387
|
};
|
|
3388
3388
|
|
|
3389
|
+
// src/utils/formatter.ts
|
|
3390
|
+
function formatOutput(markdown, format = "markdown", meta) {
|
|
3391
|
+
switch (format) {
|
|
3392
|
+
case "plain":
|
|
3393
|
+
return { text: toPlain(markdown), raw: markdown, format };
|
|
3394
|
+
case "slack":
|
|
3395
|
+
return { text: toSlack(markdown), raw: markdown, format };
|
|
3396
|
+
case "json":
|
|
3397
|
+
return { text: toJSON(markdown, meta), raw: markdown, format };
|
|
3398
|
+
case "markdown":
|
|
3399
|
+
default:
|
|
3400
|
+
return { text: markdown, raw: markdown, format };
|
|
3401
|
+
}
|
|
3402
|
+
}
|
|
3403
|
+
function validateFormat(value, fallback = "markdown") {
|
|
3404
|
+
const valid = ["markdown", "slack", "plain", "json"];
|
|
3405
|
+
if (valid.includes(value)) {
|
|
3406
|
+
return value;
|
|
3407
|
+
}
|
|
3408
|
+
return fallback;
|
|
3409
|
+
}
|
|
3410
|
+
function toPlain(md) {
|
|
3411
|
+
let text = md;
|
|
3412
|
+
text = text.replace(/^[ \t]*([-*_]){3,}[ \t]*$/gm, "");
|
|
3413
|
+
text = text.replace(/^#{1,6}\s+(.+)$/gm, (_match, heading) => {
|
|
3414
|
+
const cleaned = heading.trim();
|
|
3415
|
+
if (/[.:!?]$/.test(cleaned)) {
|
|
3416
|
+
return cleaned;
|
|
3417
|
+
}
|
|
3418
|
+
return `${cleaned}:`;
|
|
3419
|
+
});
|
|
3420
|
+
text = text.replace(/\*\*(.+?)\*\*/g, "$1");
|
|
3421
|
+
text = text.replace(/__(.+?)__/g, "$1");
|
|
3422
|
+
text = text.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "$1");
|
|
3423
|
+
text = text.replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, "$1");
|
|
3424
|
+
text = text.replace(/~~(.+?)~~/g, "$1");
|
|
3425
|
+
text = text.replace(/`([^`]+)`/g, "$1");
|
|
3426
|
+
text = text.replace(/```[\s\S]*?\n([\s\S]*?)```/g, "$1");
|
|
3427
|
+
text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1 ($2)");
|
|
3428
|
+
text = text.replace(/!\[([^\]]*)\]\([^)]+\)/g, "[Image: $1]");
|
|
3429
|
+
text = text.replace(/^[ \t]*[-*]\s+/gm, "\u2022 ");
|
|
3430
|
+
text = text.replace(/^>+\s?/gm, "");
|
|
3431
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
3432
|
+
return text.trim();
|
|
3433
|
+
}
|
|
3434
|
+
function toSlack(md) {
|
|
3435
|
+
let text = md;
|
|
3436
|
+
const PH_START = "\uE000";
|
|
3437
|
+
const PH_END = "\uE001";
|
|
3438
|
+
const codeBlocks = [];
|
|
3439
|
+
text = text.replace(/```\w*\n([\s\S]*?)```/g, (_match, code) => {
|
|
3440
|
+
const placeholder = `${PH_START}CB${codeBlocks.length}${PH_END}`;
|
|
3441
|
+
codeBlocks.push("```\n" + code + "```");
|
|
3442
|
+
return placeholder;
|
|
3443
|
+
});
|
|
3444
|
+
const inlineCodes = [];
|
|
3445
|
+
text = text.replace(/`([^`]+)`/g, (_match, code) => {
|
|
3446
|
+
const placeholder = `${PH_START}IC${inlineCodes.length}${PH_END}`;
|
|
3447
|
+
inlineCodes.push("`" + code + "`");
|
|
3448
|
+
return placeholder;
|
|
3449
|
+
});
|
|
3450
|
+
text = text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, "<$2|$1>");
|
|
3451
|
+
text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "<$2|$1>");
|
|
3452
|
+
text = text.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "_$1_");
|
|
3453
|
+
text = text.replace(/\*\*(.+?)\*\*/g, "*$1*");
|
|
3454
|
+
text = text.replace(/(?<!\uE000)__(.+?)__(?!\uE001)/g, "*$1*");
|
|
3455
|
+
text = text.replace(/^#{1,6}\s+(.+)$/gm, "*$1*");
|
|
3456
|
+
text = text.replace(/~~(.+?)~~/g, "~$1~");
|
|
3457
|
+
text = text.replace(/^[ \t]*[-*]\s+/gm, "\u2022 ");
|
|
3458
|
+
text = text.replace(/^[ \t]*([-*_]){3,}[ \t]*$/gm, "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
3459
|
+
for (let i = 0; i < codeBlocks.length; i++) {
|
|
3460
|
+
text = text.replace(`${PH_START}CB${i}${PH_END}`, codeBlocks[i]);
|
|
3461
|
+
}
|
|
3462
|
+
for (let i = 0; i < inlineCodes.length; i++) {
|
|
3463
|
+
text = text.replace(`${PH_START}IC${i}${PH_END}`, inlineCodes[i]);
|
|
3464
|
+
}
|
|
3465
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
3466
|
+
return text.trim();
|
|
3467
|
+
}
|
|
3468
|
+
function toJSON(md, meta) {
|
|
3469
|
+
const sections = parseSections(md);
|
|
3470
|
+
const output = {
|
|
3471
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3472
|
+
};
|
|
3473
|
+
if (meta) {
|
|
3474
|
+
output.meta = { ...meta };
|
|
3475
|
+
}
|
|
3476
|
+
output.sections = sections;
|
|
3477
|
+
output.raw = md;
|
|
3478
|
+
return JSON.stringify(output, null, 2);
|
|
3479
|
+
}
|
|
3480
|
+
function parseSections(md) {
|
|
3481
|
+
const lines = md.split("\n");
|
|
3482
|
+
const sections = [];
|
|
3483
|
+
let current = null;
|
|
3484
|
+
let bodyLines = [];
|
|
3485
|
+
const flushCurrent = () => {
|
|
3486
|
+
if (current) {
|
|
3487
|
+
current.body = bodyLines.join("\n").trim();
|
|
3488
|
+
current.items = extractListItems(current.body);
|
|
3489
|
+
sections.push(current);
|
|
3490
|
+
}
|
|
3491
|
+
};
|
|
3492
|
+
for (const line of lines) {
|
|
3493
|
+
const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
3494
|
+
if (headingMatch) {
|
|
3495
|
+
flushCurrent();
|
|
3496
|
+
current = {
|
|
3497
|
+
heading: headingMatch[2].trim(),
|
|
3498
|
+
level: headingMatch[1].length,
|
|
3499
|
+
items: [],
|
|
3500
|
+
body: ""
|
|
3501
|
+
};
|
|
3502
|
+
bodyLines = [];
|
|
3503
|
+
} else {
|
|
3504
|
+
bodyLines.push(line);
|
|
3505
|
+
}
|
|
3506
|
+
}
|
|
3507
|
+
flushCurrent();
|
|
3508
|
+
if (sections.length === 0 && md.trim().length > 0) {
|
|
3509
|
+
const body = md.trim();
|
|
3510
|
+
sections.push({
|
|
3511
|
+
heading: "Content",
|
|
3512
|
+
level: 0,
|
|
3513
|
+
items: extractListItems(body),
|
|
3514
|
+
body
|
|
3515
|
+
});
|
|
3516
|
+
}
|
|
3517
|
+
return sections;
|
|
3518
|
+
}
|
|
3519
|
+
function extractListItems(body) {
|
|
3520
|
+
const items = [];
|
|
3521
|
+
for (const line of body.split("\n")) {
|
|
3522
|
+
const match = line.match(/^[ \t]*(?:[-*]|\d+[.)]) \s*(.+)$/);
|
|
3523
|
+
if (match) {
|
|
3524
|
+
items.push(match[1].trim());
|
|
3525
|
+
}
|
|
3526
|
+
}
|
|
3527
|
+
return items;
|
|
3528
|
+
}
|
|
3529
|
+
|
|
3389
3530
|
// src/core/notifications.ts
|
|
3390
3531
|
function getTypeEmoji(type) {
|
|
3391
3532
|
switch (type) {
|
|
@@ -3427,11 +3568,12 @@ function formatSlackMessage(message) {
|
|
|
3427
3568
|
}
|
|
3428
3569
|
});
|
|
3429
3570
|
}
|
|
3571
|
+
const slackText = formatOutput(message.text, "slack").text;
|
|
3430
3572
|
blocks.push({
|
|
3431
3573
|
type: "section",
|
|
3432
3574
|
text: {
|
|
3433
3575
|
type: "mrkdwn",
|
|
3434
|
-
text:
|
|
3576
|
+
text: slackText
|
|
3435
3577
|
}
|
|
3436
3578
|
});
|
|
3437
3579
|
if (message.ticketLinks && message.ticketLinks.length > 0) {
|
|
@@ -3988,147 +4130,6 @@ function getWeekEnd(weeksAgo = 0) {
|
|
|
3988
4130
|
return end;
|
|
3989
4131
|
}
|
|
3990
4132
|
|
|
3991
|
-
// src/utils/formatter.ts
|
|
3992
|
-
function formatOutput(markdown, format = "markdown", meta) {
|
|
3993
|
-
switch (format) {
|
|
3994
|
-
case "plain":
|
|
3995
|
-
return { text: toPlain(markdown), raw: markdown, format };
|
|
3996
|
-
case "slack":
|
|
3997
|
-
return { text: toSlack(markdown), raw: markdown, format };
|
|
3998
|
-
case "json":
|
|
3999
|
-
return { text: toJSON(markdown, meta), raw: markdown, format };
|
|
4000
|
-
case "markdown":
|
|
4001
|
-
default:
|
|
4002
|
-
return { text: markdown, raw: markdown, format };
|
|
4003
|
-
}
|
|
4004
|
-
}
|
|
4005
|
-
function validateFormat(value, fallback = "markdown") {
|
|
4006
|
-
const valid = ["markdown", "slack", "plain", "json"];
|
|
4007
|
-
if (valid.includes(value)) {
|
|
4008
|
-
return value;
|
|
4009
|
-
}
|
|
4010
|
-
return fallback;
|
|
4011
|
-
}
|
|
4012
|
-
function toPlain(md) {
|
|
4013
|
-
let text = md;
|
|
4014
|
-
text = text.replace(/^[ \t]*([-*_]){3,}[ \t]*$/gm, "");
|
|
4015
|
-
text = text.replace(/^#{1,6}\s+(.+)$/gm, (_match, heading) => {
|
|
4016
|
-
const cleaned = heading.trim();
|
|
4017
|
-
if (/[.:!?]$/.test(cleaned)) {
|
|
4018
|
-
return cleaned;
|
|
4019
|
-
}
|
|
4020
|
-
return `${cleaned}:`;
|
|
4021
|
-
});
|
|
4022
|
-
text = text.replace(/\*\*(.+?)\*\*/g, "$1");
|
|
4023
|
-
text = text.replace(/__(.+?)__/g, "$1");
|
|
4024
|
-
text = text.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "$1");
|
|
4025
|
-
text = text.replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, "$1");
|
|
4026
|
-
text = text.replace(/~~(.+?)~~/g, "$1");
|
|
4027
|
-
text = text.replace(/`([^`]+)`/g, "$1");
|
|
4028
|
-
text = text.replace(/```[\s\S]*?\n([\s\S]*?)```/g, "$1");
|
|
4029
|
-
text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1 ($2)");
|
|
4030
|
-
text = text.replace(/!\[([^\]]*)\]\([^)]+\)/g, "[Image: $1]");
|
|
4031
|
-
text = text.replace(/^[ \t]*[-*]\s+/gm, "\u2022 ");
|
|
4032
|
-
text = text.replace(/^>+\s?/gm, "");
|
|
4033
|
-
text = text.replace(/\n{3,}/g, "\n\n");
|
|
4034
|
-
return text.trim();
|
|
4035
|
-
}
|
|
4036
|
-
function toSlack(md) {
|
|
4037
|
-
let text = md;
|
|
4038
|
-
const PH_START = "\uE000";
|
|
4039
|
-
const PH_END = "\uE001";
|
|
4040
|
-
const codeBlocks = [];
|
|
4041
|
-
text = text.replace(/```\w*\n([\s\S]*?)```/g, (_match, code) => {
|
|
4042
|
-
const placeholder = `${PH_START}CB${codeBlocks.length}${PH_END}`;
|
|
4043
|
-
codeBlocks.push("```\n" + code + "```");
|
|
4044
|
-
return placeholder;
|
|
4045
|
-
});
|
|
4046
|
-
const inlineCodes = [];
|
|
4047
|
-
text = text.replace(/`([^`]+)`/g, (_match, code) => {
|
|
4048
|
-
const placeholder = `${PH_START}IC${inlineCodes.length}${PH_END}`;
|
|
4049
|
-
inlineCodes.push("`" + code + "`");
|
|
4050
|
-
return placeholder;
|
|
4051
|
-
});
|
|
4052
|
-
text = text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, "<$2|$1>");
|
|
4053
|
-
text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "<$2|$1>");
|
|
4054
|
-
text = text.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "_$1_");
|
|
4055
|
-
text = text.replace(/\*\*(.+?)\*\*/g, "*$1*");
|
|
4056
|
-
text = text.replace(/(?<!\uE000)__(.+?)__(?!\uE001)/g, "*$1*");
|
|
4057
|
-
text = text.replace(/^#{1,6}\s+(.+)$/gm, "*$1*");
|
|
4058
|
-
text = text.replace(/~~(.+?)~~/g, "~$1~");
|
|
4059
|
-
text = text.replace(/^[ \t]*[-*]\s+/gm, "\u2022 ");
|
|
4060
|
-
text = text.replace(/^[ \t]*([-*_]){3,}[ \t]*$/gm, "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
4061
|
-
for (let i = 0; i < codeBlocks.length; i++) {
|
|
4062
|
-
text = text.replace(`${PH_START}CB${i}${PH_END}`, codeBlocks[i]);
|
|
4063
|
-
}
|
|
4064
|
-
for (let i = 0; i < inlineCodes.length; i++) {
|
|
4065
|
-
text = text.replace(`${PH_START}IC${i}${PH_END}`, inlineCodes[i]);
|
|
4066
|
-
}
|
|
4067
|
-
text = text.replace(/\n{3,}/g, "\n\n");
|
|
4068
|
-
return text.trim();
|
|
4069
|
-
}
|
|
4070
|
-
function toJSON(md, meta) {
|
|
4071
|
-
const sections = parseSections(md);
|
|
4072
|
-
const output = {
|
|
4073
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4074
|
-
};
|
|
4075
|
-
if (meta) {
|
|
4076
|
-
output.meta = { ...meta };
|
|
4077
|
-
}
|
|
4078
|
-
output.sections = sections;
|
|
4079
|
-
output.raw = md;
|
|
4080
|
-
return JSON.stringify(output, null, 2);
|
|
4081
|
-
}
|
|
4082
|
-
function parseSections(md) {
|
|
4083
|
-
const lines = md.split("\n");
|
|
4084
|
-
const sections = [];
|
|
4085
|
-
let current = null;
|
|
4086
|
-
let bodyLines = [];
|
|
4087
|
-
const flushCurrent = () => {
|
|
4088
|
-
if (current) {
|
|
4089
|
-
current.body = bodyLines.join("\n").trim();
|
|
4090
|
-
current.items = extractListItems(current.body);
|
|
4091
|
-
sections.push(current);
|
|
4092
|
-
}
|
|
4093
|
-
};
|
|
4094
|
-
for (const line of lines) {
|
|
4095
|
-
const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
4096
|
-
if (headingMatch) {
|
|
4097
|
-
flushCurrent();
|
|
4098
|
-
current = {
|
|
4099
|
-
heading: headingMatch[2].trim(),
|
|
4100
|
-
level: headingMatch[1].length,
|
|
4101
|
-
items: [],
|
|
4102
|
-
body: ""
|
|
4103
|
-
};
|
|
4104
|
-
bodyLines = [];
|
|
4105
|
-
} else {
|
|
4106
|
-
bodyLines.push(line);
|
|
4107
|
-
}
|
|
4108
|
-
}
|
|
4109
|
-
flushCurrent();
|
|
4110
|
-
if (sections.length === 0 && md.trim().length > 0) {
|
|
4111
|
-
const body = md.trim();
|
|
4112
|
-
sections.push({
|
|
4113
|
-
heading: "Content",
|
|
4114
|
-
level: 0,
|
|
4115
|
-
items: extractListItems(body),
|
|
4116
|
-
body
|
|
4117
|
-
});
|
|
4118
|
-
}
|
|
4119
|
-
return sections;
|
|
4120
|
-
}
|
|
4121
|
-
function extractListItems(body) {
|
|
4122
|
-
const items = [];
|
|
4123
|
-
for (const line of body.split("\n")) {
|
|
4124
|
-
const match = line.match(/^[ \t]*(?:[-*]|\d+[.)]) \s*(.+)$/);
|
|
4125
|
-
if (match) {
|
|
4126
|
-
items.push(match[1].trim());
|
|
4127
|
-
}
|
|
4128
|
-
}
|
|
4129
|
-
return items;
|
|
4130
|
-
}
|
|
4131
|
-
|
|
4132
4133
|
// src/core/work-journal.ts
|
|
4133
4134
|
import {
|
|
4134
4135
|
existsSync as existsSync2,
|