discord-transcript-ui 1.0.0 → 1.0.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.
@@ -1,26 +1,26 @@
1
1
  <!--
2
- discord-transcript-ui v1.0.0 — asset recovery information.
2
+ discord-transcript-ui v1.0.1 — asset recovery information.
3
3
 
4
4
  Keep this comment when you hand a transcript to someone else: it is enough to
5
5
  rebuild a working view even if this project is gone.
6
6
 
7
- Stylesheet : https://cdn.jsdelivr.net/npm/discord-transcript-ui@1.0.0/dist/discord-transcript.min.css
8
- sha256-338327aaabc0a9eb9a8397ba6e9613f3afde56268301e6accf5c7241c15f5ca0
9
- integrity="sha384-4dM7a+maL/n18BZguAWNq6avCI/sRXkPnC9EG8PGjVsXqi3C1/wiP16212kHZPJG"
10
- Script : https://cdn.jsdelivr.net/npm/discord-transcript-ui@1.0.0/dist/discord-transcript.min.js
11
- sha256-12b7336fc8dff3e26550a732fcbbfaeb482aac5b718c8115f959bf465fac1c65
12
- integrity="sha384-OQCd1U0f3kBi9E7F65YmXxQzGXszPziD9DlYzE97z4FJP/QYdxTFxMJPXeRc+qt2"
7
+ Stylesheet : https://cdn.jsdelivr.net/npm/discord-transcript-ui@1.0.1/dist/discord-transcript.min.css
8
+ sha256-7bd80c8438461e25f5cd321cd2a2391d21c615fdf932d03d24a7e29974a13ffe
9
+ integrity="sha384-MdwneGHI4BQDRywMXXD0VVcvuU2mSlU/cJlHVjDaS6fkNJ/5+OGgmv5w4D/VAOa+"
10
+ Script : https://cdn.jsdelivr.net/npm/discord-transcript-ui@1.0.1/dist/discord-transcript.min.js
11
+ sha256-2bf9d5d5acaa8e52366dd5d451d6c80fc6f4baa6ad098301e7e3d68da5782b69
12
+ integrity="sha384-hxBXQMtoZvVzUDgfAw6RWEVsVW7oJ3++5VYQr2i+vU0gOBIWebUzWahpufZUpQUN"
13
13
 
14
14
  Mirrors (same bytes, drop-in):
15
- jsdelivr https://cdn.jsdelivr.net/npm/discord-transc ript-ui@1.0.0/dist/discord-transcript.min.css
16
- unpkg https://unpkg.com/discord-transcript-ui@1.0.0/dist/discord-transcript.min.css
17
- github-pages https://x1xo.github.io/discord-transcript-ui/v1.0.0/discord-transcript.min.css
18
- statically https://cdn.statically.io/gh/x1xo/discord-transcript-ui/v1.0.0/dist/discord-transcript.min.css
19
- raw-githack https://raw.githack.com/x1xo/discord-transcript-ui/v1.0.0/dist/discord-transcript.min.css
20
- self-hosted https://cdn.example.com/discord-transcript/1.0.0/discord-transcript.min.css
15
+ jsdelivr https://cdn.jsdelivr.net/npm/discord-transcript-ui@1.0.1/dist/discord-transcript.min.css
16
+ unpkg https://unpkg.com/discord-transcript-ui@1.0.1/dist/discord-transcript.min.css
17
+ github-pages https://x1xo.github.io/discord-transcript-ui/v1.0.1/discord-transcript.min.css
18
+ statically https://cdn.statically.io/gh/x1xo/discord-transcript-ui/v1.0.1/dist/discord-transcript.min.css
19
+ raw-githack https://raw.githack.com/x1xo/discord-transcript-ui/v1.0.1/dist/discord-transcript.min.css
20
+ self-hosted https://cdn.example.com/discord-transcript/1.0.1/discord-transcript.min.css
21
21
 
22
- Manifest : https://cdn.jsdelivr.net/npm/discord-transcript-ui@1.0.0/dist/manifest.json
23
- Source : https://github.com/x1xo/discord-transcript-ui/tree/v1.0.0
22
+ Manifest : https://cdn.jsdelivr.net/npm/discord-transcript-ui@1.0.1/dist/manifest.json
23
+ Source : https://github.com/x1xo/discord-transcript-ui/tree/v1.0.1
24
24
  Licence : MIT
25
- Sizes : CSS 32728B raw / 6107B gzip · JS 14850B raw / 4784B gzip
25
+ Sizes : CSS 33392B raw / 6189B gzip · JS 15083B raw / 4917B gzip
26
26
  -->
@@ -544,9 +544,10 @@ discord-message:not([data-dt-ready])[author='']::before {
544
544
  display: inline-flex;
545
545
  align-items: center;
546
546
  justify-content: center;
547
- height: 15px;
548
- padding: 0 4px;
549
- border-radius: 3px;
547
+ gap: 3px;
548
+ height: 16px;
549
+ padding: 0 5px;
550
+ border-radius: 4px;
550
551
  background: var(--dt-brand);
551
552
  color: var(--dt-text-on-brand);
552
553
  font-size: 0.625rem;
@@ -556,15 +557,17 @@ discord-message:not([data-dt-ready])[author='']::before {
556
557
  text-transform: uppercase;
557
558
  }
558
559
 
560
+ /* Verified bot / application tag: a slightly rounded blurple rectangle reading
561
+ "✓ APP" (the tick is drawn here, the text comes from the script so that it is
562
+ real, readable text rather than generated content). */
559
563
  .dt-badge--verified {
560
- width: 15px;
561
- padding: 0;
562
- border-radius: 50%;
564
+ padding: 0 5px 0 4px;
563
565
  }
564
566
 
565
- .dt-badge--verified::after {
567
+ .dt-badge--verified::before {
566
568
  content: '\2713';
567
- font-size: 9px;
569
+ font-size: 0.75rem;
570
+ line-height: 1;
568
571
  }
569
572
 
570
573
  .dt-badge--server {
@@ -731,7 +734,12 @@ discord-author-info:not([data-dt-ready])::before {
731
734
  content: attr(author);
732
735
  }
733
736
 
734
- :where(discord-author-info[bot], discord-author-info[server], discord-author-info[official-app], discord-author-info[op])
737
+ :where(
738
+ discord-author-info[bot],
739
+ discord-author-info[server],
740
+ discord-author-info[official-app],
741
+ discord-author-info[op]
742
+ )
735
743
  ::after {
736
744
  margin-left: 4px;
737
745
  padding: 0 4px;
@@ -743,8 +751,14 @@ discord-author-info:not([data-dt-ready])::before {
743
751
  line-height: 15px;
744
752
  }
745
753
 
754
+ /* Bots are tagged "APP". Verified bots add the checkmark, so they read "✓ APP"
755
+ (equal :where() specificity, so the later rule wins for verified bots). */
746
756
  :where(discord-author-info[bot])::after {
747
- content: 'BOT';
757
+ content: 'APP';
758
+ }
759
+
760
+ :where(discord-author-info[bot][verified])::after {
761
+ content: '\2713\00a0APP';
748
762
  }
749
763
 
750
764
  :where(discord-author-info[server])::after {
@@ -1139,6 +1153,19 @@ discord-reply[deleted]::before {
1139
1153
  color: var(--dt-text-muted);
1140
1154
  }
1141
1155
 
1156
+ /* A reply preview sits above the author row (Discord's layout): the reply takes
1157
+ the first grid row, so the avatar and the author name share the second. */
1158
+ .dt-msg--has-reply > :where(discord-reply),
1159
+ .dt-msg--has-reply > :where(discord-command) {
1160
+ grid-column: 2;
1161
+ grid-row: 1;
1162
+ }
1163
+
1164
+ .dt-msg--has-reply > .dt-avatar,
1165
+ .dt-msg--has-reply > .dt-content {
1166
+ grid-row: 2;
1167
+ }
1168
+
1142
1169
  /* Curved connector, drawn only once the reply sits in the content column. */
1143
1170
  discord-message[data-dt-ready] :where(discord-reply)::after {
1144
1171
  content: '';
@@ -1698,6 +1725,8 @@ discord-reaction:not([data-dt-ready])::before {
1698
1725
  }
1699
1726
 
1700
1727
  discord-reaction[emoji^='http']:not([data-dt-ready])::before,
1728
+ discord-reaction[emoji^='data:']:not([data-dt-ready])::before,
1729
+ discord-reaction[emoji^='blob:']:not([data-dt-ready])::before,
1701
1730
  discord-reaction[emoji^='/']:not([data-dt-ready])::before,
1702
1731
  discord-reaction[emoji^='./']:not([data-dt-ready])::before,
1703
1732
  discord-reaction:not([emoji]):not([data-dt-ready])::before {
@@ -1719,8 +1748,10 @@ discord-reaction[count='1']:not([data-dt-ready])::after {
1719
1748
  :where(discord-reaction) img,
1720
1749
  .dt-reaction-emoji {
1721
1750
  display: inline-block;
1751
+ flex: none;
1722
1752
  width: 1rem;
1723
1753
  height: 1rem;
1754
+ overflow: hidden;
1724
1755
  object-fit: contain;
1725
1756
  vertical-align: middle;
1726
1757
  }
@@ -1810,17 +1841,32 @@ discord-reaction[count='1']:not([data-dt-ready])::after {
1810
1841
  display: inline-flex;
1811
1842
  align-items: center;
1812
1843
  justify-content: center;
1813
- width: 15px;
1814
- height: 15px;
1815
- border-radius: 50%;
1844
+ gap: 3px;
1845
+ height: 16px;
1846
+ padding: 0 5px 0 4px;
1847
+ border-radius: 4px;
1816
1848
  background: var(--dt-brand);
1817
1849
  color: var(--dt-text-on-brand);
1818
- font-size: 9px;
1850
+ font-size: 0.625rem;
1851
+ font-weight: 600;
1852
+ line-height: 1;
1853
+ letter-spacing: 0.02em;
1854
+ text-transform: uppercase;
1819
1855
  vertical-align: -2px;
1820
1856
  }
1821
1857
 
1822
- :where(discord-verified-author-tag)::after {
1858
+ :where(discord-verified-author-tag)::before {
1823
1859
  content: '\2713';
1860
+ font-size: 0.75rem;
1861
+ line-height: 1;
1862
+ }
1863
+
1864
+ :where(discord-verified-author-tag:not([verified]))::before {
1865
+ content: none;
1866
+ }
1867
+
1868
+ :where(discord-verified-author-tag)::after {
1869
+ content: 'APP';
1824
1870
  }
1825
1871
 
1826
1872
  /* ==========================================================================
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * Config (define it any time before DOMContentLoaded):
11
11
  * window.$discordMessage = {
12
- * profiles: { skyra: { author: 'Skyra', avatar: 'https://…', roleColor: '#ff0000', bot: true } },
12
+ * profiles: { miona: { author: 'Miona', avatar: 'https://…', roleColor: '#ff0000', bot: true } },
13
13
  * avatars: { default: 'blue', blue: 'https://cdn.discordapp.com/embed/avatars/0.png' }
14
14
  * };
15
15
  * window.discordTranscript = { groupWindow: 7, locale: 'en-US', observe: true };
@@ -239,9 +239,11 @@
239
239
 
240
240
  function badgeRow(identity) {
241
241
  var row = make('span', 'dt-badges');
242
+ /* Bots are tagged "APP"; verified bots additionally get the checkmark,
243
+ which is drawn by CSS (so the tag reads "✓ APP"). */
242
244
  if (identity.bot) {
243
- if (identity.verified) row.appendChild(make('span', 'dt-badge dt-badge--verified'));
244
- else row.appendChild(make('span', 'dt-badge', 'BOT'));
245
+ var botTag = identity.verified ? 'dt-badge dt-badge--verified' : 'dt-badge';
246
+ row.appendChild(make('span', botTag, 'APP'));
245
247
  } else if (identity.server) {
246
248
  row.appendChild(make('span', 'dt-badge dt-badge--server', 'SERVER'));
247
249
  } else if (identity.official) {
@@ -259,14 +261,29 @@
259
261
  var identity = identityOf(element);
260
262
  var stamp = parseStamp(element.getAttribute('timestamp'));
261
263
  var body = make('div', 'dt-body');
264
+ var replies = [];
262
265
 
263
266
  /* Optional parser-supplied header escapes the generated one. */
264
267
  var suppliedHeader = element.querySelector(':scope > discord-author-info, :scope > discord-message-header');
265
268
  if (suppliedHeader) suppliedHeader.remove();
266
269
 
267
- while (element.firstChild) body.appendChild(element.firstChild);
270
+ /* Reply previews are lifted out of the body: Discord draws them above the
271
+ author row, with the avatar level with the author name. */
272
+ while (element.firstChild) {
273
+ var child = element.firstChild;
274
+ if (child.nodeType === 1 && (child.tagName === 'DISCORD-REPLY' || child.tagName === 'DISCORD-COMMAND')) {
275
+ replies.push(child);
276
+ element.removeChild(child);
277
+ continue;
278
+ }
279
+ body.appendChild(child);
280
+ }
268
281
 
269
282
  var wrap = make('div', 'dt-msg');
283
+ if (replies.length) {
284
+ wrap.classList.add('dt-msg--has-reply');
285
+ for (var replyIndex = 0; replyIndex < replies.length; replyIndex++) wrap.appendChild(replies[replyIndex]);
286
+ }
270
287
  wrap.appendChild(avatarNode(identity, 'dt-avatar'));
271
288
 
272
289
  var content = make('div', 'dt-content');
@@ -422,8 +439,10 @@
422
439
  function upgradeReactions(element) {
423
440
  if (has(element, 'data-dt-ready')) return;
424
441
  var emoji = element.getAttribute('emoji');
425
- var isUrl = emoji && /^(https?:|\/|\.\/)/.test(emoji);
426
- if (isUrl) {
442
+ /* Any of these is an image source rather than a unicode character. Data
443
+ URIs matter: inline SVG/PNG emoji must never be emitted as visible text. */
444
+ var isImage = emoji && /^(https?:|data:|blob:|\/|\.\/)/i.test(emoji);
445
+ if (isImage) {
427
446
  var img = make('img', 'dt-reaction-emoji');
428
447
  img.src = emoji;
429
448
  img.alt = element.getAttribute('name') || '';
@@ -0,0 +1,2 @@
1
+ /*! discord-transcript-ui v1.0.1 | MIT | https://github.com/x1xo/discord-transcript-ui */
2
+ :root{--dt-font: "gg sans", "Noto Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;--dt-font-mono: "gg mono", "Source Code Pro", Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "DejaVu Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace;--dt-font-size: 1rem;--dt-line-height: 1.375rem;--dt-radius-sm: 4px;--dt-radius-md: 8px;--dt-radius-lg: 12px;--dt-bg-primary: #323339;--dt-bg-secondary: #393a41;--dt-bg-tertiary: #2c2d32;--dt-bg-embed: #393a41;--dt-bg-code: #323339;--dt-bg-inline-code: rgba(88, 101, 242, .078);--dt-bg-modifier-hover: rgba(151, 151, 159, .122);--dt-bg-modifier-active: rgba(151, 151, 159, .161);--dt-bg-message-hover: rgba(151, 151, 159, .039);--dt-bg-mentioned: rgba(248, 163, 0, .078);--dt-bg-scrollbar-thumb: #767780;--dt-bg-scrollbar-track: transparent;--dt-text-normal: #f3f3f4;--dt-text-strong: #ffffff;--dt-text-subtle: #c5c6ca;--dt-text-muted: #9d9ea5;--dt-text-link: #76aff6;--dt-text-on-brand: #ffffff;--dt-status-online: #3d9e60;--dt-status-idle: #ffcb6e;--dt-status-dnd: #dc4247;--dt-status-offline: #9d9ea5;--dt-border: rgba(151, 151, 159, .122);--dt-border-strong: rgba(151, 151, 159, .2);--dt-brand: #5865f2;--dt-accent-bar: var(--dt-brand);--dt-role-default: #f3f3f4;--dt-embed-default-color: #4f545c;--dt-divider: rgba(151, 151, 159, .122);--dt-line-color: #595a63;--dt-mention-bg: rgba(88, 101, 242, .239);--dt-mention-text: #cdd7ff;--dt-mention-role-color: var(--dt-role-default);--dt-mention-channel-bg: rgba(151, 151, 159, .122);--dt-mention-channel-text: var(--dt-text-normal);--dt-spoiler-bg: #7d7e87;--dt-spoiler-revealed-bg: rgba(151, 151, 159, .078);--dt-gutter: 16px;--dt-avatar-size: 40px;--dt-avatar-gap: 16px;--dt-msg-padding-right: 48px;--dt-reply-avatar-size: 16px;--dt-button-secondary: rgba(151, 151, 159, .122);--dt-button-secondary-hover: rgba(151, 151, 159, .2);--dt-button-primary: #5865f2;--dt-button-primary-hover: #4654c0;--dt-button-success: #248046;--dt-button-danger: #da3e44;--dt-button-link: rgba(151, 151, 159, .122);--dt-reaction-bg: rgba(151, 151, 159, .122);--dt-reaction-border: rgba(151, 151, 159, .122);--dt-reaction-bg-reacted: rgba(88, 101, 242, .239);--dt-reaction-border-reacted: #5865f2;--dt-reaction-text-reacted: #dfe4ff;--dt-focus-ring: #76aff6;--dt-transition: .12s ease}discord-messages[light-theme],discord-messages[data-theme=light],:root[data-theme=light]{--dt-bg-primary: #ffffff;--dt-bg-secondary: #ffffff;--dt-bg-tertiary: #f3f3f4;--dt-bg-embed: #ffffff;--dt-bg-code: #f3f3f4;--dt-bg-inline-code: rgba(88, 101, 242, .078);--dt-bg-modifier-hover: rgba(151, 151, 159, .122);--dt-bg-modifier-active: rgba(151, 151, 159, .161);--dt-bg-message-hover: rgba(151, 151, 159, .078);--dt-bg-mentioned: rgba(248, 163, 0, .1);--dt-bg-scrollbar-thumb: #8b8c94;--dt-bg-scrollbar-track: transparent;--dt-text-normal: #2e2e34;--dt-text-strong: #28282d;--dt-text-subtle: #595a63;--dt-text-muted: #6c6d76;--dt-text-link: #006dd4;--dt-role-default: #2e2e34;--dt-border: rgba(151, 151, 159, .278);--dt-border-strong: rgba(151, 151, 159, .4);--dt-divider: rgba(151, 151, 159, .278);--dt-line-color: #c5c6ca;--dt-embed-default-color: #d4d7dc;--dt-mention-bg: rgba(88, 101, 242, .15);--dt-mention-text: #2e3c88;--dt-mention-channel-bg: rgba(151, 151, 159, .122);--dt-mention-channel-text: #2e2e34;--dt-spoiler-bg: #8f9097;--dt-spoiler-revealed-bg: #ebeced;--dt-reaction-border: rgba(151, 151, 159, .278);--dt-reaction-text-reacted: #273478;--dt-status-online: #01783e;--dt-status-idle: #faaa00;--dt-status-dnd: #d22d39;--dt-status-offline: #5f606a;--dt-focus-ring: #006dd4}discord-messages[data-theme=dark]{--dt-bg-primary: #323339;--dt-bg-secondary: #393a41;--dt-bg-tertiary: #2c2d32;--dt-bg-embed: #393a41;--dt-bg-code: #323339;--dt-bg-inline-code: rgba(88, 101, 242, .078);--dt-bg-modifier-hover: rgba(151, 151, 159, .122);--dt-bg-modifier-active: rgba(151, 151, 159, .161);--dt-bg-message-hover: rgba(151, 151, 159, .039);--dt-bg-mentioned: rgba(248, 163, 0, .078);--dt-bg-scrollbar-thumb: #767780;--dt-bg-scrollbar-track: transparent;--dt-text-normal: #f3f3f4;--dt-text-strong: #ffffff;--dt-text-subtle: #c5c6ca;--dt-text-muted: #9d9ea5;--dt-text-link: #76aff6;--dt-role-default: #f3f3f4;--dt-border: rgba(151, 151, 159, .122);--dt-border-strong: rgba(151, 151, 159, .2);--dt-divider: rgba(151, 151, 159, .122);--dt-line-color: #595a63;--dt-embed-default-color: #4f545c;--dt-mention-bg: rgba(88, 101, 242, .239);--dt-mention-text: #cdd7ff;--dt-mention-channel-bg: rgba(151, 151, 159, .122);--dt-mention-channel-text: #f3f3f4;--dt-spoiler-bg: #7d7e87;--dt-spoiler-revealed-bg: rgba(151, 151, 159, .078);--dt-reaction-border: rgba(151, 151, 159, .122);--dt-reaction-text-reacted: #dfe4ff;--dt-status-online: #3d9e60;--dt-status-idle: #ffcb6e;--dt-status-dnd: #dc4247;--dt-status-offline: #9d9ea5;--dt-focus-ring: #76aff6}:where(discord-messages,discord-message,discord-author-info,discord-reply,discord-embed,discord-embed-description,discord-embed-fields,discord-embed-field,discord-embed-footer,discord-attachments,discord-image-attachment,discord-file-attachment,discord-audio-attachment,discord-video-attachment,discord-reactions,discord-reaction,discord-spoiler,discord-time,discord-mention,discord-custom-emoji,discord-code,discord-pre,discord-quote,discord-list-item,discord-unordered-list,discord-ordered-list,discord-header,discord-command,discord-system-message,discord-thread,discord-thread-message,discord-action-row,discord-button,discord-verified-author-tag){box-sizing:border-box}:where(discord-messages,discord-message,discord-embed,discord-attachments,discord-reactions,discord-reply,discord-system-message,discord-command,discord-thread,discord-thread-message,discord-action-row,discord-pre,discord-quote,discord-unordered-list,discord-ordered-list,discord-header){display:block;font-family:var(--dt-font);font-size:var(--dt-font-size);line-height:var(--dt-line-height);color:var(--dt-text-normal);text-align:left}:where(discord-message,discord-reply,discord-embed,discord-attachments,discord-reactions){-webkit-text-size-adjust:100%;word-wrap:break-word;overflow-wrap:anywhere}:where(discord-bold){font-weight:700}:where(discord-italic){font-style:italic}:where(discord-underlined){text-decoration:underline}:where(discord-strikethrough){text-decoration:line-through}:where(discord-subscript){font-size:.8125rem;vertical-align:sub}:where(discord-header){display:block;margin:8px 0 0;font-weight:600;line-height:1.375em}:where(discord-header[level="1"]){font-size:1.5rem}:where(discord-header[level="2"]){font-size:1.25rem}:where(discord-header[level="3"]){font-size:1rem}:where(discord-quote){display:block;margin:4px 0;padding:0 8px 0 12px;color:var(--dt-text-subtle);border-left:4px solid var(--dt-line-color);border-radius:var(--dt-radius-sm)}:where(discord-unordered-list,discord-ordered-list){margin:0;padding-left:1.375em}:where(discord-list-item){display:list-item;margin:0 0 4px;padding:0}:where(discord-unordered-list)>discord-list-item{list-style:disc outside}:where(discord-ordered-list)>discord-list-item{list-style:decimal outside}:where(discord-link){color:var(--dt-text-link);text-decoration:none}:where(discord-link):hover{text-decoration:underline}:where(discord-message,discord-embed,discord-embed-description,discord-embed-field,discord-reply,discord-quote) a:not([class]){color:var(--dt-text-link);text-decoration:none}:where(discord-message,discord-embed,discord-embed-description,discord-embed-field,discord-reply,discord-quote) a:not([class]):hover{text-decoration:underline}.dt-page{min-height:100vh;margin:0;background:var(--dt-bg-primary);color:var(--dt-text-normal);font-family:var(--dt-font);font-size:var(--dt-font-size);line-height:var(--dt-line-height);-webkit-font-smoothing:antialiased}.dt-page__inner{max-width:100%;margin:0 auto;padding:1rem 0 4rem}.dt-page__title{margin:0 0 1rem;padding:0 16px;font-size:1.25rem;font-weight:700;color:var(--dt-text-strong)}.dt-page__meta{margin:0 0 1.5rem;padding:0 16px;font-size:.875rem;color:var(--dt-text-muted)}:where(discord-messages){display:block;position:relative;margin:0 auto;padding:8px 0 16px;background:var(--dt-bg-primary);color:var(--dt-text-normal);font-family:var(--dt-font);line-height:var(--dt-line-height);overflow-x:hidden;overflow-y:auto;scrollbar-color:var(--dt-bg-scrollbar-thumb) var(--dt-bg-scrollbar-track)}:where(discord-messages[no-background]){background:transparent;padding:0}:where(discord-messages[channel-name]):before{content:attr(channel-name);display:block;margin:0 0 8px;padding:4px 16px 12px;border-bottom:1px solid var(--dt-divider);font-size:1.25rem;font-weight:700;color:var(--dt-text-strong)}discord-messages[channel-type=text][channel-name]:before,discord-messages[channel-type=voice][channel-name]:before,discord-messages[channel-type=thread][channel-name]:before,discord-messages[channel-type=forum][channel-name]:before,discord-messages[channel-type=locked][channel-name]:before{content:"#\a0" attr(channel-name)}discord-messages ::-webkit-scrollbar{width:16px;height:16px}discord-messages ::-webkit-scrollbar-thumb{background:var(--dt-bg-scrollbar-thumb);border:4px solid transparent;background-clip:padding-box;border-radius:8px}discord-messages ::-webkit-scrollbar-track{background:var(--dt-bg-scrollbar-track)}:where(discord-message){position:relative;display:block;margin:0;padding:2px var(--dt-msg-padding-right) 2px var(--dt-gutter);color:var(--dt-text-normal);font-family:var(--dt-font);font-size:var(--dt-font-size);line-height:var(--dt-line-height);-webkit-user-select:text;user-select:text}:where(discord-message:hover){background:var(--dt-bg-message-hover)}discord-message:not([data-dt-ready]):before{content:attr(author) "\a0";font-weight:600;color:var(--dt-role-default)}discord-message:not([data-dt-ready]):not([author]):before,discord-message:not([data-dt-ready])[author=""]:before{content:""}.dt-msg{display:grid;grid-template-columns:var(--dt-avatar-size) minmax(0,1fr);column-gap:var(--dt-avatar-gap);align-items:start}.dt-avatar{grid-column:1;width:var(--dt-avatar-size);height:var(--dt-avatar-size);margin-top:2px;border-radius:50%;overflow:hidden;background:var(--dt-bg-tertiary)}.dt-avatar img{display:block;width:100%;height:100%;object-fit:cover}.dt-content{grid-column:2;min-width:0}.dt-header{display:flex;flex-wrap:wrap;align-items:center;min-height:1.375rem}.dt-author{margin-right:8px;font-weight:500;color:var(--dt-role-default);text-decoration:none}.dt-author--interactive:hover{text-decoration:underline;cursor:pointer}.dt-badges{display:inline-flex;align-items:center;gap:4px;margin-right:8px}.dt-badge{display:inline-flex;align-items:center;justify-content:center;gap:3px;height:16px;padding:0 5px;border-radius:4px;background:var(--dt-brand);color:var(--dt-text-on-brand);font-size:.625rem;font-weight:600;line-height:1;letter-spacing:.02em;text-transform:uppercase}.dt-badge--verified{padding:0 5px 0 4px}.dt-badge--verified:before{content:"\2713";font-size:.75rem;line-height:1}.dt-badge--server{background:#3ba55c}.dt-badge--official{background:#1abc84}.dt-timestamp{font-size:.75rem;line-height:1.375rem;color:var(--dt-text-muted);white-space:nowrap}.dt-timestamp:hover{text-decoration:underline}.dt-edited{margin-left:4px;font-size:.625rem;color:var(--dt-text-muted)}.dt-body{display:block;min-width:0}.dt-body>:first-child{margin-top:0}.dt-jumbo{display:flex;flex-wrap:wrap;align-items:center;gap:2px}.dt-jumbo discord-custom-emoji img,.dt-jumbo>img.emoji{width:48px;height:48px}discord-message[highlight],discord-message[ephemeral],discord-message[mentioned]{background:var(--dt-bg-mentioned)}discord-message[highlight]:after,discord-message[ephemeral]:after,discord-message[mentioned]:after{content:"";position:absolute;top:0;bottom:0;left:0;width:2px;background:var(--dt-accent-bar);pointer-events:none}discord-message[ephemeral]{background:#5865f214}discord-message[highlight]:hover,discord-message[mentioned]:hover{background:var(--dt-bg-mentioned)}discord-message[data-dt-continuation] .dt-avatar,discord-message[message-body-only] .dt-avatar{visibility:hidden}discord-message[data-dt-continuation] .dt-header,discord-message[message-body-only] .dt-header{display:none}discord-message[data-dt-continuation]:hover:before,discord-message[data-dt-continuation]:focus-within:before{content:attr(data-dt-short-time);position:absolute;top:3px;left:var(--dt-gutter);width:calc(var(--dt-avatar-size) - 4px);font-size:.6875rem;line-height:1.375rem;color:var(--dt-text-muted);white-space:nowrap;overflow:hidden;pointer-events:none}discord-message[data-dt-group-start]{margin-top:1.0625rem}discord-message:first-child{margin-top:0}discord-messages[compact-mode],discord-message[compact-mode]{--dt-avatar-size: 16px;--dt-avatar-gap: 8px;--dt-gutter: 16px;--dt-msg-padding-right: 16px}discord-messages[compact-mode] discord-message{padding-top:1px;padding-bottom:1px}discord-messages[compact-mode] .dt-avatar{margin-top:.25rem}discord-messages[compact-mode] .dt-header{display:inline;margin-right:8px}discord-messages[compact-mode] .dt-author{margin-right:6px}discord-messages[compact-mode] .dt-body{display:inline}discord-messages[compact-mode] .dt-timestamp{margin-right:6px;font-size:.6875rem}:where(discord-author-info){display:inline-flex;align-items:center;gap:4px;font-weight:500;color:var(--dt-role-default)}discord-author-info:not([data-dt-ready]):before{content:attr(author)}:where(discord-author-info[bot],discord-author-info[server],discord-author-info[official-app],discord-author-info[op]) :after{margin-left:4px;padding:0 4px;border-radius:3px;background:var(--dt-brand);color:var(--dt-text-on-brand);font-size:.625rem;font-weight:600;line-height:15px}:where(discord-author-info[bot]):after{content:"APP"}:where(discord-author-info[bot][verified]):after{content:"\2713\a0aPP"}:where(discord-author-info[server]):after{content:"SERVER";background:#3ba55c}:where(discord-author-info[official-app]):after{content:"OFFICIAL";background:#1abc84}:where(discord-author-info[op]):after{content:"OP"}:where(discord-mention){display:inline;padding:0 2px;border-radius:3px;background:var(--dt-mention-bg);color:var(--dt-mention-text);font-weight:500;cursor:pointer}:where(discord-mention):hover{background:var(--dt-bg-modifier-active)}:where(discord-mention[type=channel]),:where(discord-mention[type=voice]),:where(discord-mention[type=thread]),:where(discord-mention[type=forum]),:where(discord-mention[type=locked]){background:var(--dt-mention-channel-bg);color:var(--dt-mention-channel-text)}:where(discord-mention[type=role]){background:var(--dt-mention-bg);color:var(--dt-mention-role-color)}discord-mention:not([no-prefix]):before{content:"@"}discord-mention:not([no-prefix])[type=channel]:before,discord-mention:not([no-prefix])[type=voice]:before,discord-mention:not([no-prefix])[type=thread]:before,discord-mention:not([no-prefix])[type=forum]:before,discord-mention:not([no-prefix])[type=locked]:before{content:"#"}:where(discord-custom-emoji){display:inline-block;vertical-align:-.25em}:where(discord-custom-emoji) img{display:inline-block;width:1.375em;height:1.375em;object-fit:contain;vertical-align:middle}discord-custom-emoji:not([data-dt-ready]):not(:has(img)):before{content:attr(name);font-size:.75rem;color:var(--dt-text-muted)}:where(discord-time){display:inline;padding:0 2px;border-radius:3px;background:var(--dt-bg-modifier-hover);font-size:.875rem;white-space:nowrap}:where(discord-time):hover{background:var(--dt-bg-modifier-active)}:where(discord-spoiler){display:inline;border-radius:var(--dt-radius-sm);background:var(--dt-spoiler-bg);color:transparent;cursor:pointer;transition:background var(--dt-transition),color var(--dt-transition)}:where(discord-spoiler)::selection{background:transparent;color:transparent}:where(discord-spoiler[activated]),:where(discord-spoiler[revealed]),:where(discord-spoiler[data-dt-revealed]){background:var(--dt-spoiler-revealed-bg);color:inherit;cursor:auto}discord-spoiler:not([data-dt-ready]):hover{background:var(--dt-spoiler-revealed-bg);color:inherit}discord-spoiler[data-dt-ready]{outline:none}discord-spoiler[data-dt-ready]:focus-visible{box-shadow:0 0 0 2px var(--dt-focus-ring)}:where(discord-code){display:inline;padding:0 2px;border-radius:var(--dt-radius-sm);background:var(--dt-bg-inline-code);border:1px solid var(--dt-border-strong);font-family:var(--dt-font-mono);font-size:.85em;white-space:pre-wrap;word-break:break-word}:where(discord-code[multiline]){display:block;margin:6px 0 0;padding:8px 12px;border:1px solid var(--dt-border);border-radius:var(--dt-radius-sm);background:var(--dt-bg-code);font-size:.75rem;line-height:1rem;white-space:pre;overflow-x:auto;tab-size:4}:where(discord-pre){position:relative;display:block;margin:6px 0 0;padding:0;border:1px solid var(--dt-border);border-radius:var(--dt-radius-sm);background:var(--dt-bg-code);overflow:hidden}:where(discord-pre)>:where(discord-code),:where(discord-pre) pre{display:block;margin:0;padding:8px 12px;border:0;border-radius:0;background:none;font-family:var(--dt-font-mono);font-size:.75rem;line-height:1rem;white-space:pre;overflow-x:auto;tab-size:4}:where(discord-pre) code{font-family:inherit}.dt-code-lang{display:block;padding:6px 12px 0;font-family:var(--dt-font);font-size:.75rem;color:var(--dt-text-muted)}.dt-copy{position:absolute;top:6px;right:8px;display:none;padding:2px 8px;border:1px solid var(--dt-border-strong);border-radius:var(--dt-radius-sm);background:var(--dt-bg-primary);color:var(--dt-text-normal);font-family:var(--dt-font);font-size:.75rem;cursor:pointer}discord-pre:hover .dt-copy,.dt-copy:focus-visible{display:block}.dt-copy:hover{background:var(--dt-bg-modifier-hover)}:where(discord-system-message){position:relative;display:block;margin:0;padding:2px var(--dt-msg-padding-right) 2px calc(var(--dt-gutter) + var(--dt-avatar-size) + var(--dt-avatar-gap));background:transparent;color:var(--dt-text-muted);font-size:.9375rem}:where(discord-system-message):before{content:"";position:absolute;top:7px;left:calc(var(--dt-gutter) + (var(--dt-avatar-size) - 16px) / 2);width:16px;height:16px;border-radius:50%;background:var(--dt-bg-modifier-hover)}discord-system-message[type=join]:before{background:var(--dt-status-online)}discord-system-message[type=leave]:before,discord-system-message[type=missed-call]:before,discord-system-message[type=alert]:before,discord-system-message[type=error]:before{background:var(--dt-status-dnd)}discord-system-message[type=boost]:before{background:#ff73fa}discord-system-message[type=pin]:before{background:var(--dt-status-idle)}discord-system-message[type=upgrade]:before,discord-system-message[type=thread]:before,discord-system-message[type=edit]:before,discord-system-message[type=call]:before{background:var(--dt-brand)}discord-system-message a,discord-system-message :where(discord-link){color:var(--dt-text-muted);font-weight:500}discord-system-message .dt-system-time{margin-left:4px;font-size:.75rem;color:var(--dt-text-muted)}:where(discord-command){position:relative;display:block;margin:0 0 2px;padding:0;font-size:.9375rem}discord-command:not([data-dt-ready]):before{content:attr(author) " used /" attr(command) "\a0";font-weight:500;color:var(--dt-text-normal)}.dt-avatar--initials{display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600;text-transform:uppercase}:where(discord-thread){position:relative;display:block;margin:4px 0 0;padding:4px 120px 4px 12px;border-left:2px solid var(--dt-line-color);font-size:.875rem;color:var(--dt-text-muted)}discord-thread:not([data-dt-ready]):before{content:attr(name);font-weight:500;color:var(--dt-text-normal)}discord-thread[cta]:after{content:attr(cta) " " "\203a";position:absolute;top:4px;right:8px;font-size:.875rem;font-weight:500;color:var(--dt-text-muted);pointer-events:none}discord-thread-message{display:block;margin:2px 0;font-size:.875rem}discord-thread-message:not([data-dt-ready]):before{content:attr(author) "\a0";font-weight:500;color:var(--dt-role-default)}:where(discord-reply){position:relative;display:block;margin:0 0 2px;color:var(--dt-text-normal);font-size:.875rem;line-height:1.125rem;min-height:1.125rem}discord-reply:not([data-dt-ready]):before{content:attr(author) "\a0";font-weight:500;color:var(--dt-role-default)}discord-reply[mentions]:not([data-dt-ready]):before{content:"@" attr(author) "\a0"}discord-reply[deleted]>*{display:none}discord-reply[deleted]:before{content:"Original message was deleted";font-style:italic;font-weight:400;color:var(--dt-text-muted)}.dt-msg--has-reply>:where(discord-reply),.dt-msg--has-reply>:where(discord-command){grid-column:2;grid-row:1}.dt-msg--has-reply>.dt-avatar,.dt-msg--has-reply>.dt-content{grid-row:2}discord-message[data-dt-ready] :where(discord-reply):after{content:"";position:absolute;left:-36px;bottom:-2px;width:36px;height:12px;border-left:2px solid var(--dt-line-color);border-top:2px solid var(--dt-line-color);border-top-left-radius:6px;pointer-events:none}discord-reply[data-dt-ready] .dt-reply-avatar{display:inline-block;width:var(--dt-reply-avatar-size);height:var(--dt-reply-avatar-size);margin-right:4px;border-radius:50%;overflow:hidden;vertical-align:-3px;background:var(--dt-bg-tertiary)}discord-reply[data-dt-ready] .dt-reply-avatar img{display:block;width:100%;height:100%;object-fit:cover}discord-reply[data-dt-ready] .dt-reply-author{margin-right:4px;font-weight:500;color:var(--dt-role-default)}discord-reply[data-dt-ready] .dt-reply-author:hover{text-decoration:underline;cursor:pointer}discord-reply[data-dt-ready] .dt-reply-avatar,discord-reply[data-dt-ready] .dt-reply-author{-webkit-user-select:none;user-select:none}discord-messages[compact-mode] :where(discord-reply):after{display:none}:where(discord-embed){position:relative;display:block;margin:8px 0 0;padding:2px 16px 16px 12px;border:1px solid var(--dt-border);border-left:4px solid var(--dt-embed-color, var(--dt-embed-default-color));border-radius:var(--dt-radius-sm);background:var(--dt-bg-embed);max-width:516px;color:var(--dt-text-normal);font-size:.875rem;line-height:1.125rem}.dt-embed-content{min-width:0}discord-embed[thumbnail] .dt-embed-content,discord-embed[data-dt-thumbnail] .dt-embed-content,discord-embed:has(.dt-embed-thumbnail) .dt-embed-content{padding-right:96px}discord-embed[thumbnail]:not(:has(.dt-embed-content)),discord-embed[data-dt-thumbnail]:not(:has(.dt-embed-content)),discord-embed:has(.dt-embed-thumbnail):not(:has(.dt-embed-content)){padding-right:104px}discord-embed:not([data-dt-ready])[embed-title]:before{content:attr(embed-title);display:block;margin:0 0 8px;font-size:1rem;font-weight:600;line-height:1.375rem;color:var(--dt-text-strong)}discord-embed:not([data-dt-ready]):not([embed-title])[author-name]:before{content:attr(author-name);display:block;margin:0 0 8px;font-weight:600;line-height:1.125rem}.dt-embed-provider{display:block;margin-bottom:8px;color:var(--dt-text-normal)}.dt-embed-author{display:flex;align-items:center;gap:8px;margin-bottom:8px;font-size:.875rem;font-weight:600;line-height:1.125rem}.dt-embed-author img{width:24px;height:24px;border-radius:50%;object-fit:cover}.dt-embed-author a{color:var(--dt-text-normal);text-decoration:none}.dt-embed-author a:hover{text-decoration:underline}.dt-embed-title{display:block;margin:0 0 8px;font-size:1rem;font-weight:600;line-height:1.375rem;color:var(--dt-text-strong);text-decoration:none}.dt-embed-title--link,a.dt-embed-title:hover,.dt-embed-title a:hover{text-decoration:underline}a.dt-embed-title{color:var(--dt-text-link)}.dt-embed-thumbnail{position:absolute;top:8px;right:16px;width:80px;height:80px;border-radius:var(--dt-radius-sm);overflow:hidden;background:var(--dt-bg-tertiary)}.dt-embed-thumbnail img{display:block;width:100%;height:100%;object-fit:cover}:where(discord-embed-description){display:block;margin:0;font-size:.875rem;line-height:1.125rem;white-space:pre-line}:where(discord-embed-fields){display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:8px;margin-top:8px}:where(discord-embed-field){grid-column:1 / -1;min-width:0;font-size:.875rem;line-height:1.125rem}:where(discord-embed-field[inline]){grid-column:span 4}discord-embed[thumbnail] :where(discord-embed-field[inline]),discord-embed[data-dt-thumbnail] :where(discord-embed-field[inline]){grid-column:span 6}.dt-embed-field-title{display:block;margin:0 0 2px;font-weight:600;color:var(--dt-text-strong)}discord-embed-field:not([data-dt-ready]):not(:has(.dt-embed-field-title)):before{content:attr(field-title);display:block;margin-bottom:2px;font-weight:600;color:var(--dt-text-strong)}.dt-embed-image{display:block;margin-top:16px}.dt-embed-image img,.dt-embed-image video{display:block;max-width:100%;max-height:300px;border-radius:var(--dt-radius-sm);object-fit:contain}:where(discord-embed-footer){display:flex;align-items:center;gap:8px;margin-top:8px;font-size:.75rem;line-height:1rem;color:var(--dt-text-muted)}discord-embed-footer:empty:before{content:attr(footer)}.dt-embed-footer-icon{width:20px;height:20px;border-radius:50%;overflow:hidden;background:var(--dt-bg-tertiary)}.dt-embed-footer-icon img{display:block;width:100%;height:100%;object-fit:cover}.dt-embed-footer-sep{display:inline-block;width:4px;height:4px;border-radius:50%;background:var(--dt-text-muted);opacity:.6}:where(discord-attachments){display:flex;flex-direction:column;align-items:flex-start;gap:8px;margin-top:8px;max-width:550px}:where(discord-attachments:empty){display:none}:where(discord-image-attachment){position:relative;display:block;max-width:100%;border-radius:var(--dt-radius-md);overflow:hidden;line-height:0}:where(discord-image-attachment) img{display:block;max-width:100%;max-height:350px;border-radius:var(--dt-radius-md);object-fit:contain;cursor:pointer}:where(discord-image-attachment) a{display:block}discord-image-attachment[url]:not([data-dt-ready]):not(:has(img)){min-width:220px;min-height:120px;border:1px dashed var(--dt-border-strong)}discord-image-attachment[spoiler] img,discord-video-attachment[spoiler] video{filter:blur(44px);transition:filter var(--dt-transition)}discord-image-attachment[spoiler][data-dt-revealed] img,discord-video-attachment[spoiler][data-dt-revealed] video{filter:none}.dt-spoiler-overlay{position:absolute;inset:0;z-index:1;display:flex;align-items:center;justify-content:center;border:0;border-radius:var(--dt-radius-md);background:#00000059;color:#fff;font-family:var(--dt-font);font-size:.75rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;cursor:pointer}.dt-spoiler-overlay:hover{background:#00000073}discord-image-attachment[data-dt-revealed]>.dt-spoiler-overlay,discord-video-attachment[data-dt-revealed]>.dt-spoiler-overlay{display:none}:where(discord-file-attachment){display:flex;align-items:center;gap:12px;width:100%;max-width:420px;padding:12px;border:1px solid var(--dt-border);border-radius:var(--dt-radius-md);background:var(--dt-bg-secondary)}:where(discord-file-attachment) a{display:flex;align-items:center;gap:12px;width:100%;color:inherit;text-decoration:none}discord-file-attachment:empty{display:grid;grid-template-columns:30px minmax(0,1fr);align-content:center;column-gap:12px}discord-file-attachment:empty:before{grid-column:1;grid-row:1 / span 2;content:"FILE";display:flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:var(--dt-radius-sm);background:var(--dt-bg-modifier-hover);color:var(--dt-text-muted);font-size:.5625rem;font-weight:700}discord-file-attachment[type]:empty:before{content:attr(type)}discord-file-attachment:empty:after{grid-column:2;content:attr(name) "\a" attr(bytes) " " attr(bytes-unit);white-space:pre-line;line-height:1.25rem}discord-file-attachment[bytes=""]:empty:after,discord-file-attachment:not([bytes]):empty:after{content:attr(name)}.dt-file-icon{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:var(--dt-radius-sm);background:var(--dt-bg-modifier-hover);color:var(--dt-text-muted);font-size:.5625rem;font-weight:700;text-transform:uppercase;flex:none}.dt-file-meta{display:flex;flex-direction:column;min-width:0}.dt-file-name{font-size:.875rem;font-weight:500;color:var(--dt-text-strong);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dt-file-size{font-size:.75rem;color:var(--dt-text-muted)}:where(discord-audio-attachment){display:block;width:100%;max-width:420px}:where(discord-audio-attachment) audio{display:block;width:100%;max-width:420px;border-radius:var(--dt-radius-md);outline:none}:where(discord-video-attachment){position:relative;display:block;max-width:100%;border-radius:var(--dt-radius-md);overflow:hidden;background:#000;line-height:0}:where(discord-video-attachment) video{display:block;max-width:100%;max-height:400px;border-radius:var(--dt-radius-md)}:where(discord-video-attachment) video:focus-visible,:where(discord-audio-attachment) audio:focus-visible{box-shadow:0 0 0 2px var(--dt-focus-ring)}:where(discord-reactions){display:flex;flex-wrap:wrap;align-items:center;gap:4px;margin-top:8px}:where(discord-reactions:empty){display:none}:where(discord-reaction){display:inline-flex;align-items:center;gap:6px;min-width:36px;height:24px;padding:2px 6px;border:1px solid var(--dt-reaction-border);border-radius:var(--dt-radius-md);background:var(--dt-reaction-bg);color:var(--dt-text-normal);font-family:var(--dt-font);font-size:.875rem;line-height:1;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background var(--dt-transition),border-color var(--dt-transition)}:where(discord-reaction:hover){border-color:var(--dt-border-strong)}:where(discord-reaction[reacted]){background:var(--dt-reaction-bg-reacted);border-color:var(--dt-reaction-border-reacted);color:var(--dt-reaction-text-reacted)}discord-reaction:not([data-dt-ready]):before{content:attr(emoji);font-size:1rem;line-height:1}discord-reaction[emoji^=http]:not([data-dt-ready]):before,discord-reaction[emoji^="data:"]:not([data-dt-ready]):before,discord-reaction[emoji^="blob:"]:not([data-dt-ready]):before,discord-reaction[emoji^="/"]:not([data-dt-ready]):before,discord-reaction[emoji^="./"]:not([data-dt-ready]):before,discord-reaction:not([emoji]):not([data-dt-ready]):before{content:none}discord-reaction:not([data-dt-ready]):after{content:attr(count);font-size:.875rem;font-weight:500;line-height:1}discord-reaction:not([count]):not([data-dt-ready]):after,discord-reaction[count="1"]:not([data-dt-ready]):after{content:none}:where(discord-reaction) img,.dt-reaction-emoji{display:inline-block;flex:none;width:1rem;height:1rem;overflow:hidden;object-fit:contain;vertical-align:middle}.dt-reaction-count{font-size:.75rem;font-weight:600;line-height:1;color:inherit}:where(discord-action-row){display:flex;flex-wrap:wrap;gap:8px;margin-top:8px;max-width:600px}:where(discord-button){display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:32px;padding:2px 16px;border:0;border-radius:var(--dt-radius-sm);background:var(--dt-button-secondary);color:#fff;font-family:var(--dt-font);font-size:.875rem;font-weight:500;line-height:1rem;white-space:nowrap;cursor:pointer;transition:background var(--dt-transition)}:where(discord-button):hover{background:var(--dt-button-secondary-hover)}:where(discord-button[type=primary]){background:var(--dt-button-primary)}:where(discord-button[type=primary]):hover{background:var(--dt-button-primary-hover)}:where(discord-button[type=success]){background:var(--dt-button-success)}:where(discord-button[type=destructive],discord-button[type=danger]){background:var(--dt-button-danger)}:where(discord-button[type=link]){background:var(--dt-button-link)}:where(discord-button[disabled]){opacity:.5;cursor:not-allowed}.dt-button-emoji{width:1rem;height:1rem;object-fit:contain}.dt-button-link-icon{width:12px;height:12px;opacity:.9}:where(discord-verified-author-tag){display:inline-flex;align-items:center;justify-content:center;gap:3px;height:16px;padding:0 5px 0 4px;border-radius:4px;background:var(--dt-brand);color:var(--dt-text-on-brand);font-size:.625rem;font-weight:600;line-height:1;letter-spacing:.02em;text-transform:uppercase;vertical-align:-2px}:where(discord-verified-author-tag):before{content:"\2713";font-size:.75rem;line-height:1}:where(discord-verified-author-tag:not([verified])):before{content:none}:where(discord-verified-author-tag):after{content:"APP"}.dt-divider{height:1px;margin:8px 0;border:0;background:var(--dt-divider)}.dt-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:where(discord-message,discord-embed,discord-attachments,discord-reactions) :focus-visible{outline:none;box-shadow:0 0 0 2px var(--dt-focus-ring)}@media(prefers-reduced-motion:reduce){:where(discord-spoiler),:where(discord-reaction),:where(discord-button),discord-image-attachment img{transition:none}}@media(max-width:480px){:where(discord-messages){--dt-msg-padding-right: 16px}:where(discord-embed),:where(discord-attachments){max-width:100%}}@media print{:root,discord-messages,discord-message{--dt-bg-primary: #ffffff;--dt-bg-secondary: #f2f3f5;--dt-bg-embed: #f2f3f5;--dt-bg-code: #f2f3f5;--dt-text-normal: #000000;--dt-text-strong: #000000;--dt-text-muted: #444444}:where(discord-spoiler){background:none;color:inherit}.dt-copy,.dt-spoiler-overlay{display:none!important}}
@@ -0,0 +1,2 @@
1
+ /*! discord-transcript-ui v1.0.1 | MIT | https://github.com/x1xo/discord-transcript-ui */
2
+ (function(){"use strict";if(typeof window=="undefined"||typeof document=="undefined"||window.DiscordTranscript&&window.DiscordTranscript.version)return;var Z="1.0.0",mt=420*1e3,T={blue:"https://cdn.discordapp.com/embed/avatars/0.png",gray:"https://cdn.discordapp.com/embed/avatars/1.png",green:"https://cdn.discordapp.com/embed/avatars/2.png",orange:"https://cdn.discordapp.com/embed/avatars/3.png",red:"https://cdn.discordapp.com/embed/avatars/4.png",pink:"https://cdn.discordapp.com/embed/avatars/5.png"},R=["#5865f2","#3ba55c","#faa81a","#ed4245","#eb459e","#00a8fc","#9b59b6","#1abc9c"],$=[],w=[];function k(){return window.$discordMessage=window.$discordMessage||{}}function q(){return window.discordTranscript=window.discordTranscript||{}}function G(){var t={},r;for(r in T)t[r]=T[r];var e=k().avatars||{};for(r in e)e[r]&&(t[r]=e[r]);return(!t.default||T[t.default])&&(t.default=t[e.default]||T.blue),t}function H(t){var r=G();return t==null||t===""?r.default:r[t]?r[t]:t}function J(t){var r=t.getAttribute("profile"),e=k().profiles||{};return r&&e[r]||{}}function Q(t,r,e){var a=t.getAttribute(r);return a===null||a===""?e:a}function X(t){var r=J(t),e=Q(t,"author",r.author||"User"),a=t.getAttribute("avatar")||r.avatar;return{author:e,avatarUrl:H(a),hasAvatar:!!a,roleColor:t.getAttribute("role-color")||r.roleColor||null,bot:s(t,"bot")||!!r.bot,verified:s(t,"verified")||!!r.verified,server:s(t,"server")||!!r.server,official:s(t,"official-app")||!!r.officialApp,op:s(t,"op")||!!r.op}}function s(t,r){return t.hasAttribute(r)}function K(t){for(var r=0,e=0;e<t.length;e++)r=(r+t.charCodeAt(e))%997;return R[r%R.length]}function M(t){if(t==null||t==="")return null;if(/^\d+$/.test(t))return new Date(Number(t));var r=new Date(t);return isNaN(r.getTime())?null:r}function tt(){return q().timeZone||void 0}function rt(){return q().locale||"en-US"}function A(t,r){return new Intl.DateTimeFormat(rt(),Object.assign({timeZone:tt()},t)).format(r)}function z(t){return!(t||q().hour24)}function D(t,r){return A({hour:"numeric",minute:"2-digit",hour12:z(r)},t).replace(/\u202f/g," ")}function et(t,r){var e=new Date,a=new Date(e.getFullYear(),e.getMonth(),e.getDate()),d=new Date(t.getFullYear(),t.getMonth(),t.getDate()),i=Math.round((a-d)/864e5);return i===0?"Today at "+D(t,r):i===1?"Yesterday at "+D(t,r):A({day:"2-digit",month:"2-digit",year:"numeric"},t)}function E(t,r,e){switch(r){case"t":return D(t,e);case"T":return A({hour:"numeric",minute:"2-digit",second:"2-digit",hour12:z(e)},t).replace(/\u202f/g," ");case"d":return A({day:"2-digit",month:"2-digit",year:"numeric"},t);case"D":return A({day:"numeric",month:"long",year:"numeric"},t);case"F":return A({weekday:"long",day:"numeric",month:"long",year:"numeric"},t)+" at "+D(t,e);case"R":return _(t);case"f":default:return A({day:"numeric",month:"long",year:"numeric"},t)+" at "+D(t,e)}}function _(t){for(var r=Math.round((t.getTime()-Date.now())/1e3),e=r>0,a=[["year",31536e3],["month",2592e3],["week",604800],["day",86400],["hour",3600],["minute",60],["second",1]],d=0;d<a.length;d++){var i=a[d][1];if(Math.abs(r)>=i||i===1){var n=Math.abs(Math.round(r/i)),u=a[d][0]+(n===1?"":"s");return e?"in "+n+" "+u:n+" "+u+" ago"}}return"now"}function o(t,r,e){var a=document.createElement(t);return r&&(a.className=r),e!==void 0&&(a.textContent=e),a}function j(t,r){var e=o("span",r||"dt-avatar");if(t.hasAvatar){var a=o("img");a.src=t.avatarUrl,a.alt="",a.decoding="async",e.appendChild(a)}else e.classList.add("dt-avatar--initials"),e.style.backgroundColor=K(t.author),e.textContent=(t.author||"?").charAt(0);return e}function at(t){var r=o("span","dt-badges");if(t.bot){var e=t.verified?"dt-badge dt-badge--verified":"dt-badge";r.appendChild(o("span",e,"APP"))}else t.server?r.appendChild(o("span","dt-badge dt-badge--server","SERVER")):t.official&&r.appendChild(o("span","dt-badge dt-badge--official","OFFICIAL"));return t.op&&r.appendChild(o("span","dt-badge","OP")),r.children.length?r:null}function dt(t){if(!s(t,"data-dt-ready")){var r=P(t),e=M(t.getAttribute("timestamp")),a=o("div","dt-body"),d=[],i=t.querySelector(":scope > discord-author-info, :scope > discord-message-header");for(i&&i.remove();t.firstChild;){var n=t.firstChild;if(n.nodeType===1&&(n.tagName==="DISCORD-REPLY"||n.tagName==="DISCORD-COMMAND")){d.push(n),t.removeChild(n);continue}a.appendChild(n)}var u=o("div","dt-msg");if(d.length){u.classList.add("dt-msg--has-reply");for(var l=0;l<d.length;l++)u.appendChild(d[l])}u.appendChild(j(r,"dt-avatar"));var c=o("div","dt-content"),f=o("div","dt-header"),v=o("span","dt-author",r.author);r.roleColor&&(v.style.color=r.roleColor),f.appendChild(v);var p=at(r);p&&f.appendChild(p);var g=s(t,"twenty-four");if(e){var b=o("span","dt-timestamp",et(e,g));b.title=E(e,"F",g),f.appendChild(b),t.setAttribute("data-dt-short-time",D(e,g))}c.appendChild(f),c.appendChild(a),u.appendChild(c),t.appendChild(u),s(t,"edited")&&a.appendChild(o("span","dt-edited","(edited)")),it(a)&&a.classList.add("dt-jumbo"),t.setAttribute("data-dt-ready","")}}function P(t){return X(t)}function it(t){var r=(t.textContent||"").replace(/\s+/g,"");if(r.length>0)return!1;var e=t.querySelectorAll("discord-custom-emoji, img.emoji");return e.length>0&&e.length<=6}function ot(t){if(q().grouping!==!1)for(var r=(q().groupWindow||7)*60*1e3,e=null,a=null,d=0;d<t.length;d++){var i=t[d];if(i.removeAttribute("data-dt-continuation"),i.removeAttribute("data-dt-group-start"),i.hasAttribute("message-body-only")){i.setAttribute("data-dt-continuation",""),e=null,a=null;continue}var n=i.getAttribute("profile")||i.getAttribute("author")||i.getAttribute("avatar"),u=M(i.getAttribute("timestamp")),l=e!==null&&n!==null&&n===e,c=a===null||u===null||Math.abs(u-a)<=r;l&&c?i.setAttribute("data-dt-continuation",""):e!==null&&i.setAttribute("data-dt-group-start",""),e=n,a=u}}function nt(t){if(!(s(t,"data-dt-ready")||s(t,"deleted"))){var r=P(t),e=[];t.querySelector(":scope > .dt-reply-avatar")||r.hasAvatar&&e.push(j(r,"dt-reply-avatar"));var a=o("span","dt-reply-author",(s(t,"mentions")?"@":"")+r.author);r.roleColor&&(a.style.color=r.roleColor),e.push(a);var d=o("span","dt-sr-only","replying to ");t.insertBefore(d,t.firstChild);for(var i=e.length-1;i>=0;i--)t.insertBefore(e[i],d.nextSibling);t.setAttribute("data-dt-ready","")}}function ut(t){if(!s(t,"data-dt-ready")){var r=t.getAttribute("timestamp");if(r){var e=M(r==="now"?String(Date.now()):r);if(e){var a=s(t,"twenty-four"),d=t.getAttribute("format")||"f";t.setAttribute("data-dt-stamp",e.toISOString()),t.textContent=E(e,d,a),t.setAttribute("datetime",e.toISOString()),t.title=E(e,"F",a),t.setAttribute("data-dt-ready",""),d==="R"&&w.indexOf(t)===-1&&w.push(t)}}}}function st(t){return M(t.getAttribute("data-dt-stamp")||t.getAttribute("timestamp"))}function N(){for(var t=0;t<w.length;t++){var r=st(w[t]);r&&(w[t].textContent=_(r))}}function ct(t){for(var r=t.querySelectorAll("discord-spoiler:not([data-dt-ready])"),e=0;e<r.length;e++){var a=r[e];a.setAttribute("data-dt-ready",""),a.setAttribute("role","button"),a.hasAttribute("tabindex")||a.setAttribute("tabindex","0"),a.setAttribute("aria-expanded",s(a,"activated")?"true":"false")}for(var d=t.querySelectorAll("discord-image-attachment[spoiler], discord-video-attachment[spoiler]"),i=0;i<d.length;i++)d[i].querySelector(":scope > .dt-spoiler-overlay")||d[i].appendChild(o("button","dt-spoiler-overlay","Spoiler"))}function U(t){var r=!s(t,"data-dt-revealed");r?t.setAttribute("data-dt-revealed",""):t.removeAttribute("data-dt-revealed"),t.hasAttribute("aria-expanded")&&t.setAttribute("aria-expanded",r?"true":"false")}function lt(t){if(!s(t,"data-dt-ready")){var r=t.getAttribute("emoji"),e=r&&/^(https?:|data:|blob:|\/|\.\/)/i.test(r);if(e){var a=o("img","dt-reaction-emoji");a.src=r,a.alt=t.getAttribute("name")||"",a.loading="lazy",a.decoding="async",t.appendChild(a)}else r&&t.appendChild(o("span","dt-reaction-emoji",r));var d=parseInt(t.getAttribute("count")||"1",10);d>1&&t.appendChild(o("span","dt-reaction-count",String(d))),t.setAttribute("data-dt-ready","")}}function ft(t){var r=t.querySelector(":scope > .dt-reaction-count");return r&&parseInt(r.textContent,10)||1}function W(t,r){var e=t.querySelector(":scope > .dt-reaction-count");if(r<=1){e&&e.remove();return}e?e.textContent=String(r):t.appendChild(o("span","dt-reaction-count",String(r)))}function pt(t){if(!s(t,"data-dt-ready")){var r=t.getAttribute("color");r&&t.style.setProperty("--dt-embed-color",r);var e=t.querySelector(":scope > .dt-embed-content");if(!e){for(e=o("div","dt-embed-content");t.firstChild;)e.appendChild(t.firstChild);t.appendChild(e)}var a=t.getAttribute("provider");a&&!e.querySelector(":scope > .dt-embed-provider")&&e.insertBefore(o("span","dt-embed-provider",a),e.firstChild);var d=t.getAttribute("author-name");if(d&&!e.querySelector(":scope > .dt-embed-author")){var i=o("div","dt-embed-author"),n=t.getAttribute("author-image");if(n){var u=o("img");u.src=n,u.alt="",u.loading="lazy",u.decoding="async",i.appendChild(u)}var l=t.getAttribute("author-url");if(l){var c=o("a",null,d);c.href=l,c.target="_blank",c.rel="noopener noreferrer",i.appendChild(c)}else i.appendChild(o("span",null,d));e.insertBefore(i,e.firstChild)}var f=t.getAttribute("embed-title")||t.getAttribute("title");if(f&&!e.querySelector(":scope > .dt-embed-title")){var v=t.getAttribute("url"),p=v?o("a","dt-embed-title dt-embed-title--link",f):o("span","dt-embed-title",f);v&&(p.href=v,p.target="_blank",p.rel="noopener noreferrer");var g=e.querySelector(":scope > .dt-embed-author, :scope > .dt-embed-provider");g?g.insertAdjacentElement("afterend",p):e.insertBefore(p,e.firstChild)}var b=t.getAttribute("thumbnail");if(b&&!t.querySelector(":scope > .dt-embed-thumbnail")){var x=o("div","dt-embed-thumbnail"),y=o("img");y.src=b,y.alt="",y.loading="lazy",y.decoding="async",x.appendChild(y),t.appendChild(x)}var C=t.getAttribute("video"),O=t.getAttribute("image");if((C||O)&&!t.querySelector(":scope > .dt-embed-image")){var S=o("div","dt-embed-image");if(C){var m=o("video");m.controls=!0,m.preload="metadata",m.src=C,S.appendChild(m)}else{var h=o("img");h.src=O,h.alt="",h.loading="lazy",h.decoding="async",S.appendChild(h)}var F=e.querySelector(":scope > discord-embed-footer");e.insertBefore(S,F||null)}t.setAttribute("data-dt-ready","")}}function vt(t){if(!s(t,"data-dt-ready")){var r=t.getAttribute("url");if(r&&!t.querySelector("img")){var e=o("img");e.src=r,e.alt=t.getAttribute("alt")||"discord image attachment",e.loading="lazy",e.decoding="async";var a=t.getAttribute("width"),d=t.getAttribute("height");a&&(e.style.maxWidth=a+"px"),d&&(e.style.maxHeight=d+"px"),t.appendChild(e)}var i=t.querySelector("img");i&&!i.getAttribute("loading")&&(i.loading="lazy"),t.setAttribute("data-dt-ready","")}}function Y(t,r){if(!s(t,"data-dt-ready")){var e=t.getAttribute("href")||t.getAttribute("src");if(e&&!t.querySelector(r)){var a=o(r);if(a.controls=!0,a.preload="metadata",a.src=e,r==="video"){a.playsInline=!0;var d=t.getAttribute("poster");d&&(a.poster=d)}t.appendChild(a)}t.setAttribute("data-dt-ready","")}}function gt(t){if(!s(t,"data-dt-ready")){var r=t.getAttribute("href");if(r&&!t.firstChild){var e=o("a");e.href=r,e.target=t.getAttribute("target")||"_blank",e.rel="noopener noreferrer";var a=t.getAttribute("name")||r.split("/").pop()||"file";e.appendChild(o("span","dt-file-icon",t.getAttribute("type")||"FILE"));var d=o("span","dt-file-meta");d.appendChild(o("span","dt-file-name",a)),d.appendChild(o("span","dt-file-size",[t.getAttribute("bytes"),t.getAttribute("bytes-unit")].filter(Boolean).join(" "))),e.appendChild(d),t.appendChild(e)}t.setAttribute("data-dt-ready","")}}function ht(t){if(!(s(t,"data-dt-ready")||t.querySelector(":scope > .dt-copy"))){var r=o("button","dt-copy","Copy");r.type="button",t.appendChild(r),t.setAttribute("data-dt-ready","")}}function bt(t){for(var r=t.querySelectorAll("discord-attachments img:not([loading]), discord-embed img:not([loading]), discord-embed video, discord-thread img"),e=0;e<r.length;e++)r[e].setAttribute("loading","lazy")}function I(t){if(!(!t||!t.querySelectorAll)){for(var r=t.querySelectorAll("discord-message:not([data-dt-ready])"),e=0;e<r.length;e++)dt(r[e]);for(var a=t.querySelectorAll("discord-messages"),d=0;d<a.length;d++){var i=a[d].querySelectorAll(":scope > discord-message");i.length&&ot(i)}for(var n=t.querySelectorAll("discord-reply:not([data-dt-ready])"),u=0;u<n.length;u++)nt(n[u]);for(var l=t.querySelectorAll("discord-time:not([data-dt-ready])"),c=0;c<l.length;c++)ut(l[c]);for(var f=t.querySelectorAll("discord-embed:not([data-dt-ready])"),v=0;v<f.length;v++)pt(f[v]);for(var p=t.querySelectorAll("discord-file-attachment:not([data-dt-ready])"),g=0;g<p.length;g++)gt(p[g]);for(var b=t.querySelectorAll("discord-image-attachment:not([data-dt-ready])"),x=0;x<b.length;x++)vt(b[x]);for(var y=t.querySelectorAll("discord-video-attachment:not([data-dt-ready])"),C=0;C<y.length;C++)Y(y[C],"video");for(var O=t.querySelectorAll("discord-audio-attachment:not([data-dt-ready])"),S=0;S<O.length;S++)Y(O[S],"audio");for(var m=t.querySelectorAll("discord-reaction:not([data-dt-ready])"),h=0;h<m.length;h++)lt(m[h]);for(var F=t.querySelectorAll("discord-pre:not([data-dt-ready])"),B=0;B<F.length;B++)ht(F[B]);ct(t),bt(t),yt(t)}}function yt(t){for(var r=t.querySelectorAll("discord-messages"),e=0;e<r.length;e++)r[e].hasAttribute("light-theme")&&!r[e].hasAttribute("data-theme")&&r[e].setAttribute("data-theme","light")}function At(t){var r=t.target;if(!(!r||!r.closest)){var e=r.closest("discord-spoiler");if(e){U(e);return}var a=r.closest(".dt-spoiler-overlay");if(a&&a.parentElement){a.parentElement.setAttribute("data-dt-revealed","");return}var d=r.closest("discord-reaction");if(d&&d.hasAttribute("data-dt-ready")){var i=ft(d);s(d,"reacted")?(d.removeAttribute("reacted"),W(d,Math.max(1,i-1))):(d.setAttribute("reacted",""),W(d,i+1));return}var n=r.closest(".dt-copy");if(n&&n.parentElement&&navigator.clipboard){var u=n.parentElement,l=u.querySelector("discord-code, pre, code");navigator.clipboard.writeText((l||u).textContent).then(function(){n.textContent="Copied",setTimeout(function(){n.textContent="Copy"},1200)})}}}function Ct(t){if(!(t.key!=="Enter"&&t.key!==" ")){var r=t.target;if(!(!r||!r.closest)){var e=r.closest("discord-spoiler");e&&(t.preventDefault(),U(e))}}}var L=null;function St(t){L||(L=window.requestAnimationFrame(function(){L=null,I(t||document)}))}function V(){if(I(document),document.addEventListener("click",At,!1),document.addEventListener("keydown",Ct,!1),window.setInterval&&$.push(window.setInterval(function(){w.length&&N()},6e4)),q().observe!==!1&&window.MutationObserver){var t=new MutationObserver(function(r){for(var e=0;e<r.length;e++)if(r[e].addedNodes.length){St(document);return}});t.observe(document.documentElement,{childList:!0,subtree:!0})}}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",V,!1):V(),window.DiscordTranscript={version:Z,upgrade:function(t){I(t||document)},refresh:N,formatStamp:E,parseStamp:M}})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "discord-transcript-ui",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Dependency-free, light-DOM custom elements and one stylesheet for rendering Discord chat transcripts in plain HTML.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -32,7 +32,8 @@
32
32
  "verify": "node build/verify.mjs",
33
33
  "scaffold": "node tools/scaffold.mjs",
34
34
  "serve": "node build/serve.mjs",
35
- "demo": "node build/serve.mjs"
35
+ "demo": "node build/serve.mjs",
36
+ "preview": "node tools/scaffold.mjs --body examples/messages.html --out examples/local-preview.html --config examples/config.js --local --title \"local preview\""
36
37
  },
37
38
  "devDependencies": {
38
39
  "esbuild": "^0.25.12"
@@ -544,9 +544,10 @@ discord-message:not([data-dt-ready])[author='']::before {
544
544
  display: inline-flex;
545
545
  align-items: center;
546
546
  justify-content: center;
547
- height: 15px;
548
- padding: 0 4px;
549
- border-radius: 3px;
547
+ gap: 3px;
548
+ height: 16px;
549
+ padding: 0 5px;
550
+ border-radius: 4px;
550
551
  background: var(--dt-brand);
551
552
  color: var(--dt-text-on-brand);
552
553
  font-size: 0.625rem;
@@ -556,15 +557,17 @@ discord-message:not([data-dt-ready])[author='']::before {
556
557
  text-transform: uppercase;
557
558
  }
558
559
 
560
+ /* Verified bot / application tag: a slightly rounded blurple rectangle reading
561
+ "✓ APP" (the tick is drawn here, the text comes from the script so that it is
562
+ real, readable text rather than generated content). */
559
563
  .dt-badge--verified {
560
- width: 15px;
561
- padding: 0;
562
- border-radius: 50%;
564
+ padding: 0 5px 0 4px;
563
565
  }
564
566
 
565
- .dt-badge--verified::after {
567
+ .dt-badge--verified::before {
566
568
  content: '\2713';
567
- font-size: 9px;
569
+ font-size: 0.75rem;
570
+ line-height: 1;
568
571
  }
569
572
 
570
573
  .dt-badge--server {
@@ -731,7 +734,12 @@ discord-author-info:not([data-dt-ready])::before {
731
734
  content: attr(author);
732
735
  }
733
736
 
734
- :where(discord-author-info[bot], discord-author-info[server], discord-author-info[official-app], discord-author-info[op])
737
+ :where(
738
+ discord-author-info[bot],
739
+ discord-author-info[server],
740
+ discord-author-info[official-app],
741
+ discord-author-info[op]
742
+ )
735
743
  ::after {
736
744
  margin-left: 4px;
737
745
  padding: 0 4px;
@@ -743,8 +751,14 @@ discord-author-info:not([data-dt-ready])::before {
743
751
  line-height: 15px;
744
752
  }
745
753
 
754
+ /* Bots are tagged "APP". Verified bots add the checkmark, so they read "✓ APP"
755
+ (equal :where() specificity, so the later rule wins for verified bots). */
746
756
  :where(discord-author-info[bot])::after {
747
- content: 'BOT';
757
+ content: 'APP';
758
+ }
759
+
760
+ :where(discord-author-info[bot][verified])::after {
761
+ content: '\2713\00a0APP';
748
762
  }
749
763
 
750
764
  :where(discord-author-info[server])::after {
@@ -1139,6 +1153,19 @@ discord-reply[deleted]::before {
1139
1153
  color: var(--dt-text-muted);
1140
1154
  }
1141
1155
 
1156
+ /* A reply preview sits above the author row (Discord's layout): the reply takes
1157
+ the first grid row, so the avatar and the author name share the second. */
1158
+ .dt-msg--has-reply > :where(discord-reply),
1159
+ .dt-msg--has-reply > :where(discord-command) {
1160
+ grid-column: 2;
1161
+ grid-row: 1;
1162
+ }
1163
+
1164
+ .dt-msg--has-reply > .dt-avatar,
1165
+ .dt-msg--has-reply > .dt-content {
1166
+ grid-row: 2;
1167
+ }
1168
+
1142
1169
  /* Curved connector, drawn only once the reply sits in the content column. */
1143
1170
  discord-message[data-dt-ready] :where(discord-reply)::after {
1144
1171
  content: '';
@@ -1698,6 +1725,8 @@ discord-reaction:not([data-dt-ready])::before {
1698
1725
  }
1699
1726
 
1700
1727
  discord-reaction[emoji^='http']:not([data-dt-ready])::before,
1728
+ discord-reaction[emoji^='data:']:not([data-dt-ready])::before,
1729
+ discord-reaction[emoji^='blob:']:not([data-dt-ready])::before,
1701
1730
  discord-reaction[emoji^='/']:not([data-dt-ready])::before,
1702
1731
  discord-reaction[emoji^='./']:not([data-dt-ready])::before,
1703
1732
  discord-reaction:not([emoji]):not([data-dt-ready])::before {
@@ -1719,8 +1748,10 @@ discord-reaction[count='1']:not([data-dt-ready])::after {
1719
1748
  :where(discord-reaction) img,
1720
1749
  .dt-reaction-emoji {
1721
1750
  display: inline-block;
1751
+ flex: none;
1722
1752
  width: 1rem;
1723
1753
  height: 1rem;
1754
+ overflow: hidden;
1724
1755
  object-fit: contain;
1725
1756
  vertical-align: middle;
1726
1757
  }
@@ -1810,17 +1841,32 @@ discord-reaction[count='1']:not([data-dt-ready])::after {
1810
1841
  display: inline-flex;
1811
1842
  align-items: center;
1812
1843
  justify-content: center;
1813
- width: 15px;
1814
- height: 15px;
1815
- border-radius: 50%;
1844
+ gap: 3px;
1845
+ height: 16px;
1846
+ padding: 0 5px 0 4px;
1847
+ border-radius: 4px;
1816
1848
  background: var(--dt-brand);
1817
1849
  color: var(--dt-text-on-brand);
1818
- font-size: 9px;
1850
+ font-size: 0.625rem;
1851
+ font-weight: 600;
1852
+ line-height: 1;
1853
+ letter-spacing: 0.02em;
1854
+ text-transform: uppercase;
1819
1855
  vertical-align: -2px;
1820
1856
  }
1821
1857
 
1822
- :where(discord-verified-author-tag)::after {
1858
+ :where(discord-verified-author-tag)::before {
1823
1859
  content: '\2713';
1860
+ font-size: 0.75rem;
1861
+ line-height: 1;
1862
+ }
1863
+
1864
+ :where(discord-verified-author-tag:not([verified]))::before {
1865
+ content: none;
1866
+ }
1867
+
1868
+ :where(discord-verified-author-tag)::after {
1869
+ content: 'APP';
1824
1870
  }
1825
1871
 
1826
1872
  /* ==========================================================================
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * Config (define it any time before DOMContentLoaded):
11
11
  * window.$discordMessage = {
12
- * profiles: { skyra: { author: 'Skyra', avatar: 'https://…', roleColor: '#ff0000', bot: true } },
12
+ * profiles: { miona: { author: 'Miona', avatar: 'https://…', roleColor: '#ff0000', bot: true } },
13
13
  * avatars: { default: 'blue', blue: 'https://cdn.discordapp.com/embed/avatars/0.png' }
14
14
  * };
15
15
  * window.discordTranscript = { groupWindow: 7, locale: 'en-US', observe: true };
@@ -239,9 +239,11 @@
239
239
 
240
240
  function badgeRow(identity) {
241
241
  var row = make('span', 'dt-badges');
242
+ /* Bots are tagged "APP"; verified bots additionally get the checkmark,
243
+ which is drawn by CSS (so the tag reads "✓ APP"). */
242
244
  if (identity.bot) {
243
- if (identity.verified) row.appendChild(make('span', 'dt-badge dt-badge--verified'));
244
- else row.appendChild(make('span', 'dt-badge', 'BOT'));
245
+ var botTag = identity.verified ? 'dt-badge dt-badge--verified' : 'dt-badge';
246
+ row.appendChild(make('span', botTag, 'APP'));
245
247
  } else if (identity.server) {
246
248
  row.appendChild(make('span', 'dt-badge dt-badge--server', 'SERVER'));
247
249
  } else if (identity.official) {
@@ -259,14 +261,29 @@
259
261
  var identity = identityOf(element);
260
262
  var stamp = parseStamp(element.getAttribute('timestamp'));
261
263
  var body = make('div', 'dt-body');
264
+ var replies = [];
262
265
 
263
266
  /* Optional parser-supplied header escapes the generated one. */
264
267
  var suppliedHeader = element.querySelector(':scope > discord-author-info, :scope > discord-message-header');
265
268
  if (suppliedHeader) suppliedHeader.remove();
266
269
 
267
- while (element.firstChild) body.appendChild(element.firstChild);
270
+ /* Reply previews are lifted out of the body: Discord draws them above the
271
+ author row, with the avatar level with the author name. */
272
+ while (element.firstChild) {
273
+ var child = element.firstChild;
274
+ if (child.nodeType === 1 && (child.tagName === 'DISCORD-REPLY' || child.tagName === 'DISCORD-COMMAND')) {
275
+ replies.push(child);
276
+ element.removeChild(child);
277
+ continue;
278
+ }
279
+ body.appendChild(child);
280
+ }
268
281
 
269
282
  var wrap = make('div', 'dt-msg');
283
+ if (replies.length) {
284
+ wrap.classList.add('dt-msg--has-reply');
285
+ for (var replyIndex = 0; replyIndex < replies.length; replyIndex++) wrap.appendChild(replies[replyIndex]);
286
+ }
270
287
  wrap.appendChild(avatarNode(identity, 'dt-avatar'));
271
288
 
272
289
  var content = make('div', 'dt-content');
@@ -422,8 +439,10 @@
422
439
  function upgradeReactions(element) {
423
440
  if (has(element, 'data-dt-ready')) return;
424
441
  var emoji = element.getAttribute('emoji');
425
- var isUrl = emoji && /^(https?:|\/|\.\/)/.test(emoji);
426
- if (isUrl) {
442
+ /* Any of these is an image source rather than a unicode character. Data
443
+ URIs matter: inline SVG/PNG emoji must never be emitted as visible text. */
444
+ var isImage = emoji && /^(https?:|data:|blob:|\/|\.\/)/i.test(emoji);
445
+ if (isImage) {
427
446
  var img = make('img', 'dt-reaction-emoji');
428
447
  img.src = emoji;
429
448
  img.alt = element.getAttribute('name') || '';