snapshot of eee7b5cfc0776c68816d7fdaa8af9d7a0e0da2e6 Annotations about the code that implements koment.

editors/vscode/panel.js

1 'use strict';
2
3 const statusTone = {
4 ok: 'ok',
5 moved: 'moved',
6 ambiguous: 'failing',
7 drifted: 'failing',
8 orphaned: 'failing'
9 };
10
11 function escape(text) {
12 return String(text ?? '').replace(
13 /[&<>"']/g,
14 (character) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[character]
15 );
16 }
17
18 function paragraphs(body) {
19 return String(body ?? '')
20 .split(/\n{2,}/)
21 .map((block) => block.trim())
22 .filter(Boolean)
23 .map((block) => `<p>${escape(block).replace(/\n/g, '<br>')}</p>`)
24 .join('');
25 }
26
27 function entry(item, index) {
28 const tone = statusTone[item.status] ?? 'failing';
29 const warning = item.warning ? `<p class="warning">${escape(item.warning)}</p>` : '';
30 return `<li>
31 <button type="button" data-reveal="${index}">
32 <span class="meta"><span class="kind">${escape(item.kind)}</span><span class="status ${tone}">${escape(item.status)}</span><span class="line">L${Number(item.line) || 0}</span></span>
33 <span class="body">${paragraphs(item.body)}${warning}</span>
34 </button>
35 </li>`;
36 }
37
38 // The panel exists because a body is a paragraph and every inline surface VS
39 // Code offers is one line (ADR 0114). Rendering prose is the whole job, so the
40 // markup is prose, not rows.
41 function panelHTML({ items, file, nonce, styleNonce }) {
42 const list = items.length
43 ? `<ul>${items.map(entry).join('')}</ul>`
44 : `<p class="empty">No annotations in this file.</p>`;
45 return `<!DOCTYPE html>
46 <html lang="en">
47 <head>
48 <meta charset="utf-8">
49 <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'nonce-${styleNonce}'; script-src 'nonce-${nonce}';">
50 <style nonce="${styleNonce}">
51 :root { color-scheme: light dark; }
52 body {
53 margin: 0; padding: 0.4rem 0.2rem;
54 font-family: var(--vscode-font-family); font-size: var(--vscode-font-size);
55 color: var(--vscode-foreground); background: transparent;
56 }
57 ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.15rem; }
58 button {
59 display: block; width: 100%; text-align: left; cursor: pointer;
60 background: none; border: none; border-left: 2px solid transparent;
61 padding: 0.45rem 0.6rem; color: inherit; font: inherit;
62 }
63 button:hover { background: var(--vscode-list-hoverBackground); }
64 button:focus-visible { outline: 1px solid var(--vscode-focusBorder); outline-offset: -1px; }
65 .meta { display: flex; gap: 0.5rem; align-items: baseline; margin-bottom: 0.2rem; }
66 .kind { font-weight: 600; }
67 .status { font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.04em; }
68 .status.ok { color: var(--vscode-descriptionForeground); }
69 .status.moved { color: var(--vscode-editorWarning-foreground); }
70 .status.failing { color: var(--vscode-editorError-foreground); }
71 .line { margin-left: auto; color: var(--vscode-descriptionForeground); font-variant-numeric: tabular-nums; }
72 .body p { margin: 0 0 0.4rem; line-height: 1.45; white-space: normal; }
73 .body p:last-child { margin-bottom: 0; }
74 .warning { color: var(--vscode-editorError-foreground); }
75 .empty { color: var(--vscode-descriptionForeground); padding: 0.6rem; }
76 .file { color: var(--vscode-descriptionForeground); padding: 0 0.6rem 0.4rem; }
77 </style>
78 </head>
79 <body>
80 ${file ? `<p class="file">${escape(file)}</p>` : ''}
81 ${list}
82 <script nonce="${nonce}">
83 const vscode = acquireVsCodeApi();
84 document.addEventListener('click', (event) => {
85 const target = event.target.closest('[data-reveal]');
86 if (target) {
87 vscode.postMessage({ reveal: Number(target.dataset.reveal) });
88 }
89 });
90 </script>
91 </body>
92 </html>`;
93 }
94
95 module.exports = { escape, panelHTML, paragraphs };

Find an annotation

Search file paths, rationale, kinds, and authors.

moveEnter openEsc close