@mikitasazan/notify 1.15.1 → 1.15.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.
- package/dist/render.js +44 -14
- package/package.json +1 -1
package/dist/render.js
CHANGED
|
@@ -350,12 +350,28 @@ export const markdownToTelegram = (text) => {
|
|
|
350
350
|
.filter((c) => c !== '')
|
|
351
351
|
.join(' · ');
|
|
352
352
|
}
|
|
353
|
+
// Each replace used to run over the OUTPUT of the previous one, so a tag
|
|
354
|
+
// this function had just written was still visible to the next pattern.
|
|
355
|
+
// Two shapes came out illegal for Telegram, and Telegram answers 4xx to
|
|
356
|
+
// both — the package does not retry a 4xx, so the whole card is lost:
|
|
357
|
+
// `[](url)` — the README badge — became `<a><a>…</a></a>`,
|
|
358
|
+
// `` `a **b** c` `` became `<code>a <b>b</b> c</code>`.
|
|
359
|
+
// A produced tag is therefore parked in `spans` behind a sentinel that no
|
|
360
|
+
// pattern below can match, and put back only after the last replace.
|
|
361
|
+
// `plain` unwraps a parked span to its text, which is how a link label
|
|
362
|
+
// that already holds a link (or code) is flattened instead of nested.
|
|
363
|
+
const spans = [];
|
|
364
|
+
const park = (html) => `\u0000${spans.push(html) - 1}\u0000`;
|
|
365
|
+
const plain = (s) => s.replace(/\u0000(\d+)\u0000/g, (_, i) => spans[Number(i)].replace(/<[^>]+>/g, ''));
|
|
366
|
+
const bold = (s) => s.replace(/\*\*([^*\n]+)\*\*/g, '<b>$1</b>');
|
|
353
367
|
row = row
|
|
354
|
-
|
|
355
|
-
.replace(
|
|
356
|
-
.replace(
|
|
368
|
+
// Code first: nothing inside a `code` span may become a tag.
|
|
369
|
+
.replace(/`([^`\n]+)`/g, (_, code) => park(`<code>${code}</code>`))
|
|
370
|
+
.replace(/!\[([^\]]*)\]\((https?:\/\/[^\s)]+)\)/g, (_, alt, url) => park(`<a href="${url}">${plain(alt).trim() || 'image'}</a>`))
|
|
371
|
+
.replace(/\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g, (_, label, url) => park(`<a href="${url}">${bold(plain(label)).trim() || 'link'}</a>`))
|
|
372
|
+
.replace(/\[([^\]]+)\]\([^)]*\)/g, (_, label) => plain(label))
|
|
357
373
|
.replace(/\*\*([^*\n]+)\*\*/g, '<b>$1</b>')
|
|
358
|
-
.replace(
|
|
374
|
+
.replace(/\u0000(\d+)\u0000/g, (_, i) => spans[Number(i)]);
|
|
359
375
|
out.push(row);
|
|
360
376
|
}
|
|
361
377
|
if (fence) {
|
|
@@ -374,12 +390,20 @@ export const markdownToTelegram = (text) => {
|
|
|
374
390
|
*/
|
|
375
391
|
const firstSection = (text) => {
|
|
376
392
|
const lines = text.replace(/<!--[\s\S]*?-->/g, '').split('\n');
|
|
377
|
-
|
|
393
|
+
// The cut is made at the next heading of the FIRST heading's level, not at
|
|
394
|
+
// any heading at all. `#{1,6}` treated a `###` subsection inside the first
|
|
395
|
+
// section as the second heading, so everything after it was silently
|
|
396
|
+
// dropped from a merged PR or a closed issue — the body the card exists to
|
|
397
|
+
// carry. A deeper heading belongs to the section it sits in and is kept.
|
|
398
|
+
let level = 0;
|
|
378
399
|
const kept = [];
|
|
379
400
|
for (const line of lines) {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
if (
|
|
401
|
+
const m = line.match(/^\s*(#{1,6})\s+/);
|
|
402
|
+
if (m) {
|
|
403
|
+
if (level === 0) {
|
|
404
|
+
level = m[1].length;
|
|
405
|
+
}
|
|
406
|
+
else if (m[1].length <= level) {
|
|
383
407
|
break;
|
|
384
408
|
}
|
|
385
409
|
}
|
|
@@ -593,7 +617,7 @@ const twoBlocks = (run, change) => {
|
|
|
593
617
|
// the action text becomes the link: `Report: <a>Analytics for 12.08</a>`.
|
|
594
618
|
// `aside` is the one qualifier an identifier needs to be readable on its own —
|
|
595
619
|
// which day a report covers, which day its arrows are measured against. It
|
|
596
|
-
// rides in brackets
|
|
620
|
+
// rides in brackets on the TYPE WORD instead of taking a row of its own,
|
|
597
621
|
// because a row of its own reads as another fact about the subject rather than
|
|
598
622
|
// as part of the name.
|
|
599
623
|
const typeLine = (icon, type, action, url, aside) => {
|
|
@@ -601,7 +625,13 @@ const typeLine = (icon, type, action, url, aside) => {
|
|
|
601
625
|
// template prints the word "null". That is how line 2 of a card became
|
|
602
626
|
// `ℹ️ null` — reachable through `--json` and through a direct call from JS,
|
|
603
627
|
// where there are no types.
|
|
604
|
-
|
|
628
|
+
// The qualifier sits ON the type word, before the colon — `Deploy (OK):`,
|
|
629
|
+
// `Report (20.08):` — never after the name. After the name it read as a
|
|
630
|
+
// remark about the title («Deploy to Beget (OK)») rather than about the
|
|
631
|
+
// event, and the owner asked on 03.09.2026 why the outcome trailed the
|
|
632
|
+
// title at all. `field`/`fieldLink` escape the label, so the raw aside is
|
|
633
|
+
// safe to fold into it.
|
|
634
|
+
const label = aside ? `${cap(type)} (${aside})` : type;
|
|
605
635
|
const name = action?.trim();
|
|
606
636
|
// No name: the card must not invent one. It used to write the word `open`
|
|
607
637
|
// into the identifier slot, so a report with a link and no title arrived as
|
|
@@ -611,11 +641,11 @@ const typeLine = (icon, type, action, url, aside) => {
|
|
|
611
641
|
// something else instead. The type word itself takes the link, so nothing
|
|
612
642
|
// clickable is lost and nothing false is said.
|
|
613
643
|
if (!name) {
|
|
614
|
-
const bare = `<b>${esc(cap(
|
|
615
|
-
return `${icon} ${url ? `<a href="${esc(url)}">${bare}</a>` : bare}
|
|
644
|
+
const bare = `<b>${esc(cap(label))}</b>`;
|
|
645
|
+
return `${icon} ${url ? `<a href="${esc(url)}">${bare}</a>` : bare}`;
|
|
616
646
|
}
|
|
617
|
-
const line = url ? fieldLink(
|
|
618
|
-
return line === null ? `${icon} <b>${esc(cap(
|
|
647
|
+
const line = url ? fieldLink(label, url, name) : field(label, name);
|
|
648
|
+
return line === null ? `${icon} <b>${esc(cap(label))}</b>` : `${icon} ${line}`;
|
|
619
649
|
};
|
|
620
650
|
// `workflowUrl ?? url`: half the senders send the run link under the name
|
|
621
651
|
// `--url` — that name was in the package before and stayed in their calls.
|
package/package.json
CHANGED