@mikitasazan/notify 1.13.0 → 1.14.0
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 +84 -14
- package/package.json +1 -1
package/dist/render.js
CHANGED
|
@@ -354,12 +354,17 @@ const renderGroup = (g) => [
|
|
|
354
354
|
* was the same row the issue card had already lost for the same reason: you
|
|
355
355
|
* could not read what the card was about without reading two lines.
|
|
356
356
|
*/
|
|
357
|
-
const commitRow = (hash,
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
357
|
+
const commitRow = (hash, title) => {
|
|
358
|
+
// The title is the content — what the commit DID — so it is what the row
|
|
359
|
+
// says. The hash is a pointer, and pointers live in the last block with
|
|
360
|
+
// `Log`, `Check` and `Source`; the owner caught the hash still carrying the
|
|
361
|
+
// link from the middle of the card (31.08.2026): "source, это hash", and on
|
|
362
|
+
// a manual deploy that buried link was the card's ONLY way back to its
|
|
363
|
+
// source while the pointer block sat empty.
|
|
364
|
+
//
|
|
365
|
+
// With no title there is nothing to say but the hash, so it stands here as
|
|
366
|
+
// plain text — the link to it is in the pointer block either way.
|
|
367
|
+
return field('Commit', title ? firstLine(title) : hash);
|
|
363
368
|
};
|
|
364
369
|
const bodyQuote = (body) => body ? note(body) : null;
|
|
365
370
|
/**
|
|
@@ -517,7 +522,7 @@ const renderDeploy = (e) => {
|
|
|
517
522
|
// The run URL is gone from this line too — it is the `Source:` row now.
|
|
518
523
|
typeLine(icon, 'Deploy', mechanism(e.workflowName, e.via), undefined, e.status === 'fail' ? 'Fail' : 'OK'),
|
|
519
524
|
...twoBlocks([field('Target', e.target), reason('Reason', e.note), field('Still red', e.stillRed ? `day ${e.stillRed}` : null)], [
|
|
520
|
-
commitRow(e.commit, e.
|
|
525
|
+
commitRow(e.commit, e.commitTitle),
|
|
521
526
|
fieldPerson('Author', e.commitAuthor),
|
|
522
527
|
bodyQuote(e.commitBody)
|
|
523
528
|
])
|
|
@@ -614,7 +619,7 @@ const renderCi = (e) => {
|
|
|
614
619
|
// on a nightly card, the same person everywhere else.
|
|
615
620
|
...twoBlocks([reason('Reason', e.note), field('Still red', e.stillRed ? `day ${e.stillRed}` : null)], [
|
|
616
621
|
fieldTelegram('Actor', e.actor),
|
|
617
|
-
commitRow(e.commit, e.
|
|
622
|
+
commitRow(e.commit, e.commitTitle),
|
|
618
623
|
fieldPerson('Author', e.commitAuthor),
|
|
619
624
|
bodyQuote(e.commitBody)
|
|
620
625
|
])
|
|
@@ -626,7 +631,26 @@ const renderCi = (e) => {
|
|
|
626
631
|
// the thing the card is about could not be read without reading three lines.
|
|
627
632
|
// The action is not repeated in words: the icon carries it, and no two actions
|
|
628
633
|
// of one type share an icon.
|
|
629
|
-
|
|
634
|
+
// The number left line 2 on 31.08.2026, by the same rule that moved the commit
|
|
635
|
+
// hash the same day: `#347` is a pointer, and every pointer lives in the last
|
|
636
|
+
// block. Line 2 keeps the title, which is what the thing IS; the number comes
|
|
637
|
+
// back as the text of the `Source` link, where it names exactly what opens.
|
|
638
|
+
//
|
|
639
|
+
// With no title there is nothing left to say, so line 2 falls back to the bare
|
|
640
|
+
// type word — `typeLine` already does that on an empty name. The number is not
|
|
641
|
+
// put back here: it would then appear twice on a titled card and once on an
|
|
642
|
+
// untitled one, which is the inconsistency this move exists to remove.
|
|
643
|
+
//
|
|
644
|
+
// With NO url the number stays put, because then the `Source` row does not
|
|
645
|
+
// exist and dropping it here would erase the number from everything a person
|
|
646
|
+
// reads — the card would name a task without saying which. Same law as
|
|
647
|
+
// `fieldLink`: an identifier must not vanish just because the caller passed no
|
|
648
|
+
// address for it.
|
|
649
|
+
const named = (number, title, url) => {
|
|
650
|
+
if (!title)
|
|
651
|
+
return url ? '' : `#${number}`;
|
|
652
|
+
return url ? title : `#${number} ${title}`;
|
|
653
|
+
};
|
|
630
654
|
// The people come BEFORE the text, and the text comes only when it is the
|
|
631
655
|
// news. An `assigned` card carries one new fact — who took it — and it used to
|
|
632
656
|
// sit dead last, under the issue's entire description: the owner read a card
|
|
@@ -654,7 +678,7 @@ const prBody = (action, body) => VERDICT.has(action) ? quoted('Review', body) :
|
|
|
654
678
|
// old order, title then Author then Assignee then finally the body — "why
|
|
655
679
|
// does the assignee cut apart what should be inseparable?"
|
|
656
680
|
const renderPr = (e) => join([
|
|
657
|
-
typeLine(iconFor(e), 'PR', named(e.number, e.title)),
|
|
681
|
+
typeLine(iconFor(e), 'PR', named(e.number, e.title, e.url)),
|
|
658
682
|
prBody(e.action, e.body),
|
|
659
683
|
e.body ? '' : null,
|
|
660
684
|
fieldPerson('Author', e.author),
|
|
@@ -667,7 +691,7 @@ const renderPr = (e) => join([
|
|
|
667
691
|
// lines, which is what the earlier "he already saw it" reasoning was trying
|
|
668
692
|
// to save — the expandable quote buys the context back without the cost.
|
|
669
693
|
const renderIssue = (e) => join([
|
|
670
|
-
typeLine(iconFor(e), 'Issue', named(e.number, e.title)),
|
|
694
|
+
typeLine(iconFor(e), 'Issue', named(e.number, e.title, e.url)),
|
|
671
695
|
bodyQuote(e.body),
|
|
672
696
|
e.body ? '' : null,
|
|
673
697
|
fieldPerson('Author', e.author),
|
|
@@ -855,13 +879,44 @@ const sourceUrl = (e) => {
|
|
|
855
879
|
const url = 'url' in e ? e.url : undefined;
|
|
856
880
|
return wf ?? url;
|
|
857
881
|
};
|
|
882
|
+
const link = (url, text) => `<a href="${esc(firstLine(url))}">${esc(text)}</a>`;
|
|
883
|
+
/**
|
|
884
|
+
* Everything the card can be traced back to, as one `Source:` row.
|
|
885
|
+
*
|
|
886
|
+
* A card can have more than one honest source — a deploy through Actions has
|
|
887
|
+
* both a run and the commit that triggered it — and one label with two links
|
|
888
|
+
* beside each other reads better than two rows both called `Source`. They are
|
|
889
|
+
* ordered widest first: the run contains the commit, not the other way round.
|
|
890
|
+
*/
|
|
891
|
+
const sourceLinks = (e) => {
|
|
892
|
+
const out = [];
|
|
893
|
+
const run = sourceUrl(e);
|
|
894
|
+
const commitUrl = 'commitUrl' in e ? e.commitUrl : undefined;
|
|
895
|
+
const commit = 'commit' in e ? e.commit : undefined;
|
|
896
|
+
// A pull request and an issue are named by their number and by NOTHING else.
|
|
897
|
+
// `pull request #118` says the type a second time — line 2 already opens with
|
|
898
|
+
// `PR:` — and the owner cut it the hour it shipped: "сверху написано PR,
|
|
899
|
+
// зачем здесь ещё писать PR? Здесь можно просто номер и всё."
|
|
900
|
+
//
|
|
901
|
+
// Only these two types have a number, and only for them is the type word
|
|
902
|
+
// redundant: `workflow run` and `commit 9b1fc68` name things line 2 does NOT,
|
|
903
|
+
// so they keep their nouns.
|
|
904
|
+
const numbered = 'number' in e && typeof e.number === 'number' ? `#${e.number}` : null;
|
|
905
|
+
if (run)
|
|
906
|
+
out.push(link(run, numbered ?? SOURCE_NAME[e.type] ?? 'source'));
|
|
907
|
+
// Without a hash there is no text to put on the link but the word itself,
|
|
908
|
+
// and `commit` alone next to `workflow run` says nothing a reader can use.
|
|
909
|
+
if (commitUrl && commit)
|
|
910
|
+
out.push(link(commitUrl, `commit ${firstLine(commit)}`));
|
|
911
|
+
return out;
|
|
912
|
+
};
|
|
858
913
|
const pointerBlock = (e) => {
|
|
859
|
-
const
|
|
914
|
+
const sources = sourceLinks(e);
|
|
860
915
|
const logs = 'logs' in e ? e.logs : undefined;
|
|
861
916
|
const rows = [
|
|
862
917
|
fieldCode('Log', logs),
|
|
863
918
|
fieldCode('Check', e.check),
|
|
864
|
-
|
|
919
|
+
sources.length > 0 ? `<b>Source:</b> ${sources.join(' · ')}` : null
|
|
865
920
|
].filter((r) => r !== null);
|
|
866
921
|
return rows.length > 0 ? `\n\n${rows.join('\n')}` : '';
|
|
867
922
|
};
|
|
@@ -876,8 +931,23 @@ const cutMarker = (e) => {
|
|
|
876
931
|
if (e.path) {
|
|
877
932
|
return '⋯ cut, full text attached';
|
|
878
933
|
}
|
|
934
|
+
// A bare `⋯ cut` announces a loss and then says nothing about it. The owner
|
|
935
|
+
// met one on a live PR card (31.08.2026) — a description long enough to be
|
|
936
|
+
// clamped — and asked what the three dots even referred to. The card had a
|
|
937
|
+
// `Source` link the whole time: the rest was one tap away and the marker
|
|
938
|
+
// never said so.
|
|
939
|
+
//
|
|
940
|
+
// So the marker NAMES the row that holds the rest, and never repeats its
|
|
941
|
+
// value: it used to print the log path in full, and the pointer block then
|
|
942
|
+
// printed the same path again on the very next line.
|
|
943
|
+
//
|
|
944
|
+
// `below` is literal, not a figure of speech: the marker closes the clamped
|
|
945
|
+
// body and the pointer block is appended after it.
|
|
879
946
|
const logs = 'logs' in e ? e.logs : undefined;
|
|
880
|
-
|
|
947
|
+
if (logs) {
|
|
948
|
+
return '⋯ cut, full text at Log below';
|
|
949
|
+
}
|
|
950
|
+
return sourceLinks(e).length > 0 ? '⋯ cut, full text at Source below' : '⋯ cut';
|
|
881
951
|
};
|
|
882
952
|
/**
|
|
883
953
|
* Renders an event into finished HTML text, cut to Telegram's limit.
|
package/package.json
CHANGED